diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..c0737607 --- /dev/null +++ b/.clang-format @@ -0,0 +1,10 @@ +BasedOnStyle: Google +BreakBeforeBraces: Linux +AlignConsecutiveDeclarations: true +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +SortIncludes: false +IndentWidth: 4 +ColumnLimit: 120 diff --git a/.gitignore b/.gitignore index ea0e8c77..1a7ac6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,20 @@ /.idea/ ./build/ +/build *.o *.a /*.cproject /*.autotools /.project /output -/sdk-tests/unit_test/unit_test.BASE -/sdk-tests/unit_test/unit_test.LOCAL -/sdk-tests/unit_test/unit_test.REMOTE .DS_Store *.DS_Store *.crt *.key sdk-tests/certs/unittest_private.key sdk-tests/certs/unittest_private.key -.vscode/settings.json +/.vscode/settings.json +/.vs +upload-fail-save.log +local_fw_info.json +ota.bin diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 00000000..350cfa37 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,211 @@ +# 项目信息 +project (QCloud_IoT_SDK C) + +# CMake 最低版本号要求 +cmake_minimum_required (VERSION 3.5) + +######################CONFIG BEGIN#################################### +# 编译类型: release/debug +set(BUILD_TYPE "release") + +# 代码抽取,ON表示根据配置抽取源码到ouput/qcloud_iot_c_sdk目录 +set(EXTRACT_SRC OFF) + +# 编译工具链 +set(COMPILE_TOOLS "gcc") +set(CMAKE_C_COMPILER $ENV{CROSS_COMPILE}gcc) +set(PLATFORM "linux") + +#set(COMPILE_TOOLS "MSVC") +#set(PLATFORM "windows") + +# 是否打开MQTT通道的总开关 +set(FEATURE_MQTT_COMM_ENABLED ON) + +# 是否打开设备影子的总开关 +set(FEATURE_MQTT_DEVICE_SHADOW ON) + +# 是否打开CoAP通道的总开关 +set(FEATURE_COAP_COMM_ENABLED OFF) + +# 是否打开MQTT通道网关功能 +set(FEATURE_GATEWAY_ENABLED ON) + +# 是否打开OTA固件升级总开关 +set(FEATURE_OTA_COMM_ENABLED ON) + +# OTA信令通道类型:MQTT/COAP +set(FEATURE_OTA_SIGNAL_CHANNEL "MQTT") + +# MQTT/CoAP接入认证方式,使用证书认证:CERT;使用密钥认证:KEY +set(FEATURE_AUTH_MODE "KEY") + +# 接入认证是否不使用TLS,证书方式必须选择使用TLS,密钥认证可选择不使用TLS +set(FEATURE_AUTH_WITH_NOTLS OFF) + +# 是否打开多线程功能支持 +set(FEATURE_MULTITHREAD_ENABLED ON) + +# 是否使能设备动态注册 +set(FEATURE_DEV_DYN_REG_ENABLED ON) + +# 是否打开日志上报云端功能 +set(FEATURE_LOG_UPLOAD_ENABLED OFF) + +# 是否打开代码中获取设备信息功能,OFF时将从device_info.json中读取设备信息 +set(FEATURE_DEBUG_DEV_INFO_USED OFF) + +# 是否打开获取iot后台时间功能 +set(FEATURE_SYSTEM_COMM_ENABLED ON) + +# 是否使用HTTPS下载固件 +set(FEATURE_OTA_USE_HTTPS ON) + +# 是否打开AT模组TCP功能 +set(FEATURE_AT_TCP_ENABLED OFF) + +# 设置AT模组设备(目前只支持esp8266) +set(AT_DEVICE_NAME "esp8266") + +# 是否打开AT模组中断接收功能 +set(FEATURE_AT_UART_RECV_IRQ OFF) + +# 是否打开AT模组多线程功能 +set(FEATURE_AT_OS_USED ON) + +# 是否打开AT模组调试功能 +set(FEATURE_AT_DEBUG OFF) + +# 是否打开广播功能 +set(FEATURE_BROADCAST_ENABLED ON) + +# 是否打开RRPC功能 +set(FEATURE_RRPC_ENABLED ON) + +# 是否打开远程配置功能 +set(FEATURE_REMOTE_CONFIG_MQTT_ENABLED ON) + +######################CONFIG END###################################### + +# 设置CMAKE使用编译工具及编译选项 +if (PLATFORM STREQUAL "linux" AND COMPILE_TOOLS STREQUAL "gcc") + if(${BUILD_TYPE} STREQUAL "release") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -Wno-error=sign-compare -Wno-error=format -Os -pthread") # 编译选项 + elseif(${BUILD_TYPE} STREQUAL "debug") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Werror -Wall -Wno-error=sign-compare -Wno-error=format -Os -pthread") # 编译选项 + endif() +elseif (PLATFORM STREQUAL "windows" AND COMPILE_TOOLS STREQUAL "MSVC") + # 去除相应的警告 + add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_USE_32BIT_TIME_T) + if(CMAKE_C_FLAGS MATCHES "/W[0-4]") + string(REGEX REPLACE "/W[0-4]" "/W2" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W2") + endif() +else () + #用户自定义 + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -Wno-error=sign-compare -Wno-error=format -Os") # 编译选项 + message(WARNING "User defined platform or compile tools!") +endif() + +# 解析配置 +if(${BUILD_TYPE} STREQUAL "release") + option(IOT_DEBUG "Enable IOT_DEBUG" OFF) +elseif(${BUILD_TYPE} STREQUAL "debug") + option(IOT_DEBUG "Enable IOT_DEBUG" ON) +else() + message(FATAL_ERROR "INVAILD BUILD_TYPE:${BUILD_TYPE}!") +endif() + +if(${FEATURE_AUTH_MODE} STREQUAL "KEY") + option(AUTH_MODE_KEY "Enable AUTH_MODE_KEY" ON) + option(AUTH_MODE_CERT "Enable AUTH_MODE_CERT" OFF) +elseif(${FEATURE_AUTH_MODE} STREQUAL "CERT" AND ${FEATURE_AUTH_WITH_NOTLS} STREQUAL "OFF") + option(AUTH_MODE_KEY "Enable AUTH_MODE_KEY" OFF) + option(AUTH_MODE_CERT "Enable AUTH_MODE_CERT" ON) + option(AUTH_WITH_NOTLS "Enable AUTH_WITH_NOTLS" OFF) +else() + message(FATAL_ERROR "INVAILD AUTH_MODE:${FEATURE_AUTH_MODE} WITH AUTH_WITH_NOTLS:${FEATURE_AUTH_WITH_NOTLS}!") +endif() + +if(${FEATURE_OTA_COMM_ENABLED} STREQUAL "ON") + if(${FEATURE_OTA_SIGNAL_CHANNEL} STREQUAL "MQTT" AND ${FEATURE_MQTT_COMM_ENABLED} STREQUAL "ON" ) + option(OTA_MQTT_CHANNEL "Enable TA_MQTT_CHANNEL" ON) + elseif(${FEATURE_OTA_SIGNAL_CHANNEL} STREQUAL "COAP" AND ${FEATURE_COAP_COMM_ENABLED} STREQUAL "ON") + option(OTA_MQTT_CHANNEL "Enable TA_MQTT_CHANNEL" OFF) + else() + message(FATAL_ERROR "INVAILD OTA_SIGNAL_CHANNEL:${FEATURE_OTA_SIGNAL_CHANNEL} OR DISABLED OTA_COMM, MQTT_COMM, COAP_COMM!") + endif() +endif() + +option(GATEWAY_ENABLED "Enable GATEWAY" ${FEATURE_GATEWAY_ENABLED}) +option(AUTH_WITH_NOTLS "Enable AUTH_WITH_NOTLS" ${FEATURE_AUTH_WITH_NOTLS}) +option(COAP_COMM_ENABLED "Enable COAP_COMM" ${FEATURE_COAP_COMM_ENABLED}) +option(SYSTEM_COMM "Enable SYSTEM_COMM" ${FEATURE_SYSTEM_COMM_ENABLED}) +option(MULTITHREAD_ENABLED "Enable Multi-thread support" ${FEATURE_MULTITHREAD_ENABLED}) +option(DEV_DYN_REG_ENABLED "Enable DEV_DYN_REG" ${FEATURE_DEV_DYN_REG_ENABLED}) +option(LOG_UPLOAD "Enable LOG_UPLOAD" ${FEATURE_LOG_UPLOAD_ENABLED}) +option(DEBUG_DEV_INFO_USED "Enable DEBUG_DEV_INFO_USED" ${FEATURE_DEBUG_DEV_INFO_USED}) +option(OTA_USE_HTTPS "Enable OTA_USE_HTTPS" ${FEATURE_OTA_USE_HTTPS}) +option(AT_TCP_ENABLED "Enable AT_TCP" ${FEATURE_AT_TCP_ENABLED}) +option(BROADCAST_ENABLED "Enable BROADCAST" ${FEATURE_BROADCAST_ENABLED}) +option(RRPC_ENABLED "Enable RRPC" ${FEATURE_RRPC_ENABLED}) +option(REMOTE_CONFIG_MQTT "Enable REMOTE_CONFIG_MQTT" ${FEATURE_REMOTE_CONFIG_MQTT_ENABLED}) + +if(AT_TCP_ENABLED STREQUAL "ON") + option(AT_UART_RECV_IRQ "Enable AT_UART_RECV_IRQ" ${FEATURE_AT_UART_RECV_IRQ}) + option(AT_OS_USED "Enable AT_UART_RECV_IRQ" ${FEATURE_AT_OS_USED}) + option(AT_DEBUG "Enable AT_DEBUG" ${FEATURE_AT_DEBUG}) +else() + option(AT_UART_RECV_IRQ "Enable AT_UART_RECV_IRQ" OFF) + option(AT_OS_USED "Enable AT_UART_RECV_IRQ" OFF) + option(AT_DEBUG "Enable AT_DEBUG" OFF) +endif() + +configure_file ( + "${PROJECT_SOURCE_DIR}/tools/cmake_scripts/config.h.in" + "${PROJECT_SOURCE_DIR}/include/config.h" + @ONLY +) + +# 头文件目录 +include_directories(${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/include/exports + ${PROJECT_SOURCE_DIR}/platform/at_device/esp8266 + ${PROJECT_SOURCE_DIR}/sdk_src/internal_inc + ${PROJECT_SOURCE_DIR}/external_libs/mbedtls/include) + +file(GLOB src_include ${PROJECT_SOURCE_DIR}/include/*.h) +file(GLOB src_inc_export ${PROJECT_SOURCE_DIR}/include/exports/*.h) +file(COPY ${src_include} DESTINATION ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/include) +file(COPY ${src_inc_export} DESTINATION ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/include/exports) + +if(${EXTRACT_SRC} STREQUAL "ON" AND NOT DEFINED SAMPLE_ONLY) + file(GLOB src_internal_inc ${PROJECT_SOURCE_DIR}/sdk_src/internal_inc/*.h) + file(COPY ${src_include} DESTINATION ${PROJECT_SOURCE_DIR}/output/qcloud_iot_c_sdk/include) + file(COPY ${src_inc_export} DESTINATION ${PROJECT_SOURCE_DIR}/output/qcloud_iot_c_sdk/include/exports) + file(COPY ${src_internal_inc} DESTINATION ${PROJECT_SOURCE_DIR}/output/qcloud_iot_c_sdk/sdk_src/internal_inc) + + if(AT_TCP_ENABLED STREQUAL "ON") + file(GLOB src_at_inc ${PROJECT_SOURCE_DIR}/platform/at_device/${AT_DEVICE_NAME}/*.h) + file(COPY ${src_at_inc} DESTINATION ${PROJECT_SOURCE_DIR}/output/qcloud_iot_c_sdk/platform) + endif() +endif() + +# 添加源代码目录 +if(NOT DEFINED SAMPLE_ONLY) + add_subdirectory(${PROJECT_SOURCE_DIR}/sdk_src) + add_subdirectory(${PROJECT_SOURCE_DIR}/platform) + add_subdirectory(${PROJECT_SOURCE_DIR}/external_libs/mbedtls) +endif() + +add_subdirectory(${PROJECT_SOURCE_DIR}/samples) +if(SAMPLE_ONLY STREQUAL "ON") + message(STATUS "Only compile samples!") +endif() + +# 证书及设备信息 +if(NOT DEFINED SAMPLE_ONLY) + file(COPY ${PROJECT_SOURCE_DIR}/certs DESTINATION ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/bin) + file(COPY ${PROJECT_SOURCE_DIR}/device_info.json DESTINATION ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/bin) +endif() diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 00000000..77289b00 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,17 @@ +{ + "configurations": [ + { + "name": "x86-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "msvc_x86" + ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 index 61572aa5..9ba06473 --- a/Makefile +++ b/Makefile @@ -1,45 +1,106 @@ +# Basic Settings +SHELL := /bin/bash +TOP_DIR ?= $(CURDIR) +SUBDIRS := directory-not-exist-actually + +# Settings of input directory +SCRIPT_DIR := $(TOP_DIR)/tools/build_scripts +SRC_DIR := sdk_src +PLATFORM_DIR := platform +EXP_INC_DIR := include include/exports +INT_INC_DIR := sdk_src/internal_inc + +# Thirdparty libs directory +THIRD_PARTY_PATH := $(TOP_DIR)/external_libs +TEST_LIB_DIR := $(THIRD_PARTY_PATH)/googletest + +# Sample directory +SAMPLE_DIR := $(TOP_DIR)/samples + +# Test directory +TESTS_DIR := $(TOP_DIR)/sdk-tests + include make.settings -include src/configs/default_settings.mk -include src/scripts/parse_make_settings.mk +include $(SCRIPT_DIR)/parse_make_settings.mk + +# Settings of output directory +TEMP_DIR := $(TOP_DIR)/tmp +DIST_DIR := $(TOP_DIR)/output +FINAL_DIR := $(DIST_DIR)/$(BUILD_TYPE) + +# Makefile echo +ifeq ($(DEBUG_MAKEFILE),n) + Q := @ + TOP_Q := @ +else + Q := + TOP_Q := +endif # IoT SDK sources files defination COMP_LIB := libiot_sdk.a COMP_LIB_COMPONENTS := \ - src/utils/digest \ - src/utils/farra \ - src/utils/lite \ - src/device/src \ - src/sdk-impl \ + $(SRC_DIR)/utils \ + $(SRC_DIR)/network \ + $(SRC_DIR)/network/socket \ + $(SRC_DIR)/protocol/http \ + +ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) + COMP_LIB_COMPONENTS += \ + $(SRC_DIR)/network/tls +endif $(call CompLib_Map, MQTT_COMM_ENABLED, \ - src/mqtt/src \ + $(SRC_DIR)/protocol/mqtt \ ) -$(call CompLib_Map, MQTT_COMM_ENABLED, \ - src/system/src \ +$(call CompLib_Map, COAP_COMM_ENABLED, \ + $(SRC_DIR)/protocol/coap \ ) $(call CompLib_Map, MQTT_DEVICE_SHADOW, \ - src/shadow/src \ + $(SRC_DIR)/services/shadow \ ) -$(call CompLib_Map, COAP_COMM_ENABLED, \ - src/coap/src \ +$(call CompLib_Map, SYSTEM_COMM_ENABLED, \ + $(SRC_DIR)/services/system \ ) -$(call CompLib_Map, OTA_COMM_ENABLED, \ - src/ota/src \ +$(call CompLib_Map, LOG_UPLOAD_ENABLED, \ + $(SRC_DIR)/services/log \ ) -$(call CompLib_Map, NBIOT_COMM_ENABLED, \ - src/nbiot/src \ +$(call CompLib_Map, OTA_COMM_ENABLED, \ + $(SRC_DIR)/services/ota \ ) $(call CompLib_Map, GATEWAY_ENABLED, \ - src/gateway/src \ + $(SRC_DIR)/services/gateway \ ) +$(call CompLib_Map, DEV_DYN_REG_ENABLED, \ + $(SRC_DIR)/services/dynreg \ +) +$(call CompLib_Map, EVENT_POST_ENABLED, \ + $(SRC_DIR)/services/event \ +) + +$(call CompLib_Map, AT_TCP_ENABLED, \ + $(SRC_DIR)/network/at_socket \ +) + +$(call CompLib_Map, BROADCAST_ENABLED, \ + $(SRC_DIR)/services/broadcast \ +) + +$(call CompLib_Map, RRPC_ENABLED, \ + $(SRC_DIR)/services/rrpc \ +) + +$(call CompLib_Map, REMOTE_CONFIG_MQTT_ENABLED, \ + $(SRC_DIR)/services/config \ +) IOTSDK_SRC_FILES := \ @@ -54,23 +115,29 @@ $(foreach v, \ EXCLUDE_SRC_FILES := \ ifeq (,$(filter -DOTA_COAP_CHANNEL, $(CFLAGS))) -EXCLUDE_SRC_FILES += $(TOP_DIR)/src/ota/src/ota_coap.c +EXCLUDE_SRC_FILES += $(TOP_DIR)/$(SRC_DIR)/services/ota/ota_coap.c IOTSDK_SRC_FILES := $(filter-out $(EXCLUDE_SRC_FILES),$(IOTSDK_SRC_FILES)) else -EXCLUDE_SRC_FILES += $(TOP_DIR)/src/ota/src/ota_mqtt.c +EXCLUDE_SRC_FILES += $(TOP_DIR)/$(SRC_DIR)/services/ota/ota_mqtt.c IOTSDK_SRC_FILES := $(filter-out $(EXCLUDE_SRC_FILES),$(IOTSDK_SRC_FILES)) endif + # IoT Platform sources files defination PLATFORM_LIB := libiot_platform.a PLATFORM_LIB_COMPONENTS := \ - src/platform/os/$(PLATFORM_OS) \ - + $(PLATFORM_DIR)/os/$(PLATFORM_OS) \ + ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) PLATFORM_LIB_COMPONENTS += \ - src/platform/ssl/$(PLATFORM_SSL) + $(PLATFORM_DIR)/tls/$(PLATFORM_SSL) endif - + +ifneq (,$(filter -DAT_TCP_ENABLED,$(CFLAGS))) + PLATFORM_LIB_COMPONENTS += \ + $(PLATFORM_DIR)/at_device/$(PLATFORM_AT_DEV) +endif + IOTPLATFORM_SRC_FILES := \ $(foreach v, \ @@ -81,41 +148,12 @@ $(foreach v, \ ) \ ) + # IoT Include files defination COMP_LIB_COMPONENTS_INCLUDES := \ - src/utils/digest \ - src/utils/farra \ - src/utils/lite \ - src/device/include \ - src/sdk-impl \ - src/sdk-impl/exports \ + $(EXP_INC_DIR) \ + $(INT_INC_DIR) \ external_libs/mbedtls/include \ - src/system/include \ - -$(call CompInc_Map, MQTT_COMM_ENABLED, \ - src/mqtt/include \ -) - -$(call CompInc_Map, MQTT_DEVICE_SHADOW, \ - src/shadow/include \ -) - -$(call CompInc_Map, COAP_COMM_ENABLED, \ - src/coap/include \ -) - -$(call CompInc_Map, OTA_COMM_ENABLED, \ - src/ota/include \ -) - -$(call CompInc_Map, NBIOT_COMM_ENABLED, \ - src/nbiot/include \ -) - -$(call CompInc_Map, GATEWAY_ENABLED, \ - src/gateway/include \ -) - IOTSDK_INCLUDE_FILES := \ @@ -127,10 +165,15 @@ $(foreach v, \ ) \ ) -CFLAGS += -Werror -Wall -Wno-error=sign-compare -Wno-error=format -Os ${IOTSDK_INCLUDE_FILES} -pthread +$(call CompInc_Map, AT_TCP_ENABLED, \ + $(PLATFORM_DIR)/at_device/$(PLATFORM_AT_DEV) \ +) + +CFLAGS += -Werror -Wall -Wno-error=sign-compare -Wno-error=format -Os ${IOTSDK_INCLUDE_FILES} -pthread -DFORCE_SSL_VERIFY + +#CFLAGS += -DMQTT_RMDUP_MSG_ENABLED -include src/scripts/rules.mk -include samples/samples.mk +include $(SCRIPT_DIR)/rules.mk ifneq (,$(filter -DSDKTESTS_ENABLED, $(CFLAGS))) include sdk-tests/unit_test/unit_test.mk diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 0f97a7d3..037ad28f --- a/README.md +++ b/README.md @@ -1,318 +1,119 @@ -# 腾讯物联网通信 SDK -腾讯物联网通信 SDK 依靠安全且性能强大的数据通道,为物联网领域开发人员提供终端(如传感器, 执行器, 嵌入式设备或智能家电等等)和云端的双向通信能力。 +# 腾讯云物联网设备端 C-SDK -# 快速开始 -本节将讲述如何在腾讯物联网通信控制台申请设备, 并结合本 SDK 快速体验设备通过 MQTT+TLS/SSL 协议连接到腾讯云, 发送和接收消息;通过 CoAP+DTLS 协议连接到腾讯云,上报数据。 +腾讯云物联网设备端 C-SDK 依靠安全且性能强大的数据通道,为物联网领域开发人员提供设备端快速接入云端,并和云端进行双向通信的能力。 -## 一. 控制台创建设备 +在版本v3.1.0之后,SDK对编译环境,代码及目录结构进行了重构优化,提高了可用性和可移植性。 -#### 1. 注册/登录腾讯云账号 -访问[腾讯云登录页面](https://cloud.tencent.com/login?s_url=https%3A%2F%2Fcloud.tencent.com%2F), 点击[立即注册](https://cloud.tencent.com/register?s_url=https%3A%2F%2Fcloud.tencent.com%2F), 免费获取腾讯云账号,若您已有账号,可直接登录。 +本SDK仅适用于物联网通信平台IoT Hub,对于物联网开发平台,请访问 [IoT Explorer C-SDK](https://github.com/tencentyun/qcloud-iot-explorer-sdk-embedded-c) -#### 2. 访问物联网通信控制台 -登录后点击右上角控制台,进入控制台后,鼠标悬停在云产品上,弹出层叠菜单,点击物联网通信。 +## 一、C-SDK 适用范围 +C-SDK 采用模块化设计,分离核心协议服务与硬件抽象层,并提供灵活的配置选项和多种编译方式,适用于不同设备的开发平台和使用环境。 -![](https://main.qcloudimg.com/raw/1a0c668f382a13a6ec33a6b4b1dbd8b5.png) +#### 1. 具备网络通讯能力并使用Linux/Windows操作系统的设备 -或者直接访问[物联网通信控制台](https://console.qcloud.com/iotcloud) +对于具备网络通讯能力并使用标准 Linux/Windows 系统的设备比如PC/服务器/网关设备,及较高级的嵌入式设备比如树莓派等等,可直接在该设备上编译运行SDK。 +对于需要交叉编译的嵌入式 Linux 设备,如果开发环境的toolchain具备glibc或类似的库,可以提供包括socket通讯,select同步IO,动态内存分配,获取时间/休眠/随机数/打印函数,以及临界数据保护如Mutex机制(仅在需要多线程时)等系统调用,则只要做简单适配(比如在CMakeLists.txt或make.settings里面修改交叉编译器的设定)就可以编译运行SDK。 + +#### 2. 具备网络通讯能力并采用RTOS系统的设备 + +对于具备网络通讯能力并采用RTOS的物联网设备,C-SDK需要针对不同的RTOS做移植适配工作,目前C-SDK已经适配了包括FreeRTOS/RT-Thread/TencentOS tiny等多个面向物联网的RTOS平台。 +在RTOS设备移植SDK时,如果平台提供了类似newlib的C运行库和类似lwIP的嵌入式TCP/IP协议栈,则移植适配工作也可以轻松完成。 -#### 3. 创建产品和设备 -点击页面**创建新产品**按钮, 创建一个产品。 +#### 3. MCU+通讯模组的设备 -![](https://main.qcloudimg.com/raw/a0da21dc6ac9a9e1dede0077d40cfb22.png) +对于不具备网络通讯能力的MCU,一般采用MCU+通讯模组的方式,通讯模组(包括WiFi/2G/4G/NB-IoT)一般提供了基于串口的AT指令协议供MCU进行网络通讯。针对这种场景,C-SDK 封装了AT-socket网络层,网络层之上的核心协议和服务层无须移植。并提供了基于FreeRTOS和不带操作系统(nonOS)两种方式的HAL实现,具体可以参考docs目录文档。 -在弹出的产品窗口中,选择节点类型和产品类型,输入产品名称,选择认证方式和数据格式,输入产品描述,然后点击确定创建。如果是普通直连设备,可按下图选择。 +除此之外,腾讯云物联网还提供了专用的AT指令集,如果通讯模组实现了该指令集,则设备接入和通讯更为简单,所需代码量更少,针对这种场景,请参考面向腾讯云定制AT模组专用的 [MCU AT SDK](https://github.com/tencentyun/qcloud-iot-sdk-tencent-at-based.git) -![](https://main.qcloudimg.com/raw/7ee90122a01f5f277785885669a56aec.png) +## 二、SDK 目录结构简介 -如果是普通网关设备,可按下图选择。 +#### 1. 目录结构及顶层文件简介 -![](https://main.qcloudimg.com/raw/d3f5de3bd07a779f9b1306085fa4d1f1.png) +| 名称 | 说明 | +| ------------------ | ------------------------------------------------------------ | +| CMakeLists.txt | cmake编译描述文件 | +| CMakeSettings.json | visual studio下的cmake配置文件 | +| cmake_build.sh | Linux下使用cmake的编译脚本 | +| make.settings | Linux下使用Makefile直接编译的配置文件 | +| Makefile | Linux下使用Makefile直接编译 | +| device_info.json | 设备信息文件,当DEBUG_DEV_INFO_USED=OFF时,将从该文件解析出设备信息 | +| docs | 文档目录,SDK在不同平台下使用说明文档。 | +| external_libs | 第三方软件包组件,如mbedtls | +| samples | 应用示例 | +| include | 提供给用户使用的外部头文件 | +| platform | 平台相关的源码文件,目前提供了针对不同OS(Linux/Windows/FreeRTOS/nonOS),TLS(mbedtls)以及AT模组下的实现。 | +| sdk_src | SDK核心通信协议及服务代码 | +| tools | SDK配套的编译及代码生成脚本工具 | -在生成的产品页面下,点击**设备列表**页面添加新设备。 +## 三、SDK 编译方式说明 -![](https://main.qcloudimg.com/raw/0530e0da724cd36baefc7011ebce4775.png) +C-SDK 支持三种编译方式: -如果产品认证方式为证书认证,输入设备名称成功后,切记点击弹窗中的**下载**按钮,下载所得包中的设备密钥文件和设备证书用于设备连接物联网通信的鉴权。 +- cmake 方式 +- Makefile 方式 +- 代码抽取方式 -![](https://main.qcloudimg.com/raw/6592056f1b55fa9262e4b2ab31d0b218.png) +编译方式以及编译配置选项的详细说明请参考docs目录文档 **C-SDK_Build编译环境及配置选项说明** -如果产品认证方式为密钥认证,输入设备名称成功后,会在弹窗中显示新添加设备的密钥 +## 四、SDK 示例体验 -![](https://main.qcloudimg.com/raw/fe7a013b1d8c29c477d0ed6d00643751.png) +C-SDK的samples目录有使用各个功能的示例,关于运行示例的详细说明,请参考docs目录各个文档 -如果是网关产品,还需要按照普通产品的方式先创建子产品和子设备,并在网关产品页面添加子产品和子设备。需要注意的是子设备是无法直连物联网平台的产品,由网关设备代理连接,所以子设备的认证方式不影响连接,由网关设备来负责认证接入。 -创建好子产品之后,先到网关产品页面的子产品栏目添加子产品 +## 五、注意事项 -![](https://main.qcloudimg.com/raw/00da59942515b1d772323c7087f627e3.png) +#### 多设备连接 +从版本3.2.0开始,SDK支持多个设备作为客户端同时访问物联网后台,并对多线程环境下的接口使用进行优化增强,具体请参考docs目录文档**C-SDK_MTMC多线程多设备支持** +该版本以面向对象方式对状态变量和参数进行封装,对外部接口的影响是证书设备进行初始化上有变化,其他的接口都没有变化,用户只要参考相关示例修改_setup_connect_init_params函数即可。 -再到网关设备页面的子设备栏目添加子设备 +#### OTA升级API变化 +从SDK版本3.0.3开始,OTA升级支持了断点续传,当固件下载过程中如果因为网络异常或其他原因被打断,可以将已经下载的固件部分保存,在下次恢复下载时候可以不用从零开始下载,而是从未下载的部分开始。 +在支持这一新特性之后,OTA相关API的使用方法发生了变化,对于从3.0.2及以前的版本升级的用户,需要修改用户逻辑代码,否则固件下载会失败,请参考**samples/ota/ota_mqtt_sample.c**进行修改。 -![](https://main.qcloudimg.com/raw/c24938ac8ed3aa3e0834cb40598740ca.png) +#### 代码命名变化 +为了提高代码可读性,保证命名规范,SDK 3.1.0版本对部分变量、函数及宏命名进行了变更,对于从3.0.3及以前的版本升级的用户,可以在Linux环境下面执行tools/update_from_old_SDK.sh脚本对自己的用户代码执行名字替换,替换完成就可以直接使用新版本的SDK。 -#### 4. 创建可订阅可发布的Topic - -按照**第三步**中进入产品设置页面的方法进入页面后, 点击权限列表,再点击**添加Topic权限**。 - -![](https://main.qcloudimg.com/raw/65a2d1b7251de37ce1ca2ba334733c57.png) - -在弹窗中输入 data, 并设置操作权限为**发布和订阅**,点击创建。 - -![](https://main.qcloudimg.com/raw/f429b32b12e3cb0cf319b1efe11ccceb.png) - -随后将会创建出 productID/\${deviceName}/data 的 Topic,在产品页面的权限列表中可以查看该产品的所有权限。 - -对于网关产品,除了添加本产品的Topic权限,还需要为子产品添加Topic权限 - -![](https://main.qcloudimg.com/raw/3de74cfd5b235fe942fe18c359ad08af.png) - -## 二. 编译示例程序 - -#### 1. 下载SDK -登录 Linux, 运行如下命令从 github 克隆代码, 或者访问最新[下载](https://github.com/tencentyun/qcloud-iot-sdk-embedded-c/releases)地址, 将下载到的压缩包在 Linux 上解压缩 - -`git clone https://github.com/tencentyun/qcloud-iot-sdk-embedded-c.git` - -#### 2. 填入设备信息 -编辑 samples/mqtt/mqtt_sample.c 文件和 samples/coap/coap_sample.c 文件中如下代码段, 填入之前创建产品和设备步骤中得到的 **产品ID**,**设备名称**: - -1. 若使用**证书认证**加密方式,填写 **QCLOUD_IOT_CERT_FILENAME** 和 **QCLOUD_IOT_CERT_FILENAME** 并将文件放置在根目录下 certs 目录中。将根目录下 make.settings 文件中的配置项 FEATURE_AUTH_MODE 设置为 CERT,FEATURE_AUTH_WITH_NOTLS 设置为 n。 - -``` -FEATURE_AUTH_MODE = CERT # MQTT/CoAP接入认证方式,使用证书认证:CERT;使用密钥认证:KEY -FEATURE_AUTH_WITH_NOTLS = n # 接入认证是否不使用TLS,证书方式必须选择使用TLS,密钥认证可选择不使用TLS -``` - -2. 若使用**秘钥认证**加密方式,填写 **QCLOUD_IOT_DEVICE_SECRET**。将根目录下 make.settings 文件中的配置项 FEATURE_AUTH_MODE 设置为 KEY,FEATURE_AUTH_WITH_NOTLS 设置为 n 时通过 TLS 密钥认证方式连接,设置为 y 时,则通过 HMAC-SHA1 加密算法连接。 +| 旧命名 | 新命名 | +| ------------------ | ------------------------------------------------------------ | +| QCLOUD_ERR_SUCCESS | QCLOUD_RET_SUCCESS | +| QCLOUD_ERR_MQTT_RECONNECTED | QCLOUD_RET_MQTT_RECONNECTED | +| QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED | QCLOUD_RET_MQTT_MANUALLY_DISCONNECTED | +| QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED | QCLOUD_RET_MQTT_CONNACK_CONNECTION_ACCEPTED | +| QCLOUD_ERR_MQTT_ALREADY_CONNECTED | QCLOUD_RET_MQTT_ALREADY_CONNECTED | +| MAX_SIZE_OF_DEVICE_SERC | MAX_SIZE_OF_DEVICE_SECRET | +| devCertFileName | dev_cert_file_name | +| devPrivateKeyFileName | dev_key_file_name | +| devSerc | device_secret | +| MAX_SIZE_OF_PRODUCT_KEY | MAX_SIZE_OF_PRODUCT_SECRET | +| product_key | product_secret。 | +| DEBUG | eLOG_DEBUG | +| INFO | eLOG_INFO | +| WARN | eLOG_WARN | +| ERROR | eLOG_ERROR | +| DISABLE | eLOG_DISABLE | +| Log_writter | IOT_Log_Gen | +| qcloud_iot_dyn_reg_dev | IOT_DynReg_Device | +| IOT_SYSTEM_GET_TIME | IOT_Get_SysTime | ``` -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" - -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" - - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 +#! /bin/bash -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" -#endif +sed -i "s/QCLOUD_ERR_SUCCESS/QCLOUD_RET_SUCCESS/g" `grep -rwl QCLOUD_ERR_SUCCESS ./*` +sed -i "s/QCLOUD_ERR_MQTT_RECONNECTED/QCLOUD_RET_MQTT_RECONNECTED/g" `grep -rwl QCLOUD_ERR_MQTT_RECONNECTED ./*` +sed -i "s/QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED/QCLOUD_RET_MQTT_MANUALLY_DISCONNECTED/g" `grep -rwl QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED ./*` +sed -i "s/QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED/QCLOUD_RET_MQTT_CONNACK_CONNECTION_ACCEPTED/g" `grep -rwl QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED ./*` +sed -i "s/QCLOUD_ERR_MQTT_ALREADY_CONNECTED/QCLOUD_RET_MQTT_ALREADY_CONNECTED/g" `grep -rwl QCLOUD_ERR_MQTT_ALREADY_CONNECTED ./*` +sed -i "s/MAX_SIZE_OF_DEVICE_SERC/MAX_SIZE_OF_DEVICE_SECRET/g" `grep -rwl MAX_SIZE_OF_DEVICE_SERC ./*` +sed -i "s/devCertFileName/dev_cert_file_name/g" `grep -rwl devCertFileName ./*` +sed -i "s/devPrivateKeyFileName/dev_key_file_name/g" `grep -rwl devPrivateKeyFileName ./*` +sed -i "s/devSerc/device_secret/g" `grep -rwl devSerc ./*` +sed -i "s/MAX_SIZE_OF_PRODUCT_KEY/MAX_SIZE_OF_PRODUCT_SECRET/g" `grep -rwl MAX_SIZE_OF_PRODUCT_KEY ./*` +sed -i "s/product_key/product_secret/g" `grep -rwl product_key ./*` +sed -i "s/DEBUG/eLOG_DEBUG/g" `grep -rwl DEBUG ./*` +sed -i "s/INFO/eLOG_INFO/g" `grep -rwl INFO ./*` +sed -i "s/WARN/eLOG_WARN/g" `grep -rwl WARN ./*` +sed -i "s/ERROR/eLOG_ERROR/g" `grep -rwl ERROR ./*` +sed -i "s/DISABLE/eLOG_DISABLE/g" `grep -rwl DISABLE ./*` +sed -i "s/Log_writter/IOT_Log_Gen/g" `grep -rwl Log_writter ./*` +sed -i "s/qcloud_iot_dyn_reg_dev/IOT_DynReg_Device/g" `grep -rwl qcloud_iot_dyn_reg_dev ./*` +sed -i "s/IOT_SYSTEM_GET_TIME/IOT_Get_SysTime/g" `grep -rwl IOT_SYSTEM_GET_TIME ./*` ``` - -3. 若为**网关产品**,需要将根目录下 make.settings 文件中的配置项 FEATURE_GATEWAY_ENABLED 设置为 y。 - -``` -FEATURE_GATEWAY_ENABLED = y # 是否打开网关功能 -``` - -并编辑samples/gateway/gateway_sample.c 文件中如下代码段, 填入之前创建网关产品和子产品及设备步骤中得到的**网关产品ID**,**网关设备名称**,**子产品ID**,**子设备名称**: - -``` -/* 网关产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_GW_PRODUCT_ID" -/* 网关设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_GW_DEVICE_NAME" - -#ifdef AUTH_MODE_CERT - /* 网关客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_GW_DEVICE_NAME_cert.crt" - /* 网关客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_GW_DEVICE_NAME_private.key" - - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 - -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_GW_IOT_PSK" -#endif - -/* 子产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_SUBDEV_PRODUCT_ID "YOUR_SUBDEV_PRODUCT_ID" -/* 子设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_SUBDEV_DEVICE_NAME "YOUR_SUBDEV_DEVICE_NAME" -``` - -#### 3. 编译 SDK 产生示例程序 -在根目录执行 - -``` -$make clean -$make -``` - -编译成功完成后, 生成的样例程序在当前目录的 output/release/bin 目录下: - -``` -output/release/bin/ -├── aircond_shadow_sample -├── aircond_shadow_sample_v2 -├── certs -│   ├── README.md -│   ├── TEST_CLIENT_cert.crt -│   └── TEST_CLIENT_private.key -├── coap_sample -├── door_coap_sample -├── door_mqtt_sample -├── gateway_sample -├── mqtt_sample -├── ota_mqtt_sample -└── shadow_sample -``` - -## 三. 运行示例程序 - -#### 1. 执行 MQTT 示例程序 -``` -./mqtt_sample -INF|2019-03-06 17:20:17|device.c|iot_device_info_set(65): SDK_Ver: 2.3.1, Product_ID: S3EUVBRJLB, Device_Name: demo-device -DBG|2019-03-06 17:20:17|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Connecting to /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... -DBG|2019-03-06 17:20:17|HAL_TLS_mbedtls.c|HAL_TLS_Connect(209): Setting up the SSL/TLS structure... -DBG|2019-03-06 17:20:17|HAL_TLS_mbedtls.c|HAL_TLS_Connect(251): Performing the SSL/TLS handshake... -INF|2019-03-06 17:20:17|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... -INF|2019-03-06 17:20:17|mqtt_client.c|IOT_MQTT_Construct(115): mqtt connect with id: jwPv6 success -INF|2019-03-06 17:20:17|mqtt_sample.c|main(340): Cloud Device Construct Success -DBG|2019-03-06 17:20:17|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(129): topicName=S3EUVBRJLB/demo-device/data|packet_id=21872|pUserdata=(null) -INF|2019-03-06 17:20:17|mqtt_sample.c|event_handler(82): subscribe success, packet-id=21872 -DBG|2019-03-06 17:20:17|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=21873|topicName=S3EUVBRJLB/demo-device/data|payload={"action": "publish_test", "count": "0"} -INF|2019-03-06 17:20:17|mqtt_sample.c|on_message_callback(139): Receive Message With topicName:S3EUVBRJLB/demo-device/data, payload:{"action": "publish_test", "count": "0"} -INF|2019-03-06 17:20:18|mqtt_sample.c|event_handler(109): publish success, packet-id=21873 -INF|2019-03-06 17:20:18|mqtt_client_connect.c|qcloud_iot_mqtt_disconnect(441): mqtt disconnect! -INF|2019-03-06 17:20:18|mqtt_client.c|IOT_MQTT_Destroy(159): mqtt release! - -``` - -#### 2. 观察消息发送 -如下日志信息显示示例程序通过 MQTT 的 Publish 类型消息, 上报数据到 /{productID}/{deviceName}/data, 服务器已经收到并成功完成了该消息的处理 -``` -INF|2019-03-06 17:20:18|mqtt_sample.c|event_handler(109): publish success, packet-id=21873 -``` - -#### 3. 观察消息接收 -如下日志信息显示该消息因为是到达已被订阅的 Topic, 所以又被服务器原样推送到示例程序, 并进入相应的回调函数 -``` -INF|2019-03-06 17:20:17|mqtt_sample.c|on_message_callback(139): Receive Message With topicName:S3EUVBRJLB/demo-device/data, payload:{"action": "publish_test", "count": "0"} -``` - -#### 4. 观察控制台日志 -可以登录物联网通信控制台, 点击左边导航栏中的**云日志**, 查看刚才上报的消息 -![](https://main.qcloudimg.com/raw/09d3ec0ec827eaa274dad8ca8e1bf04c.png) - -#### 5. 执行 CoAP 示例程序 -``` -./coap_sample -INF|2019-03-06 17:34:28|device.c|iot_device_info_set(65): SDK_Ver: 2.3.1, Product_ID: S3EUVBRJLB, Device_Name: demo-device -INF|2019-03-06 17:34:30|coap_client.c|IOT_COAP_Construct(83): coap connect success -INF|2019-03-06 17:34:30|coap_client_message.c|coap_message_send(404): add coap message id: 53915 into wait list ret: 0 -DBG|2019-03-06 17:34:30|coap_client_message.c|_coap_message_handle(297): receive coap piggy ACK message, id 53915 -INF|2019-03-06 17:34:30|coap_client_auth.c|_coap_client_auth_callback(42): auth token message success, code_class: 2 code_detail: 5 -DBG|2019-03-06 17:34:30|coap_client_auth.c|_coap_client_auth_callback(52): auth_token_len = 10, auth_token = SJGRYBBEGM -DBG|2019-03-06 17:34:30|coap_client_message.c|_coap_message_list_proc(148): remove the message id 53915 from list -INF|2019-03-06 17:34:30|coap_client_message.c|_coap_message_list_proc(87): remove node -INF|2019-03-06 17:34:30|coap_client.c|IOT_COAP_Construct(92): device auth successfully, connid: Vu501 -INF|2019-03-06 17:34:30|coap_sample.c|main(163): topic name is S3EUVBRJLB/demo-device/data -INF|2019-03-06 17:34:30|coap_client_message.c|coap_message_send(404): add coap message id: 53916 into wait list ret: 0 -DBG|2019-03-06 17:34:30|coap_sample.c|main(170): client topic has been sent, msg_id: 53916 -DBG|2019-03-06 17:34:31|coap_client_message.c|_coap_message_handle(297): receive coap piggy ACK message, id 53916 -INF|2019-03-06 17:34:31|coap_sample.c|event_handler(90): message received ACK, msgid: 53916 -DBG|2019-03-06 17:34:31|coap_client_message.c|_coap_message_list_proc(148): remove the message id 53916 from list -INF|2019-03-06 17:34:31|coap_client_message.c|_coap_message_list_proc(87): remove node -INF|2019-03-06 17:34:31|coap_client.c|IOT_COAP_Destroy(126): coap release! -``` - -#### 6. 观察消息发送 -如下日志信息显示示例程序通过 CoAP 上报数据到 /{productID}/{deviceName}/data 成功。 -``` -INF|2019-03-06 17:34:31|coap_sample.c|event_handler(90): message received ACK, msgid: 53916 -``` - -#### 7. 执行网关实例程序 -如下日志信息显示示例程序通过MQTT网关代理子设备上下线状态变化,发布和订阅消息成功。 -``` -./gateway_sample -INF|2019-03-06 20:18:57|device.c|iot_device_info_set(65): SDK_Ver: 2.3.1, Product_ID: NINEPLMEB6, Device_Name: Gateway-demo -DBG|2019-03-06 20:18:57|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Connecting to /NINEPLMEB6.iotcloud.tencentdevices.com/8883... -DBG|2019-03-06 20:18:57|HAL_TLS_mbedtls.c|HAL_TLS_Connect(209): Setting up the SSL/TLS structure... -DBG|2019-03-06 20:18:57|HAL_TLS_mbedtls.c|HAL_TLS_Connect(251): Performing the SSL/TLS handshake... -INF|2019-03-06 20:18:58|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /NINEPLMEB6.iotcloud.tencentdevices.com/8883... -INF|2019-03-06 20:18:58|mqtt_client.c|IOT_MQTT_Construct(115): mqtt connect with id: 35L53 success -DBG|2019-03-06 20:18:58|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(129): topicName=$gateway/operation/result/NINEPLMEB6/Gateway-demo|packet_id=56164|pUserdata=(null) -DBG|2019-03-06 20:18:58|gateway_api.c|_gateway_event_handler(23): gateway sub|unsub(3) success, packet-id=56164 -DBG|2019-03-06 20:18:58|gateway_api.c|IOT_Gateway_Subdev_Online(125): there is no session, create a new session -DBG|2019-03-06 20:18:58|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$gateway/operation/NINEPLMEB6/Gateway-demo|payload={"type":"online","payload":{"devices":[{"product_id":"S3EUVBRJLB","device_name":"demo-device"}]} -INF|2019-03-06 20:18:58|gateway_common.c|_gateway_message_handler(135): client_id(S3EUVBRJLB/demo-device), online success. result 0 -DBG|2019-03-06 20:18:59|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(129): topicName=S3EUVBRJLB/demo-device/data|packet_id=56165|pUserdata=(null) -DBG|2019-03-06 20:18:59|gateway_api.c|_gateway_event_handler(23): gateway sub|unsub(3) success, packet-id=56165 -INF|2019-03-06 20:18:59|gateway_sample.c|_event_handler(101): subscribe success, packet-id=56165 -DBG|2019-03-06 20:18:59|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=56166|topicName=S3EUVBRJLB/demo-device/data|payload={"data":"test gateway"} -INF|2019-03-06 20:18:59|gateway_sample.c|_message_handler(152): Receive Message With topicName:S3EUVBRJLB/demo-device/data, payload:{"data":"test gateway"} -DBG|2019-03-06 20:19:00|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=56167|topicName=S3EUVBRJLB/demo-device/data|payload={"data":"test gateway"} -INF|2019-03-06 20:19:00|gateway_sample.c|_event_handler(128): publish success, packet-id=56166 -INF|2019-03-06 20:19:00|gateway_sample.c|_message_handler(152): Receive Message With topicName:S3EUVBRJLB/demo-device/data, payload:{"data":"test gateway"} -DBG|2019-03-06 20:19:01|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$gateway/operation/NINEPLMEB6/Gateway-demo|payload={"type":"offline","payload":{"devices":[{"product_id":"S3EUVBRJLB","device_name":"demo-device"}] -INF|2019-03-06 20:19:01|gateway_sample.c|_event_handler(128): publish success, packet-id=56167 -INF|2019-03-06 20:19:02|gateway_common.c|_gateway_message_handler(140): client_id(S3EUVBRJLB/demo-device), offline success. result 0 -INF|2019-03-06 20:19:02|mqtt_client_connect.c|qcloud_iot_mqtt_disconnect(441): mqtt disconnect! -INF|2019-03-06 20:19:02|mqtt_client.c|IOT_MQTT_Destroy(159): mqtt release! -``` - -#### 8. 多线程环境实例程序 -SDK对于MQTT接口在多线程环境下的使用有如下注意事项,详细代码用例可以参考samples/mqtt/multi_thread_mqtt_sample.c -``` -1. 不允许多线程调用IOT_MQTT_Yield,IOT_MQTT_Construct以及IOT_MQTT_Destroy -2. 可以多线程调用IOT_MQTT_Publish,IOT_MQTT_Subscribe及IOT_MQTT_Unsubscribe -3. IOT_MQTT_Yield 作为从socket读取并处理MQTT报文的函数,应保证一定的执行时间,避免被长时间挂起或抢占 -``` - -#### 9. 设备日志上报功能 -从版本v2.3.1开始,SDK增加设备端日志上报功能,可将设备端的Log通过HTTP上报到云端,并可在控制台展示,方便用户远程调试、诊断及监控设备运行状况。目前该功能仅支持MQTT模式。 -只要将SDK的编译宏FEATURE_LOG_UPLOAD_ENABLED置为y(默认为y),并在控制台设置上报级别,则在代码中调用Log_e/w/i/d接口的日志除了会在终端打印出来,还会上报云端并在控制台展示,如下图。 -![](https://main.qcloudimg.com/raw/cae7f9e7cf1e354cfc1e3578eb6746bc.png) - -上报级别设置可参见下图,Level级别越大则上报的日志越多,比如Level3(信息)会将ERROR/WARN/INFO级别的日志都上报而DEBUG级别则不上报。控制台默认为关闭状态,则表示设备端仅在MQTT连接失败的时候才会上报ERROR级别日志。 -![](https://main.qcloudimg.com/raw/826b648993a267b1cc2f082148d8d073.png) - -代码具体用例可以参考mqtt_sample以及qcloud_iot_export_log.h注释说明,用户除了打开编译宏开关,还需要调用IOT_Log_Init_Uploader函数进行初始化。SDK在IOT_MQTT_Yield函数中会定时进行上报,此外,用户可根据自身需要,在程序出错退出的时候调用IOT_Log_Upload(true)强制上报。同时SDK提供在HTTP通讯出错无法上报日志时的缓存和恢复正常后重新上报机制,但需要用户根据设备具体情况提供相关回调函数,如不提供回调或回调函数提供不全则该缓存机制不生效,HTTP通讯失败时日志会被丢掉。 - -## 四. 可变接入参数配置 - -可变接入参数配置:SDK 的使用可以根据具体场景需求,配置相应的参数,满足实际业务的运行。可变接入参数包括: -1. MQTT 心跳消息发送周期, 单位: ms -2. MQTT 阻塞调用(包括连接, 订阅, 发布等)的超时时间, 单位:ms。 建议 5000 ms -3. TLS 连接握手超时时间, 单位: ms -4. MQTT 协议发送消息和接受消息的 buffer 大小默认是 512 字节,最大支持 256 KB -5. CoAP 协议发送消息和接受消息的 buffer 大小默认是 512 字节,最大支持 64 KB -6. 重连最大等待时间 -修改 qcloud_iot_export.h 文件如下宏定义可以改变对应接入参数的配置。 -``` -/* MQTT心跳消息发送周期, 单位:ms */ -#define QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL (240 * 1000) - -/* MQTT 阻塞调用(包括连接, 订阅, 发布等)的超时时间, 单位:ms 建议5000ms */ -#define QCLOUD_IOT_MQTT_COMMAND_TIMEOUT (5000) - -/* TLS连接握手超时时间, 单位:ms */ -#define QCLOUD_IOT_TLS_HANDSHAKE_TIMEOUT (5000) - -/* MQTT消息发送buffer大小, 支持最大256*1024 */ -#define QCLOUD_IOT_MQTT_TX_BUF_LEN (512) - -/* MQTT消息接收buffer大小, 支持最大256*1024 */ -#define QCLOUD_IOT_MQTT_RX_BUF_LEN (512) - -/* COAP 发送消息buffer大小,最大支持64*1024字节 */ -#define COAP_SENDMSG_MAX_BUFLEN (512) - -/* COAP 接收消息buffer大小,最大支持64*1024字节 */ -#define COAP_RECVMSG_MAX_BUFLEN (512) - -/* 重连最大等待时间 */ -#define MAX_RECONNECT_WAIT_INTERVAL (60000) -``` - -##关于 SDK 的更多使用方式及接口了解, 请访问[官方 WiKi](https://github.com/tencentyun/qcloud-iot-sdk-embedded-c/wiki) \ No newline at end of file diff --git a/cmake_build.sh b/cmake_build.sh new file mode 100755 index 00000000..b3663408 --- /dev/null +++ b/cmake_build.sh @@ -0,0 +1,58 @@ +#! /bin/bash + +if [ "$#" -eq "0" ]; then + rm -rf output + rm -rf build + echo "Build all (SDK libs and samples)" + mkdir -p build + cd build + cmake .. + make + exit +elif [ "$#" -eq "1" -a $1 == "samples" ]; then + if [ ! -d "output/release/bin" ]; then + rm -rf output/release/bin + elif [ ! -d "output/debug/bin" ]; then + rm -rf output/debug/bin + else + echo "Output folder not found! Please build SDK first" + exit + fi + rm -rf build + echo "Build samples only" + mkdir -p build + cd build + cmake -DSAMPLE_ONLY=ON .. + make + exit +elif [ "$#" -eq "1" -a $1 == "clean" ]; then + echo "Clean all (SDK lib and samples)" + rm -rf output + rm -rf build + exit +elif [ "$#" -eq "1" -a $1 == "code-check" ]; then +# code-check requires clang-tidy and cpplint +# sudo apt install clang-tidy +# pip install cpplint + echo "run code check" + rm -rf build + mkdir -p build + cd build + cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. + echo "clang-tidy check begin" + clang_extra_arg="-extra-arg=-I/usr/lib/gcc/x86_64-linux-gnu/7/include -extra-arg=-I/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed" + clang_check_rules="-checks=-clang-analyzer-osx*,-clang-analyzer-security.insecureAPI.strcpy,-clang-diagnostic-missing-braces,-clang-diagnostic-varargs" + ../tools/run-clang-tidy ${clang_extra_arg} ${clang_check_rules} >../code-check-clang-tidy.txt + echo "clang-tidy check end" + echo "cpplint check begin" + cd .. + # find ./samples/ ./include/ ./sdk_src/ ./platform/ -name *.c -o -name *.h | xargs clang-format -i + cpplint_rules="--filter=-whitespace/line_length,-readability/casting,-build/include_subdir,-whitespace/braces,-whitespace/comments,-whitespace/blank_line,-whitespace/parens,-whitespace/semicolon,-whitespace/end_of_line,-whitespace/ending_newline,-whitespace/comma,-build/header_guard,-runtime/int,-runtime/printf,-readability/todo,-build/include_order,-build/include_what_you_use" + cpplint_coverage="include/ samples/ platform/ sdk_src/" + cpplint ${cpplint_rules} --recursive ${cpplint_coverage} &>./code-check-cpplint.txt + echo "cpplint check end" + exit +else + echo "Usage: "$0" " + exit +fi diff --git a/device_info.json b/device_info.json new file mode 100755 index 00000000..de233580 --- /dev/null +++ b/device_info.json @@ -0,0 +1,21 @@ +{ + "auth_mode":"KEY", + + "productId":"PRODUCT_ID", + "productSecret":"YOUR_PRODUCT_SECRET", + "deviceName":"YOUR_DEV_NAME", + + "key_deviceinfo":{ + "deviceSecret":"YOUR_IOT_PSK" + }, + + "cert_deviceinfo":{ + "devCertFile":"YOUR_DEVICE_CERT_FILE_NAME", + "devPrivateKeyFile":"YOUR_DEVICE_PRIVATE_KEY_FILE_NAME" + }, + + "subDev":{ + "sub_productId":"YOUR_SUBDEV_PRODUCT_ID", + "sub_devName":"YOUR_SUBDEV_DEVICE_NAME" + } +} \ No newline at end of file diff --git "a/docs/C-SDK_API\345\217\212\345\217\257\345\217\230\345\217\202\346\225\260\350\257\264\346\230\216.md" "b/docs/C-SDK_API\345\217\212\345\217\257\345\217\230\345\217\202\346\225\260\350\257\264\346\230\216.md" new file mode 100755 index 00000000..f2156858 --- /dev/null +++ "b/docs/C-SDK_API\345\217\212\345\217\257\345\217\230\345\217\202\346\225\260\350\257\264\346\230\216.md" @@ -0,0 +1,193 @@ +# C-SDK API函数及可变参数说明 + +设备端 C-SDK 供用户调用的API函数声明,常量以及可变参数定义等头文件位于include目录下面,本文档主要对该目录下面的可变参数以及API函数进行说明。 + +## 可变参数配置 + +C-SDK 的使用可以根据具体场景需求,配置相应的参数,满足实际业务的运行。可变接入参数包括: +1. MQTT 阻塞调用(包括连接, 订阅, 发布等)的超时时间, 单位: 毫秒。 建议 5000 毫秒 +2. MQTT 协议发送消息和接受消息的 buffer 大小默认是 2048 字节,目前云端一条MQTT消息最大长度为 16 KB +3. COAP 协议发送消息和接受消息的 buffer 大小默认是 512 字节,目前云端一条COAP消息最大长度为 1 KB +4. MQTT 心跳消息发送周期, 最大值为690秒,单位: 毫秒 +5. 重连最大等待时间,单位:毫秒。设备断线重连时,若失败则等待时间会翻倍,当超过该最大等待时间则退出重连 + +修改 include/qcloud_iot_export_variables.h 文件如下宏定义可以改变对应接入参数的配置。 +修改完需要重新编译 SDK +``` +/* default MQTT/CoAP timeout value when connect/pub/sub (unit: ms) */ +#define QCLOUD_IOT_MQTT_COMMAND_TIMEOUT (5 * 1000) + +/* default MQTT keep alive interval (unit: ms) */ +#define QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL (240 * 1000) + +/* default MQTT Tx buffer size, MAX: 16*1024 */ +#define QCLOUD_IOT_MQTT_TX_BUF_LEN (2048) + +/* default MQTT Rx buffer size, MAX: 16*1024 */ +#define QCLOUD_IOT_MQTT_RX_BUF_LEN (2048) + +/* default COAP Tx buffer size, MAX: 1*1024 */ +#define COAP_SENDMSG_MAX_BUFLEN (512) + +/* default COAP Rx buffer size, MAX: 1*1024 */ +#define COAP_RECVMSG_MAX_BUFLEN (512) + +/* MAX MQTT reconnect interval (unit: ms) */ +#define MAX_RECONNECT_WAIT_INTERVAL (60 * 1000) +``` + +## API 函数说明 +以下是 C-SDK v3.1.0版本提供的主要功能和对应 API 接口说明,用于客户编写业务逻辑,更加详细的说明如接口参数及返回值可查看SDK代码 include/exports/qcloud_iot_export_*.h 等头文件中的注释 +接口使用示例代码请参考samples目录下的对应代码,以及docs/IoT_Hub目录下的文档说明 + +### 1. MQTT 接口 +关于MQTT接口使用介绍,可以参考SDK docs/IoT_Hub/mqtt_sample_快速入门文档 + +| 序号 | 函数名 | 说明 | +| ---- | -------------------- | ----------------------------------------------- | +| 1 | IOT_MQTT_Construct | 构造 MQTTClient 并连接 MQTT 云端服务 | +| 2 | IOT_MQTT_Destroy | 关闭 MQTT 连接并销毁 MQTTClient | +| 3 | IOT_MQTT_Yield | 在当前线程上下文中,进行 MQTT 报文读取,消息处理,超时请求,心跳包及重连状态管理等任务 | +| 4 | IOT_MQTT_Publish | 发布 MQTT 消息 | +| 5 | IOT_MQTT_Subscribe | 订阅 MQTT 主题 | +| 6 | IOT_MQTT_Unsubscribe | 取消订阅已订阅的 MQTT 主题 | +| 7 | IOT_MQTT_IsConnected | 查看当前 MQTT 是否已连接 | +| 8 | IOT_MQTT_IsSubReady | 查询对应的主题是否已经订阅成功 | +| 9 | IOT_MQTT_GetDeviceInfo | 获取该 MQTTclien对应的设备信息 | +| 10 | IOT_MQTT_StartLoop | 多线程环境下,启动 MQTTclient后台Yield线程 | +| 11 | IOT_MQTT_StopLoop | 多线程环境下,停止 MQTTclient后台Yield线程 | + +- 接口使用说明 +``` +MQTT构造时候除了提供设备信息,还需要提供一个回调函数,用于接收消息包括连接状态通知,订阅主题是否成功,QoS1消息是否发布成功等等事件通知。订阅主题时则需提供另一个回调函数,用于接收该主题的消息下发。具体接口使用方式可以参考docs/IoT_Hub目录的mqtt_sample_快速入门文档。 +``` + +### 2. 设备影子接口 +关于设备影子功能介绍,可以参考[设备影子详情](https://cloud.tencent.com/document/product/634/11918) +同时可以参考SDK docs/IoT_Hub/设备影子文档 + +| 序号 | 函数名 | 说明 | +| ---- | -------------------------------------------------- | ---------------------------------------------- | +| 1 | IOT_Shadow_Construct | 构造设备影子客户端 ShadowClient,并连接 MQTT 云端服务 | +| 2 | IOT_Shadow_Publish | 影子客户端发布 MQTT 消息 | +| 3 | IOT_Shadow_Subscribe | 影子客户端订阅 MQTT 主题 | +| 4 | IOT_Shadow_Unsubscribe | 影子客户端取消订阅已订阅的 MQTT 主题 | +| 5 | IOT_Shadow_IsConnected | 查看当前影子客户端的 MQTT 是否已连接 | +| 6 | IOT_Shadow_Destroy | 关闭 Shadow MQTT 连接并销毁 ShadowClient | +| 7 | IOT_Shadow_Yield | 在当前线程上下文中,进行 MQTT 报文读取,消息处理,超时请求,心跳包及重连状态管理等任务 | +| 8 | IOT_Shadow_Update | 异步更新设备影子文档 | +| 9 | IOT_Shadow_Update_Sync | 同步方式更新设备影子文档 | +| 10 | IOT_Shadow_Get | 异步方式获取设备影子文档 | +| 11 | IOT_Shadow_Get_Sync | 同步方式获取设备影子文档 | +| 12 | IOT_Shadow_Register_Property | 注册当前设备的设备属性 | +| 13 | IOT_Shadow_UnRegister_Property | 删除已经注册过的设备属性 | +| 14 | IOT_Shadow_JSON_ConstructReport | 在JSON文档中添加reported字段,不覆盖更新 | +| 15 | IOT_Shadow_JSON_Construct_OverwriteReport | 在JSON文档中添加reported字段,覆盖更新 | +| 16 | IOT_Shadow_JSON_ConstructReportAndDesireAllNull | 在JSON文档中添加reported字段,同时清空desired字段 | +| 17 | IOT_Shadow_JSON_ConstructDesireAllNull | 在JSON文档中添加 "desired": null 字段 | +| 18 | IOT_Shadow_Get_Mqtt_Client | 获取该ShadowClient对应的MQTTclient | + +### CoAP 接口 +关于CoAP功能介绍,可以参考SDK docs/IoT_Hub/CoAP通讯文档 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------------- | ------------------------------------------------- | +| 1 | IOT_COAP_Construct | 构造 CoAPClient 并完成 CoAP 连接 | +| 2 | IOT_COAP_Destroy | 关闭 CoAP 连接并销毁 CoAPClient | +| 3 | IOT_COAP_Yield | 在当前线程上下文中,进行 CoAP 报文读取和消息处理等任务 | +| 4 | IOT_COAP_SendMessage | 发布 CoAP 消息 | +| 5 | IOT_COAP_GetMessageId | 获取 COAP Response 消息 msgId | +| 6 | IOT_COAP_GetMessagePayload | 获取 COAP Response 消息内容 | +| 7 | IOT_COAP_GetMessageCode | 获取 COAP Response 消息错误码 | +| 9 | IOT_COAP_GetDeviceInfo | 获取该 COAPclien对应的设备信息 | + +### OTA 接口 +关于 OTA 固件下载功能介绍,可以参考[设备固件升级](https://cloud.tencent.com/document/product/634/14674) +同时可以参考SDK docs/IoT_Hub/固件升级文档 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------------- | ------------------------------------------------- | +| 1 | IOT_OTA_Init | 初始化 OTA 模块,客户端在调用此接口之前需要先进行 MQTT/COAP 的初始化 | +| 2 | IOT_OTA_Destroy | 释放 OTA 模块相关的资源 | +| 3 | IOT_OTA_ReportVersion | 向 OTA 服务器报告本地固件版本信息 | +| 4 | IOT_OTA_IsFetching | 检查是否处于下载固件的状态 | +| 5 | IOT_OTA_IsFetchFinish | 检查固件是否已经下载完成 | +| 6 | IOT_OTA_FetchYield | 从具有特定超时值的远程服务器获取固件 | +| 7 | IOT_OTA_Ioctl | 获取指定的 OTA 信息 | +| 8 | IOT_OTA_GetLastError | 获取最后一个错误代码 | +| 9 | IOT_OTA_StartDownload | 根据获取到的固件更新地址以及本地固件信息偏移(是否断点续传),与固件服务器建立http连接 | +| 10 | IOT_OTA_UpdateClientMd5 | 断点续传前,计算本地固件的MD5 | +| 11 | IOT_OTA_ReportUpgradeBegin | 当进行固件升级前,向服务器上报即将升级的状态 | +| 12 | IOT_OTA_ReportUpgradeSuccess | 当固件升级成功之后,向服务器上报升级成功的状态 | +| 13 | IOT_OTA_ReportUpgradeFail | 当固件升级失败之后,向服务器上报升级失败的状态 | + +### 日志接口 +设备日志上报云端功能的说明可以参考SDK docs/IoT_Hub/设备日志上报文档 + +| 序号 | 函数名 | 说明 | +| ---- | -------------------------- | --------------------------------------------- | +| 1 | IOT_Log_Set_Level | 设置 SDK 日志的打印等级 | +| 2 | IOT_Log_Get_Level | 返回 SDK 日志打印的等级 | +| 3 | IOT_Log_Set_MessageHandler | 设置日志回调函数,重定向 SDK 日志于其它输出方式 | +| 4 | IOT_Log_Init_Uploader | 开启 SDK 日志上报云端的功能并初始化资源 | +| 5 | IOT_Log_Fini_Uploader | 停止 SDK 日志上报云端功能并释放资源 | +| 6 | IOT_Log_Upload | 将 SDK 运行日志上报到云端 | +| 7 | IOT_Log_Set_Upload_Level | 设置 SDK 日志的上报等级 | +| 8 | IOT_Log_Get_Upload_Level | 返回 SDK 日志上报的等级 | +| 9 | Log_d/i/w/e | 按级别打印添加 SDK 日志的接口 | + +### 系统时间接口 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------------- | ------------------------------------------------- | +| 1 | IOT_Get_SysTime | 获取 IoT hub 后台系统时间,目前仅支持 MQTT 通道对时功能 | +| 2 | IOT_Sync_NTPTime | 同步 IoT hub 后台时间戳并通过 NTP 算法设置设备系统时间,目前仅支持 MQTT 通道对时功能 | + +### 网关功能接口 +关于网关功能介绍,可以参考SDK docs/IoT_Hub/网关功能文档 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------------------- | ----------------------------------------------------| +| 1 | IOT_Gateway_Construct | 构造 Gateway client 并完成 MQTT 连接 | +| 2 | IOT_Gateway_Destroy | 关闭 MQTT 连接并销毁 Gateway client | +| 3 | IOT_Gateway_Subdev_Bind | 网关绑定子设备 | +| 4 | IOT_Gateway_Subdev_Unbind | 网关解绑子设备 | +| 5 | IOT_Gateway_Subdev_Online | 代理子设备上线 | +| 6 | IOT_Gateway_Subdev_Offline | 代理子设备下线 | +| 7 | IOT_Gateway_Yield | 在当前线程上下文中,进行 MQTT 报文读取,消息处理,超时请求,心跳包及重连状态管理等任务 | +| 8 | IOT_Gateway_Publish | 发布 MQTT 消息 | +| 9 | IOT_Gateway_Subscribe | 订阅 MQTT 主题 | +| 10 | IOT_Gateway_Unsubscribe | 取消订阅已订阅的 MQTT 主题 | +| 11 | IOT_Gateway_Get_Mqtt_Client | 获取该GatewayClient对应的MQTTclient | +| 12 | IOT_Gateway_Subdev_GetBindList | 获取网关在云平台已绑定的子设备列表 | +| 13 | IOT_Gateway_Subdev_DestoryBindList | 销毁获取到的已绑定子设备列表数据 | + +### 动态注册接口 +关于动态注册功能介绍,可以参考SDK docs/IoT_Hub/动态注册文档 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------------- | ------------------------------------------------- | +| 1 | IOT_DynReg_Device | 向后台动态注册设备并获取设备密钥或者证书 | + +### 广播通信接口 +关于广播通信功能介绍,可以参考SDK docs/IoT_Hub/广播通信文档 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------------- | ------------------------------------------------- | +| 1 | IOT_Broadcast_Subscribe | 订阅接收广播消息的主题并提供消息回调处理函数 | + +### 同步通信接口 +关于同步通信rrpc功能介绍,可以参考SDK docs/IoT_Hub/同步通信文档 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------------- | ------------------------------------------------- | +| 1 | IOT_RRPC_Init | 订阅接收rrpc消息的主题并提供消息回调处理函数 | +| 2 | IOT_RRPC_Reply | 回复rrpc消息 | + +### 远程配置接口 +关于远程配置功能介绍,可以参考SDK docs/IoT_Hub/remote_config_mqtt_sample_远程配置文档 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------------- | -------------------------- | +| 1 | IOT_Subscribe_Config | 向云平台订阅远程配置 topic | +| 2 | IOT_Get_Config | 向云平台获取设备配置 | diff --git "a/docs/C-SDK_Build\347\274\226\350\257\221\347\216\257\345\242\203\345\217\212\351\205\215\347\275\256\351\200\211\351\241\271\350\257\264\346\230\216.md" "b/docs/C-SDK_Build\347\274\226\350\257\221\347\216\257\345\242\203\345\217\212\351\205\215\347\275\256\351\200\211\351\241\271\350\257\264\346\230\216.md" new file mode 100755 index 00000000..1acaa1bc --- /dev/null +++ "b/docs/C-SDK_Build\347\274\226\350\257\221\347\216\257\345\242\203\345\217\212\351\205\215\347\275\256\351\200\211\351\241\271\350\257\264\346\230\216.md" @@ -0,0 +1,192 @@ +# C-SDK 编译方式及配置选项说明 + +本文档对C-SDK 的编译方式和编译配置选项进行说明,并介绍了 Linux和Windows 开发环境下面的编译环境搭建以及编译示例。 + +## C-SDK 编译方式说明 + +C-SDK 支持三种编译方式 + +#### 1. cmake 方式 + +推荐使用cmake作为跨平台的编译工具,支持在Linux和Windows开发环境下进行编译。 +cmake方式采用CMakeLists.txt作为编译配置选项输入文件 + +#### 2. Makefile 方式 + +对不支持cmake的环境,使用Makefile直接编译的方式,该方式与SDK v3.0.3及之前的版本保持一致,采用make.settings作为编译配置选项输入文件,修改完成后执行make即可 + +#### 3. 代码抽取方式 + +该方式可根据需求选择功能,将相关代码抽取到一个单独的文件夹,文件夹里面的代码层次目录简洁,方便用户拷贝集成到自己的开发环境。 +该方式需要依赖cmake工具,在CMakeLists.txt中配置相关功能模块的开关,并将EXTRACT_SRC置为ON,Linux环境运行以下命令 +``` +mkdir build +cd build +cmake .. +``` +即可在output/qcloud_iot_c_sdk中找到相关代码文件,目录层次如下: +``` + qcloud_iot_c_sdk + ├── include + │   ├── config.h + │   ├── exports + ├── platform + └── sdk_src + └── internal_inc +``` +include目录为SDK供用户使用的API及可变参数,其中config.h为根据编译选项生成的编译宏。API具体介绍请参考**C-SDK_API及可变参数说明**。 +platform目录为平台相关的代码,可根据设备的具体情况进行修改适配。具体的函数说明请参考文档**C-SDK_Porting跨平台移植概述** +sdk_src为SDK的核心逻辑及协议相关代码,一般不需要修改,其中internal_inc为SDK内部使用的头文件。 + +用户可将qcloud_iot_c_sdk拷贝到其目标平台的编译开发环境,并根据具体情况修改编译选项。 + +## C-SDK 编译选项说明 + +#### 1. 编译配置选项 +以下配置选项大部分都适用于cmake和make.setting。cmake中的ON值对应于make.setting的y,OFF对应于n。 + +| 名称 | cmake值 | 说明 | +| :------------------------------- | ------------- | ------------------------------------------------------------ | +| BUILD_TYPE | release/debug | release:不启用IOT_DEBUG信息,编译输出到release目录下
debug:启用IOT_DEBUG信息,编译输出到debug目录下 | +| EXTRACT_SRC | ON/OFF | 代码抽取功能开关,仅对使用cmake有效 | +| COMPILE_TOOLS | gcc | 支持gcc和msvc,也可以是交叉编译器比如arm-none-linux-gnueabi-gcc | +| PLATFORM | linux | 包括linux/windows/freertos/nonos | +| FEATURE_MQTT_COMM_ENABLED | ON/OFF | MQTT通道总开关 | +| FEATURE_MQTT_DEVICE_SHADOW | ON/OFF | 设备影子总开关 | +| FEATURE_COAP_COMM_ENABLED | ON/OFF | CoAP通道总开关 | +| FEATURE_GATEWAY_ENABLED | ON/OFF | 网关功能总开关 | +| FEATURE_OTA_COMM_ENABLED | ON/OFF | OTA固件升级总开关 | +| FEATURE_OTA_SIGNAL_CHANNEL | MQTT/COAP | OTA信令通道类型 | +| FEATURE_AUTH_MODE | KEY/CERT | 接入认证方式 | +| FEATURE_AUTH_WITH_NOTLS | ON/OFF | OFF: TLS使能, ON: TLS关闭 | +| FEATURE_MULTITHREAD_ENABLED | ON/OFF | 是否使能SDK对多线程环境的支持 | +| FEATURE_DEV_DYN_REG_ENABLED | ON/OFF | 设备动态注册开关 | +| FEATURE_LOG_UPLOAD_ENABLED | ON/OFF | 日志上报开关 | +| FEATURE_DEBUG_DEV_INFO_USED | ON/OFF | 设备信息获取来源开关 | +| FEATURE_SYSTEM_COMM_ENABLED | ON/OFF | 获取后台时间开关 | +| FEATURE_OTA_USE_HTTPS | ON/OFF | 是否使用HTTPS下载固件 | +| FEATURE_AT_TCP_ENABLED | ON/OFF | AT模组TCP功能开关 | +| FEATURE_AT_UART_RECV_IRQ | ON/OFF | AT模组中断接受功能开关 | +| FEATURE_AT_OS_USED | ON/OFF | AT模组多线程功能开关 | +| FEATURE_AT_DEBUG | ON/OFF | AT模组调试功能开关 | + + +配置选项之间存在依赖关系,当依赖选项的值为有效值时,部分配置选项才有效,主要如下: + +| 名称 | 依赖选项 | 有效值 | +| :------------------------------- | ------------------------------------------------------- | ------------ | +| FEATURE_MQTT_DEVICE_SHADOW | FEATURE_MQTT_COMM_ENABLED | ON | +| FEATURE_GATEWAY_ENABLED | FEATURE_MQTT_COMM_ENABLED | ON | +| FEATURE_OTA_SIGNAL_CHANNEL(MQTT) | FEATURE_OTA_COMM_ENABLED
FEATURE_MQTT_COMM_ENABLED | ON
ON | +| FEATURE_OTA_SIGNAL_CHANNEL(COAP) | FEATURE_OTA_COMM_ENABLED
FEATURE_COAP_COMM_ENABLED | ON
ON | +| FEATURE_AUTH_WITH_NOTLS | FEATURE_AUTH_MODE | KEY | +| FEATURE_AT_UART_RECV_IRQ | FEATURE_AT_TCP_ENABLED | ON | +| FEATURE_AT_OS_USED | FEATURE_AT_TCP_ENABLED | ON | +| FEATURE_AT_DEBUG | FEATURE_AT_TCP_ENABLED | ON | + +#### 2. 设备信息选项 + +在腾讯云物联控制台创建设备之后,需要将设备信息(ProductID/DeviceName/DeviceSecret/Cert/Key文件)配置在SDK中才能正确运行。在开发阶段,SDK 提供两种方式存储设备信息: +1. 存放在代码中(编译选项DEBUG_DEV_INFO_USED = ON),则在`platform/os/xxx/HAL_Device_xxx.c`中修改设备信息,在无文件系统的平台下可以使用这种方式。 +2. 存放在配置文件中(编译选项DEBUG_DEV_INFO_USED = OFF),则在`device_info.json`文件修改设备信息,此方式下更改设备信息不需重新编译SDK,在Linux/Windows平台下开发推荐使用这种方式。 + + +## C-SDK 编译环境 + +### Linux(Ubuntu)环境 + +本文使用Ubuntu的版本为14.04或16.04 + +1. 必要软件安装 +``` +$ sudo apt-get install -y build-essential make git gcc cmake +``` + SDK需要cmake版本在3.5以上,默认安装的cmake版本较低,可以参考如下链接进行cmake特定版本的下载与安装 + 下载链接:https://cmake.org/download/ + 安装参考:https://gitlab.kitware.com/cmake/cmake + + +2. 配置修改 +修改CMakeLists.txt确保以下选项存在(以密钥认证设备为例) +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` + +3. 执行脚本编译 +完整编译库和示例 +``` +./cmake_build.sh +``` +输出的库文件,头文件及示例在`output/release`文件夹中。 +在一次完整编译之后,若只需要编译示例,则执行 +``` +./cmake_build.sh samples +``` + +4. 填写设备信息 +将在腾讯云物联网平台创建的设备的设备信息(以**密钥认证设备**为例)填写到device_info.json中,如: +``` +{ + "auth_mode":"KEY", + "productId":"S3EUVBRJLB", + "deviceName":"test_device", + "key_deviceinfo":{ + "deviceSecret":"vX6PQqazsGsMyf5SMfs6OA6y" + } +} +``` + +5. 运行示例 +示例输出位于`output/release/bin`文件夹中,比如运行mqtt_sample示例,输入`./output/release/bin/mqtt_sample`即可。 + + +### Windows环境 + +#### 获取和安装Visio Studio 2019开发环境 + +请访问[Visual Studio下载网站](https://visualstudio.microsoft.com/zh-hans/downloads/),下载并安装Visio Studio 2019,本文档下载安装的是16.2版本 Community。 + +![](https://main.qcloudimg.com/raw/730f793e3166db859682cdbfd0c7181f.jpg) + +然后选择**使用C++的桌面开发**,并确保勾选**用于Windows的C++ CMAKE工具**: + +![](https://main.qcloudimg.com/raw/89a63cb6ae5231a66b17e80acac37267.jpg) + +#### 编译并运行 + +1. 运行visual studio,选择**打开本地文件夹**,并选择下载的C SDK目录。 + + ![](https://main.qcloudimg.com/raw/f0c65e7c5ce13ca13b967c178c0449c6.jpg) + +2. [修改用户信息]() + +3. 双击打开根目录的CMakeLists.txt,并确认编译工具链中设置的平台为**windows**和编译工具为**MSVC**(其他配置选项请参考[cmake编译配置与代码抽取]())。 + + ![](https://main.qcloudimg.com/raw/8a16723698646a2dca5ab08a57927304.jpg) + + ```cmake + # 编译工具链 + #set(COMPILE_TOOLS "gcc") + #set(PLATFORM "linux") + + set(COMPILE_TOOLS "MSVC") + set(PLATFORM "windows") + ``` + +4. visual studio会自动生成cmake缓存,请等待cmake缓存生成完毕。 + + ![](https://main.qcloudimg.com/raw/633bf217afc2d52e92618a90bd7d9da0.jpg) + +5. 缓存生成完毕后,点击**生成->全部生成**。 + +![](https://main.qcloudimg.com/raw/f85d2435c49a802eedd87b751408ecce.jpg) + +6. 选择相应的示例运行,示例应与用户信息相对应。 + + ![](https://main.qcloudimg.com/raw/a0f2bacc0d31d2da9d327d5c855655a3.jpg) diff --git "a/docs/C-SDK_MTMC\345\244\232\347\272\277\347\250\213\345\244\232\350\256\276\345\244\207\346\224\257\346\214\201.md" "b/docs/C-SDK_MTMC\345\244\232\347\272\277\347\250\213\345\244\232\350\256\276\345\244\207\346\224\257\346\214\201.md" new file mode 100755 index 00000000..c747ea0b --- /dev/null +++ "b/docs/C-SDK_MTMC\345\244\232\347\272\277\347\250\213\345\244\232\350\256\276\345\244\207\346\224\257\346\214\201.md" @@ -0,0 +1,24 @@ +# C-SDK 多线程及多设备支持 + +多线程及多设备支持实例需要首先使能编译配置开关FEATURE_MULTITHREAD_ENABLED + +## Multi-Thread 多线程环境使用说明 + +设备端 C-SDK 支持在多线程多任务环境下使用,但是对接口的使用有一定规范。 +比如对于MQTT接口在多线程环境下的使用有如下注意事项: +``` +1. 不允许多线程调用IOT_MQTT_Yield,IOT_MQTT_Construct以及IOT_MQTT_Destroy +2. 可以多线程调用IOT_MQTT_Publish,IOT_MQTT_Subscribe及IOT_MQTT_Unsubscribe +3. IOT_MQTT_Yield 作为从socket读取并处理MQTT报文的函数,应保证一定的执行时间,避免被长时间挂起或抢占 +``` +在多线程环境下,建议可以使用 IOT_MQTT_StartLoop 和 IOT_MQTT_StopLoop 来启动和停止后台 IOT_MQTT_Yield 线程,则在需要读取报文的时候不再需要主动调用IOT_MQTT_Yield函数,由后台线程来读取并处理MQTT报文。 +使用示例可以参考 samples/mqtt/multi_thread_mqtt_sample + +其他模块接口的使用可以参考MQTT接口的使用 + +## Multi-Client 多设备接入使用 + +在SDK版本3.2.0之后,支持同时使用多个设备接入。SDK采用面向对象方式对状态变量和参数进行封装,使得比如一个MQTT/Shadow Client实例可以对应一个设备,通过提供多个设备三元组,创建多个Client实例,则可以同时进行多个设备的接入和通讯。 +具体的示例代码可以参考 samples/multi_client 下面的sample,通过创建多个线程,每个线程里面创建各自的 MQTT/Shadow Client,则相当于多个设备在同时访问后台服务。 + + diff --git "a/docs/C-SDK_Porting\350\267\250\345\271\263\345\217\260\347\247\273\346\244\215\346\246\202\350\277\260.md" "b/docs/C-SDK_Porting\350\267\250\345\271\263\345\217\260\347\247\273\346\244\215\346\246\202\350\277\260.md" new file mode 100755 index 00000000..0fdde418 --- /dev/null +++ "b/docs/C-SDK_Porting\350\267\250\345\271\263\345\217\260\347\247\273\346\244\215\346\246\202\350\277\260.md" @@ -0,0 +1,106 @@ +## C-SDK跨平台移植 + +本文档介绍如何将设备端 C-SDK 移植到目标硬件平台。C-SDK 采用模块化设计,分离核心协议服务与硬件抽象层,在进行跨平台移植时,一般只需要对硬件抽象层进行修改适配就可以。 + +## C-SDK 架构 + +#### 架构图 + +![framework](https://main.qcloudimg.com/raw/b1a38c7d9a39a5414ccb3c8552d0efbc.png) + +#### 架构说明 + +SDK分四层设计,从上至下分别为平台服务层、核心协议层、网络层、硬件抽象层。 + +- 服务层 +在网络协议层之上,实现了包括设备接入鉴权,设备影子,数据模板,网关,动态注册,日志上报和OTA等功能,并提供相关API接口给用户使用,关于服务层API说明,请参考文档[C-SDK_API及可变参数说明]() + +- 协议层 +设备端和IoT平台交互的网络协议包括MQTT/COAP/HTTP + +- 网络层 +实现基于TLS/SSL(TLS/DTLS)方式,POSIX_socket(TCP/UDP)方式和AT_socket方式的网络协议栈,不同服务可根据需要使用不同的协议栈接口函数。 + +- 硬件抽象层 +实现对不同硬件平台的底层操作的抽象封装,需要针对具体的软硬件平台开展移植,分为必须实现和可选实现两部分HAL层接口。 + +## 硬件抽象层移植 + +HAL层主要有几大块的移植,分别是OS相关的、网络及TLS相关的、时间及打印相关的、设备信息相关的。 +SDK在 **platform/os** 目录示例了Linux、Windows、FreeRTOS及nonOS四个场景的硬件抽象层实现,可以参考最相近的目录展开目标平台的移植。 + +#### OS相关接口 +以下函数跟线程/互斥锁/信号量相关的,只有在使能多线程/多任务情况下(MULTITHREAD_ENABLED)才需要移植 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------- | ------------------------------------------ | +| 1 | HAL_Malloc | 动态申请内存块 | +| 2 | HAL_Free | 释放内存块 | +| 3 | HAL_ThreadCreate | 线程创建 | +| 4 | HAL_MutexCreate | 创建互斥锁 | +| 5 | HAL_MutexDestroy | 销毁互斥锁 | +| 6 | HAL_MutexLock | mutex 加锁 | +| 7 | HAL_MutexUnlock | mutex 解锁 | +| 8 | HAL_SemaphoreCreate | 创建信号量 | +| 9 | HAL_SemaphoreDestroy | 销毁信号量 | +| 10 | HAL_SemaphoreWait | 等待信号量 | +| 11 | HAL_SemaphorePost | 释放信号量 | +| 12 | HAL_SleepMs | 休眠 | + +#### 网络及TLS相关的HAL接口 + +网络相关接口提供二选一的适配移植。对于具备网络通讯能力并且本身集成TCP/IP网络协议栈的设备,需要实现POSIX_socket的网络HAL接口,使用TLS/SSL加密通讯的还需要实现TLS相关的HAL接口。而对于[MCU+通用TCP_AT模组]()的设备,则可以选择SDK提供的AT_Socket框架,并实现相关的AT模组接口。 + +##### 基于POSIX_socket的HAL接口 + +其中TCP/UDP相关接口基于POSIX socket函数实现。TLS相关接口依赖于 **mbedtls** 库,移植之前必须确保系统上有可用的**mbedtls**库。如果采用其他TLS/SSL库,可参考**platform/tls/mbedtls**相关实现进行移植适配。 +UDP/DTLS 相关的函数仅在使能 **COAP** 通讯的时候才需要移植。 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------- | ------------------------------------------ | +| 1 | HAL_TCP_Connect | 建立 TCP 连接 | +| 2 | HAL_TCP_Disconnect | 断开 TCP 连接 | +| 3 | HAL_TCP_Write | TCP 写 | +| 4 | HAL_TCP_Read | TCP 读 | +| 5 | HAL_TLS_Connect | 建立 TLS 连接 | +| 6 | HAL_TLS_Disconnect | 断开 TLS 连接 | +| 7 | HAL_TLS_Write | TLS 写 | +| 8 | HAL_TLS_Read | TLS 读 | +| 9 | HAL_UDP_Connect | 建立 TCP 连接 | +| 10 | HAL_UDP_Disconnect | 断开 TCP 连接 | +| 11 | HAL_UDP_Write | UDP 写 | +| 12 | HAL_UDP_Read | UPD 读 | +| 13 | HAL_DTLS_Connect | 建立 DTLS 连接 | +| 14 | HAL_DTLS_Disconnect | 断开 DTLS 连接 | +| 15 | HAL_DTLS_Write | DTLS 写 | +| 16 | HAL_DTLS_Read | DTLS 读 | + +##### 基于AT_socket的HAL接口 +通过使能编译宏**AT_TCP_ENABLED**选择AT_socket, 则SDK会调用 network_at_tcp.c 的at_socket接口,at_socket层不需要移植,需要实现AT串口驱动及AT模组驱动,AT模组驱动只需要实现AT框架中at_device的驱动结构体 *at_device_op_t* 的驱动接口即可,可以参照at_device目录下的已支持的模组。AT串口驱动需要实现串口的中断接收,然后在中断服务程序中调用回调函数 *at_client_uart_rx_isr_cb* 即可,可以参考 HAL_AT_UART_freertos.c 实现目标平台的移植。 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------- | ------------------------------------------ | +| 1 | HAL_AT_Uart_Init |初始化 AT串口 | +| 2 | HAL_AT_Uart_Deinit | 去初始化 AT串口 | +| 3 | HAL_AT_Uart_Send | AT串口发送数据 | +| 4 | HAL_AT_UART_IRQHandler | AT串口接收中断服务程序 | + + +#### 时间及打印相关的HAL接口 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------- | ------------------------------------------ | +| 1 | HAL_Printf | 将格式化的数据写入标准输出流中 | +| 2 | HAL_Snprintf | 将格式化的数据写入字符串 | +| 3 | HAL_UptimeMs | 检索自系统启动以来已运行的毫秒数 | +| 4 | HAL_DelayMs | 阻塞延时,单位毫秒 | + +#### 设备信息相关的HAL接口 + +接入IoT平台需要在平台创建产品和设备信息,同时需要将产品及设备信息保存在设备侧的非易失存储介质。可以参考 platform/os/linux/HAL_Device_linux.c示例实现。 + +| 序号 | 函数名 | 说明 | +| ---- | ---------------------- | ------------------------------------------ | +| 1 | HAL_GetDevInfo | 设备信息读取 | +| 2 | HAL_SetDevInfo | 设备信息保存 | + diff --git "a/docs/Device_Auth\350\256\276\345\244\207\346\216\245\345\205\245\350\256\244\350\257\201.md" "b/docs/Device_Auth\350\256\276\345\244\207\346\216\245\345\205\245\350\256\244\350\257\201.md" new file mode 100755 index 00000000..0886b07b --- /dev/null +++ "b/docs/Device_Auth\350\256\276\345\244\207\346\216\245\345\205\245\350\256\244\350\257\201.md" @@ -0,0 +1,133 @@ +## 概述 + +腾讯云物联网平台为每个创建的产品分配唯一标识 ProductID,用户可以自定义 DeviceName 标识设备,用产品标识 + 设备标识 + 设备证书/密钥来验证设备的合法性。用户在创建产品时需要选择设备认证方式,在设备接入时需要根据指定的方式上报产品、设备信息与对应的密钥信息,认证通过后才能连接物联网通信平台。由于不同用户的设备端资源、安全等级要求都不同,平台提供了多种认证方案,以满足不同的使用场景。 + +物联网平台提供以下三种认证方案: +- 证书认证(设备级):为每台设备分配证书 + 私钥,使用非对称加密认证接入,用户需要为每台设备烧录不同的配置信息。 +- 密钥认证(设备级):为每台设备分配设备密钥,使用对称加密认证接入,用户需要为每台设备烧录不同的配置信息。 +- 动态注册认证(产品级):为同一产品下的所有设备分配统一密钥,设备通过注册请求获取设备证书/密钥后认证接入,用户可以为同一批设备烧录相同的配置信息。IoT Explorer平台暂不支持动态注册认证。 + +三种方案在易用性、安全性和对设备资源要求上各有优劣,您可以根据自己的业务场景综合评估选择。方案对比如下: + +| 特性 | 证书认证 |密钥认证| 动态注册认证| +|--------|--------|--------|--------| +| 设备烧录信息 | ProductId、DeviceName、
设备证书、设备私钥| ProductId、DeviceName、设备密钥 |ProductId、DeviceName、ProductSecret| +| 是否需要提前创建设备 | 必须| 必须 |支持根据注册请求中携带的 DeviceName 自动创建| +| 安全性 | 高 | 一般 | 一般 | +| 使用限制 | 单产品下最多创建20万设备| 单产品下最多创建20万设备 | 单产品下最多创建20万设备,用户可自定义通过注册请求自动创建的设备数上限| +| 设备资源要求 | 较高,需要支持 TLS| 较低 |较低,支持 AES 即可| + +## 设备身份信息 + - 证书设备要通过平台的安全认证,必须具备四元组信息:产品 ID(ProductId)、设备名(DeviceName)、设备证书文件(DeviceCert)、设备私钥文件(DevicePrivateKey),其中证书文件和私钥文件由平台生成,且一一对应。 + - 密钥设备要通过平台的安全认证,必须具备三元组信息:产品 ID(ProductId)、设备名(DeviceName)、设备密钥(DeviceSecret),其中设备密钥由平台生成。 + +## 设备身份信息烧录 +- 创建产品后,将上述的四元组或者三元组信息,在设备生产的特定环节,烧录到非易失介质中,设备 SDK 运行时读取存放的设备信息,进行设备认证。 + +- SDK提供了设备信息读写的HAL接口,必须实现。可以参考linux平台HAL_Device_linux.c中设备信息读写的实现。 + +- 设备信息HAL接口 : + +| HAL_API | 说明 | +| -----------------------------------| ---------------------------------- | +| HAL_SetDevInfo | 设备信息写入 | +| HAL_GetDevInfo | 设备信息读取 | + +## 开发阶段设备信息配置 + +创建设备之后,需要将设备信息(ProductID/DeviceName/DeviceSecret/Cert/Key文件)配置在SDK中才能正确运行示例。在开发阶段,SDK 提供两种方式存储设备信息: +1. 存放在代码中(编译选项DEBUG_DEV_INFO_USED = ON),则在`platform/os/xxx/HAL_Device_xxx.c`中修改设备信息,在无文件系统的平台下可以使用这种方式。 +``` +/* product Id */ +static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; + +/* device name */ +static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_DEV_NAME"; + +#ifdef DEV_DYN_REG_ENABLED +/* product secret for device dynamic Registration */ +static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "YOUR_PRODUCT_SECRET"; +#endif + +#ifdef AUTH_MODE_CERT +/* public cert file name of certificate device */ +static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "YOUR_DEVICE_NAME_cert.crt"; +/* private key file name of certificate device */ +static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key"; +#else +/* device secret of PSK device */ +static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "YOUR_IOT_PSK"; +#endif +``` + +2. 存放在配置文件中(编译选项DEBUG_DEV_INFO_USED = OFF),则在`device_info.json`文件修改设备信息,此方式下更改设备信息不需重新编译SDK,在Linux/Windows平台下开发推荐使用这种方式。 +``` +{ + "auth_mode":"KEY/CERT", + + "productId":"PRODUCT_ID", + "productSecret":"YOUR_PRODUCT_SECRET", + "deviceName":"YOUR_DEV_NAME", + + "key_deviceinfo":{ + "deviceSecret":"YOUR_IOT_PSK" + }, + + "cert_deviceinfo":{ + "devCertFile":"YOUR_DEVICE_CERT_FILE_NAME", + "devPrivateKeyFile":"YOUR_DEVICE_PRIVATE_KEY_FILE_NAME" + }, + + "subDev":{ + "sub_productId":"YOUR_SUBDEV_PRODUCT_ID", + "sub_devName":"YOUR_SUBDEV_DEVICE_NAME" + } +} +``` + +## 应用示例 +- 初始化连接参数 + +``` +static DeviceInfo sg_devInfo; + +static int _setup_connect_init_params(MQTTInitParams* initParams) +{ + int ret; + + ret = HAL_GetDevInfo((void *)&sg_devInfo); + if(QCLOUD_ERR_SUCCESS != ret){ + return ret; + } + + initParams->device_name = sg_devInfo.device_name; + initParams->product_id = sg_devInfo.product_id; + ...... +} +``` + + +- 密钥设备鉴权参数生成 + +``` +static int _serialize_connect_packet(unsigned char *buf, size_t buf_len, MQTTConnectParams *options, uint32_t *serialized_len) { + ...... + ...... + int username_len = strlen(options->client_id) + strlen(QCLOUD_IOT_DEVICE_SDK_APPID) + MAX_CONN_ID_LEN + cur_timesec_len + 4; + options->username = (char*)HAL_Malloc(username_len); + get_next_conn_id(options->conn_id); + HAL_Snprintf(options->username, username_len, "%s;%s;%s;%ld", options->client_id, QCLOUD_IOT_DEVICE_SDK_APPID, options->conn_id, cur_timesec); + +#if defined(AUTH_WITH_NOTLS) && defined(AUTH_MODE_KEY) + if (options->device_secret != NULL && options->username != NULL) { + char sign[41] = {0}; + utils_hmac_sha1(options->username, strlen(options->username), sign, options->device_secret, options->device_secret_len); + options->password = (char*) HAL_Malloc (51); + if (options->password == NULL) IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); + HAL_Snprintf(options->password, 51, "%s;hmacsha1", sign); + } +#endif + ...... +} +``` + diff --git "a/docs/FreeRTOS+lwIP\345\271\263\345\217\260\347\247\273\346\244\215\350\257\264\346\230\216.md" "b/docs/FreeRTOS+lwIP\345\271\263\345\217\260\347\247\273\346\244\215\350\257\264\346\230\216.md" new file mode 100755 index 00000000..2f2586f2 --- /dev/null +++ "b/docs/FreeRTOS+lwIP\345\271\263\345\217\260\347\247\273\346\244\215\350\257\264\346\230\216.md" @@ -0,0 +1,69 @@ +# 文档说明 +本文档介绍如何将腾讯云物联 C-SDK 移植到**FreeRTOS+lwIP** 平台。 + +## FreeRTOS移植简介 +FreeRTOS作为一个微内核系统,主要提供任务创建及调度和任务间通信等OS核心机制,在不同设备平台还需要搭配多个软件组件包括C运行库(如newlib或者ARM CMSIS库)和TCP/IP网络协议栈(如lwIP)才能形成完整的嵌入式运行平台。同时各个设备平台的编译开发环境也各不相同,因此在移植C-SDK的时候,需要根据不同设备的具体情况进行适配。 +SDK 在**platform/os/freertos**里面提供了一个基于 **FreeRTOS+lwIP+newlib** 的参考实现,该实现已经在乐鑫ESP8266平台上验证测试过。 + +## 从腾讯云物联 C-SDK 中抽取相关代码 + +因为基于RTOS系统的平台编译方式各不相同,一般无法直接使用SDK 的cmake或者make编译,因此SDK提供了代码抽取功能,可根据需要将相关代码抽取到一个单独的文件夹,文件夹里面的代码层次目录简洁,方便用户拷贝集成到自己的开发环境。 + +首先修改 CMakeLists.txt 中配置为freertos平台,并开启代码抽取功能: +``` +set(BUILD_TYPE "release") +set(PLATFORM "freertos") +set(EXTRACT_SRC ON) +set(FEATURE_AT_TCP_ENABLED OFF) +``` +在Linux环境运行以下命令 +``` +mkdir build +cd build +cmake .. +``` +即可在output/qcloud_iot_c_sdk中找到相关代码文件,目录层次如下: +``` + qcloud_iot_c_sdk + ├── include + │   ├── config.h + │   ├── exports + ├── platform + └── sdk_src + └── internal_inc +``` +include目录为SDK供用户使用的API及可变参数,其中config.h为根据编译选项生成的编译宏。API具体介绍请参考**C-SDK_API及可变参数说明**。 +platform目录为平台相关的代码,可根据设备的具体情况进行修改适配。具体的函数说明请参考文档**C-SDK_Porting跨平台移植概述** +sdk_src为SDK的核心逻辑及协议相关代码,一般不需要修改,其中internal_inc为SDK内部使用的头文件。 + +用户可将qcloud_iot_c_sdk拷贝到其目标平台的编译开发环境,并根据具体情况修改编译选项。 + +## 乐鑫ESP8266 RTOS平台移植示例 +在Linux开发环境基于乐鑫ESP8266 RTOS平台搭建一个工程示例,完整可实际运行例程可参考[基于ESP8266 Launcher开发板的工程](https://github.com/tencentyun/qcloud-iot-c-sdk-porting-examples/tree/master/QCloud_IoT_ESP8266_RTOS) + +### 1. 获取 ESP8266_RTOS_SDK 并创建工程 + +请参考[ESP8266_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK) 获取RTOS_SDK 和交叉编译器,并创建一个项目工程 + +### 2. 拷贝SDK代码 + +将上面抽取的qcloud_iot_c_sdk目录拷贝到components/qcloud_iot下面 + +在components/qcloud_iot下面新建一个编译配置文件component.mk,内容如下 +``` +# +# Component Makefile +# + +COMPONENT_ADD_INCLUDEDIRS := \ + qcloud_iot_c_sdk/include \ + qcloud_iot_c_sdk/include/exports \ + qcloud_iot_c_sdk/sdk_src/internal_inc + +COMPONENT_SRCDIRS := \ + qcloud_iot_c_sdk/sdk_src \ + qcloud_iot_c_sdk/platform + +``` + +这样就可以将qcloud_iot_c_sdk作为一个组件进行编译了,之后在用户代码里面就可以调用物联 C-SDK的接口进行连接和收发消息。 diff --git "a/docs/IoT_Hub/IoT_Hub\351\200\232\344\277\241\345\271\263\345\217\260\345\277\253\351\200\237\345\205\245\351\227\250.md" "b/docs/IoT_Hub/IoT_Hub\351\200\232\344\277\241\345\271\263\345\217\260\345\277\253\351\200\237\345\205\245\351\227\250.md" new file mode 100755 index 00000000..0f9bb143 --- /dev/null +++ "b/docs/IoT_Hub/IoT_Hub\351\200\232\344\277\241\345\271\263\345\217\260\345\277\253\351\200\237\345\205\245\351\227\250.md" @@ -0,0 +1,34 @@ +# 腾讯云物联网通信 C-SDK +腾讯云物联网通信IoT Hub C-SDK 依靠安全且性能强大的数据通道,为物联网领域开发人员提供设备终端和云端的双向通信能力。 +以下为SDK各项功能对应的文档。 + +## 快速入门 +请参考**mqtt_sample_快速入门.md**文档,介绍如何在腾讯云物联网通信IoT Hub控制台创建设备, 并结合本 SDK 的**mqtt_sample**快速体验设备端通过 MQTT 协议连接到腾讯云IoT Hub, 发送和接收消息。 + +## 设备影子 +请参考**shadow_sample_设备影子.md**文档,介绍设备影子功能,并结合 SDK 的**shadow_sample**展示影子的数据流和功能 + +## 固件升级 +请参考**ota_sample_固件升级.md**文档,介绍固件升级功能,并结合 SDK 的**ota_mqtt_sample**展示固件升级的流程和功能 + +## 网关功能 +请参考**gateway_sample_网关功能.md**文档,介绍如何在腾讯IoT Hub控制台申请网关设备并绑定子设备, 并结合本 SDK 的**gateway_sample**快速体验网关设备通过 MQTT 协议连接到腾讯云IoT Hub, 代理子设备上下线,发送和接收消息。 + +## 设备互通 +请参考**door_aircond_sample_设备互通.md**文档,介绍一个智能家居设备互通的场景, 结合本 SDK 的**aircond_shadow_sample**和**door_mqtt_sample**快速体验基于IoT Hub的消息转发和规则引擎实现设备之间的联动。 + +## 动态注册 +请参考**dynreg_dev_sample_动态注册.md**文档,介绍腾讯云物联网的设备接入认证以及动态注册功能。 + +## 广播通信 +请参考**broadcast_sample_广播通信.md**文档,介绍腾讯云物联网的广播通信功能。 + +## 同步通信 +请参考**rrpc_sample_同步通信.md**文档,介绍腾讯云物联网的同步通信功能。 + +## 设备日志上报功能 +请参考**log_upload_设备日志上报.md**文档,介绍设备日志上报功能及使用 + +## CoAP通讯 +请参考**coap_sample.md**文档,介绍腾讯云物联网的CoAP协议通信功能 + diff --git "a/docs/IoT_Hub/broadcast_sample_\345\271\277\346\222\255\351\200\232\344\277\241.md" "b/docs/IoT_Hub/broadcast_sample_\345\271\277\346\222\255\351\200\232\344\277\241.md" new file mode 100755 index 00000000..9e6e90b2 --- /dev/null +++ "b/docs/IoT_Hub/broadcast_sample_\345\271\277\346\222\255\351\200\232\344\277\241.md" @@ -0,0 +1,112 @@ +# 广播通信 +本文档介绍广播通信功能,并结合 SDK 的 **broadcast_sample** 展示广播功能。 + +## 一. 控制台创建设备 + +#### 1. 场景说明 +用户有多个空调设备接入物联网通信平台,现在需要服务器向所有的空调设备发送一条相同的指令来关闭空调。 +服务器调用`PublishBroadcastMessage`接口,指定产品`ProductId`和广播消息`Payload`,该产品所有在线的设备就会收到消息内容为`Payload`的广播消息。 +广播消息的Topic为`$broadcast/rxd/{productID}/{deviceName}`。 + +#### 2. 创建产品和设备 +请参考 [设备互通](https://cloud.tencent.com/document/product/634/11913) 创建空调产品,并依次创建airConditioner1,airConditioner2等多个空调设备。 + + +## 二. 编译运行示例程序(以**密钥认证设备**为例) + +#### 1. 编译 SDK +修改CMakeLists.txt确保以下选项存在 +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_BROADCAST_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出`broadcast_sample`位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +将上面创建的airConditioner1设备的设备信息填写到一个JSON文件aircond_device_info1.json中: +``` +{ + "auth_mode":"KEY", + "productId":"KL4J2K3JZ8", + "deviceName":"airConditioner1", + "key_deviceinfo":{ + "deviceSecret":"zOZXUaycuwlePtTcD78dBA==" + } +} +``` +将airConditioner2的设备信息填到aircond_device_info2.json中: +``` +{ + "auth_mode":"KEY", + "productId":"KL4J2K3JZ8", + "deviceName":"airConditioner2", + "key_deviceinfo":{ + "deviceSecret":"+IiVNsyKRh0AW1lcOIE07A==" + } +} +``` +依次将其他的设备信息填到对应的json文件。 + +#### 3. 执行`broadcast_sample`示例程序 +因为这个场景涉及到多个sample同时运行,可以打开多个终端运行`broadcast_sample`示例,可以看到所有的示例都订阅了`$broadcast/rxd/{productID}/{deviceName}`主题,然后就处于等待状态。 +设备airConditioner1输出如下: +``` +./broadcast_sample -c ./aircond_device_info1.json -l 100 +INF|2020-08-03 22:50:28|qcloud_iot_device.c|iot_device_info_set(50): SDK_Ver: 3.2.0, Product_ID: KL4J2K3JZ8, Device_Name: airConditioner1 +DBG|2020-08-03 22:50:28|HAL_TLS_mbedtls.c|HAL_TLS_Connect(200): Setting up the SSL/TLS structure... +DBG|2020-08-03 22:50:28|HAL_TLS_mbedtls.c|HAL_TLS_Connect(242): Performing the SSL/TLS handshake... +DBG|2020-08-03 22:50:28|HAL_TLS_mbedtls.c|HAL_TLS_Connect(243): Connecting to /KL4J2K3JZ8.iotcloud.tencentdevices.com/8883... +INF|2020-08-03 22:50:28|HAL_TLS_mbedtls.c|HAL_TLS_Connect(265): connected with /KL4J2K3JZ8.iotcloud.tencentdevices.com/8883... +INF|2020-08-03 22:50:28|mqtt_client.c|IOT_MQTT_Construct(113): mqtt connect with id: 932If success +INF|2020-08-03 22:50:28|broadcast_sample.c|main(197): Cloud Device Construct Success +DBG|2020-08-03 22:50:28|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$broadcast/rxd/KL4J2K3JZ8/airConditioner1|packet_id=22429 +INF|2020-08-03 22:50:28|broadcast_sample.c|_mqtt_event_handler(49): subscribe success, packet-id=22429 +DBG|2020-08-03 22:50:28|broadcast.c|_broadcast_event_callback(37): broadcast topic subscribe success +``` +设备airConditioner2输出如下: +``` +./broadcast_sample -c ./aircond_device_info2.json -l 100 +INF|2020-08-03 22:51:24|qcloud_iot_device.c|iot_device_info_set(50): SDK_Ver: 3.2.0, Product_ID: KL4J2K3JZ8, Device_Name: airConditioner2 +DBG|2020-08-03 22:51:24|HAL_TLS_mbedtls.c|HAL_TLS_Connect(200): Setting up the SSL/TLS structure... +DBG|2020-08-03 22:51:24|HAL_TLS_mbedtls.c|HAL_TLS_Connect(242): Performing the SSL/TLS handshake... +DBG|2020-08-03 22:51:24|HAL_TLS_mbedtls.c|HAL_TLS_Connect(243): Connecting to /KL4J2K3JZ8.iotcloud.tencentdevices.com/8883... +INF|2020-08-03 22:51:24|HAL_TLS_mbedtls.c|HAL_TLS_Connect(265): connected with /KL4J2K3JZ8.iotcloud.tencentdevices.com/8883... +INF|2020-08-03 22:51:25|mqtt_client.c|IOT_MQTT_Construct(113): mqtt connect with id: f9px6 success +INF|2020-08-03 22:51:25|broadcast_sample.c|main(197): Cloud Device Construct Success +DBG|2020-08-03 22:51:25|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$broadcast/rxd/KL4J2K3JZ8/airConditioner2|packet_id=29904 +INF|2020-08-03 22:51:25|broadcast_sample.c|_mqtt_event_handler(49): subscribe success, packet-id=29904 +DBG|2020-08-03 22:51:25|broadcast.c|_broadcast_event_callback(37): broadcast topic subscribe success +``` + +#### 4. 调用云API `PublishBroadcastMessage` 发送广播消息 +打开腾讯云[API控制台](https://console.cloud.tencent.com/api/explorer?Product=iotcloud&Version=2018-06-14&Action=PublishBroadcastMessage&SignVersion=),填写个人密钥和设备参数信息,选择在线调用并发送请求 +![image.png](https://main.qcloudimg.com/raw/94c4a7cbd9c8e76d728494ebaf58bf93.png) + +#### 5. 观察空调设备的消息接收 +观察设备airConditioner1的打印输出,可以看到已经收到服务器发送的消息。 +``` +DBG|2020-08-03 22:55:32|broadcast.c|_broadcast_message_cb(25): topic=$broadcast/rxd/KL4J2K3JZ8/airConditioner1 +INF|2020-08-03 22:55:32|broadcast.c|_broadcast_message_cb(26): len=6, topic_msg=closed +INF|2020-08-03 22:55:32|broadcast_sample.c|_broadcast_message_handler(134): broadcast message=closed +``` +观察设备airConditioner2的打印输出,可以看到同时收到服务器发送的消息。 +``` +DBG|2020-08-03 22:55:32|broadcast.c|_broadcast_message_cb(25): topic=$broadcast/rxd/KL4J2K3JZ8/airConditioner2 +INF|2020-08-03 22:55:32|broadcast.c|_broadcast_message_cb(26): len=6, topic_msg=closed +INF|2020-08-03 22:55:32|broadcast_sample.c|_broadcast_message_handler(134): broadcast message=closed +``` + +#### 6. 空调设备关闭 +接收到指令的设备解析指令进行处理。 + +***至此,完成了广播通信的示例运行。*** diff --git "a/docs/IoT_Hub/coap_sample_CoAP\351\200\232\350\256\257.md" "b/docs/IoT_Hub/coap_sample_CoAP\351\200\232\350\256\257.md" new file mode 100755 index 00000000..add6622f --- /dev/null +++ "b/docs/IoT_Hub/coap_sample_CoAP\351\200\232\350\256\257.md" @@ -0,0 +1,52 @@ +# CoAP通讯 +IoT Hub支持设备端通过CoAP协议接入,请参考[CoAP 协议说明](https://cloud.tencent.com/document/product/634/14063) + +请先参考**mqtt_sample_快速入门.md**文档,介绍如何在腾讯云物联网通信IoT Hub控制台创建设备 + +## 编译 SDK +编译运行示例程序coap_sample,首先修改CMakeLists.txt确保以下选项存在(以密钥认证设备为例) +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_COAP_COMM_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +编译SDK + +## 填写设备信息 +将上面在腾讯云物联网IoT Hub创建的设备的设备信息(以**密钥认证设备**为例)填写到device_info.json中 +``` +{ + "auth_mode":"KEY", + "productId":"S3EUVBRJLB", + "deviceName":"test_device", + "key_deviceinfo":{ + "deviceSecret":"vX6PQqazsGsMyf5SMfs6OA6y" + } +} +``` + +## 执行coap_sample +``` +./output/release/bin/coap_sample +INF|2019-09-16 23:49:36|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: S3EUVBRJLB, Device_Name: test_device +INF|2019-09-16 23:49:38|coap_client.c|IOT_COAP_Construct(82): coap connect success +INF|2019-09-16 23:49:38|coap_client_message.c|coap_message_send(402): add coap message id: 9734 into wait list ret: 0 +DBG|2019-09-16 23:49:38|coap_client_message.c|_coap_message_handle(295): receive coap piggy ACK message, id 9734 +INF|2019-09-16 23:49:38|coap_client_auth.c|_coap_client_auth_callback(43): auth token message success, code_class: 2 code_detail: 5 +DBG|2019-09-16 23:49:38|coap_client_auth.c|_coap_client_auth_callback(53): auth_token_len = 10, auth_token = YWAIGGUGUC +DBG|2019-09-16 23:49:38|coap_client_message.c|_coap_message_list_proc(146): remove the message id 9734 from list +INF|2019-09-16 23:49:38|coap_client_message.c|_coap_message_list_proc(85): remove node +INF|2019-09-16 23:49:38|coap_client.c|IOT_COAP_Construct(91): device auth successfully, connid: Xy9W9 +INF|2019-09-16 23:49:38|coap_sample.c|main(170): topic name is S3EUVBRJLB/test_device/data +INF|2019-09-16 23:49:38|coap_client_message.c|coap_message_send(402): add coap message id: 9735 into wait list ret: 0 +DBG|2019-09-16 23:49:38|coap_sample.c|main(177): client topic has been sent, msg_id: 9735 +DBG|2019-09-16 23:49:39|coap_client_message.c|_coap_message_handle(295): receive coap piggy ACK message, id 9735 +INF|2019-09-16 23:49:39|coap_sample.c|event_handler(78): message received ACK, msgid: 9735 +DBG|2019-09-16 23:49:39|coap_client_message.c|_coap_message_list_proc(146): remove the message id 9735 from list +INF|2019-09-16 23:49:39|coap_client_message.c|_coap_message_list_proc(85): remove node +INF|2019-09-16 23:49:39|coap_client.c|IOT_COAP_Destroy(125): coap release! +``` \ No newline at end of file diff --git "a/docs/IoT_Hub/door_aircond_sample_\350\256\276\345\244\207\344\272\222\351\200\232.md" "b/docs/IoT_Hub/door_aircond_sample_\350\256\276\345\244\207\344\272\222\351\200\232.md" new file mode 100755 index 00000000..34047436 --- /dev/null +++ "b/docs/IoT_Hub/door_aircond_sample_\350\256\276\345\244\207\344\272\222\351\200\232.md" @@ -0,0 +1,146 @@ + +# 设备互通 +本文档根据一个智能家居设备互通的场景, 结合本 SDK 的**aircond_shadow_sample**和**door_mqtt_sample**快速体验基于IoT Hub的消息转发和规则引擎实现设备之间的联动。 + +## 一. 控制台创建设备 + +#### 1. 场景说明 +本文档的用户场景请参考腾讯云文档中心的[设备互通](https://cloud.tencent.com/document/product/634/11913) +假设一个智能家居的场景,门打开时候触发空调的温度控制,两个设备之间的消息是通过云端规则引擎进行转发的 + +![](https://mc.qcloudimg.com/static/img/d158634d34fbddbed17bfaa49cb24d90/airv1schema.png) + +#### 2. 创建产品和设备,配置规则引擎 +请参考[设备互通](https://cloud.tencent.com/document/product/634/11913) 分别创建空调和门产品,再创建airConditioner1和door1设备,并配置好规则引擎。 + + +## 二. 编译运行示例程序(以**密钥认证设备**为例) + +#### 1. 编译 SDK +修改CMakeLists.txt确保以下选项存在 +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_MQTT_DEVICE_SHADOW ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出aircond_shadow_sample和door_mqtt_sample位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +将上面创建的airConditioner1设备的设备信息填写到一个JSON文件aircond_device_info.json中 +``` +{ + "auth_mode":"KEY", + "productId":"GYT9V6D4AF", + "deviceName":"airConditioner1", + "key_deviceinfo":{ + "deviceSecret":"vXeds12qazsGsMyf5SMfs6OA6y" + } +} +``` +再将door1设备的设备信息填写到另一个JSON文件door_device_info.json中 +``` +{ + "auth_mode":"KEY", + "productId":"S3EUVBRJLB", + "deviceName":"door1", + "key_deviceinfo":{ + "deviceSecret":"i92E3QMNmxi5hvIxUHjO8gTdg" + } +} +``` + +#### 3. 执行aircond_shadow_sample示例程序 +因为这个场景涉及到两个sample同时运行,可以先在当前终端console运行空调示例,可以看到示例订阅了 /{productID}/{deviceName}/control 主题,然后就处于循环等待状态 +``` + ./output/release/bin/aircond_shadow_sample -c ./aircond_device_info.json +INF|2019-09-16 23:25:17|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: GYT9V6D4AF, Device_Name: airConditioner1 +DBG|2019-09-16 23:25:17|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure... +DBG|2019-09-16 23:25:17|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake... +DBG|2019-09-16 23:25:17|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /GYT9V6D4AF.iotcloud.tencentdevices.com/8883... +INF|2019-09-16 23:25:18|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /GYT9V6D4AF.iotcloud.tencentdevices.com/8883... +INF|2019-09-16 23:25:19|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: Nh9Vc success +DBG|2019-09-16 23:25:19|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$shadow/operation/result/GYT9V6D4AF/airConditioner1|packet_id=56171 +DBG|2019-09-16 23:25:19|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=56171 +INF|2019-09-16 23:25:19|aircond_shadow_sample.c|event_handler(96): subscribe success, packet-id=56171 +INF|2019-09-16 23:25:19|shadow_client.c|IOT_Shadow_Construct(172): Sync device data successfully +INF|2019-09-16 23:25:19|aircond_shadow_sample.c|main(256): Cloud Device Construct Success +DBG|2019-09-16 23:25:19|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=GYT9V6D4AF/airConditioner1/control|packet_id=56172 +DBG|2019-09-16 23:25:19|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=56172 +INF|2019-09-16 23:25:19|aircond_shadow_sample.c|event_handler(96): subscribe success, packet-id=56172 +INF|2019-09-16 23:25:19|aircond_shadow_sample.c|main(291): airConditioner state: close +INF|2019-09-16 23:25:19|aircond_shadow_sample.c|main(292): currentTemperature: 32.000000, energyConsumption: 0.000000 +``` + +#### 4. 执行door_mqtt_sample示例程序,模拟回家事件 +这时打开另一个终端console,运行门的示例,可以看到示例往 /{productID}/{deviceName}/event 主题发送了JSON消息{"action": "come_home", "targetDevice": "airConditioner1"},表示将回家的消息通知目标设备airConditioner1,然后程序就退出了 + +``` +./output/release/bin/door_mqtt_sample -c ../devinfo/door_device_info.json -t airConditioner1 -a come_home +INF|2019-09-16 23:29:11|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: S3EUVBRJLB, Device_Name: test_dev_key +DBG|2019-09-16 23:29:11|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure... +DBG|2019-09-16 23:29:11|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake... +DBG|2019-09-16 23:29:11|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-16 23:29:11|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-16 23:29:11|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: d89Wh success +INF|2019-09-16 23:29:11|door_mqtt_sample.c|main(229): Cloud Device Construct Success +DBG|2019-09-16 23:29:11|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=46683|topicName=S3EUVBRJLB/test_dev_key/event|payload={"action": "come_home", "targetDevice": "airConditioner1"} +INF|2019-09-16 23:29:11|door_mqtt_sample.c|main(246): Wait for publish ack +INF|2019-09-16 23:29:11|door_mqtt_sample.c|event_handler(81): publish success, packet-id=46683 +INF|2019-09-16 23:29:13|mqtt_client_connect.c|qcloud_iot_mqtt_disconnect(437): mqtt disconnect! +INF|2019-09-16 23:29:13|mqtt_client.c|IOT_MQTT_Destroy(186): mqtt release! +``` + +#### 5. 观察空调设备的消息接收,模拟消息响应 +这个时候观察aircond_shadow_sample的打印输出,可以看到已经收到door1发送的回家消息,并将空调打开,开始调节温度。 +``` +INF|2019-09-16 23:29:11|aircond_shadow_sample.c|main(291): airConditioner state: close +INF|2019-09-16 23:29:11|aircond_shadow_sample.c|main(292): currentTemperature: 32.000000, energyConsumption: 0.000000 +INF|2019-09-16 23:29:12|aircond_shadow_sample.c|on_message_callback(140): Receive Message With topicName:GYT9V6D4AF/airConditioner1/control, payload:{"action":"come_home","targetDevice":"airConditioner1"} +INF|2019-09-16 23:29:12|aircond_shadow_sample.c|main(291): airConditioner state: open +INF|2019-09-16 23:29:12|aircond_shadow_sample.c|main(292): currentTemperature: 31.000000, energyConsumption: 1.000000 +INF|2019-09-16 23:29:13|aircond_shadow_sample.c|main(291): airConditioner state: open +INF|2019-09-16 23:29:13|aircond_shadow_sample.c|main(292): currentTemperature: 30.000000, energyConsumption: 2.000000 +``` + +#### 6. 执行door_mqtt_sample示例程序,模拟离开事件 +这时如果再次运行门的示例,更改程序启动参数,可以看到示例往 /{productID}/{deviceName}/event 主题发送了JSON消息{"action": "leave_home", "targetDevice": "airConditioner1"},表示将离开的消息通知目标设备airConditioner1 + +``` +./output/release/bin/door_mqtt_sample -c ../devinfo/door_device_info.json -t airConditioner1 -a leave_home +INF|2019-09-16 23:40:35|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: S3EUVBRJLB, Device_Name: test_dev_key +DBG|2019-09-16 23:40:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure... +DBG|2019-09-16 23:40:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake... +DBG|2019-09-16 23:40:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-16 23:40:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-16 23:40:35|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: 3I59W success +INF|2019-09-16 23:40:35|door_mqtt_sample.c|main(229): Cloud Device Construct Success +DBG|2019-09-16 23:40:35|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=39867|topicName=S3EUVBRJLB/test_dev_key/event|payload={"action": "leave_home", "targetDevice": "airConditioner1"} +INF|2019-09-16 23:40:35|door_mqtt_sample.c|main(246): Wait for publish ack +INF|2019-09-16 23:40:35|door_mqtt_sample.c|event_handler(81): publish success, packet-id=39867 +INF|2019-09-16 23:40:37|mqtt_client_connect.c|qcloud_iot_mqtt_disconnect(437): mqtt disconnect! +INF|2019-09-16 23:40:37|mqtt_client.c|IOT_MQTT_Destroy(186): mqtt release! +``` + +#### 7. 观察空调设备的消息接收,模拟消息响应 +这个时候观察aircond_shadow_sample的打印输出,可以看到已经收到door1发送的离开消息,并将空调关闭,温度开始升高。 +``` +INF|2019-09-16 23:40:35|aircond_shadow_sample.c|main(291): airConditioner state: open +INF|2019-09-16 23:40:35|aircond_shadow_sample.c|main(292): currentTemperature: 26.000000, energyConsumption: 6.000000 +INF|2019-09-16 23:40:36|aircond_shadow_sample.c|on_message_callback(140): Receive Message With topicName:GYT9V6D4AF/airConditioner1/control, payload:{"action":"leave_home","targetDevice":"airConditioner1"} +INF|2019-09-16 23:40:36|aircond_shadow_sample.c|main(291): airConditioner state: close +INF|2019-09-16 23:40:36|aircond_shadow_sample.c|main(292): currentTemperature: 26.500000, energyConsumption: 6.000000 +INF|2019-09-16 23:40:37|aircond_shadow_sample.c|main(291): airConditioner state: close +INF|2019-09-16 23:40:37|aircond_shadow_sample.c|main(292): currentTemperature: 27.000000, energyConsumption: 6.000000 +INF|2019-09-16 23:40:39|aircond_shadow_sample.c|main(291): airConditioner state: close +``` + +至此,完成了模拟设备互通联动的示例运行。 diff --git "a/docs/IoT_Hub/dynreg_dev_sample_\345\212\250\346\200\201\346\263\250\345\206\214.md" "b/docs/IoT_Hub/dynreg_dev_sample_\345\212\250\346\200\201\346\263\250\345\206\214.md" new file mode 100755 index 00000000..435cda3a --- /dev/null +++ "b/docs/IoT_Hub/dynreg_dev_sample_\345\212\250\346\200\201\346\263\250\345\206\214.md" @@ -0,0 +1,81 @@ +# 设备接入及动态注册 + +关于IoT Hub设备接入认证的详细介绍,请参考 [设备身份认证 ](https://cloud.tencent.com/document/product/634/35272) +简单来说,物联网通信平台IoT Hub提供三种设备端接入认证的方案: + +- 证书认证(设备级):为每台设备分配证书 + 私钥,使用非对称加密认证接入,用户需要为每台设备烧录不同的配置信息。 +- 密钥认证(设备级):为每台设备分配设备密钥,使用对称加密认证接入,用户需要为每台设备烧录不同的配置信息。 +- 动态注册认证(产品级):为同一产品下的所有设备分配统一密钥,设备通过注册请求获取设备证书/密钥后认证接入,用户可以为同一批设备烧录相同的配置信息。 + +使用设备动态注册功能,可以使得同一个产品型号的设备出厂时烧录的是统一的固件,该固件只包含统一的产品ID和产品密钥。设备出厂后判断设备信息为空(判断设备信息为空的逻辑由业务逻辑实现,可参考示例),则触发设备动态注册,从平台申请设备的证书(创建的产品为证书认证产品)或者设备的密钥(创建的产品为密钥认证方式),将获取到的设备信息保存下来之后,后续的设备接入就可以使用。 + +## 一. 控制台使能动态注册 + +动态注册时,设备名称的生成有两种方式,一种是在控制台使能了动态注册产品的自动创建设备功能,则设备可以自行生成设备名称,但需保证同一产品下没有重复,一般取设备的唯一信息比如CPUID或mac地址。另一种是没有使能动态注册产品的自动创建设备,则需要在控制台预先录入各设备的名称,且设备动态注册时设备要与录入的设备名称一致,此种方式更加安全,便利性有所下降。 + +控制台使能动态注册设置如下图示: +![](https://main.qcloudimg.com/raw/a02f57cbe40f26ead94170396d78253c.jpg) + +将产品密钥ProductSecret保存下来。 + +## 二. 编译运行示例程序(以**密钥认证设备**为例) +#### 1. 编译 SDK +修改CMakeLists.txt确保以下选项存在 +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_DEV_DYN_REG_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出dynreg_dev_sample位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +将控制台获取到的产品信息填写到一个JSON文件dynreg_device_info.json中,其中deviceName字段填写要生成的设备名字,deviceSecret字段保持为"YOUR_IOT_PSK",这样dynreg_dev_sample就会判断设备信息为空,知道这个设备是需要进行动态注册。这部分逻辑可以由用户自行实现,sample仅作示例。 +``` +{ + "auth_mode":"KEY", + "productId":"S3EUVBRJLB", + "productSecret":"8Xz56tyfgQAZEDCTUGau4snA", + "deviceName":"device_1234", + "key_deviceinfo":{ + "deviceSecret":"YOUR_IOT_PSK" + } +} +``` +#### 3. 运行示例 +执行设备动态注册例程dynreg_dev_sample: +``` +./output/release/bin/dynreg_dev_sample -c ./dynreg_device_info.json +DBG|2019-09-17 11:50:35|dynreg_dev_sample.c|main(80): dev psk not exist! +DBG|2019-09-17 11:50:35|dynreg.c|IOT_DynReg_Device(467): sign:ZWM4YTEyMWE2ODUxYzk1M2Q0MDc2OWNmN2FhMTg1ZWM1ODgxMWNkNQ== +DBG|2019-09-17 11:50:35|dynreg.c|IOT_DynReg_Device(483): request:{"deviceName":"device_1234","nonce":1439928322,"productId":"S3EUVBRJLB","timestamp":1568692235,"signature":"ZWM4YTEyMWE2ODUxYzk1M2Q0MDc2OWNmN2FhMTg1ZWM1ODgxMWNkNQ=="} +DBG|2019-09-17 11:50:35|dynreg.c|IOT_DynReg_Device(485): resbuff len:256 +DBG|2019-09-17 11:50:35|HAL_TLS_mbedtls.c|_mbedtls_client_init(134): psk/pskid is empty!|psk=(null)|psd_id=(null) +DBG|2019-09-17 11:50:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure... +DBG|2019-09-17 11:50:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake... +DBG|2019-09-17 11:50:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /gateway.tencentdevices.com/443... +INF|2019-09-17 11:50:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /gateway.tencentdevices.com/443... +DBG|2019-09-17 11:50:35|utils_httpc.c|qcloud_http_client_connect(749): http client connect success +DBG|2019-09-17 11:50:37|dynreg.c|_parse_devinfo(244): recv: {"code":0,"message":"","len":53,"payload":"eHGRUBar9LBPI+mcaHnVEZsj05mSdoZLPhd54hDJXv/2va2rXSpfddgRy5XE/FIS835NjUr5Mhw1AJSg4yGC/w=="} +DBG|2019-09-17 11:50:37|dynreg.c|_parse_devinfo(258): payload:eHGRUBar9LBPI+mcaHnVEZsj05mSdoZLPhd54hDJXv/2va2rXSpfddgRy5XE/FIS835NjUr5Mhw1AJSg4yGC/w== +DBG|2019-09-17 11:50:37|dynreg.c|IOT_DynReg_Device(489): request dev info success +DBG|2019-09-17 11:50:37|HAL_Device_linux.c|iot_save_devinfo_to_json_file(340): JsonDoc(183):{ +"auth_mode":"KEY", +"productId":"S3EUVBRJLB", +"productSecret":"8XzjN8rfgFVGDTNTUGau4snA", +"deviceName":"device_1234", +"key_deviceinfo":{ +"deviceSecret":"7WmFArtyFGH5632QwJWtYwio" +} +} +DBG|2019-09-17 11:50:37|dynreg_dev_sample.c|main(99): dynamic register success,productID: S3EUVBRJLB, devName: device_1234, device_secret: 7WmFArtyFGH5632QwJWtYwio +``` +可以看到设备动态注册已经成功,获取到的设备密钥也写入到dynreg_device_info.json文件中了 diff --git "a/docs/IoT_Hub/gateway_sample_\347\275\221\345\205\263\345\212\237\350\203\275.md" "b/docs/IoT_Hub/gateway_sample_\347\275\221\345\205\263\345\212\237\350\203\275.md" new file mode 100755 index 00000000..fcf083df --- /dev/null +++ "b/docs/IoT_Hub/gateway_sample_\347\275\221\345\205\263\345\212\237\350\203\275.md" @@ -0,0 +1,166 @@ +# 网关设备快速入门 +本文档将讲述如何在腾讯IoT Hub控制台申请网关设备并绑定子设备, 并结合本 SDK 的**gateway_sample**快速体验网关设备通过 MQTT 协议连接到腾讯云IoT Hub, 代理子设备上下线,发送和接收消息。 + + +## 一. 控制台创建网关设备 + +#### 1. 创建网关产品和设备 +点击页面**创建新产品**按钮, 创建一个产品。 + +![](https://main.qcloudimg.com/raw/a0da21dc6ac9a9e1dede0077d40cfb22.png) + +在弹出的产品窗口中,选择节点类型和产品类型,输入产品名称,选择认证方式和数据格式,输入产品描述,然后点击确定创建。普通网关设备,可按下图选择。 + +![](https://main.qcloudimg.com/raw/d3f5de3bd07a779f9b1306085fa4d1f1.png) + +在生成的产品页面下,点击**设备列表**页面添加新设备。 + +![](https://main.qcloudimg.com/raw/0530e0da724cd36baefc7011ebce4775.png) + +如果产品认证方式为证书认证,输入设备名称成功后,切记点击弹窗中的**下载**按钮,下载所得包中的设备密钥文件和设备证书用于设备连接物联网通信的鉴权。 + +![](https://main.qcloudimg.com/raw/6592056f1b55fa9262e4b2ab31d0b218.png) + +如果产品认证方式为密钥认证,输入设备名称成功后,会在弹窗中显示新添加设备的密钥 + +![](https://main.qcloudimg.com/raw/fe7a013b1d8c29c477d0ed6d00643751.png) + +网关产品,除了自身创建产品和设备,当需要代理子设备进行通讯时,还需要按照普通产品的方式先创建子产品和子设备,并在网关产品页面添加子产品和子设备。需要注意的是子设备是无法直连物联网平台的产品,由网关设备代理连接,所以子设备的认证方式不影响连接,由网关设备来负责认证接入。 +创建好子产品之后,先到网关产品页面的子产品栏目添加子产品 + +![](https://main.qcloudimg.com/raw/00da59942515b1d772323c7087f627e3.png) + +再到网关设备页面的子设备栏目添加子设备 + +![](https://main.qcloudimg.com/raw/c24938ac8ed3aa3e0834cb40598740ca.png) + +#### 2. 创建可订阅可发布的Topic + +进入产品设置页面的后, 点击权限列表,再点击**添加Topic权限**。 + +![](https://main.qcloudimg.com/raw/65a2d1b7251de37ce1ca2ba334733c57.png) + +在弹窗中输入 data, 并设置操作权限为**发布和订阅**,点击创建。 + +![](https://main.qcloudimg.com/raw/f429b32b12e3cb0cf319b1efe11ccceb.png) + +随后将会创建出 productID/\${deviceName}/data 的 Topic,在产品页面的权限列表中可以查看该产品的所有权限。 + +对于网关产品,除了添加本产品的Topic权限,还需要为子产品添加Topic权限 + +![](https://main.qcloudimg.com/raw/3de74cfd5b235fe942fe18c359ad08af.png) + +## 二. 编译运行示例程序 + +#### 1. 编译 SDK +修改CMakeLists.txt确保以下选项存在(以**密钥认证设备**为例) +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_GATEWAY_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +将上面在腾讯云物联网IoT Hub创建的网关设备和子设备的设备信息(以**密钥认证设备**为例)填写到device_info.json中 +``` +{ + "auth_mode":"KEY", + "productId":"NINEPLMEB6", + "deviceName":"Gateway-demo", + "key_deviceinfo":{ + "deviceSecret":"vX23qEazsGsMyf5SMfs6OA6y" + } + + "subDev":{ + "sub_productId":"S3EUVBRJLB", + "sub_devName":"test_device" + } +} +``` + +#### 3. 执行网关示例程序 +如下日志信息显示示例程序通过MQTT网关代理子设备上下线状态变化,发布和订阅消息成功。 +``` +./gateway_sample +INF|2019-09-16 14:35:34|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: NINEPLMEB6, Device_Name: Gateway-demo +DBG|2019-09-16 14:35:34|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure... +DBG|2019-09-16 14:35:34|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake... +DBG|2019-09-16 14:35:34|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /NINEPLMEB6.iotcloud.tencentdevices.com/8883... +INF|2019-09-16 14:35:34|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /NINEPLMEB6.iotcloud.tencentdevices.com/8883... +INF|2019-09-16 14:35:34|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: Senw3 success +DBG|2019-09-16 14:35:34|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$gateway/operation/result/NINEPLMEB6/Gateway-demo|packet_id=27802 +DBG|2019-09-16 14:35:34|gateway_api.c|_gateway_event_handler(23): gateway sub|unsub(3) success, packet-id=27802 +DBG|2019-09-16 14:35:34|gateway_api.c|IOT_Gateway_Subdev_Online(125): there is no session, create a new session +DBG|2019-09-16 14:35:34|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$gateway/operation/NINEPLMEB6/Gateway-demo|payload={"type":"online","payload":{"devices":[{"product_id":"S3EUVBRJLB","device_name":"test_device"}]}} +INF|2019-09-16 14:35:35|gateway_common.c|_gateway_message_handler(134): client_id(S3EUVBRJLB/test_device), online success. result 0 +DBG|2019-09-16 14:35:35|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=S3EUVBRJLB/test_device/data|packet_id=27803 +DBG|2019-09-16 14:35:35|gateway_api.c|_gateway_event_handler(23): gateway sub|unsub(3) success, packet-id=27803 +INF|2019-09-16 14:35:35|gateway_sample.c|_event_handler(61): subscribe success, packet-id=27803 +DBG|2019-09-16 14:35:35|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=27804|topicName=S3EUVBRJLB/test_device/data|payload={"data":"test gateway"} +INF|2019-09-16 14:35:35|gateway_sample.c|_event_handler(88): publish success, packet-id=27804 +INF|2019-09-16 14:35:35|gateway_sample.c|_message_handler(111): Receive Message With topicName:S3EUVBRJLB/test_device/data, payload:{"data":"test gateway"} +DBG|2019-09-16 14:35:36|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$gateway/operation/NINEPLMEB6/Gateway-demo|payload={"type":"offline","payload":{"devices":[{"product_id":"S3EUVBRJLB","device_name":"test_device"}]}} +INF|2019-09-16 14:35:36|gateway_common.c|_gateway_message_handler(139): client_id(S3EUVBRJLB/test_device), offline success. result 0 +INF|2019-09-16 14:35:37|mqtt_client_connect.c|qcloud_iot_mqtt_disconnect(437): mqtt disconnect! +INF|2019-09-16 14:35:37|mqtt_client.c|IOT_MQTT_Destroy(186): mqtt release! +``` + +#### 4. 观察子设备上线 +如下日志信息显示示例程序的网关设备Gateway-demo通过MQTT代理子设备test_device的上线成功: +``` +DBG|2019-09-16 14:35:34|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$gateway/operation/NINEPLMEB6/Gateway-demo|payload={"type":"online","payload":{"devices":[{"product_id":"S3EUVBRJLB","device_name":"test_device"}]}} +INF|2019-09-16 14:35:35|gateway_common.c|_gateway_message_handler(134): client_id(S3EUVBRJLB/test_device), online success. result 0 +``` + +#### 5. 观察网关发送接收子设备的消息 +如下日志信息显示示例程序的网关设备Gateway-demo通过MQTT代理子设备test_device的消息发送接收 +``` +DBG|2019-09-16 14:35:35|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=27804|topicName=S3EUVBRJLB/test_device/data|payload={"data":"test gateway"} +INF|2019-09-16 14:35:35|gateway_sample.c|_event_handler(88): publish success, packet-id=27804 +INF|2019-09-16 14:35:35|gateway_sample.c|_message_handler(111): Receive Message With topicName:S3EUVBRJLB/test_device/data, payload:{"data":"test gateway"} +``` + +## 三. 代码说明 + +#### 如何通过SDK绑定子设备 +网关绑定和解绑子设备可以通过控制台操作,也可以由网关通过MQTT报文进行,SDK提供了对应的接口 +``` +int IOT_Gateway_Subdev_Bind(void *client, GatewayParam *param, DeviceInfo *pBindSubDevInfo); +int IOT_Gateway_Subdev_Unbind(void *client, GatewayParam *param, DeviceInfo *pSubDevInfo); +``` +使用方式可以参考gateway_sample示例代码 +当执行`gateway_sample -b psk_device_info.json`时,会先去绑定psk_device_info.json里面指定的子设备,再执行上下线及收发消息操作 + +#### 如何代理多个子设备 +gateway_sample示例演示了网关代理一个子设备的情况,如果用户需要增加更多子设备,可以先在控制台添加子设备,然后在代码里面通过创建更多GatewayParam参数实例,并将GatewayParam参数传递给网关各个API,即可以实现网关代理多个子设备进行通讯。 +``` + // one GatewayParam only support one sub-device + // use more GatewayParam to add more sub-device + GatewayParam gw_param1 = DEFAULT_GATEWAY_PARAMS;; + gw_param1.product_id = gw_dev_info.gw_info.product_id; + gw_param1.device_name = gw_dev_info.gw_info.device_name; + + gw_param1.subdev_product_id = "SUB-PRODUCT1"; + gw_param1.subdev_device_name = "SUB-DEVICE1"; + + IOT_Gateway_Subdev_Online(client, &gw_param1); +``` + +#### 获取网关在云平台上已绑定的设备列表 +网关在进行子设备绑定前可获取云平台上已绑定的子设备列表,SDK 提供了对应的接口 +``` +int IOT_Gateway_Subdev_GetBindList(void *client, GatewayParam *param, SubdevBindList *subdev_bindlist); +void IOT_Gateway_Subdev_DestoryBindList(SubdevBindList *subdev_bindlist); + +``` + diff --git "a/docs/IoT_Hub/log_upload_\350\256\276\345\244\207\346\227\245\345\277\227\344\270\212\346\212\245.md" "b/docs/IoT_Hub/log_upload_\350\256\276\345\244\207\346\227\245\345\277\227\344\270\212\346\212\245.md" new file mode 100755 index 00000000..9a0e01c3 --- /dev/null +++ "b/docs/IoT_Hub/log_upload_\350\256\276\345\244\207\346\227\245\345\277\227\344\270\212\346\212\245.md" @@ -0,0 +1,17 @@ +# 设备日志上报功能 +## 功能简介 +设备端日志上报功能,可将设备端的Log通过HTTP上报到云端,并可在控制台展示,方便用户远程调试、诊断及监控设备运行状况。目前该功能仅支持MQTT模式。 +只要将SDK的编译宏FEATURE_LOG_UPLOAD_ENABLED置为y(默认为y),并在控制台设置上报级别,则在代码中调用Log_e/w/i/d接口的日志除了会在终端打印出来,还会上报云端并在控制台展示,如下图。 +![](https://main.qcloudimg.com/raw/cae7f9e7cf1e354cfc1e3578eb6746bc.png) + +## 日志级别 +上报级别设置可参见下图,Level级别越大则上报的日志越多,比如Level3(信息)会将ERROR/WARN/INFO级别的日志都上报而DEBUG级别则不上报。控制台默认为关闭状态,则表示设备端仅在MQTT连接失败的时候才会上报ERROR级别日志。 +![](https://main.qcloudimg.com/raw/826b648993a267b1cc2f082148d8d073.png) + +## 功能使用 +代码具体用例可以参考mqtt_sample以及qcloud_iot_export_log.h注释说明,用户除了打开编译宏开关,还需要调用IOT_Log_Init_Uploader函数进行初始化。SDK在IOT_MQTT_Yield函数中会定时进行上报,此外,用户可根据自身需要,在程序出错退出的时候调用IOT_Log_Upload(true)强制上报。同时SDK提供在HTTP通讯出错无法上报日志时的缓存和恢复正常后重新上报机制,但需要用户根据设备具体情况提供相关回调函数,如不提供回调或回调函数提供不全则该缓存机制不生效,HTTP通讯失败时日志会被丢掉。 + +打开日志上报功能,请确保编译配置文件CMakeLists.txt中使能下面选项 +``` +set(FEATURE_LOG_UPLOAD_ENABLED ON) +``` diff --git "a/docs/IoT_Hub/mqtt_sample_\345\277\253\351\200\237\345\205\245\351\227\250.md" "b/docs/IoT_Hub/mqtt_sample_\345\277\253\351\200\237\345\205\245\351\227\250.md" new file mode 100755 index 00000000..87293940 --- /dev/null +++ "b/docs/IoT_Hub/mqtt_sample_\345\277\253\351\200\237\345\205\245\351\227\250.md" @@ -0,0 +1,145 @@ + +# 快速开始 +本文档将讲述如何在腾讯云物联网通信IoT Hub控制台申请设备, 并结合本 SDK 的**mqtt_sample**快速体验设备端通过 MQTT 协议连接到腾讯云IoT Hub, 发送和接收消息。 + +## 一. 控制台创建设备 + +#### 1. 注册/登录腾讯云账号 +访问[腾讯云登录页面](https://cloud.tencent.com/login?s_url=https%3A%2F%2Fcloud.tencent.com%2F), 点击[立即注册](https://cloud.tencent.com/register?s_url=https%3A%2F%2Fcloud.tencent.com%2F), 免费获取腾讯云账号,若您已有账号,可直接登录。 + +#### 2. 访问物联网通信控制台 +登录后点击右上角控制台,进入控制台后,鼠标悬停在云产品上,弹出层叠菜单,点击物联网通信。 + +![](https://main.qcloudimg.com/raw/f8719b28d557496ce3388e0439ca38b6.png) + +或者直接访问[物联网通信控制台](https://console.qcloud.com/iotcloud) + +#### 3. 创建产品和设备 +点击页面**创建新产品**按钮, 创建一个产品。 + +![](https://main.qcloudimg.com/raw/a0da21dc6ac9a9e1dede0077d40cfb22.png) + +在弹出的产品窗口中,选择节点类型和产品类型,输入产品名称,选择认证方式和数据格式,输入产品描述,然后点击确定创建。对于普通直连设备,可按下图选择。 + +![](https://main.qcloudimg.com/raw/7ee90122a01f5f277785885669a56aec.png) + +在生成的产品页面下,点击**设备列表**页面添加新设备。 + +![](https://main.qcloudimg.com/raw/0530e0da724cd36baefc7011ebce4775.png) + +如果产品认证方式为证书认证,输入设备名称成功后,切记点击弹窗中的**下载**按钮,下载所得包中的设备密钥文件和设备证书用于设备连接物联网通信的鉴权。 + +![](https://main.qcloudimg.com/raw/6592056f1b55fa9262e4b2ab31d0b218.png) + +如果产品认证方式为密钥认证,输入设备名称成功后,会在弹窗中显示新添加设备的密钥 + +![](https://main.qcloudimg.com/raw/fe7a013b1d8c29c477d0ed6d00643751.png) + +#### 4. 创建可订阅可发布的Topic + +按照**第三步**中进入产品设置页面的方法进入页面后, 点击权限列表,再点击**添加Topic权限**。 + +![](https://main.qcloudimg.com/raw/65a2d1b7251de37ce1ca2ba334733c57.png) + +在弹窗中输入 data, 并设置操作权限为**发布和订阅**,点击创建。 + +![](https://main.qcloudimg.com/raw/f429b32b12e3cb0cf319b1efe11ccceb.png) + +随后将会创建出 productID/\${deviceName}/data 的 Topic,在产品页面的权限列表中可以查看该产品的所有权限。 + +#### 5. 创建消息转发规则 +消息在设备间的转发需要通过规则引擎进行,具体用法请参考[规则引擎](https://cloud.tencent.com/document/product/634/14446) + +需要注意的是同一个设备,如果想进行自发自收,也需要创建转发规则,对于本示例,可以参考下图设立转发规则(需要将图片中productID以及deviceName部分替换为上面创建的设备信息) +![](https://main.qcloudimg.com/raw/5cdda90be21256386bcd786268f72e6f.png) + +## 二. 编译运行示例程序 + +#### 1. 编译 SDK +修改CMakeLists.txt确保以下选项存在(以密钥认证设备为例) +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +将上面在腾讯云物联网IoT Hub创建的设备的设备信息(以**密钥认证设备**为例)填写到device_info.json中 +``` +{ + "auth_mode":"KEY", + "productId":"S3EUVBRJLB", + "deviceName":"test_device", + "key_deviceinfo":{ + "deviceSecret":"vX6PQqazsGsMyf5SMfs6OA6y" + } +} +``` + +#### 3. 执行 mqtt_sample 示例程序 +``` +./output/release/bin/mqtt_sample +INF|2019-09-12 21:28:20|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: S3EUVBRJLB, Device_Name: test_device +DBG|2019-09-12 21:28:20|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure... +DBG|2019-09-12 21:28:20|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake... +DBG|2019-09-12 21:28:20|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-12 21:28:20|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-12 21:28:20|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: p8t0W success +INF|2019-09-12 21:28:20|mqtt_sample.c|main(303): Cloud Device Construct Success +DBG|2019-09-12 21:28:20|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$sys/operation/result/S3EUVBRJLB/test_device|packet_id=1932 +INF|2019-09-12 21:28:20|mqtt_sample.c|_mqtt_event_handler(71): subscribe success, packet-id=1932 +DBG|2019-09-12 21:28:20|system_mqtt.c|_system_mqtt_sub_event_handler(80): mqtt sys topic subscribe success +DBG|2019-09-12 21:28:20|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$sys/operation/S3EUVBRJLB/test_device|payload={"type": "get", "resource": ["time"]} +DBG|2019-09-12 21:28:20|system_mqtt.c|_system_mqtt_message_callback(63): Recv Msg Topic:$sys/operation/result/S3EUVBRJLB/test_device, payload:{"type":"get","time":1568294900} +INF|2019-09-12 21:28:21|mqtt_sample.c|main(316): system time is 1568294900 +DBG|2019-09-12 21:28:21|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=S3EUVBRJLB/test_device/data|packet_id=1933 +INF|2019-09-12 21:28:21|mqtt_sample.c|_mqtt_event_handler(71): subscribe success, packet-id=1933 +DBG|2019-09-12 21:28:21|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=1934|topicName=S3EUVBRJLB/test_device/data|payload={"action": "publish_test", "count": "0"} +INF|2019-09-12 21:28:21|mqtt_sample.c|_mqtt_event_handler(98): publish success, packet-id=1934 +INF|2019-09-12 21:28:21|mqtt_sample.c|on_message_callback(195): Receive Message With topicName:S3EUVBRJLB/test_device/data, payload:{"action": "publish_test", "count": "0"} +INF|2019-09-12 21:28:22|mqtt_client_connect.c|qcloud_iot_mqtt_disconnect(437): mqtt disconnect! +INF|2019-09-12 21:28:22|system_mqtt.c|_system_mqtt_sub_event_handler(98): mqtt client has been destroyed +INF|2019-09-12 21:28:22|mqtt_client.c|IOT_MQTT_Destroy(186): mqtt release! +``` + +#### 4. 观察消息发送 +如下日志信息显示示例程序通过 MQTT 的 Publish 类型消息, 上报数据到 /{productID}/{deviceName}/data, 服务器已经收到并成功完成了该消息的处理 +``` +INF|2019-09-12 21:28:21|mqtt_sample.c|_mqtt_event_handler(98): publish success, packet-id=1934 +``` + +#### 5. 观察消息接收 +如下日志信息显示该消息因为是到达已被订阅的 Topic, 所以又被服务器原样推送到示例程序, 并进入相应的回调函数 +``` +INF|2019-09-12 21:28:21|mqtt_sample.c|on_message_callback(195): Receive Message With topicName:S3EUVBRJLB/test_device/data, payload:{"action": "publish_test", "count": "0"} +``` + +#### 6. 观察控制台日志 +可以登录物联网通信控制台, 点击左边导航栏中的**云日志**, 查看刚才上报的消息 +![](https://main.qcloudimg.com/raw/f589691c7e007b59a5426ede6dc17ddb.png) + +#### 7. 观察 NTP 时间日志 +如下日志信息显示 NTP 对时,设备 publish 获取 NTP 时间的报文,云平台记录接收到设备获取 NTP 时间报文的时间戳 ntptime1,记录给设备回复时的时间戳 ntptime2,将 ntptime1 和 ntptime2 回复给设备,设备接收到云平台的回复报文,通过算法计算出设备上真实的时间,并调用系统时间设置函数设置时间,通过例子程序日志可以看出时间被正确设置。 +windows / linux 平台已经适配时间设置,其他平台需要适配系统时间设置,执行例程时 windows 需要以管理员身份运行程序,linux 需要以超级用户身份运行程序。 +``` +sudo ./output/release/bin/mqtt_sample +DBG|2020-10-22 10:48:26|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$sys/ +operation/S3EUVBRJLB/test_device|payload={"type": "get", "resource": ["time"]} +DBG|2020-10-22 10:48:27|system_mqtt.c|_system_mqtt_message_callback(47): Recv Msg Topic:$sys/operation/result/ +S3EUVBRJLB/test_device, payload:{"type":"get","time":1603334906,"ntptime1":1603334906594,"ntptime2":1603334906594} +INF|2020-10-22 10:48:26|system_mqtt.c|IOT_Sync_NTPTime(294): set systime ms success, timestamp 1603334906644 ms +INF|2020-10-22 10:48:26|mqtt_sample.c|main(325): sync ntp time success! + +``` +在 `HAL_Timer_freertos.c HAL_Timer_rtthread.c HAL_Timer_nonos.c` 文件中提供了 `timestamp_to_date` 函数将时间戳转换为年、月、日、时、分、秒、毫秒方便嵌入式设备设置 RTC 时钟。 +`HAL_Timer_set_systime_sec` 设置系统时间函数在 32bit 平台使用; `HAL_Timer_set_systime_ms` 设置系统时间函数在 64bit 平台使用。 + diff --git "a/docs/IoT_Hub/ota_mqtt_subdev_sample\347\275\221\345\205\263\345\255\220\350\256\276\345\244\207\345\215\207\347\272\247.md" "b/docs/IoT_Hub/ota_mqtt_subdev_sample\347\275\221\345\205\263\345\255\220\350\256\276\345\244\207\345\215\207\347\272\247.md" new file mode 100755 index 00000000..2c809351 --- /dev/null +++ "b/docs/IoT_Hub/ota_mqtt_subdev_sample\347\275\221\345\205\263\345\255\220\350\256\276\345\244\207\345\215\207\347\272\247.md" @@ -0,0 +1,267 @@ +# 网关 OTA 子设备固件升级 + +关于物联平台 OTA 固件升级功能及流程介绍,请参考官网文档[设备固件升级](https://cloud.tencent.com/document/product/634/14674) + +## 一. 子设备升级流程介绍 + +由于子设备无法直接和云端建立连接,为满足子设备固件升级的需求,网关上使用设备 OTA 升级方式对子设备进行固件升级,支持网关子设备单台升级和批量升级,流程如下图所示: +![](https://main.qcloudimg.com/raw/531945fe455b518f1f9788ae9e0006b0.png) + +## 二. 上传固件 + +进行固件升级,首先要上传固件到物联网后台,可以通过控制台进行上传,如下图示: +![](https://main.qcloudimg.com/raw/2ccbc69f812c91884941060b17db86e8.png) + +## 三. 编译运行示例程序(以**MQTT密钥认证设备**为例) +#### 1. 编译 SDK +修改CMakeLists.txt确保以下选项存在 +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_OTA_COMM_ENABLED ON) +set(FEATURE_OTA_SIGNAL_CHANNEL "MQTT") +set(FEATURE_GATEWAY_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出ota_mqtt_sample位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +##### 1. 填写网关设备信息 +将网关设备信息填写到配置文件device_info.json中 +``` +{ + "auth_mode":"KEY", + + "productId":"JR1WOKB7Q7", + "productSecret":"YOUR_PRODUCT_SECRET", + "deviceName":"gw_deng1", + + "key_deviceinfo":{ + "deviceSecret":"1RRdhkwmZ45wYXjuPfygeA==" + } +} +``` +##### 2. 填写子设备信息 +例子程序中的子设备信息被配置 `ota_mqtt_subdev_sample.c` 在如下代码中,实际环境中子设备的信息一般由子设备上报给网关。 +``` +static DeviceInfo sg_subdev_info[] = { + {.product_id = "E69UADXUYY", .device_name = "light1"}, + {.product_id = "E69UADXUYY", .device_name = "light2"}, + {.product_id = "E69UADXUYY", .device_name = "light3"}, + {.product_id = "YI7XCD5DRH", .device_name = "airConditioner1"}, +}; +gw->sub_dev_info = sg_subdev_info; +gw->sub_dev_num = sizeof(sg_subdev_info) / sizeof(DeviceInfo); +``` + +#### 3. 运行示例 +执行子设备 OTA MQTT 例程 ota_mqtt_subdev_sample: +``` +./output/release/bin/ota_mqtt_subdev_sample +INF|2020-10-18 19:23:24|qcloud_iot_device.c|iot_device_info_set(50): SDK_Ver: 3.2.2, Product_ID: JR1WOKB7Q7, Device_Name: gw_deng1 +DBG|2020-10-18 19:23:24|HAL_TLS_mbedtls.c|HAL_TLS_Connect(200): Setting up the SSL/TLS structure... +DBG|2020-10-18 19:23:24|HAL_TLS_mbedtls.c|HAL_TLS_Connect(242): Performing the SSL/TLS handshake... +DBG|2020-10-18 19:23:24|HAL_TLS_mbedtls.c|HAL_TLS_Connect(243): Connecting to /JR1WOKB7Q7.iotcloud.tencentdevices.com/8883... +INF|2020-10-18 19:23:25|HAL_TLS_mbedtls.c|HAL_TLS_Connect(265): connected with /JR1WOKB7Q7.iotcloud.tencentdevices.com/8883... +INF|2020-10-18 19:23:25|mqtt_client.c|IOT_MQTT_Construct(118): mqtt connect with id: 3awT3 success +DBG|2020-10-18 19:23:25|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$gateway/operation/result/JR1WOKB7Q7/gw_deng1|packet_id=61021 +DBG|2020-10-18 19:23:25|gateway_api.c|_gateway_event_handler(34): gateway sub|unsub(3) success, packet-id=61021 +INF|2020-10-18 19:23:25|mqtt_client.c|_mqtt_yield_thread(258): MQTT client JR1WOKB7Q7gw_deng1 start loop +DBG|2020-10-18 19:23:26|gateway_api.c|IOT_Gateway_Subdev_Online(131): there is no session, create a new session +DBG|2020-10-18 19:23:26|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$gateway/operation/JR1WOKB7Q7/gw_deng1|payload={"type":"online","payload":{"devices":[{"product_id":"E69UADXUYY","device_name":"light1"}]}} +DBG|2020-10-18 19:23:27|gateway_common.c|_gateway_message_handler(163): msg payload: {"type":"online","payload":{"devices":[{"product_id":"E69UADXUYY","device_name":"light1","result":0}]}} +INF|2020-10-18 19:23:27|gateway_common.c|_gateway_message_handler(222): client_id(E69UADXUYY/light1), online result 0 +DBG|2020-10-18 19:23:27|ota_mqtt_subdev_sample.c|main(796): subDev Pid:E69UADXUYY devName:light1 online success. +DBG|2020-10-18 19:23:27|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$ota/update/E69UADXUYY/light1|packet_id=61022 +DBG|2020-10-18 19:23:27|gateway_api.c|_gateway_event_handler(34): gateway sub|unsub(3) success, packet-id=61022 +INF|2020-10-18 19:23:27|ota_mqtt_subdev_sample.c|_event_handler(555): subscribe success, packet-id=61022 +DBG|2020-10-18 19:23:27|ota_mqtt.c|_otamqtt_event_callback(119): OTA topic subscribe success +DBG|2020-10-18 19:23:27|ota_mqtt_subdev_sample.c|main(805): subDev Pid:E69UADXUYY devName:light1 initialize OTA Handle success. +INF|2020-10-18 19:23:27|ota_mqtt_subdev_sample.c|_get_subdev_fw_running_version(406): E69UADXUYY-light1 FW running version: 0.1 +INF|2020-10-18 19:23:27|ota_client.c|IOT_OTA_ResetStatus(131): reset OTA state! +DBG|2020-10-18 19:23:27|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61023|topicName=$ota/report/E69UADXUYY/light1|payload={"type": "report_version", "report":{"version":"0.1"}} +DBG|2020-10-18 19:23:27|gateway_api.c|IOT_Gateway_Subdev_Online(131): there is no session, create a new session +DBG|2020-10-18 19:23:27|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$gateway/operation/JR1WOKB7Q7/gw_deng1|payload={"type":"online","payload":{"devices":[{"product_id":"E69UADXUYY","device_name":"light2"}]}} +INF|2020-10-18 19:23:27|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61023 +DBG|2020-10-18 19:23:27|ota_mqtt.c|_otamqtt_upgrage_cb(105): topic=$ota/update/E69UADXUYY/light1 +INF|2020-10-18 19:23:27|ota_mqtt.c|_otamqtt_upgrage_cb(106): len=84, topic_msg={"result_code":0,"result_msg":"success","type":"report_version_rsp","version":"0.1"} +INF|2020-10-18 19:23:27|ota_client.c|_ota_callback(98): Report version success! +DBG|2020-10-18 19:23:28|gateway_common.c|_gateway_message_handler(163): msg payload: {"type":"online","payload":{"devices":[{"product_id":"E69UADXUYY","device_name":"light2","result":0}]}} +INF|2020-10-18 19:23:28|gateway_common.c|_gateway_message_handler(222): client_id(E69UADXUYY/light2), online result 0 +DBG|2020-10-18 19:23:28|ota_mqtt_subdev_sample.c|main(796): subDev Pid:E69UADXUYY devName:light2 online success. +DBG|2020-10-18 19:23:28|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$ota/update/E69UADXUYY/light2|packet_id=61024 +DBG|2020-10-18 19:23:28|gateway_api.c|_gateway_event_handler(34): gateway sub|unsub(3) success, packet-id=61024 +INF|2020-10-18 19:23:28|ota_mqtt_subdev_sample.c|_event_handler(555): subscribe success, packet-id=61024 +DBG|2020-10-18 19:23:28|ota_mqtt.c|_otamqtt_event_callback(119): OTA topic subscribe success +DBG|2020-10-18 19:23:28|ota_mqtt_subdev_sample.c|main(805): subDev Pid:E69UADXUYY devName:light2 initialize OTA Handle success. +INF|2020-10-18 19:23:28|ota_mqtt_subdev_sample.c|_get_subdev_fw_running_version(406): E69UADXUYY-light2 FW running version: 0.1 +INF|2020-10-18 19:23:28|ota_client.c|IOT_OTA_ResetStatus(131): reset OTA state! +DBG|2020-10-18 19:23:28|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61025|topicName=$ota/report/E69UADXUYY/light2|payload={"type": "report_version", "report":{"version":"0.1"}} +DBG|2020-10-18 19:23:28|gateway_api.c|IOT_Gateway_Subdev_Online(131): there is no session, create a new session +DBG|2020-10-18 19:23:28|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$gateway/operation/JR1WOKB7Q7/gw_deng1|payload={"type":"online","payload":{"devices":[{"product_id":"E69UADXUYY","device_name":"light3"}]}} +INF|2020-10-18 19:23:28|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61025 +DBG|2020-10-18 19:23:28|ota_mqtt.c|_otamqtt_upgrage_cb(105): topic=$ota/update/E69UADXUYY/light2 +INF|2020-10-18 19:23:28|ota_mqtt.c|_otamqtt_upgrage_cb(106): len=84, topic_msg={"result_code":0,"result_msg":"success","type":"report_version_rsp","version":"0.1"} +INF|2020-10-18 19:23:28|ota_client.c|_ota_callback(98): Report version success! +DBG|2020-10-18 19:23:29|gateway_common.c|_gateway_message_handler(163): msg payload: {"type":"online","payload":{"devices":[{"product_id":"E69UADXUYY","device_name":"light3","result":0}]}} +INF|2020-10-18 19:23:29|gateway_common.c|_gateway_message_handler(222): client_id(E69UADXUYY/light3), online result 0 +DBG|2020-10-18 19:23:29|ota_mqtt_subdev_sample.c|main(796): subDev Pid:E69UADXUYY devName:light3 online success. +DBG|2020-10-18 19:23:29|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$ota/update/E69UADXUYY/light3|packet_id=61026 +DBG|2020-10-18 19:23:29|gateway_api.c|_gateway_event_handler(34): gateway sub|unsub(3) success, packet-id=61026 +INF|2020-10-18 19:23:29|ota_mqtt_subdev_sample.c|_event_handler(555): subscribe success, packet-id=61026 +DBG|2020-10-18 19:23:29|ota_mqtt.c|_otamqtt_event_callback(119): OTA topic subscribe success +DBG|2020-10-18 19:23:29|ota_mqtt_subdev_sample.c|main(805): subDev Pid:E69UADXUYY devName:light3 initialize OTA Handle success. +INF|2020-10-18 19:23:29|ota_mqtt_subdev_sample.c|_get_subdev_fw_running_version(406): E69UADXUYY-light3 FW running version: 0.1 +INF|2020-10-18 19:23:29|ota_client.c|IOT_OTA_ResetStatus(131): reset OTA state! +DBG|2020-10-18 19:23:29|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61027|topicName=$ota/report/E69UADXUYY/light3|payload={"type": "report_version", "report":{"version":"0.1"}} +DBG|2020-10-18 19:23:29|gateway_api.c|IOT_Gateway_Subdev_Online(131): there is no session, create a new session +DBG|2020-10-18 19:23:29|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$gateway/operation/JR1WOKB7Q7/gw_deng1|payload={"type":"online","payload":{"devices":[{"product_id":"YI7XCD5DRH","device_name":"airConditioner1"}]}} +INF|2020-10-18 19:23:29|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61027 +DBG|2020-10-18 19:23:29|ota_mqtt.c|_otamqtt_upgrage_cb(105): topic=$ota/update/E69UADXUYY/light3 +INF|2020-10-18 19:23:29|ota_mqtt.c|_otamqtt_upgrage_cb(106): len=84, topic_msg={"result_code":0,"result_msg":"success","type":"report_version_rsp","version":"0.1"} +INF|2020-10-18 19:23:29|ota_client.c|_ota_callback(98): Report version success! +DBG|2020-10-18 19:23:29|gateway_common.c|_gateway_message_handler(163): msg payload: {"type":"online","payload":{"devices":[{"product_id":"YI7XCD5DRH","device_name":"airConditioner1","result":0}]}} +INF|2020-10-18 19:23:29|gateway_common.c|_gateway_message_handler(222): client_id(YI7XCD5DRH/airConditioner1), online result 0 +DBG|2020-10-18 19:23:29|ota_mqtt_subdev_sample.c|main(796): subDev Pid:YI7XCD5DRH devName:airConditioner1 online success. +DBG|2020-10-18 19:23:29|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$ota/update/YI7XCD5DRH/airConditioner1|packet_id=61028 +DBG|2020-10-18 19:23:29|gateway_api.c|_gateway_event_handler(34): gateway sub|unsub(3) success, packet-id=61028 +INF|2020-10-18 19:23:29|ota_mqtt_subdev_sample.c|_event_handler(555): subscribe success, packet-id=61028 +DBG|2020-10-18 19:23:29|ota_mqtt.c|_otamqtt_event_callback(119): OTA topic subscribe success +DBG|2020-10-18 19:23:30|ota_mqtt_subdev_sample.c|main(805): subDev Pid:YI7XCD5DRH devName:airConditioner1 initialize OTA Handle success. +INF|2020-10-18 19:23:30|ota_mqtt_subdev_sample.c|_get_subdev_fw_running_version(406): YI7XCD5DRH-airConditioner1 FW running version: 0.1 +INF|2020-10-18 19:23:30|ota_client.c|IOT_OTA_ResetStatus(131): reset OTA state! +DBG|2020-10-18 19:23:30|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61029|topicName=$ota/report/YI7XCD5DRH/airConditioner1|payload={"type": "report_version", "report":{"version":"0.1"}} +INF|2020-10-18 19:23:30|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61029 +INF|2020-10-18 19:23:30|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +DBG|2020-10-18 19:23:30|ota_mqtt.c|_otamqtt_upgrage_cb(105): topic=$ota/update/YI7XCD5DRH/airConditioner1 +INF|2020-10-18 19:23:30|ota_mqtt.c|_otamqtt_upgrage_cb(106): len=84, topic_msg={"result_code":0,"result_msg":"success","type":"report_version_rsp","version":"0.1"} +INF|2020-10-18 19:23:30|ota_client.c|_ota_callback(98): Report version success! +INF|2020-10-18 19:23:32|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +INF|2020-10-18 19:23:34|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +INF|2020-10-18 19:23:36|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +``` +从例子程序的日志可以观察到,网关代理子设备上线,订阅 OTA Topic,并将子设备当前的固件版本号上报给云平台,然后网关进入等待云平台下发固件升级命令的状态。 + +#### 4. 执行固件升级命令 + +云平台在接收到设备上报的固件版本号之后,选择要升级的新固件版本并下发升级命令;可以通过控制台操作固件升级,控制台有三种升级方式供选择,分别是: + +1. 按固件版本号升级所有设备。选择的版本号是待升级的版本号,可选多个待升级版本号。 +![](https://main.qcloudimg.com/raw/dcc27c9875ee4f94b9016e6ee094895e.png) +2. 按固件版本号批量升级指定设备。选择的版本号是待升级的版本号,可选多个待升级版本号;选择的设备是本次待升级的设备,可选多个待升级设备。 +![](https://main.qcloudimg.com/raw/aea220c450a1d32fadf3f3b693840f4c.png) +3. 按设备名称批量升级模板文件中的设备。不关心待升级的版本号,直接将模板文件中的设备升级为选择的固件。 +![](https://main.qcloudimg.com/raw/86c1c899ce0723162cd851b18ffdc973.png) + +***选择 1、2 方式如果待升级设备当前运行的固件没有上传到控制台,那么在选择待升级版本号时就不能选择待升级设备的版本号,此时可以通过在控制台上传待升级设备当前运行的固件版本或者选择方式 3 升级。*** + + +控制台执行固件升级命令后,再观察例子程序的日志,可以看到网关通过 MQTT OTA Topic 接收到子设备 light1 light2 light3 的升级命令,通过 HTTPS 下载子设备固件并保存,下载成功后开始升级子设备固件,最后上报子设备升级成功的结果给云平台。 +``` +INF|2020-10-18 19:23:45|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +INF|2020-10-18 19:23:47|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +DBG|2020-10-18 19:23:47|ota_mqtt.c|_otamqtt_upgrage_cb(105): topic=$ota/update/E69UADXUYY/light1 +INF|2020-10-18 19:23:47|ota_mqtt.c|_otamqtt_upgrage_cb(106): len=457, topic_msg={"file_size":29972,"md5sum":"20a4d2b1f8492a22fa3e472a758bf9ec","type":"update_firmware","url":"https://ota-1255858890.cos.ap-guangzhou.myqcloud.com/100003908905_E69UADXUYY_V100R0001?","version":"V100R0001"} +DBG|2020-10-18 19:23:48|ota_mqtt.c|_otamqtt_upgrage_cb(105): topic=$ota/update/E69UADXUYY/light2 +INF|2020-10-18 19:23:48|ota_mqtt.c|_otamqtt_upgrage_cb(106): len=457, topic_msg={"file_size":29972,"md5sum":"20a4d2b1f8492a22fa3e472a758bf9ec","type":"update_firmware","url":"https://ota-1255858890.cos.ap-guangzhou.myqcloud.com/100003908905_E69UADXUYY_V100R0001?","version":"V100R0001"} +DBG|2020-10-18 19:23:48|ota_mqtt.c|_otamqtt_upgrage_cb(105): topic=$ota/update/E69UADXUYY/light3 +INF|2020-10-18 19:23:48|ota_mqtt.c|_otamqtt_upgrage_cb(106): len=457, topic_msg={"file_size":29972,"md5sum":"20a4d2b1f8492a22fa3e472a758bf9ec","type":"update_firmware","url":"https://ota-1255858890.cos.ap-guangzhou.myqcloud.com/100003908905_E69UADXUYY_V100R0001?","version":"V100R0001"} +ERR|2020-10-18 19:23:50|ota_mqtt_subdev_sample.c|_get_local_fw_info(176): open file ./FW_E69UADXUYYlight3.json failed +DBG|2020-10-18 19:23:50|ota_client.c|IOT_OTA_StartDownload(360): to download FW from offset: 0, size: 29972 +DBG|2020-10-18 19:23:50|ota_fetch.c|ofc_Init(79): head_content:Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 +Accept-Encoding: gzip, deflate +Range: bytes=0-29972 + +DBG|2020-10-18 19:23:50|HAL_TLS_mbedtls.c|_mbedtls_client_init(132): psk/pskid is empty!|psk=(null)|psd_id=(null) +DBG|2020-10-18 19:23:50|HAL_TLS_mbedtls.c|HAL_TLS_Connect(200): Setting up the SSL/TLS structure... +DBG|2020-10-18 19:23:50|HAL_TLS_mbedtls.c|HAL_TLS_Connect(242): Performing the SSL/TLS handshake... +DBG|2020-10-18 19:23:50|HAL_TLS_mbedtls.c|HAL_TLS_Connect(243): Connecting to /ota-1255858890.cos.ap-guangzhou.myqcloud.com/443... +INF|2020-10-18 19:23:50|HAL_TLS_mbedtls.c|HAL_TLS_Connect(265): connected with /ota-1255858890.cos.ap-guangzhou.myqcloud.com/443... +DBG|2020-10-18 19:23:50|utils_httpc.c|qcloud_http_client_connect(742): http client connect success +DBG|2020-10-18 19:23:50|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/E69UADXUYY/light3|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"0", "result_code":"0", "result_msg":""}, "version": "V100R0001"}} +DBG|2020-10-18 19:23:51|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/E69UADXUYY/light3|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"100", "result_code":"0", "result_msg":""}, "version": "V100R0001"}} +INF|2020-10-18 19:23:51|ota_client.c|IOT_OTA_Ioctl(656): FW MD5 check: origin=20a4d2b1f8492a22fa3e472a758bf9ec, now=20a4d2b1f8492a22fa3e472a758bf9ec +INF|2020-10-18 19:23:51|ota_mqtt_subdev_sample.c|process_ota(494): The firmware is valid +DBG|2020-10-18 19:23:51|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61030|topicName=$ota/report/E69UADXUYY/light3|payload={"type": "report_progress", "report":{"progress":{"state":"burning", "result_code":"0", "result_msg":""}, "version":"V100R0001"}} +INF|2020-10-18 19:23:51|ota_mqtt_subdev_sample.c|_subdev_process_upgrade(414): E69UADXUYY-light3 download success, fw name:./FW_E69UADXUYYlight3_V100R0001.bin, fw size:29972, fw version:V100R0001, now to upgrade subdevice ... +INF|2020-10-18 19:23:51|ota_mqtt_subdev_sample.c|process_ota(517): E69UADXUYY-light3 upgrade success +DBG|2020-10-18 19:23:51|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61031|topicName=$ota/report/E69UADXUYY/light3|payload={"type": "report_progress", "report":{"progress":{"state":"done", "result_code":"0", "result_msg":""}, "version":"V100R0001"}} +INF|2020-10-18 19:23:51|ota_client.c|IOT_OTA_ResetStatus(131): reset OTA state! +INF|2020-10-18 19:23:51|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61030 +INF|2020-10-18 19:23:51|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61031 +ERR|2020-10-18 19:23:52|ota_mqtt_subdev_sample.c|main(841): process ota success subdevice E69UADXUYY-light3 +ERR|2020-10-18 19:23:52|ota_mqtt_subdev_sample.c|_get_local_fw_info(176): open file ./FW_E69UADXUYYlight2.json failed +DBG|2020-10-18 19:23:52|ota_client.c|IOT_OTA_StartDownload(360): to download FW from offset: 0, size: 29972 +DBG|2020-10-18 19:23:52|ota_fetch.c|ofc_Init(79): head_content:Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 +Accept-Encoding: gzip, deflate +Range: bytes=0-29972 + +DBG|2020-10-18 19:23:52|HAL_TLS_mbedtls.c|_mbedtls_client_init(132): psk/pskid is empty!|psk=(null)|psd_id=(null) +DBG|2020-10-18 19:23:52|HAL_TLS_mbedtls.c|HAL_TLS_Connect(200): Setting up the SSL/TLS structure... +DBG|2020-10-18 19:23:52|HAL_TLS_mbedtls.c|HAL_TLS_Connect(242): Performing the SSL/TLS handshake... +DBG|2020-10-18 19:23:52|HAL_TLS_mbedtls.c|HAL_TLS_Connect(243): Connecting to /ota-1255858890.cos.ap-guangzhou.myqcloud.com/443... +INF|2020-10-18 19:23:52|HAL_TLS_mbedtls.c|HAL_TLS_Connect(265): connected with /ota-1255858890.cos.ap-guangzhou.myqcloud.com/443... +DBG|2020-10-18 19:23:52|utils_httpc.c|qcloud_http_client_connect(742): http client connect success +DBG|2020-10-18 19:23:52|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/E69UADXUYY/light2|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"0", "result_code":"0", "result_msg":""}, "version": "V100R0001"}} +DBG|2020-10-18 19:23:53|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/E69UADXUYY/light2|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"100", "result_code":"0", "result_msg":""}, "version": "V100R0001"}} +INF|2020-10-18 19:23:53|ota_client.c|IOT_OTA_Ioctl(656): FW MD5 check: origin=20a4d2b1f8492a22fa3e472a758bf9ec, now=20a4d2b1f8492a22fa3e472a758bf9ec +INF|2020-10-18 19:23:53|ota_mqtt_subdev_sample.c|process_ota(494): The firmware is valid +DBG|2020-10-18 19:23:53|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61032|topicName=$ota/report/E69UADXUYY/light2|payload={"type": "report_progress", "report":{"progress":{"state":"burning", "result_code":"0", "result_msg":""}, "version":"V100R0001"}} +INF|2020-10-18 19:23:53|ota_mqtt_subdev_sample.c|_subdev_process_upgrade(414): E69UADXUYY-light2 download success, fw name:./FW_E69UADXUYYlight2_V100R0001.bin, fw size:29972, fw version:V100R0001, now to upgrade subdevice ... +INF|2020-10-18 19:23:53|ota_mqtt_subdev_sample.c|process_ota(517): E69UADXUYY-light2 upgrade success +DBG|2020-10-18 19:23:53|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61033|topicName=$ota/report/E69UADXUYY/light2|payload={"type": "report_progress", "report":{"progress":{"state":"done", "result_code":"0", "result_msg":""}, "version":"V100R0001"}} +INF|2020-10-18 19:23:53|ota_client.c|IOT_OTA_ResetStatus(131): reset OTA state! +INF|2020-10-18 19:23:53|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61032 +INF|2020-10-18 19:23:53|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61033 +ERR|2020-10-18 19:23:54|ota_mqtt_subdev_sample.c|main(841): process ota success subdevice E69UADXUYY-light2 +ERR|2020-10-18 19:23:54|ota_mqtt_subdev_sample.c|_get_local_fw_info(176): open file ./FW_E69UADXUYYlight1.json failed +DBG|2020-10-18 19:23:54|ota_client.c|IOT_OTA_StartDownload(360): to download FW from offset: 0, size: 29972 +DBG|2020-10-18 19:23:54|ota_fetch.c|ofc_Init(79): head_content:Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 +Accept-Encoding: gzip, deflate +Range: bytes=0-29972 + +DBG|2020-10-18 19:23:54|HAL_TLS_mbedtls.c|_mbedtls_client_init(132): psk/pskid is empty!|psk=(null)|psd_id=(null) +DBG|2020-10-18 19:23:54|HAL_TLS_mbedtls.c|HAL_TLS_Connect(200): Setting up the SSL/TLS structure... +DBG|2020-10-18 19:23:54|HAL_TLS_mbedtls.c|HAL_TLS_Connect(242): Performing the SSL/TLS handshake... +DBG|2020-10-18 19:23:54|HAL_TLS_mbedtls.c|HAL_TLS_Connect(243): Connecting to /ota-1255858890.cos.ap-guangzhou.myqcloud.com/443... +INF|2020-10-18 19:23:54|HAL_TLS_mbedtls.c|HAL_TLS_Connect(265): connected with /ota-1255858890.cos.ap-guangzhou.myqcloud.com/443... +DBG|2020-10-18 19:23:54|utils_httpc.c|qcloud_http_client_connect(742): http client connect success +DBG|2020-10-18 19:23:54|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/E69UADXUYY/light1|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"0", "result_code":"0", "result_msg":""}, "version": "V100R0001"}} +DBG|2020-10-18 19:23:55|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/E69UADXUYY/light1|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"100", "result_code":"0", "result_msg":""}, "version": "V100R0001"}} +INF|2020-10-18 19:23:55|ota_client.c|IOT_OTA_Ioctl(656): FW MD5 check: origin=20a4d2b1f8492a22fa3e472a758bf9ec, now=20a4d2b1f8492a22fa3e472a758bf9ec +INF|2020-10-18 19:23:55|ota_mqtt_subdev_sample.c|process_ota(494): The firmware is valid +DBG|2020-10-18 19:23:55|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61034|topicName=$ota/report/E69UADXUYY/light1|payload={"type": "report_progress", "report":{"progress":{"state":"burning", "result_code":"0", "result_msg":""}, "version":"V100R0001"}} +INF|2020-10-18 19:23:55|ota_mqtt_subdev_sample.c|_subdev_process_upgrade(414): E69UADXUYY-light1 download success, fw name:./FW_E69UADXUYYlight1_V100R0001.bin, fw size:29972, fw version:V100R0001, now to upgrade subdevice ... +INF|2020-10-18 19:23:55|ota_mqtt_subdev_sample.c|process_ota(517): E69UADXUYY-light1 upgrade success +DBG|2020-10-18 19:23:55|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=61035|topicName=$ota/report/E69UADXUYY/light1|payload={"type": "report_progress", "report":{"progress":{"state":"done", "result_code":"0", "result_msg":""}, "version":"V100R0001"}} +INF|2020-10-18 19:23:55|ota_client.c|IOT_OTA_ResetStatus(131): reset OTA state! +INF|2020-10-18 19:23:55|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61034 +INF|2020-10-18 19:23:55|ota_mqtt_subdev_sample.c|_event_handler(582): publish success, packet-id=61035 +ERR|2020-10-18 19:23:56|ota_mqtt_subdev_sample.c|main(841): process ota success subdevice E69UADXUYY-light1 +INF|2020-10-18 19:23:56|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +INF|2020-10-18 19:23:58|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +INF|2020-10-18 19:24:01|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +INF|2020-10-18 19:24:03|ota_mqtt_subdev_sample.c|main(844): wait for ota upgrade command... +``` + +#### 5. 云平台查看固件升级结果 + +在云平台的控制台可以看到固件升级结果,如下图示: +![](https://main.qcloudimg.com/raw/fbdc347ed604583424c46a3e03054a7d.png) + +## 四. 例子程序代码使用说明 + +1. 固件升级,支持通过 HTTP 或者 HTTPS 来下载固件,可以通过编译选项 FEATURE_OTA_USE_HTTPS 来选择 +2. SDK 的 HTTP 或者 HTTPS 下载固件,支持断点续传功能,即当固件下载过程因为网络或者其他原因中断了,则再次下载的时候,可以从上一次中断的位置继续下载。 +3. 在 ota_mqtt_subdev_sample.c 中, process_ota 函数为 OTA 的核心流程包括等待升级命令,发起 HTTP 或者 HTTPS 下载固件并保存到网关上,校验固件文件 MD5,与子设备交互升级,上报子设备升级结果。网关上的固件保存,断点续传状态保存,与子设备交互升级的函数,跟具体平台与环境密切相关。示例中固件和断点续传状态的存储使用了文件操作,在支持标准文件操作的系统比如 Linux/Windows 上面可以直接使用,对于其他平台则需要进行适配;与子设备交互升级的函数需要根据具体环境进行适配。 + + + diff --git "a/docs/IoT_Hub/ota_sample_\345\233\272\344\273\266\345\215\207\347\272\247.md" "b/docs/IoT_Hub/ota_sample_\345\233\272\344\273\266\345\215\207\347\272\247.md" new file mode 100755 index 00000000..652db078 --- /dev/null +++ "b/docs/IoT_Hub/ota_sample_\345\233\272\344\273\266\345\215\207\347\272\247.md" @@ -0,0 +1,122 @@ +# OTA设备固件升级 + +关于物联平台 OTA 固件升级功能及流程介绍,请参考官网文档[设备固件升级](https://cloud.tencent.com/document/product/634/14674) + +## 一. 上传固件 + +进行固件升级,首先要上传固件到物联网后台,可以通过控制台进行上传,如下图示: +![](https://main.qcloudimg.com/raw/2ccbc69f812c91884941060b17db86e8.png) + +## 二. 编译运行示例程序(以**MQTT密钥认证设备**为例) +#### 1. 编译 SDK +修改CMakeLists.txt确保以下选项存在 +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_OTA_COMM_ENABLED ON) +set(FEATURE_OTA_SIGNAL_CHANNEL "MQTT") +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出ota_mqtt_sample位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +将设备信息填写到配置文件device_info.json中 +``` +{ + "auth_mode":"KEY", + "productId":"S3EUVBRJLB", + "deviceName":"test_device", + "key_deviceinfo":{ + "deviceSecret":"vX6PQqazsGsMyf5SMfs6OA6y" + } +} +``` + +#### 3. 运行示例 +执行OTA MQTT例程ota_mqtt_sample: +``` +./output/release/bin/ota_mqtt_sample +INF|2020-03-04 16:50:35|qcloud_iot_device.c|iot_device_info_set(50): SDK_Ver: 3.1.2, Product_ID: S3EUVBRJLB, Device_Name: test_device +DBG|2020-03-04 16:50:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(206): Setting up the SSL/TLS structure... +DBG|2020-03-04 16:50:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(248): Performing the SSL/TLS handshake... +DBG|2020-03-04 16:50:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(249): Connecting to /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2020-03-04 16:50:35|HAL_TLS_mbedtls.c|HAL_TLS_Connect(271): connected with /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2020-03-04 16:50:35|mqtt_client.c|IOT_MQTT_Construct(111): mqtt connect with id: BzaMF success +INF|2020-03-04 16:50:35|ota_mqtt_sample.c|main(516): Cloud Device Construct Success +DBG|2020-03-04 16:50:35|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(141): topicName=$ota/update/S3EUVBRJLB/test_device|packet_id=63333 +INF|2020-03-04 16:50:35|ota_mqtt_sample.c|_event_handler(77): subscribe success, packet-id=63333 +DBG|2020-03-04 16:50:35|ota_mqtt.c|_otamqtt_event_callback(117): OTA topic subscribe success +INF|2020-03-04 16:50:36|ota_mqtt_sample.c|_get_local_fw_running_version(363): FW running version: 1.0.0 +DBG|2020-03-04 16:50:36|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=63334|topicName=$ota/report/S3EUVBRJLB/test_device|payload={"type": "report_version", "report":{"version":"1.0.0"}} +INF|2020-03-04 16:50:36|ota_mqtt_sample.c|_event_handler(89): publish success, packet-id=63334 +DBG|2020-03-04 16:50:36|ota_mqtt.c|_otamqtt_upgrage_cb(103): topic=$ota/update/S3EUVBRJLB/test_device +INF|2020-03-04 16:50:36|ota_mqtt.c|_otamqtt_upgrage_cb(104): len=86, topic_msg={"result_code":0,"result_msg":"success","type":"report_version_rsp","version":"1.0.0"} +INF|2020-03-04 16:50:36|ota_client.c|_ota_callback(102): Report version success! +INF|2020-03-04 16:50:36|ota_mqtt_sample.c|process_ota(389): wait for ota upgrade command... +INF|2020-03-04 16:50:37|ota_mqtt_sample.c|process_ota(389): wait for ota upgrade command... +``` +可以看到设备已经上报了当前的固件版本,并在等待固件升级的命令下发 + +#### 4. 执行固件升级命令 + +在收到设备上报的固件版本之后,可以选择要升级的新固件版本并执行升级命令,可以通过控制台进行操作,控制台有三种升级方式供选择,分别是: + +1. 按固件版本号升级所有设备。选择的版本号是待升级的版本号,可选多个待升级版本号。 +![](https://main.qcloudimg.com/raw/dcc27c9875ee4f94b9016e6ee094895e.png) +2. 按固件版本号批量升级指定设备。选择的版本号是待升级的版本号,可选多个待升级版本号;选择的设备是本次待升级的设备,可选多个待升级设备。 +![](https://main.qcloudimg.com/raw/aea220c450a1d32fadf3f3b693840f4c.png) +3. 按设备名称批量升级模板文件中的设备。不关心待升级的版本号,直接将模板文件中的设备升级为选择的固件。 +![](https://main.qcloudimg.com/raw/86c1c899ce0723162cd851b18ffdc973.png) + +***选择 1、2 方式如果待升级设备当前运行的固件没有上传到控制台,那么在选择待升级版本号时就不能选择待升级设备的版本号,此时可以通过在控制台上传待升级设备当前运行的固件版本或者选择方式 3 升级。*** + + + +这个时候再观察sample的示例打印,可以看到设备端通过MQTT接收到升级命令,并且通过HTTPS去下载固件并保存到本地 +``` +INF|2020-03-04 16:50:38|ota_mqtt_sample.c|process_ota(389): wait for ota upgrade command... +DBG|2020-03-04 16:50:39|ota_mqtt.c|_otamqtt_upgrage_cb(103): topic=$ota/update/S3EUVBRJLB/test_device +INF|2020-03-04 16:50:39|ota_mqtt.c|_otamqtt_upgrage_cb(104): len=454, topic_msg={"file_size":175436,"md5sum":"ad4615b866c13afb8b293a679bfa5dc4","type":"update_firmware","url":"https://ota-1255858890.cos.ap-guangzhou.myqcloud.com/","version":"1.3.0"} + +INF|2020-03-04 16:50:39|ota_mqtt_sample.c|process_ota(389): wait for ota upgrade command... +ERR|2020-03-04 16:50:39|ota_mqtt_sample.c|_get_local_fw_info(251): open file ./FW_S3EUVBRJLBtest_device.json failed +DBG|2020-03-04 16:50:39|ota_client.c|IOT_OTA_StartDownload(347): to download FW from offset: 0, size: 175436 +DBG|2020-03-04 16:50:39|ota_fetch.c|ofc_Init(83): head_content:Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 +Accept-Encoding: gzip, deflate +Range: bytes=0-175436 + +DBG|2020-03-04 16:50:39|HAL_TLS_mbedtls.c|_mbedtls_client_init(134): psk/pskid is empty!|psk=(null)|psd_id=(null) +DBG|2020-03-04 16:50:39|HAL_TLS_mbedtls.c|HAL_TLS_Connect(206): Setting up the SSL/TLS structure... +DBG|2020-03-04 16:50:39|HAL_TLS_mbedtls.c|HAL_TLS_Connect(248): Performing the SSL/TLS handshake... +DBG|2020-03-04 16:50:39|HAL_TLS_mbedtls.c|HAL_TLS_Connect(249): Connecting to /ota-1255858890.cos.ap-guangzhou.myqcloud.com/443... +INF|2020-03-04 16:50:40|HAL_TLS_mbedtls.c|HAL_TLS_Connect(271): connected with /ota-1255858890.cos.ap-guangzhou.myqcloud.com/443... +DBG|2020-03-04 16:50:40|utils_httpc.c|qcloud_http_client_connect(747): http client connect success +DBG|2020-03-04 16:50:40|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/S3EUVBRJLB/test_device|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"0", "result_code":"0", "result_msg":""}, "version": "1.3.0"}} +DBG|2020-03-04 16:50:41|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/S3EUVBRJLB/test_device|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"31", "result_code":"0", "result_msg":""}, "version": "1.3.0"}} +DBG|2020-03-04 16:50:42|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/S3EUVBRJLB/test_device|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"59", "result_code":"0", "result_msg":""}, "version": "1.3.0"}} +DBG|2020-03-04 16:50:43|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/S3EUVBRJLB/test_device|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"88", "result_code":"0", "result_msg":""}, "version": "1.3.0"}} +DBG|2020-03-04 16:50:43|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$ota/report/S3EUVBRJLB/test_device|payload={"type": "report_progress", "report": {"progress": {"state":"downloading", "percent":"100", "result_code":"0", "result_msg":""}, "version": "1.3.0"}} +INF|2020-03-04 16:50:43|ota_client.c|IOT_OTA_Ioctl(638): FW MD5 check: origin=ad4615b866c13afb8b293a679bfa5dc4, now=ad4615b866c13afb8b293a679bfa5dc4 +INF|2020-03-04 16:50:43|ota_mqtt_sample.c|process_ota(456): The firmware is valid +DBG|2020-03-04 16:50:43|mqtt_client_publish.c|qcloud_iot_mqtt_publish(334): publish topic seq=63335|topicName=$ota/report/S3EUVBRJLB/test_device|payload={"type": "report_progress", "report":{"progress":{"state":"done", "result_code":"0", "result_msg":""}, "version":"1.3.0"}} +INF|2020-03-04 16:50:44|ota_mqtt_sample.c|_event_handler(89): publish success, packet-id=63335 +INF|2020-03-04 16:50:44|mqtt_client_connect.c|qcloud_iot_mqtt_disconnect(450): mqtt disconnect! +INF|2020-03-04 16:50:44|ota_mqtt.c|_otamqtt_event_callback(135): mqtt client has been destroyed +INF|2020-03-04 16:50:44|mqtt_client.c|IOT_MQTT_Destroy(171): mqtt release! +``` + +## 三. 代码使用说明 + +1. 固件升级,支持通过HTTP或者HTTPS来下载固件,可以通过编译选项FEATURE_OTA_USE_HTTPS来选择 +2. SDK的固件升级,支持断点续传功能,即当固件下载过程因为网络或者其他原因中断了,则再次下载的时候,可以从上一次中断的位置继续下载。 +3. 在ota_mqtt_sample.c中,process_ota函数为OTA的核心流程,包括了版本上报,等待升级命令,发起下载并保存,校验文件MD5以及回复升级结果的过程,同时为断点续传功能实时保存下载状态。该函数在各个平台适配的时候可以保持不变。而跟固件保存,断点续传状态保存相关的功能函数,则跟平台密切相关,示例中使用了文件操作,在支持标准文件操作的系统比如Linux/Windows上面可以直接使用,对于其他平台则需要进行适配。 + + diff --git "a/docs/IoT_Hub/remote_config_mqtt_sample_\350\277\234\347\250\213\351\205\215\347\275\256.md" "b/docs/IoT_Hub/remote_config_mqtt_sample_\350\277\234\347\250\213\351\205\215\347\275\256.md" new file mode 100644 index 00000000..3b93e24c --- /dev/null +++ "b/docs/IoT_Hub/remote_config_mqtt_sample_\350\277\234\347\250\213\351\205\215\347\275\256.md" @@ -0,0 +1,143 @@ +# 远程配置 + +本文档介绍通过 MQTT 对产品设备进行远程配置的功能,并结合 SDK 的**remote_config_mqtt_sample**展示远程配置功能。 + +## 一. 控制台创建设备 + +#### 1. 背景介绍 + +设备运维阶段,需要对设备配置参数进行更新以满足现场使用环境的需求。 +如温湿度设备需要更改温湿度上下限的设置;modbus 网关设备需要更改串口参数及 modbus 参数信息;zigbee 网关需要更改 zigbee 配置参数信息等等。 +* 配置推送 topic 和配置请求响应 topic: `$config/update/${productID}/${deviceName}` +* 配置请求 topic: `$config/report/${productID}/${deviceName}` + +#### 2. 远程配置流程图 + +##### 2.1 云平台主动下发配置流程 + +![image.png](https://main.qcloudimg.com/raw/5000bef6371f1080bc44deba57e34565.png) + +##### 2.2 设备主动请求配置更新 + +![image.png](https://main.qcloudimg.com/raw/c0236c38e9e46b8e99424fa96f89c605.png) + +#### 3. 创建产品和设备 + +请参考[设备互通](https://cloud.tencent.com/document/product/634/11913) 创建 AirConditioner 空调产品和设备标题内容。 +创建 airConditioner1 空调设备。 + +## 二. 编译运行示例程序(以**密钥认证设备**为例) + +#### 1. 编译 SDK + +修改CMakeLists.txt确保以下选项存在 +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_REMOTE_CONFIG_MQTT_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出 `remote_config_mqtt_sample` 位于 `output/release/bin` 文件夹中 + +#### 2. 填写设备信息 + +将上面创建的 airConditioner1 设备的设备信息填写到JSON文件 aircond_device_info1.json 中: +``` +{ + "auth_mode":"KEY", + "productId":"YI7XCD5DRH", + "deviceName":"airConditioner1", + "key_deviceinfo":{ + "deviceSecret":"+PBSkYlvNffjLDTGLpVOQA==" + } +} +``` + +#### 3. 执行`remote_config_mqtt_sample`示例程序 + +可以看到设备 airConditioner1 订阅了远程配置消息。 + +``` +./output/release/bin/remote_config_mqtt_sample -l +INF|2020-08-26 19:31:03|qcloud_iot_device.c|iot_device_info_set(50): SDK_Ver: 3.2.1, Product_ID: YI7XCD5DRH, Device_Name: airConditioner1 +DBG|2020-08-26 19:31:03|HAL_TLS_mbedtls.c|HAL_TLS_Connect(200): Setting up the SSL/TLS structure... +DBG|2020-08-26 19:31:03|HAL_TLS_mbedtls.c|HAL_TLS_Connect(242): Performing the SSL/TLS handshake... +DBG|2020-08-26 19:31:03|HAL_TLS_mbedtls.c|HAL_TLS_Connect(243): Connecting to /YI7XCD5DRH.iotcloud.tencentdevices.com/8883... +INF|2020-08-26 19:31:03|HAL_TLS_mbedtls.c|HAL_TLS_Connect(265): connected with /YI7XCD5DRH.iotcloud.tencentdevices.com/8883... +INF|2020-08-26 19:31:03|mqtt_client.c|IOT_MQTT_Construct(118): mqtt connect with id: 9AEwi success +INF|2020-08-26 19:31:03|remote_config_mqtt_sample.c|main(300): Cloud Device Construct Success +DBG|2020-08-26 19:31:03|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$config/update/YI7XCD5DRH/airConditioner1|packet_id=13502 +INF|2020-08-26 19:31:03|remote_config_mqtt_sample.c|_mqtt_event_handler(128): subscribe success, packet-id=13502 +DBG|2020-08-26 19:31:03|remote_config_mqtt.c|_config_mqtt_sub_event_handler(156): mqtt config topic subscribe success +INF|2020-08-26 19:31:03|remote_config_mqtt_sample.c|main(315): config topic subscribe success, packetid:13502 +``` + +##### 3.1 设备订阅远程配置函数 + +``` +int IOT_Subscribe_Config(void *client, ConfigSubscirbeUserData *config_sub_userdata, int subscribe_timeout) +``` + +#### 4. 云平台上给产品添加远程配置内容 + +点击 AirConditioner 产品的管理按钮,然后点击远程配置选项卡添加远程配置内容保存和启用远程配置 +![image.png](https://main.qcloudimg.com/raw/16001d465cc7f5765d44842b6a47ef0d.png) + +#### 5. 观察设备主动请求配置更新 + +观察设备 airConditioner1 的打印输出,可以看到设备发布获取配置消息并收到了云平台的下行配置回复。 `Recv Msg Topic:$config/update/YI7XCD5DRH/airConditioner1` `"type":"reply"` + +配置信息是 `{"baud rate":9600,"data bits":8,"stop bit":1,"parity":"NONE","thread sleep":1000}` +``` +DBG|2020-08-26 19:31:03|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$config/report/YI7XCD5DRH/airConditioner1|payload={"type":"get"} +DBG|2020-08-26 19:31:08|remote_config_mqtt.c|_config_mqtt_message_callback(90): Recv Msg Topic:$config/update/YI7XCD5DRH/airConditioner1, buff data:{ + "type":"reply", + "result":0, + "payload": {"baud rate":9600,"data bits":8,"stop bit":1,"parity":"NONE","thread sleep":1000} +} +INF|2020-08-26 19:31:08|remote_config_mqtt_sample.c|_on_config_proc_handler(94): config message arrived , proc result: 9600, 8, 0, 1, 1000 +INF|2020-08-26 19:31:08|remote_config_mqtt_sample.c|_on_config_proc_handler(96): config message arrived , configData: {"baud rate":9600,"data bits":8,"stop bit":1,"parity":"NONE","thread sleep":1000} + +``` + +##### 5.1 设备主动请求配置更新函数 + +``` +int IOT_Get_Config(void *client, char *json_buffer, int buffer_size, int reply_timeout) +``` + +#### 6. 观察云平台主动下发配置 + +观察设备 airConditioner1 的打印输出,可以看到已经处理了远程配置下行消息。 `Recv Msg Topic:$config/update/YI7XCD5DRH/airConditioner1` `"type":"push"` + +配置信息是 `{"baud rate":115200,"data bits":8,"stop bit":1,"parity":"NONE","thread sleep":1000}` + +``` +DBG|2020-08-26 19:31:30|remote_config_mqtt.c|_config_mqtt_message_callback(90): Recv Msg Topic:$config/update/YI7XCD5DRH/airConditioner1, payload:{ + "type":"push", + "payload": {"baud rate":115200,"data bits":8,"stop bit":1,"parity":"NONE","thread sleep":1000} +} +INF|2020-08-26 19:31:30|remote_config_mqtt_sample.c|_on_config_proc_handler(44): config message arrived , configData: {"baud rate":115200,"data bits":8,"stop bit":1,"parity":"NONE","thread sleep":1000} +INF|2020-08-26 19:31:30|remote_config_mqtt_sample.c|_on_config_proc_handler(96): config message arrived , proc end: 115200, 8, 0, 1, 1000 + +``` + +#### 7. 云平台远程配置下行结果码 result 字段说明 + +| 结果码 | 说明 | +|--------|----------------------------------| +| 0 | 远程配置获取成功 | +| 1001 | 产品在云平台上的远程配置被禁用 | +| 1002 | 产品在云平台上不存在远程配置内容 | +| 1003 | 产品在云平台上的远程配置不合法 | + +***至此,完成了远程配置的示例运行*** + +使用远程配置功能时,参考例子程序,修改 `_on_config_proc_handler` 函数适配实际设备的配置解析与更新。 diff --git "a/docs/IoT_Hub/rrpc_sample_\345\220\214\346\255\245\351\200\232\344\277\241.md" "b/docs/IoT_Hub/rrpc_sample_\345\220\214\346\255\245\351\200\232\344\277\241.md" new file mode 100755 index 00000000..060d050a --- /dev/null +++ "b/docs/IoT_Hub/rrpc_sample_\345\220\214\346\255\245\351\200\232\344\277\241.md" @@ -0,0 +1,93 @@ +# 广播通信 +本文档介绍同步通信功能,并结合 SDK 的**rrpc_sample**展示同步通信功能。 + +## 一. 控制台创建设备 + +#### 1. 背景介绍 +MQTT协议是基于发布/订阅的异步通信模式,服务器无法控制设备同步返回结果。为解决此问题,物联网通信平台实现了一套同步通信机制,称为RRPC(Revert RPC)。 +即由服务器向客户端发起请求,客户端即时响应并同步给出答复。 +* 订阅消息Topic: `$rrpc/rxd/{productID}/{deviceName}/+` +* 请求消息Topic: `$rrpc/rxd/{productID}/{deviceName}/{processID}` +* 应答消息Topic: `$rrpc/txd/{productID}/{deviceName}/{processID}` +* processID : 服务器生成的唯一的消息ID,用来标识不同RRPC消息。可以通过RRPC应答消息中携带的`processID`找到对应的RRPC请求消息。 + +#### 2. 原理图 +![image.png](https://main.qcloudimg.com/raw/1e83a60cb7b6438ebb5927b7237b77ba.png) +* **RRPC请求4s超时**,即4s内设备端没有应答就认为请求超时。 + +#### 3. 创建产品和设备 +请参考[设备互通](https://cloud.tencent.com/document/product/634/11913) 创建空调产品,并创建airConditioner1空调设备。 + +## 二. 编译运行示例程序(以**密钥认证设备**为例) + +#### 1. 编译 SDK +修改CMakeLists.txt确保以下选项存在 +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_RRPC_ENABLED ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出`rrpc_sample`位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +将上面创建的airConditioner1设备的设备信息填写到JSON文件aircond_device_info1.json中: +``` +{ + "auth_mode":"KEY", + "productId":"KL4J2K3JZ8", + "deviceName":"airConditioner1", + "key_deviceinfo":{ + "deviceSecret":"zOZXUaycuwlePtTcD78dBA==" + } +} +``` + +#### 3. 执行`rrpc_sample`示例程序 +可以看到设备airConditioner1订阅了RRPC消息,然后处于等待状态。 +``` +./rrpc_sample -c ./aircond_device_info1.json -l 1000 +INF|2020-08-03 23:57:55|qcloud_iot_device.c|iot_device_info_set(50): SDK_Ver: 3.2.0, Product_ID: KL4J2K3JZ8, Device_Name: airConditioner1 +DBG|2020-08-03 23:57:55|HAL_TLS_mbedtls.c|HAL_TLS_Connect(200): Setting up the SSL/TLS structure... +DBG|2020-08-03 23:57:55|HAL_TLS_mbedtls.c|HAL_TLS_Connect(242): Performing the SSL/TLS handshake... +DBG|2020-08-03 23:57:55|HAL_TLS_mbedtls.c|HAL_TLS_Connect(243): Connecting to /KL4J2K3JZ8.iotcloud.tencentdevices.com/8883... +INF|2020-08-03 23:57:55|HAL_TLS_mbedtls.c|HAL_TLS_Connect(265): connected with /KL4J2K3JZ8.iotcloud.tencentdevices.com/8883... +INF|2020-08-03 23:57:56|mqtt_client.c|IOT_MQTT_Construct(113): mqtt connect with id: 2LxS1 success +INF|2020-08-03 23:57:56|rrpc_sample.c|main(206): Cloud Device Construct Success +DBG|2020-08-03 23:57:56|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(142): topicName=$rrpc/rxd/KL4J2K3JZ8/airConditioner1/+|packet_id=5920 +INF|2020-08-03 23:57:56|rrpc_sample.c|_mqtt_event_handler(49): subscribe success, packet-id=5920 +DBG|2020-08-03 23:57:56|rrpc_client.c|_rrpc_event_callback(104): rrpc topic subscribe success +``` + +#### 4. 调用云API `PublishRRPCMessage` 发送RRPC请求消息 +打开腾讯云[API控制台](https://console.cloud.tencent.com/api/explorer?Product=iotcloud&Version=2018-06-14&Action=PublishRRPCMessage&SignVersion=),填写个人密钥和设备参数信息,选择在线调用并发送请求 +![image.png](https://main.qcloudimg.com/raw/fe7a7749159b25fe12a07076f9093b79.png) + +#### 5. 观察RRPC请求消息 +观察设备airConditioner1的打印输出,可以看到已经收到RRPC请求消息,`process id`为469。 +``` +DBG|2020-08-04 00:07:36|rrpc_client.c|_rrpc_message_cb(85): topic=$rrpc/rxd/KL4J2K3JZ8/airConditioner1/469 +INF|2020-08-04 00:07:36|rrpc_client.c|_rrpc_message_cb(86): len=6, topic_msg=closed +INF|2020-08-04 00:07:36|rrpc_client.c|_rrpc_get_process_id(76): len=3, process id=469 +INF|2020-08-04 00:07:36|rrpc_sample.c|_rrpc_message_handler(137): rrpc message=closed +``` + +#### 6. 观察RRPC应答消息 +观察设备airConditioner1的打印输出,可以看到已经处理了RRPC请求消息,并回复了RRPC应答消息,`process id`为469。 +``` +DBG|2020-08-04 00:07:36|mqtt_client_publish.c|qcloud_iot_mqtt_publish(340): publish packetID=0|topicName=$rrpc/txd/KL4J2K3JZ8/airConditioner1/469|payload=ok +``` + +#### 7. 观察服务器响应结果 +观察服务器的响应结果,可以看到已经收到了RRPC应答消息。`MessageId`为469,`Payload`经过`base64`编码后为`b2s=`,其与客户端实际应答消息经过`base64`编码后一致。可以确认收到了应答消息。 +![image.png](https://main.qcloudimg.com/raw/7bbd67cf4529752fc9e125754cc0fa94/image-1.png) + +***至此,完成了RRPC同步通信的示例运行*** diff --git "a/docs/IoT_Hub/shadow_sample_\350\256\276\345\244\207\345\275\261\345\255\220.md" "b/docs/IoT_Hub/shadow_sample_\350\256\276\345\244\207\345\275\261\345\255\220.md" new file mode 100755 index 00000000..8891984f --- /dev/null +++ "b/docs/IoT_Hub/shadow_sample_\350\256\276\345\244\207\345\275\261\345\255\220.md" @@ -0,0 +1,113 @@ +# 设备影子 +本文档介绍设备影子功能,并结合 SDK 的**shadow_sample**展示影子的数据流和功能。 + +## 设备影子介绍 + +设备影子本质上是一份在服务器端缓存的设备数据(JSON 形式),主要用于保存: + +- 设备的当前配置 +- 设备的当前状态 + +作为中介,设备影子可以有效实现设备和用户应用之间的数据双向同步: + +- 对于设备配置,用户应用不需要直接修改设备,只需要修改服务器端的设备影子,由设备影子同步到设备。即使当时设备不在线,设备上线后仍能从设备影子同步到最新配置。 +- 对于设备状态,设备将状态上报到设备影子,用户应用查询时,只需查询设备影子即可。这样可以有效减少设备和服务器端的网络交互,尤其是低功耗设备。 + +关于设备影子的详细介绍,请参考[设备影子详情](https://cloud.tencent.com/document/product/634/11918) + +## 编译运行示例程序(以**密钥认证设备**为例) + +#### 1. 编译 SDK 及示例 +修改CMakeLists.txt确保以下选项存在 +``` +set(BUILD_TYPE "release") +set(COMPILE_TOOLS "gcc") +set(PLATFORM "linux") +set(FEATURE_MQTT_COMM_ENABLED ON) +set(FEATURE_MQTT_DEVICE_SHADOW ON) +set(FEATURE_AUTH_MODE "KEY") +set(FEATURE_AUTH_WITH_NOTLS OFF) +set(FEATURE_DEBUG_DEV_INFO_USED OFF) +``` +执行脚本编译 +``` +./cmake_build.sh +``` +示例输出shadow_sample位于`output/release/bin`文件夹中 + +#### 2. 填写设备信息 +将设备信息填写到配置文件device_info.json中 +``` +{ + "auth_mode":"KEY", + "productId":"S3EUVBRJLB", + "deviceName":"test_device", + "key_deviceinfo":{ + "deviceSecret":"vX6PQqazsGsMyf5SMfs6OA6y" + } +} +``` +#### 3. 第一次执行shadow_sample示例程序 +示例首先订阅了$shadow/operation/result/{productID}/{deviceName}主题,然后通过向$shadow/operation/{productID}/{deviceName}主题发送shadow GET命令来获取云端缓存的设备状态,然后就循环更新updateCount变量并执行shadow UPDATE。 +假设在updateCount=3的时候停止示例运行。 + +``` +./output/release/bin/shadow_sample +INF|2019-09-17 12:49:59|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: S3EUVBRJLB, Device_Name: test_device +DBG|2019-09-17 12:49:59|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure... +DBG|2019-09-17 12:49:59|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake... +DBG|2019-09-17 12:49:59|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-17 12:49:59|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-17 12:50:00|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: bph30 success +DBG|2019-09-17 12:50:00|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$shadow/operation/result/S3EUVBRJLB/test_device|packet_id=46510 +DBG|2019-09-17 12:50:00|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=46510 +INF|2019-09-17 12:50:00|shadow_client.c|IOT_Shadow_Construct(172): Sync device data successfully +DBG|2019-09-17 12:50:00|shadow_client.c|IOT_Shadow_Get(383): GET Request Document: {"clientToken":"S3EUVBRJLB-0"} +DBG|2019-09-17 12:50:00|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$shadow/operation/S3EUVBRJLB/test_device|payload={"type":"get", "clientToken":"S3EUVBRJLB-0"} +DBG|2019-09-17 12:50:00|shadow_client_manager.c|_on_operation_result_handler(278): type:get +DBG|2019-09-17 12:50:00|shadow_client.c|_update_ack_cb(114): requestAck=0 +DBG|2019-09-17 12:50:00|shadow_client.c|_update_ack_cb(117): Received Json Document={"clientToken":"S3EUVBRJLB-0","payload":{"state":{"reported":{}},"timestamp":1568695800,"version":0},"result":0,"timestamp":1568695800,"type":"get"} +DBG|2019-09-17 12:50:00|shadow_client.c|IOT_Shadow_Update(317): UPDATE Request Document: {"state":{"reported":{"updateCount":0}}, "clientToken":"S3EUVBRJLB-1"} +DBG|2019-09-17 12:50:00|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$shadow/operation/S3EUVBRJLB/test_device|payload={"type":"update", "state":{"reported":{"updateCount":0}}, "clientToken":"S3EUVBRJLB-1"} +DBG|2019-09-17 12:50:01|shadow_client_manager.c|_on_operation_result_handler(278): type:update +INF|2019-09-17 12:50:01|shadow_sample.c|OnShadowUpdateCallback(49): recv shadow update response, response ack: 0 +DBG|2019-09-17 12:50:01|shadow_client.c|IOT_Shadow_Update(317): UPDATE Request Document: {"state":{"reported":{"updateCount":1}}, "clientToken":"S3EUVBRJLB-2"} +DBG|2019-09-17 12:50:01|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$shadow/operation/S3EUVBRJLB/test_device|payload={"type":"update", "state":{"reported":{"updateCount":1}}, "clientToken":"S3EUVBRJLB-2"} +DBG|2019-09-17 12:50:02|shadow_client_manager.c|_on_operation_result_handler(278): type:update +INF|2019-09-17 12:50:02|shadow_sample.c|OnShadowUpdateCallback(49): recv shadow update response, response ack: 0 +DBG|2019-09-17 12:50:02|shadow_client.c|IOT_Shadow_Update(317): UPDATE Request Document: {"state":{"reported":{"updateCount":2}}, "clientToken":"S3EUVBRJLB-3"} +DBG|2019-09-17 12:50:02|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$shadow/operation/S3EUVBRJLB/test_device|payload={"type":"update", "state":{"reported":{"updateCount":2}}, "clientToken":"S3EUVBRJLB-3"} +DBG|2019-09-17 12:50:03|shadow_client_manager.c|_on_operation_result_handler(278): type:update +INF|2019-09-17 12:50:03|shadow_sample.c|OnShadowUpdateCallback(49): recv shadow update response, response ack: 0 +DBG|2019-09-17 12:50:04|shadow_client.c|IOT_Shadow_Update(317): UPDATE Request Document: {"state":{"reported":{"updateCount":3}}, "clientToken":"S3EUVBRJLB-4"} +DBG|2019-09-17 12:50:04|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$shadow/operation/S3EUVBRJLB/test_device|payload={"type":"update", "state":{"reported":{"updateCount":3}}, "clientToken":"S3EUVBRJLB-4"} +``` +#### 4. 查看云端设备影子状态变化并修改状态 +从控制台的虚拟设备,可以看到该设备的updateCount已经更新为3,即便设备已经离线,仍然可以通过这份缓存来获取设备离线之前的最新状态。 +![](https://main.qcloudimg.com/raw/ec18636eb38ee25ae21389a0004cd094.png) + +这个时候如果点击修改,则可以改变影子状态,这个操作相当于模拟设备离线期间,通过云API修改设备的目标状态,比如将updateCount更改为5 + +![](https://main.qcloudimg.com/raw/9719fa972cbf158165ae208113e7bc19.png) + +确定修改之后,再次运行shadow_sample + +#### 5. 第二次执行shadow_sample示例程序 +这时候可以看到当执行shadow GET命令来获取云端缓存的设备状态,updateCount已经变为云端最新的状态。 +``` +./output/release/bin/shadow_sample +INF|2019-09-17 12:59:01|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: S3EUVBRJLB, Device_Name: test_device +DBG|2019-09-17 12:59:01|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure... +DBG|2019-09-17 12:59:01|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake... +DBG|2019-09-17 12:59:01|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-17 12:59:01|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /S3EUVBRJLB.iotcloud.tencentdevices.com/8883... +INF|2019-09-17 12:59:01|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: hY8DA success +DBG|2019-09-17 12:59:01|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$shadow/operation/result/S3EUVBRJLB/test_device|packet_id=63420 +DBG|2019-09-17 12:59:01|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=63420 +INF|2019-09-17 12:59:01|shadow_client.c|IOT_Shadow_Construct(172): Sync device data successfully +DBG|2019-09-17 12:59:01|shadow_client.c|IOT_Shadow_Get(383): GET Request Document: {"clientToken":"S3EUVBRJLB-0"} +DBG|2019-09-17 12:59:01|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$shadow/operation/S3EUVBRJLB/test_device|payload={"type":"get", "clientToken":"S3EUVBRJLB-0"} +DBG|2019-09-17 12:59:01|shadow_client_manager.c|_on_operation_result_handler(278): type:get +DBG|2019-09-17 12:59:01|shadow_client.c|_update_ack_cb(114): requestAck=0 +DBG|2019-09-17 12:59:01|shadow_client.c|_update_ack_cb(117): Received Json Document={"clientToken":"S3EUVBRJLB-0","payload":{"state":{"reported":{"updateCount":5}},"timestamp":1568696289949,"version":5},"result":0,"timestamp":1568696341,"type":"get"} +``` diff --git "a/docs/MCU+\350\205\276\350\256\257\344\272\221\345\256\232\345\210\266AT\346\250\241\347\273\204.md" "b/docs/MCU+\350\205\276\350\256\257\344\272\221\345\256\232\345\210\266AT\346\250\241\347\273\204.md" new file mode 100755 index 00000000..4c5094bb --- /dev/null +++ "b/docs/MCU+\350\205\276\350\256\257\344\272\221\345\256\232\345\210\266AT\346\250\241\347\273\204.md" @@ -0,0 +1,16 @@ +## 简介 +腾讯云物联网提供了专用的 [腾讯云IoT AT指令集](https://github.com/tencentyun/qcloud-iot-sdk-tencent-at-based/blob/master/docs/%E8%85%BE%E8%AE%AF%E4%BA%91IoT%20AT%E6%8C%87%E4%BB%A4%E9%9B%86-V3.1.3.pdf),如果通讯模组实现了该指令集,则设备接入和通讯更为简单,所需代码量更少,针对这种场景,请参考面向腾讯云定制AT模组专用的 [MCU AT SDK](https://github.com/tencentyun/qcloud-iot-sdk-tencent-at-based.git) + +目前腾讯云和主流的模组厂商进行了深度合作,将SDK的核心协议已移植到模组中,模组对外封装统一的腾讯云AT指令。已支持腾讯云定制AT指令的模组列表如下: + +| 序号 | 模组商 | 模组型号 | 通信制式 | 固件版本 | +| -------| ------------| -------------------|------------------|----------------| +| 1 | 中移 | M5311 | NB-IoT | M5311_LV_MOD_BOM_R002_1901232019_0906 | +| 2 | 中移 | M6315 | 2G | CMIOT_M6315_20180901_V10_EXT_20190827_152209 | +| 3 | 中移 | M8321 | 4G | QCloud_AT_v3.0.1_4G_Cellular 20190909_171245 | +| 4 | 有方 | N10 | 2G | N10_I_1187_PQS63010_TC_V002C | +| 5 | 有方 | N21 | NB-IoT | N21_RDD0CM_TC_V006A | +| 6 | 有方 | N720 | 4G | N720_EAB0CMF_BZ_V003A_T1 | +| 7 | 移柯 | L206 | 2G | L206Dv01.04b04.04 | +| 8 | 乐鑫 | ESP8266 | WIFI | QCloud_AT_ESP_WiFi_v1.1.0 | + diff --git "a/docs/MCU+\351\200\232\347\224\250TCP_AT\346\250\241\347\273\204\347\247\273\346\244\215(FreeRTOS).md" "b/docs/MCU+\351\200\232\347\224\250TCP_AT\346\250\241\347\273\204\347\247\273\346\244\215(FreeRTOS).md" new file mode 100755 index 00000000..420290a7 --- /dev/null +++ "b/docs/MCU+\351\200\232\347\224\250TCP_AT\346\250\241\347\273\204\347\247\273\346\244\215(FreeRTOS).md" @@ -0,0 +1,36 @@ +## 简介 + +对于不具备网络通讯能力的MCU,一般采用MCU+通讯模组的方式,通讯模组(包括WiFi/2G/4G/NB-IoT)一般提供了基于串口的AT指令协议供MCU进行网络通讯。针对这种场景,C-SDK 封装了AT-socket网络层,网络层之上的核心协议和服务层无须移植。本文阐述针对 MCU(FreeRTOS)+通用TCP AT模组的目标环境,如何移植C-SDK 并接入腾讯云物联网平台。 + +## 移植步骤 + +### 1. 下载最新版本设备端 [C-SDK](https://github.com/tencentyun/qcloud-iot-sdk-embedded-c)。 + +### 2. SDK功能配置及代码抽取 +- 使用通用TCP模组编译配置选项配置如下: + +| 名称 | 配置 | 说明 | +| :------------------------------- | ------------- | ------------------------------------------------------------ | +| BUILD_TYPE | debug/release,根据需要设置 | +| EXTRACT_SRC | ON | 使能代码抽取 | +| COMPILE_TOOLS | gcc/MSVC | 根据需要设置,IDE情况不关注 | +| PLATFORM | linux/windows | 根据需要设置,IDE情况不关注 | +| FEATURE_OTA_COMM_ENABLED | ON/OFF | 根据需要设置 | +| FEATURE_AUTH_MODE | KEY | 资源受限设备认证方式建议选秘钥认证 | +| FEATURE_AUTH_WITH_NOTLS | ON/OFF | 根据需要是否使能TLS | +| FEATURE_AT_TCP_ENABLED | ON | AT模组TCP功能开关 | +| FEATURE_AT_UART_RECV_IRQ | ON | AT模组中断接受功能开关 | +| FEATURE_AT_OS_USED | ON | AT模组多线程功能开关 | +| FEATURE_AT_DEBUG | OFF | 默认关闭AT模组调试功能,有调试需要再打开| + +- 参考文档[C-SDK_Build编译环境及配置选项说明]()抽取代码 + +### 3. HAL 层移植 + +参见[C-SDK_Porting跨平台移植概述]() +对于网络相关的HAL接口,通过上面的编译选项已选择SDK提供的AT_Socket框架,SDK会调用 network_at_tcp.c 的at_socket接口,at_socket层不需要移植,需要实现AT串口驱动及AT模组驱动,AT模组驱动只需要实现AT框架中at_device的驱动结构体 *at_device_op_t* 的驱动接口即可,可以参照at_device目录下的已支持的模组。目前SDK针对物联网使用较广的WiFi模组ESP8266提供了底层接口实现,供移植到其他通讯模组时作为参考。 + +### 4. 业务逻辑开发 + +对于IoT_Hub产品,可以参考Docs/IoT_Hub目录下的例程。 + diff --git "a/docs/MCU+\351\200\232\347\224\250TCP_AT\346\250\241\347\273\204\347\247\273\346\244\215(nonOS).md" "b/docs/MCU+\351\200\232\347\224\250TCP_AT\346\250\241\347\273\204\347\247\273\346\244\215(nonOS).md" new file mode 100755 index 00000000..4699a065 --- /dev/null +++ "b/docs/MCU+\351\200\232\347\224\250TCP_AT\346\250\241\347\273\204\347\247\273\346\244\215(nonOS).md" @@ -0,0 +1,38 @@ +## 简介 + +对于不具备网络通讯能力的MCU,一般采用MCU+通讯模组的方式,通讯模组(包括WiFi/2G/4G/NB-IoT)一般提供了基于串口的AT指令协议供MCU进行网络通讯。针对这种场景,C-SDK 封装了AT-socket网络层,网络层之上的核心协议和服务层无须移植。本文阐述针对 MCU(无OS)+通用TCP AT模组的目标环境,如何移植C-SDK 并接入腾讯云物联网平台。 +相较于有RTOS场景,at_socket网络接收数据的处理会有差异,应用层需要周期性的调用**IOT_MQTT_Yield**来接收服务端下行数据,错过接收窗口则会存在数据丢失的情况,所以在业务逻辑较为复杂的场景建议使用RTOS,通过配置 FEATURE_AT_OS_USED = OFF选择无OS方式。 + +## 移植步骤 + +### 1. 下载最新版本设备端 [C-SDK](https://github.com/tencentyun/qcloud-iot-sdk-embedded-c)。 + +### 2. SDK功能配置及代码抽取 +- 无RTOS使用通用TCP模组编译配置选项配置如下: + +| 名称 | 配置 | 说明 | +| :------------------------------- | ------------- | ------------------------------------------------------------ | +| BUILD_TYPE | debug/release,根据需要设置 | +| EXTRACT_SRC | ON | 使能代码抽取 | +| COMPILE_TOOLS | gcc/MSVC | 根据需要设置,IDE情况不关注 | +| PLATFORM | linux/windows | 根据需要设置,IDE情况不关注 | +| FEATURE_OTA_COMM_ENABLED | ON/OFF | 根据需要设置 | +| FEATURE_AUTH_MODE | KEY | 资源受限设备认证方式建议选秘钥认证 | +| FEATURE_AUTH_WITH_NOTLS | ON/OFF | 根据需要是否使能TLS | +| FEATURE_AT_TCP_ENABLED | ON | 使能at_socket组件 | +| FEATURE_AT_UART_RECV_IRQ | ON | 使能AT串口中断接收 | +| FEATURE_AT_OS_USED | OFF | at_socket组件无RTOS环境使用 | +| FEATURE_AT_DEBUG | OFF | 默认关闭AT模组调试功能,有调试需要再打开| + +- 参考文档[C-SDK_Build编译环境及配置选项说明]()抽取代码 + +### 3. HAL 层移植 + +参见[C-SDK_Porting跨平台移植概述]() + +对于网络相关的HAL接口,通过上面的编译选项已选择SDK提供的AT_Socket框架,SDK会调用 network_at_tcp.c 的at_socket接口,at_socket层不需要移植,需要实现AT串口驱动及AT模组驱动,AT模组驱动只需要实现AT框架中at_device的驱动结构体 *at_device_op_t* 的驱动接口即可,可以参照at_device目录下的已支持的模组。AT串口驱动需要实现串口的中断接收,然后在中断服务程序中调用回调函数 *at_client_uart_rx_isr_cb* 即可,可以参考 HAL_OS_nonos.c 实现目标平台的移植。 + +### 4. 业务逻辑开发 + +可以参考Docs/IoT_Hub目录下的例程。 + diff --git a/external_libs/mbedtls/CMakeLists.txt b/external_libs/mbedtls/CMakeLists.txt new file mode 100644 index 00000000..a0e3dbc2 --- /dev/null +++ b/external_libs/mbedtls/CMakeLists.txt @@ -0,0 +1,139 @@ +option(USE_STATIC_MBEDTLS_LIBRARY "Build mbed TLS static library." ON) +option(USE_SHARED_MBEDTLS_LIBRARY "Build mbed TLS shared library." OFF) +option(LINK_WITH_PTHREAD "Explicitly link mbed TLS library to pthread." OFF) + +set(src_crypto + ./library/aes.c + ./library/aesni.c + ./library/arc4.c + ./library/asn1parse.c + ./library/asn1write.c + ./library/base64.c + ./library/bignum.c + ./library/blowfish.c + ./library/camellia.c + ./library/ccm.c + ./library/cipher.c + ./library/cipher_wrap.c + ./library/cmac.c + ./library/ctr_drbg.c + ./library/des.c + ./library/dhm.c + ./library/ecdh.c + ./library/ecdsa.c + ./library/ecjpake.c + ./library/ecp.c + ./library/ecp_curves.c + ./library/entropy.c + ./library/entropy_poll.c + ./library/error.c + ./library/gcm.c + ./library/havege.c + ./library/hmac_drbg.c + ./library/md.c + ./library/md2.c + ./library/md4.c + ./library/md5.c + ./library/md_wrap.c + ./library/memory_buffer_alloc.c + ./library/oid.c + ./library/padlock.c + ./library/pem.c + ./library/pk.c + ./library/pk_wrap.c + ./library/pkcs12.c + ./library/pkcs5.c + ./library/pkparse.c + ./library/pkwrite.c + ./library/platform.c + ./library/ripemd160.c + ./library/rsa.c + ./library/sha1.c + ./library/sha256.c + ./library/sha512.c + ./library/threading.c + ./library/timing.c + ./library/version.c + ./library/version_features.c + ./library/xtea.c +) + +set(src_x509 + ./library/certs.c + ./library/pkcs11.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 +) + +set(src_tls + ./library/debug.c + ./library/net_sockets.c + ./library/ssl_cache.c + ./library/ssl_ciphersuites.c + ./library/ssl_cli.c + ./library/ssl_cookie.c + ./library/ssl_srv.c + ./library/ssl_ticket.c + ./library/ssl_tls.c +) + +if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes") +endif(CMAKE_COMPILER_IS_GNUCC) + +if(CMAKE_COMPILER_IS_CLANG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code") +endif(CMAKE_COMPILER_IS_CLANG) + +if(WIN32) + set(libs ${libs} ws2_32) +endif(WIN32) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +if(LINK_WITH_PTHREAD) + set(libs ${libs} pthread) +endif() + +if (NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + message(FATAL_ERROR "Need to choose static or shared mbedtls build!") +endif(NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + set(mbedtls_static_target "mbedtls_static") + set(mbedx509_static_target "mbedx509_static") + set(mbedcrypto_static_target "mbedcrypto_static") +elseif(USE_STATIC_MBEDTLS_LIBRARY) + set(mbedtls_static_target "mbedtls") + set(mbedx509_static_target "mbedx509") + set(mbedcrypto_static_target "mbedcrypto") +endif() + + + +if(USE_STATIC_MBEDTLS_LIBRARY AND ${FEATURE_AUTH_WITH_NOTLS} STREQUAL "OFF") + SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/lib/) + + add_library(${mbedcrypto_static_target} STATIC ${src_crypto}) + set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto) + target_link_libraries(${mbedcrypto_static_target} ${libs}) + + add_library(${mbedx509_static_target} STATIC ${src_x509}) + set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509) + target_link_libraries(${mbedx509_static_target} ${libs} ${mbedcrypto_static_target}) + + add_library(${mbedtls_static_target} STATIC ${src_tls}) + set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls) + target_link_libraries(${mbedtls_static_target} ${libs} ${mbedx509_static_target}) +endif() diff --git a/external_libs/mbedtls/Makefile b/external_libs/mbedtls/Makefile new file mode 100644 index 00000000..3ac8306f --- /dev/null +++ b/external_libs/mbedtls/Makefile @@ -0,0 +1,108 @@ + +DESTDIR=/usr/local +PREFIX=mbedtls_ + +.SILENT: + +.PHONY: all lib tests install uninstall clean test check covtest lcov apidoc apidoc_clean + +all: lib + $(MAKE) post_build + +no_test: programs + +programs: lib + $(MAKE) -s -C programs + +lib: + $(MAKE) -C library + +tests: lib + $(MAKE) -C tests + +ifndef WINDOWS +install: no_test + mkdir -p $(DESTDIR)/include/mbedtls + cp -r include/mbedtls $(DESTDIR)/include + + mkdir -p $(DESTDIR)/lib + cp -RP library/libmbedtls.* $(DESTDIR)/lib + cp -RP library/libmbedx509.* $(DESTDIR)/lib + cp -RP library/libmbedcrypto.* $(DESTDIR)/lib + + mkdir -p $(DESTDIR)/bin + for p in programs/*/* ; do \ + if [ -x $$p ] && [ ! -d $$p ] ; \ + then \ + f=$(PREFIX)`basename $$p` ; \ + cp $$p $(DESTDIR)/bin/$$f ; \ + fi \ + done + +uninstall: + rm -rf $(DESTDIR)/include/mbedtls + rm -f $(DESTDIR)/lib/libmbedtls.* + rm -f $(DESTDIR)/lib/libmbedx509.* + rm -f $(DESTDIR)/lib/libmbedcrypto.* + + for p in programs/*/* ; do \ + if [ -x $$p ] && [ ! -d $$p ] ; \ + then \ + f=$(PREFIX)`basename $$p` ; \ + rm -f $(DESTDIR)/bin/$$f ; \ + fi \ + done +endif + +WARNING_BORDER =*******************************************************\n +NULL_ENTROPY_WARN_L1=**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! ****\n +NULL_ENTROPY_WARN_L2=**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES ****\n +NULL_ENTROPY_WARN_L3=**** AND IS *NOT* SUITABLE FOR PRODUCTION USE ****\n + +NULL_ENTROPY_WARNING=\n$(WARNING_BORDER)$(NULL_ENTROPY_WARN_L1)$(NULL_ENTROPY_WARN_L2)$(NULL_ENTROPY_WARN_L3)$(WARNING_BORDER) + +# Post build steps +post_build: +ifndef WINDOWS + # If NULL Entropy is configured, display an appropriate warning + -scripts/config.pl get MBEDTLS_TEST_NULL_ENTROPY && ([ $$? -eq 0 ]) && \ + echo '$(NULL_ENTROPY_WARNING)' +endif + +clean: + $(MAKE) -C library clean +ifndef WINDOWS + find . \( -name \*.gcno -o -name \*.gcda -o -name \*.info \) -exec rm {} + +endif + +check: lib tests + $(MAKE) -C tests check + +test: check + +ifndef WINDOWS +# note: for coverage testing, build with: +# make CFLAGS='--coverage -g3 -O0' +covtest: + $(MAKE) check + programs/test/selftest + tests/compat.sh + tests/ssl-opt.sh + +lcov: + rm -rf Coverage + lcov --capture --initial --directory library -o files.info + lcov --capture --directory library -o tests.info + lcov --add-tracefile files.info --add-tracefile tests.info -o all.info + lcov --remove all.info -o final.info '*.h' + gendesc tests/Descriptions.txt -o descriptions + genhtml --title "mbed TLS" --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage final.info + rm -f files.info tests.info all.info final.info descriptions + +apidoc: + mkdir -p apidoc + doxygen doxygen/mbedtls.doxyfile + +apidoc_clean: + rm -rf apidoc +endif diff --git a/external_libs/mbedtls/configs/README.txt b/external_libs/mbedtls/configs/README.txt new file mode 100644 index 00000000..e9867bc1 --- /dev/null +++ b/external_libs/mbedtls/configs/README.txt @@ -0,0 +1,26 @@ +This directory contains example configuration files. + +The examples are generally focused on a particular usage case (eg, support for +a restricted number of ciphersuites) and aim at minimizing resource usage for +this target. They can be used as a basis for custom configurations. + +These files are complete replacements for the default config.h. To use one of +them, you can pick one of the following methods: + +1. Replace the default file include/mbedtls/config.h with the chosen one. + (Depending on your compiler, you may need to ajust the line with + #include "mbedtls/check_config.h" then.) + +2. Define MBEDTLS_CONFIG_FILE and adjust the include path accordingly. + For example, using make: + + CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE=''" make + + Or, using cmake: + + find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} + + CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE=''" cmake . + make + +Note that the second method also works if you want to keep your custom +configuration file outside the mbed TLS tree. diff --git a/external_libs/mbedtls/configs/config-ccm-psk-tls1_2.h b/external_libs/mbedtls/configs/config-ccm-psk-tls1_2.h new file mode 100644 index 00000000..aee10b86 --- /dev/null +++ b/external_libs/mbedtls/configs/config-ccm-psk-tls1_2.h @@ -0,0 +1,85 @@ +/* + * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites + * Distinguishing features: + * - no bignum, no PK, no X509 + * - fully modern and secure (provided the pre-shared keys have high entropy) + * - very low record overhead with CCM-8 + * - optimized for low RAM usage + * + * See README.txt for usage instructions. + */ +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */ +/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */ + +/* mbed TLS feature support */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_MD_C +#define MBEDTLS_NET_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C + +/* Save RAM at the expense of ROM */ +#define MBEDTLS_AES_ROM_TABLES + +/* Save some RAM by adjusting to your exact needs */ +#define MBEDTLS_PSK_MAX_LEN 16 /* 128-bits keys are generally enough */ + +/* + * You should adjust this to the exact number of sources you're using: default + * is the "platform_entropy_poll" source, but you may want to add other ones + * Minimum is 2 for the entropy test suite. + */ +#define MBEDTLS_ENTROPY_MAX_SOURCES 2 + +/* + * Use only CCM_8 ciphersuites, and + * save ROM and a few bytes of RAM by specifying our own ciphersuite list + */ +#define MBEDTLS_SSL_CIPHERSUITES \ + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \ + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 + +/* + * Save RAM at the expense of interoperability: do this only if you control + * both ends of the connection! (See comments in "mbedtls/ssl.h".) + * The optimal size here depends on the typical size of records. + */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 512 + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external_libs/mbedtls/configs/config-mini-tls1_1.h b/external_libs/mbedtls/configs/config-mini-tls1_1.h new file mode 100644 index 00000000..e22363d1 --- /dev/null +++ b/external_libs/mbedtls/configs/config-mini-tls1_1.h @@ -0,0 +1,75 @@ +/* + * Minimal configuration for TLS 1.1 (RFC 4346) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Minimal configuration for TLS 1.1 (RFC 4346), implementing only the + * required ciphersuite: MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_SSL_PROTO_TLS1_1 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_DES_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C +#define MBEDTLS_NET_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +/* For test certificates */ +#define MBEDTLS_BASE64_C +#define MBEDTLS_CERTS_C +#define MBEDTLS_PEM_PARSE_C + +/* For testing with compat.sh */ +#define MBEDTLS_FS_IO + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external_libs/mbedtls/configs/config-no-entropy.h b/external_libs/mbedtls/configs/config-no-entropy.h new file mode 100644 index 00000000..95f17d45 --- /dev/null +++ b/external_libs/mbedtls/configs/config-no-entropy.h @@ -0,0 +1,85 @@ +/** + * Minimal configuration of features that do not require an entropy source + * + * Copyright (C) 2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Minimal configuration of features that do not require an entropy source + * Distinguishing reatures: + * - no entropy module + * - no TLS protocol implementation available due to absence of an entropy + * source + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_PK_RSA_ALT_SUPPORT +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_PKCS1_V21 +#define MBEDTLS_SELF_TEST +#define MBEDTLS_VERSION_FEATURES +#define MBEDTLS_X509_CHECK_KEY_USAGE +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_GCM_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#define MBEDTLS_OID_C +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_VERSION_C +#define MBEDTLS_X509_USE_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_CRL_PARSE_C + +#include "check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external_libs/mbedtls/configs/config-picocoin.h b/external_libs/mbedtls/configs/config-picocoin.h new file mode 100644 index 00000000..26b24a9e --- /dev/null +++ b/external_libs/mbedtls/configs/config-picocoin.h @@ -0,0 +1,71 @@ +/* + * Reduced configuration used by Picocoin. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Reduced configuration used by Picocoin. + * + * See README.txt for usage instructions. + * + * Distinguishing features: + * - no SSL/TLS; + * - no X.509; + * - ECDSA/PK and some other chosen crypto bits. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_PK_PARSE_EC_EXTENDED +#define MBEDTLS_ERROR_STRERROR_DUMMY +#define MBEDTLS_FS_IO + +/* mbed TLS modules */ +#define MBEDTLS_AESNI_C +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#define MBEDTLS_OID_C +#define MBEDTLS_PADLOCK_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_RIPEMD160_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external_libs/mbedtls/configs/config-suite-b.h b/external_libs/mbedtls/configs/config-suite-b.h new file mode 100644 index 00000000..3c4804c7 --- /dev/null +++ b/external_libs/mbedtls/configs/config-suite-b.h @@ -0,0 +1,114 @@ +/* + * Minimal configuration for TLS NSA Suite B Profile (RFC 6460) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Minimal configuration for TLS NSA Suite B Profile (RFC 6460) + * + * Distinguishing features: + * - no RSA or classic DH, fully based on ECC + * - optimized for low RAM usage + * + * Possible improvements: + * - if 128-bit security is enough, disable secp384r1 and SHA-512 + * - use embedded certs in DER format and disable PEM_PARSE_C and BASE64_C + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_GCM_C +#define MBEDTLS_MD_C +#define MBEDTLS_NET_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +/* For test certificates */ +#define MBEDTLS_BASE64_C +#define MBEDTLS_CERTS_C +#define MBEDTLS_PEM_PARSE_C + +/* Save RAM at the expense of ROM */ +#define MBEDTLS_AES_ROM_TABLES + +/* Save RAM by adjusting to our exact needs */ +#define MBEDTLS_ECP_MAX_BITS 384 +#define MBEDTLS_MPI_MAX_SIZE 48 // 384 bits is 48 bytes + +/* Save RAM at the expense of speed, see ecp.h */ +#define MBEDTLS_ECP_WINDOW_SIZE 2 +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 + +/* Significant speed benefit at the expense of some ROM */ +#define MBEDTLS_ECP_NIST_OPTIM + +/* + * You should adjust this to the exact number of sources you're using: default + * is the "mbedtls_platform_entropy_poll" source, but you may want to add other ones. + * Minimum is 2 for the entropy test suite. + */ +#define MBEDTLS_ENTROPY_MAX_SOURCES 2 + +/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ +#define MBEDTLS_SSL_CIPHERSUITES \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* + * Save RAM at the expense of interoperability: do this only if you control + * both ends of the connection! (See coments in "mbedtls/ssl.h".) + * The minimum size here depends on the certificate chain used as well as the + * typical size of records. + */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024 + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external_libs/mbedtls/configs/config-thread.h b/external_libs/mbedtls/configs/config-thread.h new file mode 100644 index 00000000..990fe08c --- /dev/null +++ b/external_libs/mbedtls/configs/config-thread.h @@ -0,0 +1,91 @@ +/* + * Minimal configuration for using TLS as part of Thread + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * Minimal configuration for using TLS a part of Thread + * http://threadgroup.org/ + * + * Distinguishing features: + * - no RSA or classic DH, fully based on ECC + * - no X.509 + * - support for experimental EC J-PAKE key exchange + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM + +/* mbed TLS feature support */ +#define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define MBEDTLS_SSL_EXPORT_KEYS + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_CMAC_C +#define MBEDTLS_ECJPAKE_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SSL_COOKIE_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C + +/* For tests using ssl-opt.sh */ +#define MBEDTLS_NET_C +#define MBEDTLS_TIMING_C + +/* Save RAM at the expense of ROM */ +#define MBEDTLS_AES_ROM_TABLES + +/* Save RAM by adjusting to our exact needs */ +#define MBEDTLS_ECP_MAX_BITS 256 +#define MBEDTLS_MPI_MAX_SIZE 32 // 256 bits is 32 bytes + +/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external_libs/mbedtls/include/mbedtls/aes.h b/external_libs/mbedtls/include/mbedtls/aes.h new file mode 100644 index 00000000..a36e825a --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/aes.h @@ -0,0 +1,297 @@ +/** + * \file aes.h + * + * \brief AES block cipher + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 +#define MBEDTLS_AES_DECRYPT 0 + +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +#if !defined(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 + */ +void mbedtls_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 + */ +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#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/external_libs/mbedtls/include/mbedtls/aesni.h b/external_libs/mbedtls/include/mbedtls/aesni.h new file mode 100644 index 00000000..b1b7f1cd --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/aesni.h @@ -0,0 +1,111 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_AESNI_H +#define MBEDTLS_AESNI_H + +#include "aes.h" + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_HAVE_X86_64 +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES-NI features detection routine + * + * \param what The feature to detect + * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesni_has_support( unsigned int what ); + +/** + * \brief AES-NI AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief GCM multiplication: c = a * b in GF(2^128) + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Compute decryption round keys from encryption round keys + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ); + +/** + * \brief Perform key expansion (for encryption) + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_H */ diff --git a/external_libs/mbedtls/include/mbedtls/arc4.h b/external_libs/mbedtls/include/mbedtls/arc4.h new file mode 100644 index 00000000..5fc5395a --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/arc4.h @@ -0,0 +1,113 @@ +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 context structure + */ +typedef struct +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +mbedtls_arc4_context; + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + */ +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* MBEDTLS_ARC4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_arc4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ diff --git a/external_libs/mbedtls/include/mbedtls/asn1.h b/external_libs/mbedtls/include/mbedtls/asn1.h new file mode 100644 index 00000000..082832c8 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/asn1.h @@ -0,0 +1,342 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with DER encoded the ANS1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the value + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching + * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is + * unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the length + * \param tag The expected tag + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did + * not match requested tag, or another specific ASN.1 error code. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param bs The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len Length of the actual bit/octect string in bytes + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF " + * Updated the pointer to immediately behind the full sequence tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param cur First variable in the chain to fill + * \param tag Type of sequence + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param X The MPI that will receive the value + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list + * Head will be set to NULL + * + * \param head Pointer to the head of the list of named data entries to free + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/external_libs/mbedtls/include/mbedtls/asn1write.h b/external_libs/mbedtls/include/mbedtls/asn1write.h new file mode 100644 index 00000000..73ff32b6 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/asn1write.h @@ -0,0 +1,239 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + +#include "asn1.h" + +#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ + g += ret; } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param len the length to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); + +/** + * \brief Write a ASN.1 tag in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param tag the tag to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param X the MPI to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID to write + * \param oid_len length of the OID + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID of the algorithm + * \param oid_len length of the OID + * \param par_len length of parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param boolean 0 or 1 + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); + +/** + * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param val the integer value + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf the bitstring + * \param bits the total number of bits in the bitstring + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list Pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry) + * \param oid The OID to look for + * \param oid_len Size of the OID + * \param val Data to store (can be NULL if you want to fill it by hand) + * \param val_len Minimum length of the data buffer needed + * + * \return NULL if if there was a memory allocation error, or a pointer + * to the new / existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/external_libs/mbedtls/include/mbedtls/base64.h b/external_libs/mbedtls/include/mbedtls/base64.h new file mode 100644 index 00000000..352c652d --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/base64.h @@ -0,0 +1,88 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + +#include + +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/external_libs/mbedtls/include/mbedtls/bignum.h b/external_libs/mbedtls/include/mbedtls/bignum.h new file mode 100644 index 00000000..aa51556a --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/bignum.h @@ -0,0 +1,717 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can results temporarily in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * 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/external_libs/mbedtls/include/mbedtls/blowfish.h b/external_libs/mbedtls/include/mbedtls/blowfish.h new file mode 100644 index 00000000..34626eef --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/blowfish.h @@ -0,0 +1,203 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_BLOWFISH_ENCRYPT 1 +#define MBEDTLS_BLOWFISH_DECRYPT 0 +#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 +#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 +#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Blowfish context structure + */ +typedef struct +{ + uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +mbedtls_blowfish_context; + +/** + * \brief Initialize Blowfish context + * + * \param ctx Blowfish context to be initialized + */ +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); + +/** + * \brief Clear Blowfish context + * + * \param ctx Blowfish context to be cleared + */ +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); + +/** + * \brief Blowfish key schedule + * + * \param ctx Blowfish context to be initialized + * \param key encryption key + * \param keybits must be between 32 and 448 bits + * + * \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Blowfish-ECB block encryption/decryption + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Blowfish-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (8 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Blowfish CFB buffer encryption/decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Blowfish-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * \param ctx Blowfish context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 64-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + +#endif /* blowfish.h */ diff --git a/external_libs/mbedtls/include/mbedtls/bn_mul.h b/external_libs/mbedtls/include/mbedtls/bn_mul.h new file mode 100644 index 00000000..cac3f145 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/bn_mul.h @@ -0,0 +1,885 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#include "bignum.h" + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8 \n\t" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax \n\t" \ + "mulq %%rbx \n\t" \ + "addq $8, %%rsi \n\t" \ + "addq %%rcx, %%rax \n\t" \ + "movq %%r8, %%rcx \n\t" \ + "adcq $0, %%rdx \n\t" \ + "nop \n\t" \ + "addq %%rax, (%%rdi) \n\t" \ + "adcq %%rdx, %%rcx \n\t" \ + "addq $8, %%rdi \n\t" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4" "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * gcc -O0 by default uses r7 for the frame pointer, so it complains about our + * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, + * passing that option is not easy when building with yotta. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/external_libs/mbedtls/include/mbedtls/camellia.h b/external_libs/mbedtls/include/mbedtls/camellia.h new file mode 100644 index 00000000..0424d623 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/camellia.h @@ -0,0 +1,235 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CAMELLIA context structure + */ +typedef struct +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +/** + * \brief Initialize CAMELLIA context + * + * \param ctx CAMELLIA context to be initialized + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear CAMELLIA context + * + * \param ctx CAMELLIA context to be cleared + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief CAMELLIA key schedule (encryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief CAMELLIA key schedule (decryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key decryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief CAMELLIA-ECB block encryption/decryption + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief CAMELLIA-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief CAMELLIA-CFB128 buffer encryption/decryption + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief CAMELLIA-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. + * + * \param ctx CAMELLIA context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ccm.h b/external_libs/mbedtls/include/mbedtls/ccm.h new file mode 100644 index 00000000..ef75839b --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ccm.h @@ -0,0 +1,141 @@ +/** + * \file ccm.h + * + * \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CCM_H +#define MBEDTLS_CCM_H + +#include "cipher.h" + +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CCM context structure + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ +} +mbedtls_ccm_context; + +/** + * \brief Initialize CCM context (just makes references valid) + * Makes the context ready for mbedtls_ccm_setkey() or + * mbedtls_ccm_free(). + * + * \param ctx CCM context to initialize + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief CCM initialization (encryption and decryption) + * + * \param ctx CCM context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) + * \param key encryption key + * \param keybits key size in bits (must be acceptable by the cipher) + * + * \return 0 if successful, or a cipher specific error code + */ +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Free a CCM context and underlying cipher sub-context + * + * \param ctx CCM context to free + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief CCM buffer encryption + * + * \param ctx CCM context + * \param length length of the input data in bytes + * \param iv nonce (initialization vector) + * \param iv_len length of IV in bytes + * must be 2, 3, 4, 5, 6, 7 or 8 + * \param add additional data + * \param add_len length of additional data in bytes + * must be less than 2^16 - 2^8 + * \param input buffer holding the input data + * \param output buffer for holding the output data + * must be at least 'length' bytes wide + * \param tag buffer for holding the tag + * \param tag_len length of the tag to generate in bytes + * must be 4, 6, 8, 10, 14 or 16 + * + * \note The tag is written to a separate buffer. To get the tag + * concatenated with the output as in the CCM spec, use + * tag = output + length and make sure the output buffer is + * at least length + tag_len wide. + * + * \return 0 if successful + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief CCM buffer authenticated decryption + * + * \param ctx CCM context + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * \param tag buffer holding the tag + * \param tag_len length of the tag + * + * \return 0 if successful and authenticated, + * MBEDTLS_ERR_CCM_AUTH_FAILED if tag does not match + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ diff --git a/external_libs/mbedtls/include/mbedtls/certs.h b/external_libs/mbedtls/include/mbedtls/certs.h new file mode 100644 index 00000000..ca49086e --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/certs.h @@ -0,0 +1,99 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CERTS_H +#define MBEDTLS_CERTS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all CA certificates in PEM format if available */ +extern const char mbedtls_test_cas_pem[]; +extern const size_t mbedtls_test_cas_pem_len; +#endif + +/* List of all CA certificates, terminated by NULL */ +extern const char * mbedtls_test_cas[]; +extern const size_t mbedtls_test_cas_len[]; + +/* + * Convenience for users who just want a certificate: + * RSA by default, or ECDSA if RSA is not available + */ +extern const char * mbedtls_test_ca_crt; +extern const size_t mbedtls_test_ca_crt_len; +extern const char * mbedtls_test_ca_key; +extern const size_t mbedtls_test_ca_key_len; +extern const char * mbedtls_test_ca_pwd; +extern const size_t mbedtls_test_ca_pwd_len; +extern const char * mbedtls_test_srv_crt; +extern const size_t mbedtls_test_srv_crt_len; +extern const char * mbedtls_test_srv_key; +extern const size_t mbedtls_test_srv_key_len; +extern const char * mbedtls_test_cli_crt; +extern const size_t mbedtls_test_cli_crt_len; +extern const char * mbedtls_test_cli_key; +extern const size_t mbedtls_test_cli_key_len; + +#if defined(MBEDTLS_ECDSA_C) +extern const char mbedtls_test_ca_crt_ec[]; +extern const size_t mbedtls_test_ca_crt_ec_len; +extern const char mbedtls_test_ca_key_ec[]; +extern const size_t mbedtls_test_ca_key_ec_len; +extern const char mbedtls_test_ca_pwd_ec[]; +extern const size_t mbedtls_test_ca_pwd_ec_len; +extern const char mbedtls_test_srv_crt_ec[]; +extern const size_t mbedtls_test_srv_crt_ec_len; +extern const char mbedtls_test_srv_key_ec[]; +extern const size_t mbedtls_test_srv_key_ec_len; +extern const char mbedtls_test_cli_crt_ec[]; +extern const size_t mbedtls_test_cli_crt_ec_len; +extern const char mbedtls_test_cli_key_ec[]; +extern const size_t mbedtls_test_cli_key_ec_len; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const char mbedtls_test_ca_crt_rsa[]; +extern const size_t mbedtls_test_ca_crt_rsa_len; +extern const char mbedtls_test_ca_key_rsa[]; +extern const size_t mbedtls_test_ca_key_rsa_len; +extern const char mbedtls_test_ca_pwd_rsa[]; +extern const size_t mbedtls_test_ca_pwd_rsa_len; +extern const char mbedtls_test_srv_crt_rsa[]; +extern const size_t mbedtls_test_srv_crt_rsa_len; +extern const char mbedtls_test_srv_key_rsa[]; +extern const size_t mbedtls_test_srv_key_rsa_len; +extern const char mbedtls_test_cli_crt_rsa[]; +extern const size_t mbedtls_test_cli_crt_rsa_len; +extern const char mbedtls_test_cli_key_rsa[]; +extern const size_t mbedtls_test_cli_key_rsa_len; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* certs.h */ diff --git a/external_libs/mbedtls/include/mbedtls/check_config.h b/external_libs/mbedtls/include/mbedtls/check_config.h new file mode 100644 index 00000000..fe86c1e8 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/check_config.h @@ -0,0 +1,628 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.pl. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && \ + ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) +#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_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/external_libs/mbedtls/include/mbedtls/cipher.h b/external_libs/mbedtls/include/mbedtls/cipher.h new file mode 100644 index 00000000..b12e3884 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/cipher.h @@ -0,0 +1,709 @@ +/** + * \file cipher.h + * + * \brief Generic cipher wrapper. + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid, eg because it was free()ed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, + MBEDTLS_CIPHER_ID_NULL, + MBEDTLS_CIPHER_ID_AES, + MBEDTLS_CIPHER_ID_DES, + MBEDTLS_CIPHER_ID_3DES, + MBEDTLS_CIPHER_ID_CAMELLIA, + MBEDTLS_CIPHER_ID_BLOWFISH, + MBEDTLS_CIPHER_ID_ARC4, +} mbedtls_cipher_id_t; + +typedef enum { + MBEDTLS_CIPHER_NONE = 0, + MBEDTLS_CIPHER_NULL, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_CIPHER_CAMELLIA_256_CCM, +} mbedtls_cipher_type_t; + +typedef enum { + MBEDTLS_MODE_NONE = 0, + MBEDTLS_MODE_ECB, + MBEDTLS_MODE_CBC, + MBEDTLS_MODE_CFB, + MBEDTLS_MODE_OFB, /* Unused! */ + MBEDTLS_MODE_CTR, + MBEDTLS_MODE_GCM, + MBEDTLS_MODE_STREAM, + MBEDTLS_MODE_CCM, +} mbedtls_cipher_mode_t; + +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default) */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding */ + MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible!) */ + MBEDTLS_PADDING_NONE, /**< never pad (full blocks only) */ +} mbedtls_cipher_padding_t; + +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length, in bits (including parity), for DES in two key EDE */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length, in bits (including parity), for DES in three-key EDE */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in bytes */ +#define MBEDTLS_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in bytes */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows cipher functions to be called in a generic way. + */ +typedef struct { + /** Full cipher identifier (e.g. MBEDTLS_CIPHER_AES_256_CBC) */ + mbedtls_cipher_type_t type; + + /** Cipher mode (e.g. MBEDTLS_MODE_CBC) */ + mbedtls_cipher_mode_t mode; + + /** Cipher key length, in bits (default length for variable sized ciphers) + * (Includes parity bits for ciphers like DES) */ + unsigned int key_bitlen; + + /** Name of the cipher */ + const char * name; + + /** IV/NONCE size, in bytes. + * For cipher that accept many sizes: recommended size */ + unsigned int iv_size; + + /** Flags for variable IV size, variable key size, etc. */ + int flags; + + /** block size, in bytes */ + unsigned int block_size; + + /** Base cipher information and functions */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct { + /** Information about the associated cipher */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use */ + int key_bitlen; + + /** Operation that the context's key has been initialised for */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for cipher mode */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for data that hasn't been encrypted yet */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of bytes that still need processing */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in bytes (for ciphers with variable-length IVs) */ + size_t iv_size; + + /** Cipher-specific context */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC Specific context */ + mbedtls_cmac_context_t *cmac_ctx; +#endif +} mbedtls_cipher_context_t; + +/** + * \brief Returns the list of ciphers supported by the generic cipher module. + * + * \return a statically allocated array of ciphers, the last entry + * is 0. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. + * + * \return the cipher information structure associated with the + * given cipher_name, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return the cipher information structure associated with the + * given cipher_type, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher id, key size and mode. + * + * \param cipher_id Id of the cipher to search for + * (e.g. MBEDTLS_CIPHER_ID_AES) + * \param key_bitlen Length of the key in bits + * \param mode Cipher mode (e.g. MBEDTLS_MODE_CBC) + * + * \return the cipher information structure associated with the + * given cipher_type, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief Initialize a cipher_context (as NONE) + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief Free and clear the cipher-specific context of ctx. + * Freeing ctx itself remains the responsibility of the + * caller. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + +/** + * \brief Initialises and fills the cipher context structure with + * the appropriate values. + * + * \note Currently also clears structure. In future versions you + * will be required to call mbedtls_cipher_init() on the structure + * first. + * + * \param ctx context to initialise. May not be NULL. + * \param cipher_info cipher to use. + * + * \return 0 on success, + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, + * MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context failed. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); + +/** + * \brief Returns the block size of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return size of the cipher's blocks, or 0 if ctx has not been + * initialised. + */ +static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief Returns the mode of operation for the cipher. + * (e.g. MBEDTLS_MODE_CBC) + * + * \param ctx cipher's context. Must have been initialised. + * + * \return mode of operation, or MBEDTLS_MODE_NONE if ctx + * has not been initialised. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief Returns the size of the cipher's IV/NONCE in bytes. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return If IV has not been set yet: (recommended) IV size + * (0 for ciphers not using IV/NONCE). + * If IV has already been set: actual size. + */ +static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief Returns the type of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return type of the cipher, or MBEDTLS_CIPHER_NONE if ctx has + * not been initialised. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief Returns the name of the given cipher, as a string. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return name of the cipher, or NULL if ctx was not initialised. + */ +static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief Returns the key length of the cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return cipher's key length, in bits, or + * MBEDTLS_KEY_LENGTH_NONE if ctx has not been + * initialised. + */ +static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief Returns the operation of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return operation (MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT), + * or MBEDTLS_OPERATION_NONE if ctx has not been + * initialised. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief Set the key to use with the given context. + * + * \param ctx generic cipher context. May not be NULL. Must have been + * initialised using cipher_context_from_type or + * cipher_context_from_string. + * \param key The key to use. + * \param key_bitlen key length to use, in bits. + * \param operation Operation that the key will be used for, either + * MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT. + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails or a cipher specific + * error code. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief Set padding mode, for cipher modes that use padding. + * (Default: PKCS7 padding.) + * + * \param ctx generic cipher context + * \param mode padding mode + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if selected padding mode is not supported, or + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief Set the initialization vector (IV) or nonce + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * + * \returns 0 on success, or MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * + * \note Some ciphers don't use IVs nor NONCE. For these + * ciphers, this function has no effect. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ); + +/** + * \brief Finish preparation of the given context + * + * \param ctx generic cipher context + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief Add additional data (for AEAD ciphers). + * Currently only supported with GCM. + * Must be called exactly once, after mbedtls_cipher_reset(). + * + * \param ctx generic cipher context + * \param ad Additional data to use. + * \param ad_len Length of ad. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief Generic cipher update function. Encrypts/decrypts + * using the given cipher context. Writes as many block + * size'd blocks of data as possible to output. Any data + * that cannot be written immediately will either be added + * to the next block, or flushed when cipher_final is + * called. + * Exception: for MBEDTLS_MODE_ECB, expects single block + * in size (e.g. 16 bytes for AES) + * + * \param ctx generic cipher context + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. Should be able to hold at + * least ilen + block_size. Cannot be the same buffer as + * input! + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher or a cipher specific + * error code. + * + * \note If the underlying cipher is GCM, all calls to this + * function, except the last one before mbedtls_cipher_finish(), + * must have ilen a multiple of the block size. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ); + +/** + * \brief Generic cipher finalisation function. If data still + * needs to be flushed from an incomplete block, data + * contained within it will be padded with the size of + * the last block, and written to the output buffer. + * + * \param ctx Generic cipher context + * \param output buffer to write data to. Needs block_size available. + * \param olen length of the data written to the output buffer. + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, + * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting or a cipher specific error code. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief Write tag for AEAD ciphers. + * Currently only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx Generic cipher context + * \param tag buffer to write the tag + * \param tag_len Length of the tag to write + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief Check tag for AEAD ciphers. + * Currently only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx Generic cipher context + * \param tag Buffer holding the tag + * \param tag_len Length of the tag to check + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief Generic all-in-one encryption/decryption + * (for all ciphers except AEAD constructs). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. Should be able to hold at + * least ilen + block_size. Cannot be the same buffer as + * input! + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * + * \note Some ciphers don't use IVs nor NONCE. For these + * ciphers, use iv = NULL and iv_len = 0. + * + * \returns 0 on success, or + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, or + * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting, or + * a cipher specific error code. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/** + * \brief Generic autenticated encryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to authenticate. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer for the authentication tag + * \param tag_len desired tag length + * + * \returns 0 on success, or + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * a cipher specific error code. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief Generic autenticated decryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to be authenticated. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer holding the authentication tag + * \param tag_len length of the authentication tag + * + * \returns 0 on success, or + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * MBEDTLS_ERR_CIPHER_AUTH_FAILED if data isn't authentic, + * or a cipher specific error code. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext to + * be used by mistake, making this interface safer. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ diff --git a/external_libs/mbedtls/include/mbedtls/cipher_internal.h b/external_libs/mbedtls/include/mbedtls/cipher_internal.h new file mode 100644 index 00000000..6c58bcc5 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/cipher_internal.h @@ -0,0 +1,109 @@ +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/external_libs/mbedtls/include/mbedtls/cmac.h b/external_libs/mbedtls/include/mbedtls/cmac.h new file mode 100644 index 00000000..75e0b97c --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/cmac.h @@ -0,0 +1,166 @@ +/** + * \file cmac.h + * + * \brief Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication + * + * Copyright (C) 2015-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CMAC_H +#define MBEDTLS_CMAC_H + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_AES_BLOCK_SIZE 16 +#define MBEDTLS_DES3_BLOCK_SIZE 8 + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /* longest used by CMAC is AES */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */ +#endif + +/** + * CMAC context structure - Contains internal state information only + */ +struct mbedtls_cmac_context_t +{ + /** Internal state of the CMAC algorithm */ + unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Unprocessed data - either data that was not block aligned and is still + * pending to be processed, or the final block */ + unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Length of data pending to be processed */ + size_t unprocessed_len; +}; + +/** + * \brief Set the CMAC key and prepare to authenticate the input + * data. + * Should be called with an initialised cipher context. + * + * \param ctx Cipher context + * \param key CMAC key + * \param keybits length of the CMAC key in bits + * (must be acceptable by the cipher) + * + * \return 0 if successful, or a cipher specific error code + */ +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ); + +/** + * \brief Generic CMAC process buffer. + * Called between mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset() and + * mbedtls_cipher_cmac_finish(). + * May be called repeatedly. + * + * \param ctx CMAC context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief Output CMAC. + * Called after mbedtls_cipher_cmac_update(). + * Usually followed by mbedtls_cipher_cmac_reset(), then + * mbedtls_cipher_cmac_starts(), or mbedtls_cipher_free(). + * + * \param ctx CMAC context + * \param output Generic CMAC checksum result + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); + +/** + * \brief Prepare to authenticate a new message with the same key. + * Called after mbedtls_cipher_cmac_finish() and before + * mbedtls_cipher_cmac_update(). + * + * \param ctx CMAC context to be reset + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); + +/** + * \brief Output = Generic_CMAC( hmac key, input buffer ) + * + * \param cipher_info message digest info + * \param key CMAC key + * \param keylen length of the CMAC key in bits + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic CMAC-result + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_AES_C) +/** + * \brief AES-CMAC-128-PRF + * Implementation of (AES-CMAC-PRF-128), as defined in RFC 4615 + * + * \param key PRF key + * \param key_len PRF key length in bytes + * \param input buffer holding the input data + * \param in_len length of the input data in bytes + * \param output buffer holding the generated pseudorandom output (16 bytes) + * + * \return 0 if successful + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, + const unsigned char *input, size_t in_len, + unsigned char output[16] ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_cmac_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/external_libs/mbedtls/include/mbedtls/compat-1.3.h b/external_libs/mbedtls/include/mbedtls/compat-1.3.h new file mode 100644 index 00000000..27abbd97 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/compat-1.3.h @@ -0,0 +1,2634 @@ +/** + * \file compat-1.3.h + * + * \brief Compatibility definitions for using mbed TLS with client code written + * for the PolarSSL naming conventions. + * + * \deprecated Use the new names directly instead + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Including compat-1.3.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT13_H +#define MBEDTLS_COMPAT13_H + +/* + * config.h options + */ +#if defined MBEDTLS_AESNI_C +#define POLARSSL_AESNI_C MBEDTLS_AESNI_C +#endif +#if defined MBEDTLS_AES_ALT +#define POLARSSL_AES_ALT MBEDTLS_AES_ALT +#endif +#if defined MBEDTLS_AES_C +#define POLARSSL_AES_C MBEDTLS_AES_C +#endif +#if defined MBEDTLS_AES_ROM_TABLES +#define POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES +#endif +#if defined MBEDTLS_ARC4_ALT +#define POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT +#endif +#if defined MBEDTLS_ARC4_C +#define POLARSSL_ARC4_C MBEDTLS_ARC4_C +#endif +#if defined MBEDTLS_ASN1_PARSE_C +#define POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C +#endif +#if defined MBEDTLS_ASN1_WRITE_C +#define POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C +#endif +#if defined MBEDTLS_BASE64_C +#define POLARSSL_BASE64_C MBEDTLS_BASE64_C +#endif +#if defined MBEDTLS_BIGNUM_C +#define POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C +#endif +#if defined MBEDTLS_BLOWFISH_ALT +#define POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT +#endif +#if defined MBEDTLS_BLOWFISH_C +#define POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C +#endif +#if defined MBEDTLS_CAMELLIA_ALT +#define POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT +#endif +#if defined MBEDTLS_CAMELLIA_C +#define POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C +#endif +#if defined MBEDTLS_CAMELLIA_SMALL_MEMORY +#define POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY +#endif +#if defined MBEDTLS_CCM_C +#define POLARSSL_CCM_C MBEDTLS_CCM_C +#endif +#if defined MBEDTLS_CERTS_C +#define POLARSSL_CERTS_C MBEDTLS_CERTS_C +#endif +#if defined MBEDTLS_CIPHER_C +#define POLARSSL_CIPHER_C MBEDTLS_CIPHER_C +#endif +#if defined MBEDTLS_CIPHER_MODE_CBC +#define POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC +#endif +#if defined MBEDTLS_CIPHER_MODE_CFB +#define POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB +#endif +#if defined MBEDTLS_CIPHER_MODE_CTR +#define POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR +#endif +#if defined MBEDTLS_CIPHER_NULL_CIPHER +#define POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER +#endif +#if defined MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#endif +#if defined MBEDTLS_CTR_DRBG_C +#define POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C +#endif +#if defined MBEDTLS_DEBUG_C +#define POLARSSL_DEBUG_C MBEDTLS_DEBUG_C +#endif +#if defined MBEDTLS_DEPRECATED_REMOVED +#define POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED +#endif +#if defined MBEDTLS_DEPRECATED_WARNING +#define POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING +#endif +#if defined MBEDTLS_DES_ALT +#define POLARSSL_DES_ALT MBEDTLS_DES_ALT +#endif +#if defined MBEDTLS_DES_C +#define POLARSSL_DES_C MBEDTLS_DES_C +#endif +#if defined MBEDTLS_DHM_C +#define POLARSSL_DHM_C MBEDTLS_DHM_C +#endif +#if defined MBEDTLS_ECDH_C +#define POLARSSL_ECDH_C MBEDTLS_ECDH_C +#endif +#if defined MBEDTLS_ECDSA_C +#define POLARSSL_ECDSA_C MBEDTLS_ECDSA_C +#endif +#if defined MBEDTLS_ECDSA_DETERMINISTIC +#define POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC +#endif +#if defined MBEDTLS_ECP_C +#define POLARSSL_ECP_C MBEDTLS_ECP_C +#endif +#if defined MBEDTLS_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP512R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED +#endif +#if defined MBEDTLS_ECP_FIXED_POINT_OPTIM +#define POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM +#endif +#if defined MBEDTLS_ECP_MAX_BITS +#define POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS +#endif +#if defined MBEDTLS_ECP_NIST_OPTIM +#define POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM +#endif +#if defined MBEDTLS_ECP_WINDOW_SIZE +#define POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE +#endif +#if defined MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#endif +#if defined MBEDTLS_ENTROPY_C +#define POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C +#endif +#if defined MBEDTLS_ENTROPY_FORCE_SHA256 +#define POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 +#endif +#if defined MBEDTLS_ERROR_C +#define POLARSSL_ERROR_C MBEDTLS_ERROR_C +#endif +#if defined MBEDTLS_ERROR_STRERROR_BC +#define POLARSSL_ERROR_STRERROR_BC MBEDTLS_ERROR_STRERROR_BC +#endif +#if defined MBEDTLS_ERROR_STRERROR_DUMMY +#define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY +#endif +#if defined MBEDTLS_FS_IO +#define POLARSSL_FS_IO MBEDTLS_FS_IO +#endif +#if defined MBEDTLS_GCM_C +#define POLARSSL_GCM_C MBEDTLS_GCM_C +#endif +#if defined MBEDTLS_GENPRIME +#define POLARSSL_GENPRIME MBEDTLS_GENPRIME +#endif +#if defined MBEDTLS_HAVEGE_C +#define POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C +#endif +#if defined MBEDTLS_HAVE_ASM +#define POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM +#endif +#if defined MBEDTLS_HAVE_SSE2 +#define POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 +#endif +#if defined MBEDTLS_HAVE_TIME +#define POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME +#endif +#if defined MBEDTLS_HMAC_DRBG_C +#define POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_INPUT +#define POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_REQUEST +#define POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#endif +#if defined MBEDTLS_MD2_ALT +#define POLARSSL_MD2_ALT MBEDTLS_MD2_ALT +#endif +#if defined MBEDTLS_MD2_C +#define POLARSSL_MD2_C MBEDTLS_MD2_C +#endif +#if defined MBEDTLS_MD2_PROCESS_ALT +#define POLARSSL_MD2_PROCESS_ALT MBEDTLS_MD2_PROCESS_ALT +#endif +#if defined MBEDTLS_MD4_ALT +#define POLARSSL_MD4_ALT MBEDTLS_MD4_ALT +#endif +#if defined MBEDTLS_MD4_C +#define POLARSSL_MD4_C MBEDTLS_MD4_C +#endif +#if defined MBEDTLS_MD4_PROCESS_ALT +#define POLARSSL_MD4_PROCESS_ALT MBEDTLS_MD4_PROCESS_ALT +#endif +#if defined MBEDTLS_MD5_ALT +#define POLARSSL_MD5_ALT MBEDTLS_MD5_ALT +#endif +#if defined MBEDTLS_MD5_C +#define POLARSSL_MD5_C MBEDTLS_MD5_C +#endif +#if defined MBEDTLS_MD5_PROCESS_ALT +#define POLARSSL_MD5_PROCESS_ALT MBEDTLS_MD5_PROCESS_ALT +#endif +#if defined MBEDTLS_MD_C +#define POLARSSL_MD_C MBEDTLS_MD_C +#endif +#if defined MBEDTLS_MEMORY_ALIGN_MULTIPLE +#define POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE +#endif +#if defined MBEDTLS_MEMORY_BACKTRACE +#define POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE +#endif +#if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C +#endif +#if defined MBEDTLS_MEMORY_C +#define POLARSSL_MEMORY_C MBEDTLS_MEMORY_C +#endif +#if defined MBEDTLS_MEMORY_DEBUG +#define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG +#endif +#if defined MBEDTLS_MPI_MAX_SIZE +#define POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif +#if defined MBEDTLS_MPI_WINDOW_SIZE +#define POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE +#endif +#if defined MBEDTLS_NET_C +#define POLARSSL_NET_C MBEDTLS_NET_C +#endif +#if defined MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#endif +#if defined MBEDTLS_NO_PLATFORM_ENTROPY +#define POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY +#endif +#if defined MBEDTLS_OID_C +#define POLARSSL_OID_C MBEDTLS_OID_C +#endif +#if defined MBEDTLS_PADLOCK_C +#define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C +#endif +#if defined MBEDTLS_PBKDF2_C +#define POLARSSL_PBKDF2_C MBEDTLS_PBKDF2_C +#endif +#if defined MBEDTLS_PEM_PARSE_C +#define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C +#endif +#if defined MBEDTLS_PEM_WRITE_C +#define POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C +#endif +#if defined MBEDTLS_PKCS11_C +#define POLARSSL_PKCS11_C MBEDTLS_PKCS11_C +#endif +#if defined MBEDTLS_PKCS12_C +#define POLARSSL_PKCS12_C MBEDTLS_PKCS12_C +#endif +#if defined MBEDTLS_PKCS1_V15 +#define POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 +#endif +#if defined MBEDTLS_PKCS1_V21 +#define POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 +#endif +#if defined MBEDTLS_PKCS5_C +#define POLARSSL_PKCS5_C MBEDTLS_PKCS5_C +#endif +#if defined MBEDTLS_PK_C +#define POLARSSL_PK_C MBEDTLS_PK_C +#endif +#if defined MBEDTLS_PK_PARSE_C +#define POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C +#endif +#if defined MBEDTLS_PK_PARSE_EC_EXTENDED +#define POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED +#endif +#if defined MBEDTLS_PK_RSA_ALT_SUPPORT +#define POLARSSL_PK_RSA_ALT_SUPPORT MBEDTLS_PK_RSA_ALT_SUPPORT +#endif +#if defined MBEDTLS_PK_WRITE_C +#define POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C +#endif +#if defined MBEDTLS_PLATFORM_C +#define POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C +#endif +#if defined MBEDTLS_PLATFORM_EXIT_ALT +#define POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT +#endif +#if defined MBEDTLS_PLATFORM_EXIT_MACRO +#define POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_ALT +#define POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_MACRO +#define POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FREE_MACRO +#define POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO +#endif +#if defined MBEDTLS_PLATFORM_MEMORY +#define POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY +#endif +#if defined MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_ALT +#define POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_MACRO +#define POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_ALT +#define POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_MACRO +#define POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_STD_EXIT +#define POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT +#endif +#if defined MBEDTLS_PLATFORM_STD_FPRINTF +#define POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_FREE +#define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE +#endif +#if defined MBEDTLS_PLATFORM_STD_MALLOC +#define POLARSSL_PLATFORM_STD_MALLOC MBEDTLS_PLATFORM_STD_MALLOC +#endif +#if defined MBEDTLS_PLATFORM_STD_MEM_HDR +#define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#if defined MBEDTLS_PLATFORM_STD_PRINTF +#define POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_SNPRINTF +#define POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF +#endif +#if defined MBEDTLS_PSK_MAX_LEN +#define POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN +#endif +#if defined MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#endif +#if defined MBEDTLS_RIPEMD160_ALT +#define POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT +#endif +#if defined MBEDTLS_RIPEMD160_C +#define POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C +#endif +#if defined MBEDTLS_RIPEMD160_PROCESS_ALT +#define POLARSSL_RIPEMD160_PROCESS_ALT MBEDTLS_RIPEMD160_PROCESS_ALT +#endif +#if defined MBEDTLS_RSA_C +#define POLARSSL_RSA_C MBEDTLS_RSA_C +#endif +#if defined MBEDTLS_RSA_NO_CRT +#define POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT +#endif +#if defined MBEDTLS_SELF_TEST +#define POLARSSL_SELF_TEST MBEDTLS_SELF_TEST +#endif +#if defined MBEDTLS_SHA1_ALT +#define POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT +#endif +#if defined MBEDTLS_SHA1_C +#define POLARSSL_SHA1_C MBEDTLS_SHA1_C +#endif +#if defined MBEDTLS_SHA1_PROCESS_ALT +#define POLARSSL_SHA1_PROCESS_ALT MBEDTLS_SHA1_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA256_ALT +#define POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT +#endif +#if defined MBEDTLS_SHA256_C +#define POLARSSL_SHA256_C MBEDTLS_SHA256_C +#endif +#if defined MBEDTLS_SHA256_PROCESS_ALT +#define POLARSSL_SHA256_PROCESS_ALT MBEDTLS_SHA256_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA512_ALT +#define POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT +#endif +#if defined MBEDTLS_SHA512_C +#define POLARSSL_SHA512_C MBEDTLS_SHA512_C +#endif +#if defined MBEDTLS_SHA512_PROCESS_ALT +#define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT +#endif +#if defined MBEDTLS_SSL_AEAD_RANDOM_IV +#define POLARSSL_SSL_AEAD_RANDOM_IV MBEDTLS_SSL_AEAD_RANDOM_IV +#endif +#if defined MBEDTLS_SSL_ALERT_MESSAGES +#define POLARSSL_SSL_ALERT_MESSAGES MBEDTLS_SSL_ALERT_MESSAGES +#endif +#if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES +#endif +#if defined MBEDTLS_SSL_ALPN +#define POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN +#endif +#if defined MBEDTLS_SSL_CACHE_C +#define POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C +#endif +#if defined MBEDTLS_SSL_CBC_RECORD_SPLITTING +#define POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING +#endif +#if defined MBEDTLS_SSL_CLI_C +#define POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C +#endif +#if defined MBEDTLS_SSL_COOKIE_C +#define POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C +#endif +#if defined MBEDTLS_SSL_COOKIE_TIMEOUT +#define POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT +#endif +#if defined MBEDTLS_SSL_DEBUG_ALL +#define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL +#endif +#if defined MBEDTLS_SSL_DISABLE_RENEGOTIATION +#define POLARSSL_SSL_DISABLE_RENEGOTIATION MBEDTLS_SSL_DISABLE_RENEGOTIATION +#endif +#if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY +#endif +#if defined MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#define POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#endif +#if defined MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY +#endif +#if defined MBEDTLS_SSL_ENCRYPT_THEN_MAC +#define POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC +#endif +#if defined MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#define POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#endif +#if defined MBEDTLS_SSL_FALLBACK_SCSV +#define POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#endif +#if defined MBEDTLS_SSL_HW_RECORD_ACCEL +#define POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL +#endif +#if defined MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#endif +#if defined MBEDTLS_SSL_PROTO_DTLS +#define POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS +#endif +#if defined MBEDTLS_SSL_PROTO_SSL3 +#define POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1 +#define POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_1 +#define POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_2 +#define POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 +#endif +#if defined MBEDTLS_SSL_RENEGOTIATION +#define POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#endif +#if defined MBEDTLS_SSL_SERVER_NAME_INDICATION +#define POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif +#if defined MBEDTLS_SSL_SESSION_TICKETS +#define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS +#endif +#if defined MBEDTLS_SSL_SRV_C +#define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C +#endif +#if defined MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#endif +#if defined MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#endif +#if defined MBEDTLS_SSL_TLS_C +#define POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C +#endif +#if defined MBEDTLS_SSL_TRUNCATED_HMAC +#define POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC +#endif +#if defined MBEDTLS_THREADING_ALT +#define POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT +#endif +#if defined MBEDTLS_THREADING_C +#define POLARSSL_THREADING_C MBEDTLS_THREADING_C +#endif +#if defined MBEDTLS_THREADING_PTHREAD +#define POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD +#endif +#if defined MBEDTLS_TIMING_ALT +#define POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT +#endif +#if defined MBEDTLS_TIMING_C +#define POLARSSL_TIMING_C MBEDTLS_TIMING_C +#endif +#if defined MBEDTLS_VERSION_C +#define POLARSSL_VERSION_C MBEDTLS_VERSION_C +#endif +#if defined MBEDTLS_VERSION_FEATURES +#define POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES +#endif +#if defined MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#endif +#if defined MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#endif +#if defined MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CHECK_KEY_USAGE +#define POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CREATE_C +#define POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C +#endif +#if defined MBEDTLS_X509_CRL_PARSE_C +#define POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_PARSE_C +#define POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_WRITE_C +#define POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C +#endif +#if defined MBEDTLS_X509_CSR_PARSE_C +#define POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C +#endif +#if defined MBEDTLS_X509_CSR_WRITE_C +#define POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C +#endif +#if defined MBEDTLS_X509_MAX_INTERMEDIATE_CA +#define POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA +#endif +#if defined MBEDTLS_X509_RSASSA_PSS_SUPPORT +#define POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT +#endif +#if defined MBEDTLS_X509_USE_C +#define POLARSSL_X509_USE_C MBEDTLS_X509_USE_C +#endif +#if defined MBEDTLS_XTEA_ALT +#define POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT +#endif +#if defined MBEDTLS_XTEA_C +#define POLARSSL_XTEA_C MBEDTLS_XTEA_C +#endif +#if defined MBEDTLS_ZLIB_SUPPORT +#define POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT +#endif + +/* + * Misc names (macros, types, functions, enum constants...) + */ +#define AES_DECRYPT MBEDTLS_AES_DECRYPT +#define AES_ENCRYPT MBEDTLS_AES_ENCRYPT +#define ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING +#define ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING +#define ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN +#define ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD +#define ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED +#define ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC +#define ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME +#define ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING +#define ASN1_INTEGER MBEDTLS_ASN1_INTEGER +#define ASN1_NULL MBEDTLS_ASN1_NULL +#define ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING +#define ASN1_OID MBEDTLS_ASN1_OID +#define ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE +#define ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING +#define ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE +#define ASN1_SET MBEDTLS_ASN1_SET +#define ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING +#define ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING +#define ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME +#define ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING +#define BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH +#define BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED +#define BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE +#define BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING +#define BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED +#define BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER +#define BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED +#define BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY +#define BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED +#define BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE +#define BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED +#define BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE +#define BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT +#define BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT +#define BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS +#define BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS +#define BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS +#define CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT +#define CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT +#define COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE +#define CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE +#define CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN +#define CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS +#define CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE +#define CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT +#define CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +#define CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +#define CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF +#define CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON +#define CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL +#define CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN +#define DEPRECATED MBEDTLS_DEPRECATED +#define DES_DECRYPT MBEDTLS_DES_DECRYPT +#define DES_ENCRYPT MBEDTLS_DES_ENCRYPT +#define DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE +#define ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE +#define ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER +#define ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE +#define ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES +#define ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK +#define ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE +#define ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM +#define ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL +#define EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS +#define EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES +#define EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS +#define EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE +#define EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL +#define EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY +#define EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME +#define EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE +#define EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS +#define EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE +#define EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS +#define EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS +#define EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME +#define EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define GCM_DECRYPT MBEDTLS_GCM_DECRYPT +#define GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT +#define KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN +#define KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT +#define KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE +#define KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT +#define KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN +#define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT +#define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION +#define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 +#define MD_CONTEXT_T_INIT MBEDTLS_MD_CONTEXT_T_INIT +#define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC +#define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS +#define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE +#define MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE +#define MPI_CHK MBEDTLS_MPI_CHK +#define NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP +#define NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP +#define NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL +#define NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA +#define NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING +#define NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA +#define NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED +#define NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA +#define NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT +#define NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER +#define OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 +#define OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE +#define OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD +#define OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG +#define OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 +#define OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE +#define OID_AT MBEDTLS_OID_AT +#define OID_AT_CN MBEDTLS_OID_AT_CN +#define OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY +#define OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER +#define OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER +#define OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME +#define OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS +#define OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY +#define OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION +#define OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT +#define OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS +#define OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE +#define OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM +#define OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER +#define OID_AT_STATE MBEDTLS_OID_AT_STATE +#define OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME +#define OID_AT_TITLE MBEDTLS_OID_AT_TITLE +#define OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER +#define OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER +#define OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS +#define OID_CERTICOM MBEDTLS_OID_CERTICOM +#define OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES +#define OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH +#define OID_CMP MBEDTLS_OID_CMP +#define OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING +#define OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US +#define OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS +#define OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER +#define OID_DES_CBC MBEDTLS_OID_DES_CBC +#define OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC +#define OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 +#define OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 +#define OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 +#define OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 +#define OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 +#define OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 +#define OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 +#define OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 +#define OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT +#define OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 +#define OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 +#define OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 +#define OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 +#define OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 +#define OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH +#define OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED +#define OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 +#define OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 +#define OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 +#define OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 +#define OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 +#define OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 +#define OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 +#define OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 +#define OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 +#define OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 +#define OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 +#define OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 +#define OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION +#define OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE +#define OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL +#define OID_GOV MBEDTLS_OID_GOV +#define OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 +#define OID_ID_CE MBEDTLS_OID_ID_CE +#define OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY +#define OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS +#define OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG +#define OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY +#define OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG +#define OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES +#define OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME +#define OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE +#define OID_KP MBEDTLS_OID_KP +#define OID_MGF1 MBEDTLS_OID_MGF1 +#define OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS +#define OID_NETSCAPE MBEDTLS_OID_NETSCAPE +#define OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL +#define OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL +#define OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL +#define OID_NS_CERT MBEDTLS_OID_NS_CERT +#define OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE +#define OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE +#define OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT +#define OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE +#define OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL +#define OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL +#define OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME +#define OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING +#define OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG +#define OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG +#define OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 +#define OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION +#define OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 +#define OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM +#define OID_ORG_DOD MBEDTLS_OID_ORG_DOD +#define OID_ORG_GOV MBEDTLS_OID_ORG_GOV +#define OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE +#define OID_ORG_OIW MBEDTLS_OID_ORG_OIW +#define OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY +#define OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST +#define OID_PKCS MBEDTLS_OID_PKCS +#define OID_PKCS1 MBEDTLS_OID_PKCS1 +#define OID_PKCS12 MBEDTLS_OID_PKCS12 +#define OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE +#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC +#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC +#define OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC +#define OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC +#define OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 +#define OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 +#define OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 +#define OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 +#define OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 +#define OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA +#define OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 +#define OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 +#define OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 +#define OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 +#define OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 +#define OID_PKCS5 MBEDTLS_OID_PKCS5 +#define OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 +#define OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC +#define OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC +#define OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC +#define OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC +#define OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC +#define OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC +#define OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 +#define OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 +#define OID_PKCS9 MBEDTLS_OID_PKCS9 +#define OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ +#define OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL +#define OID_PKIX MBEDTLS_OID_PKIX +#define OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS +#define OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS +#define OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD +#define OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS +#define OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY +#define OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS +#define OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH +#define OID_SIZE MBEDTLS_OID_SIZE +#define OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME +#define OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS +#define OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER +#define OID_TELETRUST MBEDTLS_OID_TELETRUST +#define OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING +#define PADLOCK_ACE MBEDTLS_PADLOCK_ACE +#define PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 +#define PADLOCK_PHE MBEDTLS_PADLOCK_PHE +#define PADLOCK_PMM MBEDTLS_PADLOCK_PMM +#define PADLOCK_RNG MBEDTLS_PADLOCK_RNG +#define PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV +#define PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY +#define PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY +#define PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT +#define PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT +#define PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT +#define PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT +#define POLARSSL_AESNI_AES MBEDTLS_AESNI_AES +#define POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL +#define POLARSSL_AESNI_H MBEDTLS_AESNI_H +#define POLARSSL_AES_H MBEDTLS_AES_H +#define POLARSSL_ARC4_H MBEDTLS_ARC4_H +#define POLARSSL_ASN1_H MBEDTLS_ASN1_H +#define POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H +#define POLARSSL_BASE64_H MBEDTLS_BASE64_H +#define POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H +#define POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H +#define POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H +#define POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H +#define POLARSSL_CCM_H MBEDTLS_CCM_H +#define POLARSSL_CERTS_H MBEDTLS_CERTS_H +#define POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H +#define POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS +#define POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG +#define POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK +#define POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC +#define POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM +#define POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 +#define POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR +#define POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB +#define POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM +#define POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC +#define POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM +#define POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 +#define POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR +#define POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB +#define POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM +#define POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC +#define POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM +#define POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 +#define POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR +#define POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB +#define POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM +#define POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 +#define POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC +#define POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 +#define POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR +#define POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC +#define POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM +#define POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR +#define POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM +#define POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC +#define POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM +#define POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR +#define POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB +#define POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM +#define POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC +#define POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM +#define POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR +#define POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB +#define POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM +#define POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC +#define POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB +#define POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC +#define POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB +#define POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC +#define POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB +#define POLARSSL_CIPHER_H MBEDTLS_CIPHER_H +#define POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES +#define POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES +#define POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 +#define POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH +#define POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA +#define POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES +#define POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE +#define POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL +#define POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD +#define POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM +#define POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING +#define POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE +#define POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL +#define POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN +#define POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN +#define POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H +#define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H +#define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H +#define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H +#define POLARSSL_DEBUG_LOG_FULL MBEDTLS_DEBUG_LOG_FULL +#define POLARSSL_DEBUG_LOG_RAW MBEDTLS_DEBUG_LOG_RAW +#define POLARSSL_DECRYPT MBEDTLS_DECRYPT +#define POLARSSL_DES_H MBEDTLS_DES_H +#define POLARSSL_DHM_H MBEDTLS_DHM_H +#define POLARSSL_DHM_RFC2409_MODP_1024_G MBEDTLS_DHM_RFC2409_MODP_1024_G +#define POLARSSL_DHM_RFC2409_MODP_1024_P MBEDTLS_DHM_RFC2409_MODP_1024_P +#define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G +#define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P +#define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G +#define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P +#define POLARSSL_DHM_RFC5114_MODP_1024_G MBEDTLS_DHM_RFC5114_MODP_1024_G +#define POLARSSL_DHM_RFC5114_MODP_1024_P MBEDTLS_DHM_RFC5114_MODP_1024_P +#define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G +#define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P +#define POLARSSL_ECDH_H MBEDTLS_ECDH_H +#define POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS +#define POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS +#define POLARSSL_ECDSA_H MBEDTLS_ECDSA_H +#define POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 +#define POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 +#define POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 +#define POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 +#define POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX +#define POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE +#define POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 +#define POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 +#define POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 +#define POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 +#define POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 +#define POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 +#define POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 +#define POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 +#define POLARSSL_ECP_H MBEDTLS_ECP_H +#define POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES +#define POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN +#define POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED +#define POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED +#define POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE +#define POLARSSL_ENCRYPT MBEDTLS_ENCRYPT +#define POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H +#define POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H +#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#define POLARSSL_ERROR_H MBEDTLS_ERROR_H +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH +#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL +#define POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA +#define POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH +#define POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED +#define POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER +#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED +#define POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT +#define POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED +#define POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED +#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA +#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED +#define POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING +#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA +#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED +#define POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR +#define POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT +#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED +#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED +#define POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED +#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED +#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL +#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY +#define POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED +#define POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED +#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH +#define POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED +#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR +#define POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES +#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED +#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED +#define POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT +#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_MD2_FILE_IO_ERROR MBEDTLS_ERR_MD2_FILE_IO_ERROR +#define POLARSSL_ERR_MD4_FILE_IO_ERROR MBEDTLS_ERR_MD4_FILE_IO_ERROR +#define POLARSSL_ERR_MD5_FILE_IO_ERROR MBEDTLS_ERR_MD5_FILE_IO_ERROR +#define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED +#define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA +#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO +#define POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER +#define POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE +#define POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED +#define POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED +#define POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED +#define POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET +#define POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED +#define POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED +#define POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED +#define POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED +#define POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#define POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST +#define POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL +#define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED +#define POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA MBEDTLS_ERR_PBKDF2_BAD_INPUT_DATA +#define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA +#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA +#define POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV +#define POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED +#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT +#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH +#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED +#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG +#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH +#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA +#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR +#define POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG +#define POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY +#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +#define POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION +#define POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED +#define POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED +#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH +#define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH +#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE +#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG +#define POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR MBEDTLS_ERR_RIPEMD160_FILE_IO_ERROR +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA +#define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE +#define POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED +#define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED +#define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED +#define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED +#define POLARSSL_ERR_SHA1_FILE_IO_ERROR MBEDTLS_ERR_SHA1_FILE_IO_ERROR +#define POLARSSL_ERR_SHA256_FILE_IO_ERROR MBEDTLS_ERR_SHA256_FILE_IO_ERROR +#define POLARSSL_ERR_SHA512_FILE_IO_ERROR MBEDTLS_ERR_SHA512_FILE_IO_ERROR +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY +#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP +#define POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED +#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET +#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA +#define POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL +#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE +#define POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED +#define POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF +#define POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING +#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE +#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED +#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED +#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH +#define POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR +#define POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC +#define POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD +#define POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED +#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN +#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE +#define POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG +#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE +#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY +#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED +#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH +#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED +#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED +#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE +#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER +#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY +#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO +#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA +#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR +#define POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA +#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR +#define POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG +#define POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE +#define POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS +#define POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT +#define POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME +#define POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL +#define POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE +#define POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION +#define POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED +#define POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH +#define POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID +#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG +#define POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION +#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH +#define POLARSSL_GCM_H MBEDTLS_GCM_H +#define POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H +#define POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 +#define POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 +#define POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL +#define POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 +#define POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 +#define POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF +#define POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON +#define POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK +#define POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA +#define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE +#define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK +#define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA +#define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES +#define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE +#define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 +#define POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE +#define POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH +#define POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH +#define POLARSSL_MD2_H MBEDTLS_MD2_H +#define POLARSSL_MD4_H MBEDTLS_MD4_H +#define POLARSSL_MD5_H MBEDTLS_MD5_H +#define POLARSSL_MD_H MBEDTLS_MD_H +#define POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE +#define POLARSSL_MD_MD2 MBEDTLS_MD_MD2 +#define POLARSSL_MD_MD4 MBEDTLS_MD_MD4 +#define POLARSSL_MD_MD5 MBEDTLS_MD_MD5 +#define POLARSSL_MD_NONE MBEDTLS_MD_NONE +#define POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 +#define POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 +#define POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 +#define POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 +#define POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 +#define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 +#define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H +#define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define POLARSSL_MEMORY_H MBEDTLS_MEMORY_H +#define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC +#define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM +#define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB +#define POLARSSL_MODE_CTR MBEDTLS_MODE_CTR +#define POLARSSL_MODE_ECB MBEDTLS_MODE_ECB +#define POLARSSL_MODE_GCM MBEDTLS_MODE_GCM +#define POLARSSL_MODE_NONE MBEDTLS_MODE_NONE +#define POLARSSL_MODE_OFB MBEDTLS_MODE_OFB +#define POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM +#define POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS +#define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 +#define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS +#define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE +#define POLARSSL_NET_H MBEDTLS_NET_H +#define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG +#define POLARSSL_OID_H MBEDTLS_OID_H +#define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE +#define POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE +#define POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS +#define POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 +#define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS +#define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN +#define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H +#define POLARSSL_PBKDF2_H MBEDTLS_PBKDF2_H +#define POLARSSL_PEM_H MBEDTLS_PEM_H +#define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H +#define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H +#define POLARSSL_PKCS5_H MBEDTLS_PKCS5_H +#define POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP +#define POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS +#define POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI +#define POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE +#define POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA +#define POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY +#define POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH +#define POLARSSL_PK_H MBEDTLS_PK_H +#define POLARSSL_PK_NONE MBEDTLS_PK_NONE +#define POLARSSL_PK_RSA MBEDTLS_PK_RSA +#define POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS +#define POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT +#define POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H +#define POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H +#define POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE +#define POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H +#define POLARSSL_RSA_H MBEDTLS_RSA_H +#define POLARSSL_SHA1_H MBEDTLS_SHA1_H +#define POLARSSL_SHA256_H MBEDTLS_SHA256_H +#define POLARSSL_SHA512_H MBEDTLS_SHA512_H +#define POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H +#define POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H +#define POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H +#define POLARSSL_SSL_H MBEDTLS_SSL_H +#define POLARSSL_THREADING_H MBEDTLS_THREADING_H +#define POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL +#define POLARSSL_TIMING_H MBEDTLS_TIMING_H +#define POLARSSL_VERSION_H MBEDTLS_VERSION_H +#define POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR +#define POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR +#define POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER +#define POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH +#define POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING +#define POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL +#define POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H +#define POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H +#define POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H +#define POLARSSL_X509_H MBEDTLS_X509_H +#define POLARSSL_XTEA_H MBEDTLS_XTEA_H +#define RSA_CRYPT MBEDTLS_RSA_CRYPT +#define RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 +#define RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 +#define RSA_PRIVATE MBEDTLS_RSA_PRIVATE +#define RSA_PUBLIC MBEDTLS_RSA_PUBLIC +#define RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY +#define RSA_SIGN MBEDTLS_RSA_SIGN +#define SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL +#define SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING +#define SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED +#define SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT +#define SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC +#define SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED +#define SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED +#define SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN +#define SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY +#define SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE +#define SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED +#define SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR +#define SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER +#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY +#define SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR +#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL +#define SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT +#define SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION +#define SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION +#define SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE +#define SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY +#define SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME +#define SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT +#define SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT +#define SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED +#define SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED +#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED +#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED +#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED +#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN +#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES +#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT +#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED +#define SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED +#define SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST +#define SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY +#define SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN +#define SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN +#define SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND +#define SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND +#define SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES +#define SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE +#define SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC +#define SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED +#define SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO +#define SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE +#define SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD +#define SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE +#define SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL +#define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +#define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +#define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +#define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +#define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +#define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET +#define SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME +#define SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX +#define SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN +#define SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO +#define SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED +#define SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED +#define SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED +#define SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED +#define SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#define SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS +#define SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER +#define SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP +#define SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 +#define SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE +#define SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 +#define SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 +#define SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 +#define SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 +#define SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 +#define SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST +#define SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE +#define SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST +#define SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY +#define SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO +#define SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE +#define SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED +#define SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST +#define SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST +#define SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET +#define SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO +#define SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE +#define SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE +#define SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE +#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT +#define SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK +#define SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK +#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER +#define SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION +#define SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE +#define SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION +#define SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION +#define SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD +#define SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 +#define SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 +#define SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 +#define SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 +#define SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 +#define SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID +#define SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION +#define SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION +#define SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 +#define SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 +#define SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 +#define SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 +#define SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION +#define SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION +#define SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT +#define SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA +#define SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC +#define SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE +#define SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD +#define SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#define SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE +#define SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED +#define SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED +#define SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING +#define SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT +#define SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED +#define SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING +#define SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING +#define SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING +#define SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION +#define SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE +#define SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC +#define SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED +#define SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO +#define SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE +#define SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT +#define SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE +#define SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET +#define SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED +#define SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON +#define SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA +#define SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA +#define SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM +#define SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM +#define SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN +#define SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED +#define SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED +#define SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN +#define SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE +#define SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL +#define SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM +#define TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 +#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM +#define TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 +#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA +#define TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 +#define TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 +#define TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA +#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA +#define TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 +#define TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 +#define TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA +#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA +#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA +#define TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA +#define TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN +#define TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC +#define TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET +#define TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH +#define TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO +#define TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME +#define TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME +#define TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET +#define TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES +#define TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS +#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT +#define TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM +#define TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 +#define TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA +#define TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM +#define TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 +#define TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA +#define TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 +#define TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 +#define TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA +#define TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 +#define TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 +#define TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM +#define TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 +#define TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA +#define TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM +#define TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 +#define TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA +#define TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 +#define TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA +#define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 +#define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 +#define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA +#define UL64 MBEDTLS_UL64 +#define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 +#define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 +#define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 +#define X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER +#define X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM +#define X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE +#define X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN +#define X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN +#define XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT +#define XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT +#define _asn1_bitstring mbedtls_asn1_bitstring +#define _asn1_buf mbedtls_asn1_buf +#define _asn1_named_data mbedtls_asn1_named_data +#define _asn1_sequence mbedtls_asn1_sequence +#define _ssl_cache_context mbedtls_ssl_cache_context +#define _ssl_cache_entry mbedtls_ssl_cache_entry +#define _ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define _ssl_context mbedtls_ssl_context +#define _ssl_flight_item mbedtls_ssl_flight_item +#define _ssl_handshake_params mbedtls_ssl_handshake_params +#define _ssl_key_cert mbedtls_ssl_key_cert +#define _ssl_premaster_secret mbedtls_ssl_premaster_secret +#define _ssl_session mbedtls_ssl_session +#define _ssl_ticket_keys mbedtls_ssl_ticket_keys +#define _ssl_transform mbedtls_ssl_transform +#define _x509_crl mbedtls_x509_crl +#define _x509_crl_entry mbedtls_x509_crl_entry +#define _x509_crt mbedtls_x509_crt +#define _x509_csr mbedtls_x509_csr +#define _x509_time mbedtls_x509_time +#define _x509write_cert mbedtls_x509write_cert +#define _x509write_csr mbedtls_x509write_csr +#define aes_context mbedtls_aes_context +#define aes_crypt_cbc mbedtls_aes_crypt_cbc +#define aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 +#define aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 +#define aes_crypt_ctr mbedtls_aes_crypt_ctr +#define aes_crypt_ecb mbedtls_aes_crypt_ecb +#define aes_free mbedtls_aes_free +#define aes_init mbedtls_aes_init +#define aes_self_test mbedtls_aes_self_test +#define aes_setkey_dec mbedtls_aes_setkey_dec +#define aes_setkey_enc mbedtls_aes_setkey_enc +#define aesni_crypt_ecb mbedtls_aesni_crypt_ecb +#define aesni_gcm_mult mbedtls_aesni_gcm_mult +#define aesni_inverse_key mbedtls_aesni_inverse_key +#define aesni_setkey_enc mbedtls_aesni_setkey_enc +#define aesni_supports mbedtls_aesni_has_support +#define alarmed mbedtls_timing_alarmed +#define arc4_context mbedtls_arc4_context +#define arc4_crypt mbedtls_arc4_crypt +#define arc4_free mbedtls_arc4_free +#define arc4_init mbedtls_arc4_init +#define arc4_self_test mbedtls_arc4_self_test +#define arc4_setup mbedtls_arc4_setup +#define asn1_bitstring mbedtls_asn1_bitstring +#define asn1_buf mbedtls_asn1_buf +#define asn1_find_named_data mbedtls_asn1_find_named_data +#define asn1_free_named_data mbedtls_asn1_free_named_data +#define asn1_free_named_data_list mbedtls_asn1_free_named_data_list +#define asn1_get_alg mbedtls_asn1_get_alg +#define asn1_get_alg_null mbedtls_asn1_get_alg_null +#define asn1_get_bitstring mbedtls_asn1_get_bitstring +#define asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null +#define asn1_get_bool mbedtls_asn1_get_bool +#define asn1_get_int mbedtls_asn1_get_int +#define asn1_get_len mbedtls_asn1_get_len +#define asn1_get_mpi mbedtls_asn1_get_mpi +#define asn1_get_sequence_of mbedtls_asn1_get_sequence_of +#define asn1_get_tag mbedtls_asn1_get_tag +#define asn1_named_data mbedtls_asn1_named_data +#define asn1_sequence mbedtls_asn1_sequence +#define asn1_store_named_data mbedtls_asn1_store_named_data +#define asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier +#define asn1_write_bitstring mbedtls_asn1_write_bitstring +#define asn1_write_bool mbedtls_asn1_write_bool +#define asn1_write_ia5_string mbedtls_asn1_write_ia5_string +#define asn1_write_int mbedtls_asn1_write_int +#define asn1_write_len mbedtls_asn1_write_len +#define asn1_write_mpi mbedtls_asn1_write_mpi +#define asn1_write_null mbedtls_asn1_write_null +#define asn1_write_octet_string mbedtls_asn1_write_octet_string +#define asn1_write_oid mbedtls_asn1_write_oid +#define asn1_write_printable_string mbedtls_asn1_write_printable_string +#define asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer +#define asn1_write_tag mbedtls_asn1_write_tag +#define base64_decode mbedtls_base64_decode +#define base64_encode mbedtls_base64_encode +#define base64_self_test mbedtls_base64_self_test +#define blowfish_context mbedtls_blowfish_context +#define blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc +#define blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 +#define blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr +#define blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb +#define blowfish_free mbedtls_blowfish_free +#define blowfish_init mbedtls_blowfish_init +#define blowfish_setkey mbedtls_blowfish_setkey +#define camellia_context mbedtls_camellia_context +#define camellia_crypt_cbc mbedtls_camellia_crypt_cbc +#define camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 +#define camellia_crypt_ctr mbedtls_camellia_crypt_ctr +#define camellia_crypt_ecb mbedtls_camellia_crypt_ecb +#define camellia_free mbedtls_camellia_free +#define camellia_init mbedtls_camellia_init +#define camellia_self_test mbedtls_camellia_self_test +#define camellia_setkey_dec mbedtls_camellia_setkey_dec +#define camellia_setkey_enc mbedtls_camellia_setkey_enc +#define ccm_auth_decrypt mbedtls_ccm_auth_decrypt +#define ccm_context mbedtls_ccm_context +#define ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag +#define ccm_free mbedtls_ccm_free +#define ccm_init mbedtls_ccm_init +#define ccm_self_test mbedtls_ccm_self_test +#define cipher_auth_decrypt mbedtls_cipher_auth_decrypt +#define cipher_auth_encrypt mbedtls_cipher_auth_encrypt +#define cipher_base_t mbedtls_cipher_base_t +#define cipher_check_tag mbedtls_cipher_check_tag +#define cipher_context_t mbedtls_cipher_context_t +#define cipher_crypt mbedtls_cipher_crypt +#define cipher_definition_t mbedtls_cipher_definition_t +#define cipher_definitions mbedtls_cipher_definitions +#define cipher_finish mbedtls_cipher_finish +#define cipher_free mbedtls_cipher_free +#define cipher_free_ctx mbedtls_cipher_free_ctx +#define cipher_get_block_size mbedtls_cipher_get_block_size +#define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode +#define cipher_get_iv_size mbedtls_cipher_get_iv_size +#define cipher_get_key_size mbedtls_cipher_get_key_bitlen +#define cipher_get_name mbedtls_cipher_get_name +#define cipher_get_operation mbedtls_cipher_get_operation +#define cipher_get_type mbedtls_cipher_get_type +#define cipher_id_t mbedtls_cipher_id_t +#define cipher_info_from_string mbedtls_cipher_info_from_string +#define cipher_info_from_type mbedtls_cipher_info_from_type +#define cipher_info_from_values mbedtls_cipher_info_from_values +#define cipher_info_t mbedtls_cipher_info_t +#define cipher_init mbedtls_cipher_init +#define cipher_init_ctx mbedtls_cipher_setup +#define cipher_list mbedtls_cipher_list +#define cipher_mode_t mbedtls_cipher_mode_t +#define cipher_padding_t mbedtls_cipher_padding_t +#define cipher_reset mbedtls_cipher_reset +#define cipher_self_test mbedtls_cipher_self_test +#define cipher_set_iv mbedtls_cipher_set_iv +#define cipher_set_padding_mode mbedtls_cipher_set_padding_mode +#define cipher_setkey mbedtls_cipher_setkey +#define cipher_type_t mbedtls_cipher_type_t +#define cipher_update mbedtls_cipher_update +#define cipher_update_ad mbedtls_cipher_update_ad +#define cipher_write_tag mbedtls_cipher_write_tag +#define ctr_drbg_context mbedtls_ctr_drbg_context +#define ctr_drbg_free mbedtls_ctr_drbg_free +#define ctr_drbg_init mbedtls_ctr_drbg_init +#define ctr_drbg_init_entropy_len mbedtls_ctr_drbg_init_entropy_len +#define ctr_drbg_random mbedtls_ctr_drbg_random +#define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add +#define ctr_drbg_reseed mbedtls_ctr_drbg_reseed +#define ctr_drbg_self_test mbedtls_ctr_drbg_self_test +#define ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len +#define ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance +#define ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval +#define ctr_drbg_update mbedtls_ctr_drbg_update +#define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file +#define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file +#define debug_fmt mbedtls_debug_fmt +#define debug_print_buf mbedtls_debug_print_buf +#define debug_print_crt mbedtls_debug_print_crt +#define debug_print_ecp mbedtls_debug_print_ecp +#define debug_print_mpi mbedtls_debug_print_mpi +#define debug_print_msg mbedtls_debug_print_msg +#define debug_print_ret mbedtls_debug_print_ret +#define debug_set_log_mode mbedtls_debug_set_log_mode +#define debug_set_threshold mbedtls_debug_set_threshold +#define des3_context mbedtls_des3_context +#define des3_crypt_cbc mbedtls_des3_crypt_cbc +#define des3_crypt_ecb mbedtls_des3_crypt_ecb +#define des3_free mbedtls_des3_free +#define des3_init mbedtls_des3_init +#define des3_set2key_dec mbedtls_des3_set2key_dec +#define des3_set2key_enc mbedtls_des3_set2key_enc +#define des3_set3key_dec mbedtls_des3_set3key_dec +#define des3_set3key_enc mbedtls_des3_set3key_enc +#define des_context mbedtls_des_context +#define des_crypt_cbc mbedtls_des_crypt_cbc +#define des_crypt_ecb mbedtls_des_crypt_ecb +#define des_free mbedtls_des_free +#define des_init mbedtls_des_init +#define des_key_check_key_parity mbedtls_des_key_check_key_parity +#define des_key_check_weak mbedtls_des_key_check_weak +#define des_key_set_parity mbedtls_des_key_set_parity +#define des_self_test mbedtls_des_self_test +#define des_setkey_dec mbedtls_des_setkey_dec +#define des_setkey_enc mbedtls_des_setkey_enc +#define dhm_calc_secret mbedtls_dhm_calc_secret +#define dhm_context mbedtls_dhm_context +#define dhm_free mbedtls_dhm_free +#define dhm_init mbedtls_dhm_init +#define dhm_make_params mbedtls_dhm_make_params +#define dhm_make_public mbedtls_dhm_make_public +#define dhm_parse_dhm mbedtls_dhm_parse_dhm +#define dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile +#define dhm_read_params mbedtls_dhm_read_params +#define dhm_read_public mbedtls_dhm_read_public +#define dhm_self_test mbedtls_dhm_self_test +#define ecdh_calc_secret mbedtls_ecdh_calc_secret +#define ecdh_compute_shared mbedtls_ecdh_compute_shared +#define ecdh_context mbedtls_ecdh_context +#define ecdh_free mbedtls_ecdh_free +#define ecdh_gen_public mbedtls_ecdh_gen_public +#define ecdh_get_params mbedtls_ecdh_get_params +#define ecdh_init mbedtls_ecdh_init +#define ecdh_make_params mbedtls_ecdh_make_params +#define ecdh_make_public mbedtls_ecdh_make_public +#define ecdh_read_params mbedtls_ecdh_read_params +#define ecdh_read_public mbedtls_ecdh_read_public +#define ecdh_self_test mbedtls_ecdh_self_test +#define ecdh_side mbedtls_ecdh_side +#define ecdsa_context mbedtls_ecdsa_context +#define ecdsa_free mbedtls_ecdsa_free +#define ecdsa_from_keypair mbedtls_ecdsa_from_keypair +#define ecdsa_genkey mbedtls_ecdsa_genkey +#define ecdsa_info mbedtls_ecdsa_info +#define ecdsa_init mbedtls_ecdsa_init +#define ecdsa_read_signature mbedtls_ecdsa_read_signature +#define ecdsa_self_test mbedtls_ecdsa_self_test +#define ecdsa_sign mbedtls_ecdsa_sign +#define ecdsa_sign_det mbedtls_ecdsa_sign_det +#define ecdsa_verify mbedtls_ecdsa_verify +#define ecdsa_write_signature mbedtls_ecdsa_write_signature +#define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det +#define eckey_info mbedtls_eckey_info +#define eckeydh_info mbedtls_eckeydh_info +#define ecp_add mbedtls_ecp_add +#define ecp_check_privkey mbedtls_ecp_check_privkey +#define ecp_check_pub_priv mbedtls_ecp_check_pub_priv +#define ecp_check_pubkey mbedtls_ecp_check_pubkey +#define ecp_copy mbedtls_ecp_copy +#define ecp_curve_info mbedtls_ecp_curve_info +#define ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id +#define ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name +#define ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id +#define ecp_curve_list mbedtls_ecp_curve_list +#define ecp_gen_key mbedtls_ecp_gen_key +#define ecp_gen_keypair mbedtls_ecp_gen_keypair +#define ecp_group mbedtls_ecp_group +#define ecp_group_copy mbedtls_ecp_group_copy +#define ecp_group_free mbedtls_ecp_group_free +#define ecp_group_id mbedtls_ecp_group_id +#define ecp_group_init mbedtls_ecp_group_init +#define ecp_group_read_string mbedtls_ecp_group_read_string +#define ecp_grp_id_list mbedtls_ecp_grp_id_list +#define ecp_is_zero mbedtls_ecp_is_zero +#define ecp_keypair mbedtls_ecp_keypair +#define ecp_keypair_free mbedtls_ecp_keypair_free +#define ecp_keypair_init mbedtls_ecp_keypair_init +#define ecp_mul mbedtls_ecp_mul +#define ecp_point mbedtls_ecp_point +#define ecp_point_free mbedtls_ecp_point_free +#define ecp_point_init mbedtls_ecp_point_init +#define ecp_point_read_binary mbedtls_ecp_point_read_binary +#define ecp_point_read_string mbedtls_ecp_point_read_string +#define ecp_point_write_binary mbedtls_ecp_point_write_binary +#define ecp_self_test mbedtls_ecp_self_test +#define ecp_set_zero mbedtls_ecp_set_zero +#define ecp_sub mbedtls_ecp_sub +#define ecp_tls_read_group mbedtls_ecp_tls_read_group +#define ecp_tls_read_point mbedtls_ecp_tls_read_point +#define ecp_tls_write_group mbedtls_ecp_tls_write_group +#define ecp_tls_write_point mbedtls_ecp_tls_write_point +#define ecp_use_known_dp mbedtls_ecp_group_load +#define entropy_add_source mbedtls_entropy_add_source +#define entropy_context mbedtls_entropy_context +#define entropy_free mbedtls_entropy_free +#define entropy_func mbedtls_entropy_func +#define entropy_gather mbedtls_entropy_gather +#define entropy_init mbedtls_entropy_init +#define entropy_self_test mbedtls_entropy_self_test +#define entropy_update_manual mbedtls_entropy_update_manual +#define entropy_update_seed_file mbedtls_entropy_update_seed_file +#define entropy_write_seed_file mbedtls_entropy_write_seed_file +#define error_strerror mbedtls_strerror +#define f_source_ptr mbedtls_entropy_f_source_ptr +#define gcm_auth_decrypt mbedtls_gcm_auth_decrypt +#define gcm_context mbedtls_gcm_context +#define gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag +#define gcm_finish mbedtls_gcm_finish +#define gcm_free mbedtls_gcm_free +#define gcm_init mbedtls_gcm_init +#define gcm_self_test mbedtls_gcm_self_test +#define gcm_starts mbedtls_gcm_starts +#define gcm_update mbedtls_gcm_update +#define get_timer mbedtls_timing_get_timer +#define hardclock mbedtls_timing_hardclock +#define hardclock_poll mbedtls_hardclock_poll +#define havege_free mbedtls_havege_free +#define havege_init mbedtls_havege_init +#define havege_poll mbedtls_havege_poll +#define havege_random mbedtls_havege_random +#define havege_state mbedtls_havege_state +#define hmac_drbg_context mbedtls_hmac_drbg_context +#define hmac_drbg_free mbedtls_hmac_drbg_free +#define hmac_drbg_init mbedtls_hmac_drbg_init +#define hmac_drbg_init_buf mbedtls_hmac_drbg_init_buf +#define hmac_drbg_random mbedtls_hmac_drbg_random +#define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add +#define hmac_drbg_reseed mbedtls_hmac_drbg_reseed +#define hmac_drbg_self_test mbedtls_hmac_drbg_self_test +#define hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len +#define hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance +#define hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval +#define hmac_drbg_update mbedtls_hmac_drbg_update +#define hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file +#define hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file +#define hr_time mbedtls_timing_hr_time +#define key_exchange_type_t mbedtls_key_exchange_type_t +#define md mbedtls_md +#define md2 mbedtls_md2 +#define md2_context mbedtls_md2_context +#define md2_file mbedtls_md2_file +#define md2_finish mbedtls_md2_finish +#define md2_free mbedtls_md2_free +#define md2_hmac mbedtls_md2_hmac +#define md2_hmac_finish mbedtls_md2_hmac_finish +#define md2_hmac_reset mbedtls_md2_hmac_reset +#define md2_hmac_starts mbedtls_md2_hmac_starts +#define md2_hmac_update mbedtls_md2_hmac_update +#define md2_info mbedtls_md2_info +#define md2_init mbedtls_md2_init +#define md2_process mbedtls_md2_process +#define md2_self_test mbedtls_md2_self_test +#define md2_starts mbedtls_md2_starts +#define md2_update mbedtls_md2_update +#define md4 mbedtls_md4 +#define md4_context mbedtls_md4_context +#define md4_file mbedtls_md4_file +#define md4_finish mbedtls_md4_finish +#define md4_free mbedtls_md4_free +#define md4_hmac mbedtls_md4_hmac +#define md4_hmac_finish mbedtls_md4_hmac_finish +#define md4_hmac_reset mbedtls_md4_hmac_reset +#define md4_hmac_starts mbedtls_md4_hmac_starts +#define md4_hmac_update mbedtls_md4_hmac_update +#define md4_info mbedtls_md4_info +#define md4_init mbedtls_md4_init +#define md4_process mbedtls_md4_process +#define md4_self_test mbedtls_md4_self_test +#define md4_starts mbedtls_md4_starts +#define md4_update mbedtls_md4_update +#define md5 mbedtls_md5 +#define md5_context mbedtls_md5_context +#define md5_file mbedtls_md5_file +#define md5_finish mbedtls_md5_finish +#define md5_free mbedtls_md5_free +#define md5_hmac mbedtls_md5_hmac +#define md5_hmac_finish mbedtls_md5_hmac_finish +#define md5_hmac_reset mbedtls_md5_hmac_reset +#define md5_hmac_starts mbedtls_md5_hmac_starts +#define md5_hmac_update mbedtls_md5_hmac_update +#define md5_info mbedtls_md5_info +#define md5_init mbedtls_md5_init +#define md5_process mbedtls_md5_process +#define md5_self_test mbedtls_md5_self_test +#define md5_starts mbedtls_md5_starts +#define md5_update mbedtls_md5_update +#define md_context_t mbedtls_md_context_t +#define md_file mbedtls_md_file +#define md_finish mbedtls_md_finish +#define md_free mbedtls_md_free +#define md_free_ctx mbedtls_md_free_ctx +#define md_get_name mbedtls_md_get_name +#define md_get_size mbedtls_md_get_size +#define md_get_type mbedtls_md_get_type +#define md_hmac mbedtls_md_hmac +#define md_hmac_finish mbedtls_md_hmac_finish +#define md_hmac_reset mbedtls_md_hmac_reset +#define md_hmac_starts mbedtls_md_hmac_starts +#define md_hmac_update mbedtls_md_hmac_update +#define md_info_from_string mbedtls_md_info_from_string +#define md_info_from_type mbedtls_md_info_from_type +#define md_info_t mbedtls_md_info_t +#define md_init mbedtls_md_init +#define md_init_ctx mbedtls_md_init_ctx +#define md_list mbedtls_md_list +#define md_process mbedtls_md_process +#define md_starts mbedtls_md_starts +#define md_type_t mbedtls_md_type_t +#define md_update mbedtls_md_update +#define memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get +#define memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free +#define memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init +#define memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get +#define memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset +#define memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test +#define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status +#define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify +#define memory_buffer_set_verify mbedtls_memory_buffer_set_verify +#define memory_set_own mbedtls_memory_set_own +#define mpi mbedtls_mpi +#define mpi_add_abs mbedtls_mpi_add_abs +#define mpi_add_int mbedtls_mpi_add_int +#define mpi_add_mpi mbedtls_mpi_add_mpi +#define mpi_cmp_abs mbedtls_mpi_cmp_abs +#define mpi_cmp_int mbedtls_mpi_cmp_int +#define mpi_cmp_mpi mbedtls_mpi_cmp_mpi +#define mpi_copy mbedtls_mpi_copy +#define mpi_div_int mbedtls_mpi_div_int +#define mpi_div_mpi mbedtls_mpi_div_mpi +#define mpi_exp_mod mbedtls_mpi_exp_mod +#define mpi_fill_random mbedtls_mpi_fill_random +#define mpi_free mbedtls_mpi_free +#define mpi_gcd mbedtls_mpi_gcd +#define mpi_gen_prime mbedtls_mpi_gen_prime +#define mpi_get_bit mbedtls_mpi_get_bit +#define mpi_grow mbedtls_mpi_grow +#define mpi_init mbedtls_mpi_init +#define mpi_inv_mod mbedtls_mpi_inv_mod +#define mpi_is_prime mbedtls_mpi_is_prime +#define mpi_lsb mbedtls_mpi_lsb +#define mpi_lset mbedtls_mpi_lset +#define mpi_mod_int mbedtls_mpi_mod_int +#define mpi_mod_mpi mbedtls_mpi_mod_mpi +#define mpi_msb mbedtls_mpi_bitlen +#define mpi_mul_int mbedtls_mpi_mul_int +#define mpi_mul_mpi mbedtls_mpi_mul_mpi +#define mpi_read_binary mbedtls_mpi_read_binary +#define mpi_read_file mbedtls_mpi_read_file +#define mpi_read_string mbedtls_mpi_read_string +#define mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign +#define mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap +#define mpi_self_test mbedtls_mpi_self_test +#define mpi_set_bit mbedtls_mpi_set_bit +#define mpi_shift_l mbedtls_mpi_shift_l +#define mpi_shift_r mbedtls_mpi_shift_r +#define mpi_shrink mbedtls_mpi_shrink +#define mpi_size mbedtls_mpi_size +#define mpi_sub_abs mbedtls_mpi_sub_abs +#define mpi_sub_int mbedtls_mpi_sub_int +#define mpi_sub_mpi mbedtls_mpi_sub_mpi +#define mpi_swap mbedtls_mpi_swap +#define mpi_write_binary mbedtls_mpi_write_binary +#define mpi_write_file mbedtls_mpi_write_file +#define mpi_write_string mbedtls_mpi_write_string +#define net_accept mbedtls_net_accept +#define net_bind mbedtls_net_bind +#define net_close mbedtls_net_free +#define net_connect mbedtls_net_connect +#define net_recv mbedtls_net_recv +#define net_recv_timeout mbedtls_net_recv_timeout +#define net_send mbedtls_net_send +#define net_set_block mbedtls_net_set_block +#define net_set_nonblock mbedtls_net_set_nonblock +#define net_usleep mbedtls_net_usleep +#define oid_descriptor_t mbedtls_oid_descriptor_t +#define oid_get_attr_short_name mbedtls_oid_get_attr_short_name +#define oid_get_cipher_alg mbedtls_oid_get_cipher_alg +#define oid_get_ec_grp mbedtls_oid_get_ec_grp +#define oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage +#define oid_get_md_alg mbedtls_oid_get_md_alg +#define oid_get_numeric_string mbedtls_oid_get_numeric_string +#define oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp +#define oid_get_oid_by_md mbedtls_oid_get_oid_by_md +#define oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg +#define oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg +#define oid_get_pk_alg mbedtls_oid_get_pk_alg +#define oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg +#define oid_get_sig_alg mbedtls_oid_get_sig_alg +#define oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc +#define oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type +#define operation_t mbedtls_operation_t +#define padlock_supports mbedtls_padlock_has_support +#define padlock_xcryptcbc mbedtls_padlock_xcryptcbc +#define padlock_xcryptecb mbedtls_padlock_xcryptecb +#define pbkdf2_hmac mbedtls_pbkdf2_hmac +#define pbkdf2_self_test mbedtls_pbkdf2_self_test +#define pem_context mbedtls_pem_context +#define pem_free mbedtls_pem_free +#define pem_init mbedtls_pem_init +#define pem_read_buffer mbedtls_pem_read_buffer +#define pem_write_buffer mbedtls_pem_write_buffer +#define pk_can_do mbedtls_pk_can_do +#define pk_check_pair mbedtls_pk_check_pair +#define pk_context mbedtls_pk_context +#define pk_debug mbedtls_pk_debug +#define pk_debug_item mbedtls_pk_debug_item +#define pk_debug_type mbedtls_pk_debug_type +#define pk_decrypt mbedtls_pk_decrypt +#define pk_ec mbedtls_pk_ec +#define pk_encrypt mbedtls_pk_encrypt +#define pk_free mbedtls_pk_free +#define pk_get_len mbedtls_pk_get_len +#define pk_get_name mbedtls_pk_get_name +#define pk_get_size mbedtls_pk_get_bitlen +#define pk_get_type mbedtls_pk_get_type +#define pk_info_from_type mbedtls_pk_info_from_type +#define pk_info_t mbedtls_pk_info_t +#define pk_init mbedtls_pk_init +#define pk_init_ctx mbedtls_pk_setup +#define pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt +#define pk_load_file mbedtls_pk_load_file +#define pk_parse_key mbedtls_pk_parse_key +#define pk_parse_keyfile mbedtls_pk_parse_keyfile +#define pk_parse_public_key mbedtls_pk_parse_public_key +#define pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile +#define pk_parse_subpubkey mbedtls_pk_parse_subpubkey +#define pk_rsa mbedtls_pk_rsa +#define pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func +#define pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func +#define pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func +#define pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options +#define pk_sign mbedtls_pk_sign +#define pk_type_t mbedtls_pk_type_t +#define pk_verify mbedtls_pk_verify +#define pk_verify_ext mbedtls_pk_verify_ext +#define pk_write_key_der mbedtls_pk_write_key_der +#define pk_write_key_pem mbedtls_pk_write_key_pem +#define pk_write_pubkey mbedtls_pk_write_pubkey +#define pk_write_pubkey_der mbedtls_pk_write_pubkey_der +#define pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem +#define pkcs11_context mbedtls_pkcs11_context +#define pkcs11_decrypt mbedtls_pkcs11_decrypt +#define pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free +#define pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind +#define pkcs11_sign mbedtls_pkcs11_sign +#define pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind +#define pkcs12_derivation mbedtls_pkcs12_derivation +#define pkcs12_pbe mbedtls_pkcs12_pbe +#define pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 +#define pkcs5_pbes2 mbedtls_pkcs5_pbes2 +#define pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac +#define pkcs5_self_test mbedtls_pkcs5_self_test +#define platform_entropy_poll mbedtls_platform_entropy_poll +#define platform_set_exit mbedtls_platform_set_exit +#define platform_set_fprintf mbedtls_platform_set_fprintf +#define platform_set_malloc_free mbedtls_platform_set_malloc_free +#define platform_set_printf mbedtls_platform_set_printf +#define platform_set_snprintf mbedtls_platform_set_snprintf +#define polarssl_exit mbedtls_exit +#define polarssl_fprintf mbedtls_fprintf +#define polarssl_free mbedtls_free +#define polarssl_malloc mbedtls_malloc +#define polarssl_mutex_free mbedtls_mutex_free +#define polarssl_mutex_init mbedtls_mutex_init +#define polarssl_mutex_lock mbedtls_mutex_lock +#define polarssl_mutex_unlock mbedtls_mutex_unlock +#define polarssl_printf mbedtls_printf +#define polarssl_snprintf mbedtls_snprintf +#define polarssl_strerror mbedtls_strerror +#define ripemd160 mbedtls_ripemd160 +#define ripemd160_context mbedtls_ripemd160_context +#define ripemd160_file mbedtls_ripemd160_file +#define ripemd160_finish mbedtls_ripemd160_finish +#define ripemd160_free mbedtls_ripemd160_free +#define ripemd160_hmac mbedtls_ripemd160_hmac +#define ripemd160_hmac_finish mbedtls_ripemd160_hmac_finish +#define ripemd160_hmac_reset mbedtls_ripemd160_hmac_reset +#define ripemd160_hmac_starts mbedtls_ripemd160_hmac_starts +#define ripemd160_hmac_update mbedtls_ripemd160_hmac_update +#define ripemd160_info mbedtls_ripemd160_info +#define ripemd160_init mbedtls_ripemd160_init +#define ripemd160_process mbedtls_ripemd160_process +#define ripemd160_self_test mbedtls_ripemd160_self_test +#define ripemd160_starts mbedtls_ripemd160_starts +#define ripemd160_update mbedtls_ripemd160_update +#define rsa_alt_context mbedtls_rsa_alt_context +#define rsa_alt_info mbedtls_rsa_alt_info +#define rsa_check_privkey mbedtls_rsa_check_privkey +#define rsa_check_pub_priv mbedtls_rsa_check_pub_priv +#define rsa_check_pubkey mbedtls_rsa_check_pubkey +#define rsa_context mbedtls_rsa_context +#define rsa_copy mbedtls_rsa_copy +#define rsa_decrypt_func mbedtls_rsa_decrypt_func +#define rsa_free mbedtls_rsa_free +#define rsa_gen_key mbedtls_rsa_gen_key +#define rsa_info mbedtls_rsa_info +#define rsa_init mbedtls_rsa_init +#define rsa_key_len_func mbedtls_rsa_key_len_func +#define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt +#define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt +#define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign +#define rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify +#define rsa_private mbedtls_rsa_private +#define rsa_public mbedtls_rsa_public +#define rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt +#define rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt +#define rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt +#define rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt +#define rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign +#define rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify +#define rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign +#define rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify +#define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext +#define rsa_self_test mbedtls_rsa_self_test +#define rsa_set_padding mbedtls_rsa_set_padding +#define rsa_sign_func mbedtls_rsa_sign_func +#define safer_memcmp mbedtls_ssl_safer_memcmp +#define set_alarm mbedtls_set_alarm +#define sha1 mbedtls_sha1 +#define sha1_context mbedtls_sha1_context +#define sha1_file mbedtls_sha1_file +#define sha1_finish mbedtls_sha1_finish +#define sha1_free mbedtls_sha1_free +#define sha1_hmac mbedtls_sha1_hmac +#define sha1_hmac_finish mbedtls_sha1_hmac_finish +#define sha1_hmac_reset mbedtls_sha1_hmac_reset +#define sha1_hmac_starts mbedtls_sha1_hmac_starts +#define sha1_hmac_update mbedtls_sha1_hmac_update +#define sha1_info mbedtls_sha1_info +#define sha1_init mbedtls_sha1_init +#define sha1_process mbedtls_sha1_process +#define sha1_self_test mbedtls_sha1_self_test +#define sha1_starts mbedtls_sha1_starts +#define sha1_update mbedtls_sha1_update +#define sha224_info mbedtls_sha224_info +#define sha256 mbedtls_sha256 +#define sha256_context mbedtls_sha256_context +#define sha256_file mbedtls_sha256_file +#define sha256_finish mbedtls_sha256_finish +#define sha256_free mbedtls_sha256_free +#define sha256_hmac mbedtls_sha256_hmac +#define sha256_hmac_finish mbedtls_sha256_hmac_finish +#define sha256_hmac_reset mbedtls_sha256_hmac_reset +#define sha256_hmac_starts mbedtls_sha256_hmac_starts +#define sha256_hmac_update mbedtls_sha256_hmac_update +#define sha256_info mbedtls_sha256_info +#define sha256_init mbedtls_sha256_init +#define sha256_process mbedtls_sha256_process +#define sha256_self_test mbedtls_sha256_self_test +#define sha256_starts mbedtls_sha256_starts +#define sha256_update mbedtls_sha256_update +#define sha384_info mbedtls_sha384_info +#define sha512 mbedtls_sha512 +#define sha512_context mbedtls_sha512_context +#define sha512_file mbedtls_sha512_file +#define sha512_finish mbedtls_sha512_finish +#define sha512_free mbedtls_sha512_free +#define sha512_hmac mbedtls_sha512_hmac +#define sha512_hmac_finish mbedtls_sha512_hmac_finish +#define sha512_hmac_reset mbedtls_sha512_hmac_reset +#define sha512_hmac_starts mbedtls_sha512_hmac_starts +#define sha512_hmac_update mbedtls_sha512_hmac_update +#define sha512_info mbedtls_sha512_info +#define sha512_init mbedtls_sha512_init +#define sha512_process mbedtls_sha512_process +#define sha512_self_test mbedtls_sha512_self_test +#define sha512_starts mbedtls_sha512_starts +#define sha512_update mbedtls_sha512_update +#define source_state mbedtls_entropy_source_state +#define ssl_cache_context mbedtls_ssl_cache_context +#define ssl_cache_entry mbedtls_ssl_cache_entry +#define ssl_cache_free mbedtls_ssl_cache_free +#define ssl_cache_get mbedtls_ssl_cache_get +#define ssl_cache_init mbedtls_ssl_cache_init +#define ssl_cache_set mbedtls_ssl_cache_set +#define ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries +#define ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout +#define ssl_check_cert_usage mbedtls_ssl_check_cert_usage +#define ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id +#define ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string +#define ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec +#define ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk +#define ssl_close_notify mbedtls_ssl_close_notify +#define ssl_context mbedtls_ssl_context +#define ssl_cookie_check mbedtls_ssl_cookie_check +#define ssl_cookie_check_t mbedtls_ssl_cookie_check_t +#define ssl_cookie_ctx mbedtls_ssl_cookie_ctx +#define ssl_cookie_free mbedtls_ssl_cookie_free +#define ssl_cookie_init mbedtls_ssl_cookie_init +#define ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout +#define ssl_cookie_setup mbedtls_ssl_cookie_setup +#define ssl_cookie_write mbedtls_ssl_cookie_write +#define ssl_cookie_write_t mbedtls_ssl_cookie_write_t +#define ssl_curve_is_acceptable mbedtls_ssl_curve_is_acceptable +#define ssl_derive_keys mbedtls_ssl_derive_keys +#define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check +#define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update +#define ssl_fetch_input mbedtls_ssl_fetch_input +#define ssl_flight_item mbedtls_ssl_flight_item +#define ssl_flush_output mbedtls_ssl_flush_output +#define ssl_free mbedtls_ssl_free +#define ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol +#define ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail +#define ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite +#define ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id +#define ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name +#define ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg +#define ssl_get_peer_cert mbedtls_ssl_get_peer_cert +#define ssl_get_record_expansion mbedtls_ssl_get_record_expansion +#define ssl_get_session mbedtls_ssl_get_session +#define ssl_get_verify_result mbedtls_ssl_get_verify_result +#define ssl_get_version mbedtls_ssl_get_version +#define ssl_handshake mbedtls_ssl_handshake +#define ssl_handshake_client_step mbedtls_ssl_handshake_client_step +#define ssl_handshake_free mbedtls_ssl_handshake_free +#define ssl_handshake_params mbedtls_ssl_handshake_params +#define ssl_handshake_server_step mbedtls_ssl_handshake_server_step +#define ssl_handshake_step mbedtls_ssl_handshake_step +#define ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup +#define ssl_hdr_len mbedtls_ssl_hdr_len +#define ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len +#define ssl_hw_record_activate mbedtls_ssl_hw_record_activate +#define ssl_hw_record_finish mbedtls_ssl_hw_record_finish +#define ssl_hw_record_init mbedtls_ssl_hw_record_init +#define ssl_hw_record_read mbedtls_ssl_hw_record_read +#define ssl_hw_record_reset mbedtls_ssl_hw_record_reset +#define ssl_hw_record_write mbedtls_ssl_hw_record_write +#define ssl_init mbedtls_ssl_init +#define ssl_key_cert mbedtls_ssl_key_cert +#define ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation +#define ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites +#define ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash +#define ssl_optimize_checksum mbedtls_ssl_optimize_checksum +#define ssl_own_cert mbedtls_ssl_own_cert +#define ssl_own_key mbedtls_ssl_own_key +#define ssl_parse_certificate mbedtls_ssl_parse_certificate +#define ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec +#define ssl_parse_finished mbedtls_ssl_parse_finished +#define ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig +#define ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt +#define ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len +#define ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign +#define ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster +#define ssl_read mbedtls_ssl_read +#define ssl_read_record mbedtls_ssl_read_record +#define ssl_read_version mbedtls_ssl_read_version +#define ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed +#define ssl_renegotiate mbedtls_ssl_renegotiate +#define ssl_resend mbedtls_ssl_resend +#define ssl_reset_checksum mbedtls_ssl_reset_checksum +#define ssl_send_alert_message mbedtls_ssl_send_alert_message +#define ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure +#define ssl_send_flight_completed mbedtls_ssl_send_flight_completed +#define ssl_session mbedtls_ssl_session +#define ssl_session_free mbedtls_ssl_session_free +#define ssl_session_init mbedtls_ssl_session_init +#define ssl_session_reset mbedtls_ssl_session_reset +#define ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols +#define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support +#define ssl_set_authmode mbedtls_ssl_conf_authmode +#define ssl_set_bio mbedtls_ssl_set_bio +#define ssl_set_bio mbedtls_ssl_set_bio_timeout +#define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain +#define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting +#define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites +#define ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version +#define ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id +#define ssl_set_curves mbedtls_ssl_conf_curves +#define ssl_set_dbg mbedtls_ssl_conf_dbg +#define ssl_set_dh_param mbedtls_ssl_conf_dh_param +#define ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx +#define ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay +#define ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit +#define ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies +#define ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac +#define ssl_set_endpoint mbedtls_ssl_conf_endpoint +#define ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret +#define ssl_set_fallback mbedtls_ssl_conf_fallback +#define ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout +#define ssl_set_hostname mbedtls_ssl_set_hostname +#define ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len +#define ssl_set_max_version mbedtls_ssl_conf_max_version +#define ssl_set_min_version mbedtls_ssl_conf_min_version +#define ssl_set_own_cert mbedtls_ssl_conf_own_cert +#define ssl_set_own_cert_alt mbedtls_ssl_set_own_cert_alt +#define ssl_set_own_cert_rsa mbedtls_ssl_set_own_cert_rsa +#define ssl_set_psk mbedtls_ssl_conf_psk +#define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb +#define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation +#define ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced +#define ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period +#define ssl_set_rng mbedtls_ssl_conf_rng +#define ssl_set_session mbedtls_ssl_set_session +#define ssl_set_session_cache mbedtls_ssl_conf_session_cache +#define ssl_set_session_ticket_lifetime mbedtls_ssl_conf_session_ticket_lifetime +#define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets +#define ssl_set_sni mbedtls_ssl_conf_sni +#define ssl_set_transport mbedtls_ssl_conf_transport +#define ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac +#define ssl_set_verify mbedtls_ssl_conf_verify +#define ssl_sig_from_pk mbedtls_ssl_sig_from_pk +#define ssl_states mbedtls_ssl_states +#define ssl_ticket_keys mbedtls_ssl_ticket_keys +#define ssl_transform mbedtls_ssl_transform +#define ssl_transform_free mbedtls_ssl_transform_free +#define ssl_write mbedtls_ssl_write +#define ssl_write_certificate mbedtls_ssl_write_certificate +#define ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec +#define ssl_write_finished mbedtls_ssl_write_finished +#define ssl_write_record mbedtls_ssl_write_record +#define ssl_write_version mbedtls_ssl_write_version +#define supported_ciphers mbedtls_cipher_supported +#define t_sint mbedtls_mpi_sint +#define t_udbl mbedtls_t_udbl +#define t_uint mbedtls_mpi_uint +#define test_ca_crt mbedtls_test_ca_crt +#define test_ca_crt_ec mbedtls_test_ca_crt_ec +#define test_ca_crt_rsa mbedtls_test_ca_crt_rsa +#define test_ca_key mbedtls_test_ca_key +#define test_ca_key_ec mbedtls_test_ca_key_ec +#define test_ca_key_rsa mbedtls_test_ca_key_rsa +#define test_ca_list mbedtls_test_cas_pem +#define test_ca_pwd mbedtls_test_ca_pwd +#define test_ca_pwd_ec mbedtls_test_ca_pwd_ec +#define test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa +#define test_cli_crt mbedtls_test_cli_crt +#define test_cli_crt_ec mbedtls_test_cli_crt_ec +#define test_cli_crt_rsa mbedtls_test_cli_crt_rsa +#define test_cli_key mbedtls_test_cli_key +#define test_cli_key_ec mbedtls_test_cli_key_ec +#define test_cli_key_rsa mbedtls_test_cli_key_rsa +#define test_dhm_params mbedtls_test_dhm_params +#define test_srv_crt mbedtls_test_srv_crt +#define test_srv_crt_ec mbedtls_test_srv_crt_ec +#define test_srv_crt_rsa mbedtls_test_srv_crt_rsa +#define test_srv_key mbedtls_test_srv_key +#define test_srv_key_ec mbedtls_test_srv_key_ec +#define test_srv_key_rsa mbedtls_test_srv_key_rsa +#define threading_mutex_t mbedtls_threading_mutex_t +#define threading_set_alt mbedtls_threading_set_alt +#define timing_self_test mbedtls_timing_self_test +#define version_check_feature mbedtls_version_check_feature +#define version_get_number mbedtls_version_get_number +#define version_get_string mbedtls_version_get_string +#define version_get_string_full mbedtls_version_get_string_full +#define x509_bitstring mbedtls_x509_bitstring +#define x509_buf mbedtls_x509_buf +#define x509_crl mbedtls_x509_crl +#define x509_crl_entry mbedtls_x509_crl_entry +#define x509_crl_free mbedtls_x509_crl_free +#define x509_crl_info mbedtls_x509_crl_info +#define x509_crl_init mbedtls_x509_crl_init +#define x509_crl_parse mbedtls_x509_crl_parse +#define x509_crl_parse_der mbedtls_x509_crl_parse_der +#define x509_crl_parse_file mbedtls_x509_crl_parse_file +#define x509_crt mbedtls_x509_crt +#define x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage +#define x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage +#define x509_crt_free mbedtls_x509_crt_free +#define x509_crt_info mbedtls_x509_crt_info +#define x509_crt_init mbedtls_x509_crt_init +#define x509_crt_parse mbedtls_x509_crt_parse +#define x509_crt_parse_der mbedtls_x509_crt_parse_der +#define x509_crt_parse_file mbedtls_x509_crt_parse_file +#define x509_crt_parse_path mbedtls_x509_crt_parse_path +#define x509_crt_revoked mbedtls_x509_crt_is_revoked +#define x509_crt_verify mbedtls_x509_crt_verify +#define x509_csr mbedtls_x509_csr +#define x509_csr_free mbedtls_x509_csr_free +#define x509_csr_info mbedtls_x509_csr_info +#define x509_csr_init mbedtls_x509_csr_init +#define x509_csr_parse mbedtls_x509_csr_parse +#define x509_csr_parse_der mbedtls_x509_csr_parse_der +#define x509_csr_parse_file mbedtls_x509_csr_parse_file +#define x509_dn_gets mbedtls_x509_dn_gets +#define x509_get_alg mbedtls_x509_get_alg +#define x509_get_alg_null mbedtls_x509_get_alg_null +#define x509_get_ext mbedtls_x509_get_ext +#define x509_get_name mbedtls_x509_get_name +#define x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params +#define x509_get_serial mbedtls_x509_get_serial +#define x509_get_sig mbedtls_x509_get_sig +#define x509_get_sig_alg mbedtls_x509_get_sig_alg +#define x509_get_time mbedtls_x509_get_time +#define x509_key_size_helper mbedtls_x509_key_size_helper +#define x509_name mbedtls_x509_name +#define x509_oid_get_description mbedtls_x509_oid_get_description +#define x509_oid_get_numeric_string mbedtls_x509_oid_get_numeric_string +#define x509_self_test mbedtls_x509_self_test +#define x509_sequence mbedtls_x509_sequence +#define x509_serial_gets mbedtls_x509_serial_gets +#define x509_set_extension mbedtls_x509_set_extension +#define x509_sig_alg_gets mbedtls_x509_sig_alg_gets +#define x509_string_to_names mbedtls_x509_string_to_names +#define x509_time mbedtls_x509_time +#define x509_time_expired mbedtls_x509_time_is_past +#define x509_time_future mbedtls_x509_time_is_future +#define x509_write_extensions mbedtls_x509_write_extensions +#define x509_write_names mbedtls_x509_write_names +#define x509_write_sig mbedtls_x509_write_sig +#define x509write_cert mbedtls_x509write_cert +#define x509write_crt_der mbedtls_x509write_crt_der +#define x509write_crt_free mbedtls_x509write_crt_free +#define x509write_crt_init mbedtls_x509write_crt_init +#define x509write_crt_pem mbedtls_x509write_crt_pem +#define x509write_crt_set_authority_key_identifier mbedtls_x509write_crt_set_authority_key_identifier +#define x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints +#define x509write_crt_set_extension mbedtls_x509write_crt_set_extension +#define x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key +#define x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name +#define x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage +#define x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg +#define x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type +#define x509write_crt_set_serial mbedtls_x509write_crt_set_serial +#define x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key +#define x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier +#define x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name +#define x509write_crt_set_validity mbedtls_x509write_crt_set_validity +#define x509write_crt_set_version mbedtls_x509write_crt_set_version +#define x509write_csr mbedtls_x509write_csr +#define x509write_csr_der mbedtls_x509write_csr_der +#define x509write_csr_free mbedtls_x509write_csr_free +#define x509write_csr_init mbedtls_x509write_csr_init +#define x509write_csr_pem mbedtls_x509write_csr_pem +#define x509write_csr_set_extension mbedtls_x509write_csr_set_extension +#define x509write_csr_set_key mbedtls_x509write_csr_set_key +#define x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage +#define x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg +#define x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type +#define x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name +#define xtea_context mbedtls_xtea_context +#define xtea_crypt_cbc mbedtls_xtea_crypt_cbc +#define xtea_crypt_ecb mbedtls_xtea_crypt_ecb +#define xtea_free mbedtls_xtea_free +#define xtea_init mbedtls_xtea_init +#define xtea_self_test mbedtls_xtea_self_test +#define xtea_setup mbedtls_xtea_setup + +#endif /* compat-1.3.h */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ diff --git a/external_libs/mbedtls/include/mbedtls/config.h b/external_libs/mbedtls/include/mbedtls/config.h new file mode 100644 index 00000000..6fc9c772 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/config.h @@ -0,0 +1,2600 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/mbedtls/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_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 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 + +/** + * \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_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/mbedtls_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/mbedtls_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/mbedtls_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/mbedtls_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/mbedtls_md5.c + * Caller: library/mbedtls_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/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * library/x509write_crt.c + * library/mbedtls_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/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_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/mbedtls_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/mbedtls_x509_crt.c + * library/mbedtls_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/mbedtls_ripemd160.c + * Caller: library/mbedtls_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/mbedtls_sha1.c + * Caller: library/mbedtls_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/mbedtls_sha256.c + * Caller: library/entropy.c + * library/mbedtls_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/mbedtls_sha512.c + * Caller: library/entropy.c + * library/mbedtls_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/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_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/mbedtls_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/mbedtls_x509_crl.c + * Caller: library/mbedtls_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/mbedtls_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/external_libs/mbedtls/include/mbedtls/ctr_drbg.h b/external_libs/mbedtls/include/mbedtls/ctr_drbg.h new file mode 100644 index 00000000..059d3c5c --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ctr_drbg.h @@ -0,0 +1,290 @@ +/** + * \file ctr_drbg.h + * + * \brief CTR_DRBG based on AES-256 (NIST SP 800-90) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + +#include "aes.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */ +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */ +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) + /**< The seed length (counter + AES key) */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#else +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#endif +#endif + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CTR_DRBG context structure + */ +typedef struct +{ + unsigned char counter[16]; /*!< counter (V) */ + int reseed_counter; /*!< reseed counter */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + size_t entropy_len; /*!< amount of entropy grabbed on each + (re)seed */ + int reseed_interval; /*!< reseed interval */ + + mbedtls_aes_context aes_ctx; /*!< AES context */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief CTR_DRBG context initialization + * Makes the context ready for mbedtls_ctr_drbg_seed() or + * mbedtls_ctr_drbg_free(). + * + * \param ctx CTR_DRBG context to be initialized + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief CTR_DRBG initial seeding + * Seed and setup entropy source for future reseeds. + * + * Note: Personalization data can be provided in addition to the more generic + * entropy source to make this instantiation as unique as possible. + * + * \param ctx CTR_DRBG context to be seeded + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Clear CTR_CRBG context data + * + * \param ctx CTR_DRBG context to clear + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx CTR_DRBG context + * \param resistance MBEDTLS_CTR_DRBG_PR_ON or MBEDTLS_CTR_DRBG_PR_OFF + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each (re)seed + * (Default: MBEDTLS_CTR_DRBG_ENTROPY_LEN) + * + * \param ctx CTR_DRBG context + * \param len Amount of entropy to grab + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: MBEDTLS_CTR_DRBG_RESEED_INTERVAL) + * + * \param ctx CTR_DRBG context + * \param interval Reseed interval + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief CTR_DRBG reseeding (extracts data from entropy source) + * + * \param ctx CTR_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief CTR_DRBG update state + * + * \param ctx CTR_DRBG context + * \param additional Additional data to update state with + * \param add_len Length of additional data + * + * \note If add_len is greater than MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, + * only the first MBEDTLS_CTR_DRBG_MAX_SEED_INPUT bytes are used, + * the remaining ones are silently discarded. + */ +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief CTR_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached. + * + * \param p_rng CTR_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (Can be NULL) + * \param add_len Length of additional data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief CTR_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached. + * + * \param p_rng CTR_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * + * \return 0 if successful, or + * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx CTR_DRBG context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx CTR_DRBG context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +/* Internal functions (do not call directly) */ +int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, + int (*)(void *, unsigned char *, size_t), void *, + const unsigned char *, size_t, size_t ); + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/external_libs/mbedtls/include/mbedtls/debug.h b/external_libs/mbedtls/include/mbedtls/debug.h new file mode 100644 index 00000000..29579964 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/debug.h @@ -0,0 +1,228 @@ +/** + * \file debug.h + * + * \brief Functions for controlling and providing debug output from the library. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_DEBUG_H +#define MBEDTLS_DEBUG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#if defined(MBEDTLS_ECP_C) +#include "ecp.h" +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ + mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ + MBEDTLS_DEBUG_STRIP_PARENS args ) + +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ + mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) + +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ + mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) + +#if defined(MBEDTLS_BIGNUM_C) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ + mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ + mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ + mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) +#endif + +#else /* MBEDTLS_DEBUG_C */ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) + +#endif /* MBEDTLS_DEBUG_C */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the threshold error level to handle globally all debug output. + * Debug messages that have a level over the threshold value are + * discarded. + * (Default value: 0 = No debug ) + * + * \param threshold theshold level of messages to filter on. Messages at a + * higher level will be discarded. + * - Debug levels + * - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ +void mbedtls_debug_set_threshold( int threshold ); + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ); +#endif + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ + diff --git a/external_libs/mbedtls/include/mbedtls/des.h b/external_libs/mbedtls/include/mbedtls/des.h new file mode 100644 index 00000000..5ca2ecf2 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/des.h @@ -0,0 +1,306 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES context structure + */ +typedef struct +{ + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct +{ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + */ +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_des_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/external_libs/mbedtls/include/mbedtls/dhm.h b/external_libs/mbedtls/include/mbedtls/dhm.h new file mode 100644 index 00000000..d7ab1522 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/dhm.h @@ -0,0 +1,305 @@ +/** + * \file dhm.h + * + * \brief Diffie-Hellman-Merkle key exchange + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_DHM_H +#define MBEDTLS_DHM_H + +#include "bignum.h" + +/* + * DHM Error codes + */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ +#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ +#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ +#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read/write of file failed. */ + +/** + * RFC 3526 defines a number of standardized Diffie-Hellman groups + * for IKE. + * RFC 5114 defines a number of standardized Diffie-Hellman groups + * that can be used. + * + * Some are included here for convenience. + * + * Included are: + * RFC 3526 3. 2048-bit MODP Group + * RFC 3526 4. 3072-bit MODP Group + * RFC 3526 5. 4096-bit MODP Group + * RFC 5114 2.2. 2048-bit MODP Group with 224-bit Prime Order Subgroup + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G "02" + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G "02" + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G "02" + +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" + +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"\ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"\ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"\ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"\ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"\ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF"\ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"\ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"\ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"\ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"\ + "81BC087F2A7065B384B890D3191F2BFA" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DHM context structure + */ +typedef struct +{ + size_t len; /*!< size(P) in chars */ + mbedtls_mpi P; /*!< prime modulus */ + mbedtls_mpi G; /*!< generator */ + mbedtls_mpi X; /*!< secret value */ + mbedtls_mpi GX; /*!< self = G^X mod P */ + mbedtls_mpi GY; /*!< peer = G^Y mod P */ + mbedtls_mpi K; /*!< key = GY^X mod P */ + mbedtls_mpi RP; /*!< cached R^2 mod P */ + mbedtls_mpi Vi; /*!< blinding value */ + mbedtls_mpi Vf; /*!< un-blinding value */ + mbedtls_mpi pX; /*!< previous X */ +} +mbedtls_dhm_context; + +/** + * \brief Initialize DHM context + * + * \param ctx DHM context to be initialized + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief Parse the ServerKeyExchange parameters + * + * \param ctx DHM context + * \param p &(start of input buffer) + * \param end end of buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief Setup and write the ServerKeyExchange parameters + * + * \param ctx DHM context + * \param x_size private value size in bytes + * \param output destination buffer + * \param olen number of chars written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note This function assumes that ctx->P and ctx->G + * have already been properly set (for example + * using mbedtls_mpi_read_string or mbedtls_mpi_read_binary). + * + * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Import the peer's public value G^Y + * + * \param ctx DHM context + * \param input input buffer + * \param ilen size of buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief Create own private value X and export G^X + * + * \param ctx DHM context + * \param x_size private value size in bytes + * \param output destination buffer + * \param olen must be at least equal to the size of P, ctx->len + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Derive and export the shared secret (G^Y)^X mod P + * + * \param ctx DHM context + * \param output destination buffer + * \param output_size size of the destination buffer + * \param olen on exit, holds the actual number of bytes written + * \param f_rng RNG function, for blinding purposes + * \param p_rng RNG parameter + * + * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + * + * \note If non-NULL, f_rng is used to blind the input as + * countermeasure against timing attacks. Blinding is + * automatically used if and only if our secret value X is + * re-used and costs nothing otherwise, so it is recommended + * to always pass a non-NULL f_rng argument. + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Free and clear the components of a DHM key + * + * \param ctx DHM context to free and clear + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** \ingroup x509_module */ +/** + * \brief Parse DHM parameters in PEM or DER format + * + * \param dhm DHM context to be initialized + * \param dhmin input buffer + * \param dhminlen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific DHM or PEM error code + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup x509_module */ +/** + * \brief Load and parse DHM parameters + * + * \param dhm DHM context to be initialized + * \param path filename to read the DHM Parameters from + * + * \return 0 if successful, or a specific DHM or PEM error code + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_dhm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* dhm.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ecdh.h b/external_libs/mbedtls/include/mbedtls/ecdh.h new file mode 100644 index 00000000..625a2819 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ecdh.h @@ -0,0 +1,214 @@ +/** + * \file ecdh.h + * + * \brief Elliptic curve Diffie-Hellman + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ECDH_H +#define MBEDTLS_ECDH_H + +#include "ecp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * When importing from an EC key, select if it is our key or the peer's key + */ +typedef enum +{ + MBEDTLS_ECDH_OURS, + MBEDTLS_ECDH_THEIRS, +} mbedtls_ecdh_side; + +/** + * \brief ECDH context structure + */ +typedef struct +{ + mbedtls_ecp_group grp; /*!< elliptic curve used */ + mbedtls_mpi d; /*!< our secret value (private key) */ + mbedtls_ecp_point Q; /*!< our public value (public key) */ + mbedtls_ecp_point Qp; /*!< peer's public value (public key) */ + mbedtls_mpi z; /*!< shared secret */ + int point_format; /*!< format for point export in TLS messages */ + mbedtls_ecp_point Vi; /*!< blinding value (for later) */ + mbedtls_ecp_point Vf; /*!< un-blinding value (for later) */ + mbedtls_mpi _d; /*!< previous d (for later) */ +} +mbedtls_ecdh_context; + +/** + * \brief Generate a public key. + * Raw function that only does the core computation. + * + * \param grp ECP group + * \param d Destination MPI (secret exponent, aka private key) + * \param Q Destination point (public key) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute shared secret + * Raw function that only does the core computation. + * + * \param grp ECP group + * \param z Destination MPI (shared secret) + * \param Q Public key from other party + * \param d Our secret exponent (private key) + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note If f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks, see \c mbedtls_ecp_mul() for details. + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Initialize context + * + * \param ctx Context to initialize + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief Free context + * + * \param ctx Context to free + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief Generate a public key and a TLS ServerKeyExchange payload. + * (First function used by a TLS server for ECDHE.) + * + * \param ctx ECDH context + * \param olen number of chars written + * \param buf destination buffer + * \param blen length of buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note This function assumes that ctx->grp has already been + * properly set (for example using mbedtls_ecp_group_load). + * + * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Parse and procress a TLS ServerKeyExhange payload. + * (First function used by a TLS client for ECDHE.) + * + * \param ctx ECDH context + * \param buf pointer to start of input buffer + * \param end one past end of buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ); + +/** + * \brief Setup an ECDH context from an EC key. + * (Used by clients and servers in place of the + * ServerKeyEchange for static ECDH: import ECDH parameters + * from a certificate's EC key information.) + * + * \param ctx ECDH constext to set + * \param key EC key to use + * \param side Is it our key (1) or the peer's key (0) ? + * + * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief Generate a public key and a TLS ClientKeyExchange payload. + * (Second function used by a TLS client for ECDH(E).) + * + * \param ctx ECDH context + * \param olen number of bytes actually written + * \param buf destination buffer + * \param blen size of destination buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Parse and process a TLS ClientKeyExchange payload. + * (Second function used by a TLS server for ECDH(E).) + * + * \param ctx ECDH context + * \param buf start of input buffer + * \param blen length of input buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief Derive and export the shared secret. + * (Last function used by both TLS client en servers.) + * + * \param ctx ECDH context + * \param olen number of bytes written + * \param buf destination buffer + * \param blen buffer length + * \param f_rng RNG function, see notes for \c mbedtls_ecdh_compute_shared() + * \param p_rng RNG parameter + * + * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ecdsa.h b/external_libs/mbedtls/include/mbedtls/ecdsa.h new file mode 100644 index 00000000..52827d8d --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ecdsa.h @@ -0,0 +1,248 @@ +/** + * \file ecdsa.h + * + * \brief Elliptic curve DSA + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ECDSA_H +#define MBEDTLS_ECDSA_H + +#include "ecp.h" +#include "md.h" + +/* + * RFC 4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * (assuming ECP_MAX_BYTES is less than 126 for r and s, + * and less than 124 (total len <= 255) for the sequence) + */ +#if MBEDTLS_ECP_MAX_BYTES > 124 +#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" +#endif +/** Maximum size of an ECDSA signature in bytes */ +#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) + +/** + * \brief ECDSA context structure + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Compute ECDSA signature of a previously hashed message + * + * \note The deterministic version is usually prefered. + * + * \param grp ECP group + * \param r First output integer + * \param s Second output integer + * \param d Private signing key + * \param buf Message hash + * \param blen Length of buf + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Compute ECDSA signature of a previously hashed message, + * deterministic version (RFC 6979). + * + * \param grp ECP group + * \param r First output integer + * \param s Second output integer + * \param d Private signing key + * \param buf Message hash + * \param blen Length of buf + * \param md_alg MD algorithm used to hash the message + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief Verify ECDSA signature of a previously hashed message + * + * \param grp ECP group + * \param buf Message hash + * \param blen Length of buf + * \param Q Public key to use for verification + * \param r First integer of the signature + * \param s Second integer of the signature + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); + +/** + * \brief Compute ECDSA signature and write it to buffer, + * serialized as defined in RFC 4492 page 20. + * (Not thread-safe to use same context in multiple threads) + * + * \note The deterministice version (RFC 6979) is used if + * MBEDTLS_ECDSA_DETERMINISTIC is defined. + * + * \param ctx ECDSA context + * \param md_alg Algorithm that was used to hash the message + * \param hash Message hash + * \param hlen Length of hash + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note The "sig" buffer must be at least as large as twice the + * size of the curve used, plus 9 (eg. 73 bytes if a 256-bit + * curve is used). MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX, MBEDTLS_ERR_MPI_XXX or + * MBEDTLS_ERR_ASN1_XXX error code + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Compute ECDSA signature and write it to buffer, + * serialized as defined in RFC 4492 page 20. + * Deterministic version, RFC 6979. + * (Not thread-safe to use same context in multiple threads) + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in 2.0.0 + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Length of hash + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param md_alg MD algorithm used to hash the message + * + * \note The "sig" buffer must be at least as large as twice the + * size of the curve used, plus 9 (eg. 73 bytes if a 256-bit + * curve is used). MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX, MBEDTLS_ERR_MPI_XXX or + * MBEDTLS_ERR_ASN1_XXX error code + */ +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief Read and verify an ECDSA signature + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Size of hash + * \param sig Signature to read and verify + * \param slen Size of sig + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, + * MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than siglen, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief Generate an ECDSA keypair on the given curve + * + * \param ctx ECDSA context in which the keypair should be stored + * \param gid Group (elliptic curve) to use. One of the various + * MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a MBEDTLS_ERR_ECP_XXX code. + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Set an ECDSA context from an EC key pair + * + * \param ctx ECDSA context to set + * \param key EC key to use + * + * \return 0 on success, or a MBEDTLS_ERR_ECP_XXX code. + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); + +/** + * \brief Initialize context + * + * \param ctx Context to initialize + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief Free context + * + * \param ctx Context to free + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ecjpake.h b/external_libs/mbedtls/include/mbedtls/ecjpake.h new file mode 100644 index 00000000..b7b61604 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ecjpake.h @@ -0,0 +1,238 @@ +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ECJPAKE_H +#define MBEDTLS_ECJPAKE_H + +/* + * J-PAKE is a password-authenticated key exchange that allows deriving a + * strong shared secret from a (potentially low entropy) pre-shared + * passphrase, with forward secrecy and mutual authentication. + * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling + * + * This file implements the Elliptic Curve variant of J-PAKE, + * as defined in Chapter 7.4 of the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + * + * As the J-PAKE algorithm is inherently symmetric, so is our API. + * Each party needs to send its first round message, in any order, to the + * other party, then each sends its second round message, in any order. + * The payloads are serialized in a way suitable for use in TLS, but could + * also be use outside TLS. + */ + +#include "ecp.h" +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Roles in the EC J-PAKE exchange + */ +typedef enum { + MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ + MBEDTLS_ECJPAKE_SERVER, /**< Server */ +} mbedtls_ecjpake_role; + +/** + * EC J-PAKE context structure. + * + * J-PAKE is a symmetric protocol, except for the identifiers used in + * Zero-Knowledge Proofs, and the serialization of the second message + * (KeyExchange) as defined by the Thread spec. + * + * In order to benefit from this symmetry, we choose a different naming + * convetion from the Thread v1.0 spec. Correspondance is indicated in the + * description as a pair C: client name, S: server name + */ +typedef struct +{ + const mbedtls_md_info_t *md_info; /**< Hash to use */ + mbedtls_ecp_group grp; /**< Elliptic curve */ + mbedtls_ecjpake_role role; /**< Are we client or server? */ + int point_format; /**< Format for point export */ + + mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ +} mbedtls_ecjpake_context; + +/** + * \brief Initialize a context + * (just makes it ready for setup() or free()). + * + * \param ctx context to initialize + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); + +/** + * \brief Set up a context for use + * + * \note Currently the only values for hash/curve allowed by the + * standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1. + * + * \param ctx context to set up + * \param role Our role: client or server + * \param hash hash function to use (MBEDTLS_MD_XXX) + * \param curve elliptic curve identifier (MBEDTLS_ECP_DP_XXX) + * \param secret pre-shared secret (passphrase) + * \param len length of the shared secret + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ); + +/* + * \brief Check if a context is ready for use + * + * \param ctx Context to check + * + * \return 0 if the context is ready for use, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); + +/** + * \brief Generate and write the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes) + * + * \param ctx Context to use + * \param buf Pointer to extension contents + * \param len Extension length + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Generate and write the second round message + * (TLS: contents of the Client/ServerKeyExchange) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the second round message + * (TLS: contents of the Client/ServerKeyExchange) + * + * \param ctx Context to use + * \param buf Pointer to the message + * \param len Message length + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Derive the shared secret + * (TLS: Pre-Master Secret) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Free a context's content + * + * \param ctx context to free + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ecjpake.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ecp.h b/external_libs/mbedtls/include/mbedtls/ecp.h new file mode 100644 index 00000000..5246c789 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ecp.h @@ -0,0 +1,669 @@ +/** + * \file ecp.h + * + * \brief Elliptic curves over GF(p) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ECP_H +#define MBEDTLS_ECP_H + +#include "bignum.h" + +/* + * ECP error codes + */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ + +#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 + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ diff --git a/external_libs/mbedtls/include/mbedtls/entropy.h b/external_libs/mbedtls/include/mbedtls/entropy.h new file mode 100644 index 00000000..747aca4d --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/entropy.h @@ -0,0 +1,287 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#include "sha512.h" +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#include "sha256.h" +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +#if defined(MBEDTLS_HAVEGE_C) +#include "havege.h" +#endif + +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct +{ + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received in bytes */ + size_t threshold; /**< Minimum bytes required before release */ + int strong; /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct +{ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTSL_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/external_libs/mbedtls/include/mbedtls/entropy_poll.h b/external_libs/mbedtls/include/mbedtls/entropy_poll.h new file mode 100644 index 00000000..81258d5f --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/entropy_poll.h @@ -0,0 +1,109 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_TIMING_C) +/** + * \brief mbedtls_timing_hardclock-based entropy poll callback + */ +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/external_libs/mbedtls/include/mbedtls/error.h b/external_libs/mbedtls/include/mbedtls/error.h new file mode 100644 index 00000000..5e549f6b --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/error.h @@ -0,0 +1,107 @@ +/** + * \file error.h + * + * \brief Error to string translation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#include + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) + * + * Module Nr Codes assigned + * MPI 7 0x0002-0x0010 + * GCM 2 0x0012-0x0014 + * BLOWFISH 2 0x0016-0x0018 + * THREADING 3 0x001A-0x001E + * AES 2 0x0020-0x0022 + * CAMELLIA 2 0x0024-0x0026 + * XTEA 1 0x0028-0x0028 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 1 0x0032-0x0032 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 11 0x0042-0x0052 0x0043-0x0045 + * ASN1 7 0x0060-0x006C + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 2 0x000D-0x000F + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 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/external_libs/mbedtls/include/mbedtls/gcm.h b/external_libs/mbedtls/include/mbedtls/gcm.h new file mode 100644 index 00000000..1b77aaed --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/gcm.h @@ -0,0 +1,220 @@ +/** + * \file gcm.h + * + * \brief Galois/Counter mode for 128-bit block ciphers + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_GCM_H +#define MBEDTLS_GCM_H + +#include "cipher.h" + +#include + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief GCM context structure + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx;/*!< cipher context used */ + uint64_t HL[16]; /*!< Precalculated HTable */ + uint64_t HH[16]; /*!< Precalculated HTable */ + uint64_t len; /*!< Total data length */ + uint64_t add_len; /*!< Total add length */ + unsigned char base_ectr[16];/*!< First ECTR for tag */ + unsigned char y[16]; /*!< Y working value */ + unsigned char buf[16]; /*!< buf working value */ + int mode; /*!< Encrypt or Decrypt */ +} +mbedtls_gcm_context; + +/** + * \brief Initialize GCM context (just makes references valid) + * Makes the context ready for mbedtls_gcm_setkey() or + * mbedtls_gcm_free(). + * + * \param ctx GCM context to initialize + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief GCM initialization (encryption) + * + * \param ctx GCM context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or a cipher specific error code + */ +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief GCM buffer encryption/decryption using a block cipher + * + * \note On encryption, the output buffer can be the same as the input buffer. + * On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param mode MBEDTLS_GCM_ENCRYPT or MBEDTLS_GCM_DECRYPT + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * \param tag_len length of the tag to generate + * \param tag buffer for holding the tag + * + * \return 0 if successful + */ +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief GCM buffer authenticated decryption using a block cipher + * + * \note On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param tag buffer holding the tag + * \param tag_len length of the tag + * \param input buffer holding the input data + * \param output buffer for holding the output data + * + * \return 0 if successful and authenticated, + * MBEDTLS_ERR_GCM_AUTH_FAILED if tag does not match + */ +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic GCM stream start function + * + * \param ctx GCM context + * \param mode MBEDTLS_GCM_ENCRYPT or MBEDTLS_GCM_DECRYPT + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data (or NULL if length is 0) + * \param add_len length of additional data + * + * \return 0 if successful + */ +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief Generic GCM update function. Encrypts/decrypts using the + * given GCM context. Expects input to be a multiple of 16 + * bytes! Only the last call before mbedtls_gcm_finish() can be less + * than 16 bytes! + * + * \note On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * + * \return 0 if successful or MBEDTLS_ERR_GCM_BAD_INPUT + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic GCM finalisation function. Wraps up the GCM stream + * and generates the tag. The tag can have a maximum length of + * 16 bytes. + * + * \param ctx GCM context + * \param tag buffer for holding the tag + * \param tag_len length of the tag to generate (must be at least 4) + * + * \return 0 if successful or MBEDTLS_ERR_GCM_BAD_INPUT + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief Free a GCM context and underlying cipher sub-context + * + * \param ctx GCM context to free + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_gcm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* gcm.h */ diff --git a/external_libs/mbedtls/include/mbedtls/havege.h b/external_libs/mbedtls/include/mbedtls/havege.h new file mode 100644 index 00000000..dac5d311 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/havege.h @@ -0,0 +1,74 @@ +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_HAVEGE_H +#define MBEDTLS_HAVEGE_H + +#include + +#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct +{ + int PT1, PT2, offset[2]; + int pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; + int WALK[8192]; +} +mbedtls_havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void mbedtls_havege_free( mbedtls_havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ diff --git a/external_libs/mbedtls/include/mbedtls/hmac_drbg.h b/external_libs/mbedtls/include/mbedtls/hmac_drbg.h new file mode 100644 index 00000000..e0105580 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/hmac_drbg.h @@ -0,0 +1,299 @@ +/** + * \file hmac_drbg.h + * + * \brief HMAC_DRBG (NIST SP 800-90A) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * Error codes + */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct +{ + /* Working state: the key K is not stored explicitely, + * but is implied by the HMAC context */ + mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization + * Makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or + * mbedtls_hmac_drbg_free(). + * + * \param ctx HMAC_DRBG context to be initialized + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding + * Seed and setup entropy source for future reseeds. + * + * \param ctx HMAC_DRBG context to be seeded + * \param md_info MD algorithm to use for HMAC_DRBG + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \note The "security strength" as defined by NIST is set to: + * 128 bits if md_alg is SHA-1, + * 192 bits if md_alg is SHA-224, + * 256 bits if md_alg is SHA-256 or higher. + * Note that SHA-256 is just as efficient as SHA-224. + * + * \return 0 if successful, or + * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or + * MBEDTLS_ERR_MD_ALLOC_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * (For use with deterministic ECDSA.) + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param data Concatenation of entropy string and additional data + * \param data_len Length of data in bytes + * + * \return 0 if successful, or + * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or + * MBEDTLS_ERR_MD_ALLOC_FAILED. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx HMAC_DRBG context + * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each reseed + * (Default: given by the security strength, which + * depends on the hash used, see \c mbedtls_hmac_drbg_init() ) + * + * \param ctx HMAC_DRBG context + * \param len Amount of entropy to grab, in bytes + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) + * + * \param ctx HMAC_DRBG context + * \param interval Reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief HMAC_DRBG update state + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG reseeding (extracts data from entropy source) + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief HMAC_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (can be NULL) + * \param add_len Length of additional data (can be 0) + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or + * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief HMAC_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param out_len Length of the buffer + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or + * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/external_libs/mbedtls/include/mbedtls/md.h b/external_libs/mbedtls/include/mbedtls/md.h new file mode 100644 index 00000000..9b996a95 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/md.h @@ -0,0 +1,354 @@ +/** + * \file md.h + * + * \brief Generic message digest wrapper + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H + +#include + +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MBEDTLS_MD_NONE=0, + MBEDTLS_MD_MD2, + MBEDTLS_MD_MD4, + MBEDTLS_MD_MD5, + MBEDTLS_MD_SHA1, + MBEDTLS_MD_SHA224, + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_SHA512, + MBEDTLS_MD_RIPEMD160, +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +/** + * Opaque struct defined in md_internal.h + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * Generic message digest context. + */ +typedef struct { + /** Information about the associated message digest */ + const mbedtls_md_info_t *md_info; + + /** Digest-specific context */ + void *md_ctx; + + /** HMAC part of the context */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief Returns the list of digests supported by the generic digest module. + * + * \return a statically allocated array of digests, the last entry + * is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief Returns the message digest information associated with the + * given digest name. + * + * \param md_name Name of the digest to search for. + * + * \return The message digest information associated with md_name or + * NULL if not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief Returns the message digest information associated with the + * given digest type. + * + * \param md_type type of digest to search for. + * + * \return The message digest information associated with md_type or + * NULL if not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief Initialize a md_context (as NONE) + * This should always be called first. + * Prepares the context for mbedtls_md_setup() or mbedtls_md_free(). + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief Free and clear the internal structures of ctx. + * Can be called at any time after mbedtls_md_init(). + * Mandatory once mbedtls_md_setup() has been called. + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Select MD to use and allocate internal structures. + * Should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx Context to set up. + * \param md_info Message digest to use. + * + * \returns \c 0 on success, + * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, + * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. + */ +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Select MD to use and allocate internal structures. + * Should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \param ctx Context to set up. + * \param md_info Message digest to use. + * \param hmac 0 to save some memory if HMAC will not be used, + * non-zero is HMAC is going to be used with this context. + * + * \returns \c 0 on success, + * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, + * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. + */ +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief Clone the state of an MD context + * + * \note The two contexts must have been setup to the same type + * (cloning from SHA-256 to SHA-512 make no sense). + * + * \warning Only clones the MD state, not the HMAC state! (for now) + * + * \param dst The destination context + * \param src The context to be cloned + * + * \return \c 0 on success, + * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. + */ +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief Returns the size of the message digest output. + * + * \param md_info message digest info + * + * \return size of the message digest output in bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief Returns the type of the message digest output. + * + * \param md_info message digest info + * + * \return type of the message digest output. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief Returns the name of the message digest output. + * + * \param md_info message digest info + * + * \return name of the message digest output. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief Prepare the context to digest a new message. + * Generally called after mbedtls_md_setup() or mbedtls_md_finish(). + * Followed by mbedtls_md_update(). + * + * \param ctx generic message digest context. + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief Generic message digest process buffer + * Called between mbedtls_md_starts() and mbedtls_md_finish(). + * May be called repeatedly. + * + * \param ctx Generic message digest context + * \param input buffer holding the datal + * \param ilen length of the input data + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief Generic message digest final digest + * Called after mbedtls_md_update(). + * Usually followed by mbedtls_md_free() or mbedtls_md_starts(). + * + * \param ctx Generic message digest context + * \param output Generic message digest checksum result + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief Output = message_digest( input buffer ) + * + * \param md_info message digest info + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic message digest checksum result + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Output = message_digest( file contents ) + * + * \param md_info message digest info + * \param path input file name + * \param output generic message digest checksum result + * + * \return 0 if successful, + * MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, + * MBEDTLS_ERR_MD_BAD_INPUT_DATA if md_info was NULL. + */ +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Set HMAC key and prepare to authenticate a new message. + * Usually called after mbedtls_md_setup() or mbedtls_md_hmac_finish(). + * + * \param ctx HMAC context + * \param key HMAC secret key + * \param keylen length of the HMAC key in bytes + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief Generic HMAC process buffer. + * Called between mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * and mbedtls_md_hmac_finish(). + * May be called repeatedly. + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief Output HMAC. + * Called after mbedtls_md_hmac_update(). + * Usually followed by mbedtls_md_hmac_reset(), + * mbedtls_md_hmac_starts(), or mbedtls_md_free(). + * + * \param ctx HMAC context + * \param output Generic HMAC checksum result + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief Prepare to authenticate a new message with the same key. + * Called after mbedtls_md_hmac_finish() and before + * mbedtls_md_hmac_update(). + * + * \param ctx HMAC context to be reset + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief Output = Generic_HMAC( hmac key, input buffer ) + * + * \param md_info message digest info + * \param key HMAC secret key + * \param keylen length of the HMAC key in bytes + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic HMAC-result + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ diff --git a/external_libs/mbedtls/include/mbedtls/md2.h b/external_libs/mbedtls/include/mbedtls/md2.h new file mode 100644 index 00000000..0f93fbf4 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/md2.h @@ -0,0 +1,136 @@ +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD2 context structure + */ +typedef struct +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + size_t left; /*!< amount of data in buffer */ +} +mbedtls_md2_context; + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + */ +void mbedtls_md2_init( mbedtls_md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + */ +void mbedtls_md2_free( mbedtls_md2_context *ctx ); + +/** + * \brief Clone (the state of) an MD2 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + */ +void mbedtls_md2_starts( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + */ +void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD2_ALT */ +#include "md2_alt.h" +#endif /* MBEDTLS_MD2_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + */ +void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_md2_self_test( int verbose ); + +/* Internal use */ +void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md2.h */ diff --git a/external_libs/mbedtls/include/mbedtls/md4.h b/external_libs/mbedtls/include/mbedtls/md4.h new file mode 100644 index 00000000..45214d41 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/md4.h @@ -0,0 +1,136 @@ +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md4_context; + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + */ +void mbedtls_md4_init( mbedtls_md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + */ +void mbedtls_md4_free( mbedtls_md4_context *ctx ); + +/** + * \brief Clone (the state of) an MD4 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + */ +void mbedtls_md4_starts( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + */ +void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD4_ALT */ +#include "md4_alt.h" +#endif /* MBEDTLS_MD4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + */ +void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_md4_self_test( int verbose ); + +/* Internal use */ +void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md4.h */ diff --git a/external_libs/mbedtls/include/mbedtls/md5.h b/external_libs/mbedtls/include/mbedtls/md5.h new file mode 100644 index 00000000..5a64061a --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/md5.h @@ -0,0 +1,136 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ); + +/* Internal use */ +void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + */ +void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_md5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/external_libs/mbedtls/include/mbedtls/md_internal.h b/external_libs/mbedtls/include/mbedtls/md_internal.h new file mode 100644 index 00000000..e2441bbc --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/md_internal.h @@ -0,0 +1,114 @@ +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Name of the message digest */ + const char * name; + + /** Output length of the digest function in bytes */ + int size; + + /** Block length of the digest function in bytes */ + int block_size; + + /** Digest initialisation function */ + void (*starts_func)( void *ctx ); + + /** Digest update function */ + void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + void (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + void (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Clone state from a context */ + void (*clone_func)( void *dst, const void *src ); + + /** Internal use only */ + void (*process_func)( void *ctx, const unsigned char *input ); +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/external_libs/mbedtls/include/mbedtls/memory_buffer_alloc.h b/external_libs/mbedtls/include/mbedtls/memory_buffer_alloc.h new file mode 100644 index 00000000..d5df316f --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -0,0 +1,150 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_MEMORY_VERIFY_NONE 0 +#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) +#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) +#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call calloc() and free(). + * It sets the global mbedtls_calloc() and mbedtls_free() pointers + * to its own functions. + * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if + * MBEDTLS_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + */ +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void mbedtls_memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MBEDTLS_MEMORY_VERIFY_NONE) + * + * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, + * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS + */ +void mbedtls_memory_buffer_set_verify( int verify ); + +#if defined(MBEDTLS_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if MBEDTLS_MEMORY_BACKTRACE is defined. + */ +void mbedtls_memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param max_blocks Peak number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void mbedtls_memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Current number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param cur_blocks Current number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. + * Prints out full header information if MBEDTLS_MEMORY_DEBUG + * is defined. (Includes stack trace information for each block if + * MBEDTLS_MEMORY_BACKTRACE is defined as well). + * + * \return 0 if verified, 1 otherwise + */ +int mbedtls_memory_buffer_alloc_verify( void ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ diff --git a/external_libs/mbedtls/include/mbedtls/net.h b/external_libs/mbedtls/include/mbedtls/net.h new file mode 100644 index 00000000..774559b3 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/net.h @@ -0,0 +1,31 @@ +/** + * \file net.h + * + * \brief Deprecated header file that includes mbedtls/net_sockets.h + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * \deprecated Superseded by mbedtls/net_sockets.h + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#include "mbedtls/net_sockets.h" +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/external_libs/mbedtls/include/mbedtls/net_sockets.h b/external_libs/mbedtls/include/mbedtls/net_sockets.h new file mode 100644 index 00000000..de335526 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/net_sockets.h @@ -0,0 +1,225 @@ +/** + * \file net_sockets.h + * + * \brief Network communication functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#include +#include + +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct +{ + int fd; /**< The underlying file descriptor */ +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init( mbedtls_net_context *ctx ); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \note Sets the socket in connected mode even with UDP. + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \note Regardless of the protocol, opens the sockets and binds it. + * In addition, make the socket listening if protocol is TCP. + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to + * non-blocking and accept() would block. + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return the number of bytes received, + * or a non-zero error code: + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free( mbedtls_net_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ diff --git a/external_libs/mbedtls/include/mbedtls/oid.h b/external_libs/mbedtls/include/mbedtls/oid.h new file mode 100644 index 00000000..fcecdafd --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/oid.h @@ -0,0 +1,570 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "md.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "x509.h" +#endif + +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ + +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct { + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); +#endif + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/external_libs/mbedtls/include/mbedtls/padlock.h b/external_libs/mbedtls/include/mbedtls/padlock.h new file mode 100644 index 00000000..2045a5ab --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/padlock.h @@ -0,0 +1,107 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PADLOCK_H +#define MBEDTLS_PADLOCK_H + +#include "aes.h" + +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define MBEDTLS_HAVE_ASAN +#endif +#endif + +/* Some versions of ASan result in errors about not enough registers */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ + !defined(MBEDTLS_HAVE_ASAN) + +#ifndef MBEDTLS_HAVE_X86 +#define MBEDTLS_HAVE_X86 +#endif + +#include + +#define MBEDTLS_PADLOCK_RNG 0x000C +#define MBEDTLS_PADLOCK_ACE 0x00C0 +#define MBEDTLS_PADLOCK_PHE 0x0C00 +#define MBEDTLS_PADLOCK_PMM 0x3000 + +#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PadLock detection routine + * + * \param feature The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_padlock_has_support( int feature ); + +/** + * \brief PadLock AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief PadLock AES-CBC buffer en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ diff --git a/external_libs/mbedtls/include/mbedtls/pem.h b/external_libs/mbedtls/include/mbedtls/pem.h new file mode 100644 index 00000000..54dc02d7 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/pem.h @@ -0,0 +1,129 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header header string to write + * \param footer footer string to write + * \param der_data DER data to write + * \param der_len length of the DER data + * \param buf buffer to write to + * \param buf_len length of output buffer + * \param olen total length written / required (if buf_len is not enough) + * + * \return 0 on success, or a specific PEM or BASE64 error code. On + * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required + * size. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/external_libs/mbedtls/include/mbedtls/pk.h b/external_libs/mbedtls/include/mbedtls/pk.h new file mode 100644 index 00000000..f9f9b9bb --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/pk.h @@ -0,0 +1,616 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(MBEDTLS_RSA_C) +#include "rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "ecdsa.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The signature is valid but its length is less than expected. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct +{ + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct +{ + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + void * pk_ctx; /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a mbedtls_pk_context (as NONE) + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx Context to use + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * \param ctx Context to use + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx Context to test + * \param type Target type + * + * \return 0 if context can't do the operations, + * 1 otherwise. + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx PK context to use - must hold a private key + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx PK context to use - must hold a private key + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx Context to use + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx Context to use + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx Context to use + * + * \return Type on success, or MBEDTLS_PK_NONE + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * \param password password to decrypt the file (can be NULL) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx key to be initialized + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk the key to fill + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key public key to write away + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/external_libs/mbedtls/include/mbedtls/pk_internal.h b/external_libs/mbedtls/include/mbedtls/pk_internal.h new file mode 100644 index 00000000..01d0f214 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/pk_internal.h @@ -0,0 +1,114 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer: wrapper functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "pk.h" + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/external_libs/mbedtls/include/mbedtls/pkcs11.h b/external_libs/mbedtls/include/mbedtls/pkcs11.h new file mode 100644 index 00000000..2e889281 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/pkcs11.h @@ -0,0 +1,173 @@ +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PKCS11_H +#define MBEDTLS_PKCS11_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS11_C) + +#include "x509_crt.h" + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Context for PKCS #11 private keys. + */ +typedef struct { + pkcs11h_certificate_t pkcs11h_cert; + int len; +} mbedtls_pkcs11_context; + +/** + * Initialize a mbedtls_pkcs11_context. + * (Just making memory references valid.) + */ +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); + +/** + * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. + * + * \param cert X.509 certificate to fill + * \param pkcs11h_cert PKCS #11 helper certificate + * + * \return 0 on success. + */ +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); + +/** + * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the + * mbedtls_pkcs11_context will take over control of the certificate, freeing it when + * done. + * + * \param priv_key Private key structure to fill. + * \param pkcs11_cert PKCS #11 helper certificate + * + * \return 0 on success + */ +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); + +/** + * Free the contents of the given private key context. Note that the structure + * itself is not freed. + * + * \param priv_key Private key structure to cleanup + */ +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ); + +/** + * \brief Do an RSA private key decrypt, then remove the message + * padding + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Do a private RSA to sign a message digest + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * SSL/TLS wrappers for PKCS#11 functions + */ +static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) +{ + return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, + output_max_len ); +} + +static inline int mbedtls_ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + ((void) f_rng); + ((void) p_rng); + return mbedtls_pkcs11_sign( (mbedtls_pkcs11_context *) ctx, mode, md_alg, + hashlen, hash, sig ); +} + +static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) +{ + return ( (mbedtls_pkcs11_context *) ctx )->len; +} + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PKCS11_C */ + +#endif /* MBEDTLS_PKCS11_H */ diff --git a/external_libs/mbedtls/include/mbedtls/pkcs12.h b/external_libs/mbedtls/include/mbedtls/pkcs12.h new file mode 100644 index 00000000..9b2d9045 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/pkcs12.h @@ -0,0 +1,119 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PKCS12_H +#define MBEDTLS_PKCS12_H + +#include "md.h" +#include "cipher.h" +#include "asn1.h" + +#include + +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY, + * MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ diff --git a/external_libs/mbedtls/include/mbedtls/pkcs5.h b/external_libs/mbedtls/include/mbedtls/pkcs5.h new file mode 100644 index 00000000..ec5cb9e7 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/pkcs5.h @@ -0,0 +1,94 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PKCS5_H +#define MBEDTLS_PKCS5_H + +#include "asn1.h" +#include "md.h" + +#include +#include + +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ diff --git a/external_libs/mbedtls/include/mbedtls/platform.h b/external_libs/mbedtls/include/mbedtls/platform.h new file mode 100644 index 00000000..b1b019e5 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/platform.h @@ -0,0 +1,295 @@ +/** + * \file platform.h + * + * \brief mbed TLS Platform abstraction layer + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(_WIN32) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< Default snprintf to use */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< Default exit value to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< Default exit value to use */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void * (*mbedtls_calloc)( size_t n, size_t size ); +extern void (*mbedtls_free)( void *ptr ); + +/** + * \brief Set your own memory implementation function pointers + * + * \param calloc_func the calloc function implementation + * \param free_func the free function implementation + * + * \return 0 if successful + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief Set your own fprintf function pointer + * + * \param fprintf_func the fprintf function implementation + * + * \return 0 + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief Set your own printf function pointer + * + * \param printf_func the printf function implementation + * + * \return 0 + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(_WIN32) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief Set your own snprintf function pointer + * + * \param snprintf_func the snprintf function implementation + * + * \return 0 + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf snprintf +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief Set your own exit function pointer + * + * \param exit_func the exit function implementation + * + * \return 0 + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief Set your own seed file writing/reading functions + * + * \param nv_seed_read_func the seed reading function implementation + * \param nv_seed_write_func the seed writing function implementation + * + * \return 0 + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/external_libs/mbedtls/include/mbedtls/platform_time.h b/external_libs/mbedtls/include/mbedtls/platform_time.h new file mode 100644 index 00000000..abb34314 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/platform_time.h @@ -0,0 +1,81 @@ +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ripemd160.h b/external_libs/mbedtls/include/mbedtls/ripemd160.h new file mode 100644 index 00000000..7083fc85 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ripemd160.h @@ -0,0 +1,138 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_ripemd160_context; + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clone (the state of) an RIPEMD-160 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + */ +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ); + +/* Internal use */ +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_RIPEMD160_ALT */ +#include "ripemd160.h" +#endif /* MBEDTLS_RIPEMD160_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +void mbedtls_ripemd160( const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ripemd160_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_ripemd160.h */ diff --git a/external_libs/mbedtls/include/mbedtls/rsa.h b/external_libs/mbedtls/include/mbedtls/rsa.h new file mode 100644 index 00000000..35185dfd --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/rsa.h @@ -0,0 +1,652 @@ +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +/* + * RSA Error codes + */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the library's validity check. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 +#define MBEDTLS_RSA_PRIVATE 1 + +#define MBEDTLS_RSA_PKCS_V15 0 +#define MBEDTLS_RSA_PKCS_V21 1 + +#define MBEDTLS_RSA_SIGN 1 +#define MBEDTLS_RSA_CRYPT 2 + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ +#if defined(MBEDTLS_RSA_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RSA context structure + */ +typedef struct +{ + int ver; /*!< always 0 */ + size_t len; /*!< size(N) in chars */ + + mbedtls_mpi N; /*!< public modulus */ + mbedtls_mpi E; /*!< public exponent */ + + mbedtls_mpi D; /*!< private exponent */ + mbedtls_mpi P; /*!< 1st prime factor */ + mbedtls_mpi Q; /*!< 2nd prime factor */ + mbedtls_mpi DP; /*!< D % (P - 1) */ + mbedtls_mpi DQ; /*!< D % (Q - 1) */ + mbedtls_mpi QP; /*!< 1 / (Q % P) */ + + mbedtls_mpi RN; /*!< cached R^2 mod N */ + mbedtls_mpi RP; /*!< cached R^2 mod P */ + mbedtls_mpi RQ; /*!< cached R^2 mod Q */ + + mbedtls_mpi Vi; /*!< cached blinding value */ + mbedtls_mpi Vf; /*!< cached un-blinding value */ + + int padding; /*!< MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + MBEDTLS_RSA_PKCS_v21 for OAEP/PSS */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t as + specified in the mbedtls_md.h header file + for the EME-OAEP and EMSA-PSS + encoding */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex */ +#endif +} +mbedtls_rsa_context; + +/** + * \brief Initialize an RSA context + * + * Note: Set padding to MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \param ctx RSA context to be initialized + * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 + * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier + * + * \note The hash_id parameter is actually ignored + * when using MBEDTLS_RSA_PKCS_V15 padding. + * + * \note Choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it's merely + * a default value, which can be overriden by calling specific + * rsa_rsaes_xxx or rsa_rsassa_xxx functions. + * + * \note The chosen hash is always used for OEAP encryption. + * For PSS signatures, it's always used for making signatures, + * but can be overriden (and always is, if set to + * MBEDTLS_MD_NONE) for verifying them. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief Set padding for an already initialized RSA context + * See \c mbedtls_rsa_init() for details. + * + * \param ctx RSA context to be set + * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 + * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id); + +/** + * \brief Generate an RSA keypair + * + * \param ctx RSA context that will hold the key + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param nbits size of the public key in bits + * \param exponent public exponent (e.g., 65537) + * + * \note mbedtls_rsa_init() must be called beforehand to setup + * the RSA context. + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief Check a public RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief Check a private RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief Check a public-private RSA key pair. + * Check each of the contexts, and make sure they match. + * + * \param pub RSA context holding the public key + * \param prv RSA context holding the private key + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ); + +/** + * \brief Do an RSA public key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note This function does NOT take care of message + * padding. Also, be sure to set input[0] = 0 or assure 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/external_libs/mbedtls/include/mbedtls/sha1.h b/external_libs/mbedtls/include/mbedtls/sha1.h new file mode 100644 index 00000000..7a67c6c1 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/sha1.h @@ -0,0 +1,136 @@ +/** + * \file sha1.h + * + * \brief SHA-1 cryptographic hash function + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_sha1_context; + +/** + * \brief Initialize SHA-1 context + * + * \param ctx SHA-1 context to be initialized + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief Clear SHA-1 context + * + * \param ctx SHA-1 context to be cleared + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-1 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); + +/* Internal use */ +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/external_libs/mbedtls/include/mbedtls/sha256.h b/external_libs/mbedtls/include/mbedtls/sha256.h new file mode 100644 index 00000000..f8041adf --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/sha256.h @@ -0,0 +1,141 @@ +/** + * \file sha256.h + * + * \brief SHA-224 and SHA-256 cryptographic hash function + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-256 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ +} +mbedtls_sha256_context; + +/** + * \brief Initialize SHA-256 context + * + * \param ctx SHA-256 context to be initialized + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief Clear SHA-256 context + * + * \param ctx SHA-256 context to be cleared + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-256 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-224/256 checksum result + */ +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); + +/* Internal use */ +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-256( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void mbedtls_sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_sha256_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/external_libs/mbedtls/include/mbedtls/sha512.h b/external_libs/mbedtls/include/mbedtls/sha512.h new file mode 100644 index 00000000..627694f4 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/sha512.h @@ -0,0 +1,141 @@ +/** + * \file sha512.h + * + * \brief SHA-384 and SHA-512 cryptographic hash function + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-512 context structure + */ +typedef struct +{ + uint64_t total[2]; /*!< number of bytes processed */ + uint64_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[128]; /*!< data block being processed */ + int is384; /*!< 0 => SHA-512, else SHA-384 */ +} +mbedtls_sha512_context; + +/** + * \brief Initialize SHA-512 context + * + * \param ctx SHA-512 context to be initialized + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief Clear SHA-512 context + * + * \param ctx SHA-512 context to be cleared + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-512 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief SHA-512 context setup + * + * \param ctx context to be initialized + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief SHA-512 process buffer + * + * \param ctx SHA-512 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-512 final digest + * + * \param ctx SHA-512 context + * \param output SHA-384/512 checksum result + */ +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* MBEDTLS_SHA512_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-512( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-384/512 checksum result + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void mbedtls_sha512( const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_sha512_self_test( int verbose ); + +/* Internal use */ +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ssl.h b/external_libs/mbedtls/include/mbedtls/ssl.h new file mode 100644 index 00000000..ba499d2b --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ssl.h @@ -0,0 +1,2552 @@ +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SSL_H +#define MBEDTLS_SSL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "ecp.h" + +#include "ssl_ciphersuites.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "x509_crt.h" +#include "x509_crl.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "dhm.h" +#endif + +#if defined(MBEDTLS_ECDH_C) +#include "ecdh.h" +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) +#include "zlib.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +/* + * SSL Error codes + */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ + +/* + * Various constants + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 +#define MBEDTLS_SSL_IS_FALLBACK 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 +#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 + +#define MBEDTLS_SSL_ARC4_ENABLED 0 +#define MBEDTLS_SSL_ARC4_DISABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) +#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Maxium fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +/* \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 +#else +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 + +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret +{ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum +{ + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +} +mbedtls_ssl_states; + +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send fewer bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \return The callback must return the number of bytes received, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in ssl_internal.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +#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 +}; + + +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 fallow. + * + * \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_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^64 - 256.) + * + * 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". + * + * \param conf SSL configuration + * \param period The threshold value: a big-endian 64-bit number. + * Set to 2^64 - 1 to disable periodic renegotiation + */ +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 of 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 + * (currently unused). + * + * \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/external_libs/mbedtls/include/mbedtls/ssl_cache.h b/external_libs/mbedtls/include/mbedtls/ssl_cache.h new file mode 100644 index 00000000..3734bb72 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ssl_cache.h @@ -0,0 +1,143 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SSL_CACHE_H +#define MBEDTLS_SSL_CACHE_H + +#include "ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) +#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; +typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct mbedtls_ssl_cache_entry +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t timestamp; /*!< entry timestamp */ +#endif + mbedtls_ssl_session session; /*!< entry session */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ +#endif + mbedtls_ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct mbedtls_ssl_cache_context +{ + mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache entry timeout */ + int max_entries; /*!< maximum entries */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to store entry for + */ +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); +#endif /* MBEDTLS_HAVE_TIME */ + +/** + * \brief Set the maximum number of cache entries + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h b/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h new file mode 100644 index 00000000..deaaa375 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -0,0 +1,321 @@ +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H + +#include "pk.h" +#include "cipher.h" +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 +#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 +#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A +#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#endif + +/* Key exchanges 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/external_libs/mbedtls/include/mbedtls/ssl_cookie.h b/external_libs/mbedtls/include/mbedtls/ssl_cookie.h new file mode 100644 index 00000000..037e1c31 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ssl_cookie.h @@ -0,0 +1,108 @@ +/** + * \file ssl_cookie.h + * + * \brief DTLS cookie callbacks implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SSL_COOKIE_H +#define MBEDTLS_SSL_COOKIE_H + +#include "ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ +#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT +#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Context for the default cookie functions. + */ +typedef struct +{ + mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ +#if !defined(MBEDTLS_HAVE_TIME) + unsigned long serial; /*!< serial number for expiration */ +#endif + unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_ssl_cookie_ctx; + +/** + * \brief Initialize cookie context + */ +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Setup cookie context (generate keys) + */ +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set expiration delay for cookies + * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) + * + * \param ctx Cookie contex + * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies + * issued in the meantime. + * 0 to disable expiration (NOT recommended) + */ +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); + +/** + * \brief Free cookie context + */ +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; + +/** + * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cookie.h */ diff --git a/external_libs/mbedtls/include/mbedtls/ssl_internal.h b/external_libs/mbedtls/include/mbedtls/ssl_internal.h new file mode 100644 index 00000000..668c0f56 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ssl_internal.h @@ -0,0 +1,500 @@ +/** + * \file ssl_ticket.h + * + * \brief Internal functions shared by the SSL modules + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SSL_INTERNAL_H +#define MBEDTLS_SSL_INTERNAL_H + +#include "ssl.h" + +#if defined(MBEDTLS_MD5_C) +#include "md5.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "sha512.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#include "ecjpake.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Determine minimum supported version */ +#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +/* Determine maximum supported version */ +#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) +#define MBEDTLS_SSL_COMPRESSION_ADD 1024 +#else +#define MBEDTLS_SSL_COMPRESSION_ADD 0 +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define MBEDTLS_SSL_MAC_ADD 16 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_SSL_PADDING_ADD 256 +#else +#define MBEDTLS_SSL_PADDING_ADD 0 +#endif + +#define MBEDTLS_SSL_BUFFER_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ + + MBEDTLS_SSL_COMPRESSION_ADD \ + + 29 /* counter + header + IV */ \ + + MBEDTLS_SSL_MAC_ADD \ + + MBEDTLS_SSL_PADDING_ADD \ + ) + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 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/external_libs/mbedtls/include/mbedtls/ssl_ticket.h b/external_libs/mbedtls/include/mbedtls/ssl_ticket.h new file mode 100644 index 00000000..7c6bc61b --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/ssl_ticket.h @@ -0,0 +1,135 @@ +/** + * \file ssl_ticket.h + * + * \brief TLS server ticket callbacks implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SSL_TICKET_H +#define MBEDTLS_SSL_TICKET_H + +/* + * This implementation of the session ticket callbacks includes key + * management, rotating the keys periodically in order to preserve forward + * secrecy, when MBEDTLS_HAVE_TIME is defined. + */ + +#include "ssl.h" +#include "cipher.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Information for session ticket protection + */ +typedef struct +{ + unsigned char name[4]; /*!< random key identifier */ + uint32_t generation_time; /*!< key generation timestamp (seconds) */ + mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ +} +mbedtls_ssl_ticket_key; + +/** + * \brief Context for session ticket handling functions + */ +typedef struct +{ + mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ + unsigned char active; /*!< index of the currently active key */ + + uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ssl_ticket_context; + +/** + * \brief Initialize a ticket context. + * (Just make it ready for mbedtls_ssl_ticket_setup() + * or mbedtls_ssl_ticket_free().) + * + * \param ctx Context to be initialized + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); + +/** + * \brief Prepare context to be actually used + * + * \param ctx Context to be set up + * \param f_rng RNG callback function + * \param p_rng RNG callback context + * \param cipher AEAD cipher to use for ticket protection. + * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note It is highly recommended to select a cipher that is at + * least as strong as the the strongest ciphersuite + * supported. Usually that means a 256-bit key. + * + * \note The lifetime of the keys is twice the lifetime of tickets. + * It is recommended to pick a reasonnable lifetime so as not + * to negate the benefits of forward secrecy. + * + * \return 0 if successful, + * or a specific MBEDTLS_ERR_XXX error code + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ); + +/** + * \brief Implementation of the ticket write callback + * + * \note See \c mbedlts_ssl_ticket_write_t for description + */ +mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; + +/** + * \brief Implementation of the ticket parse callback + * + * \note See \c mbedlts_ssl_ticket_parse_t for description + */ +mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; + +/** + * \brief Free a context's content and zeroize it. + * + * \param ctx Context to be cleaned up + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ticket.h */ diff --git a/external_libs/mbedtls/include/mbedtls/threading.h b/external_libs/mbedtls/include/mbedtls/threading.h new file mode 100644 index 00000000..b0c34ecc --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/threading.h @@ -0,0 +1,106 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct +{ + pthread_mutex_t mutex; + char is_valid; +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/external_libs/mbedtls/include/mbedtls/timing.h b/external_libs/mbedtls/include/mbedtls/timing.h new file mode 100644 index 00000000..ae7a713e --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/timing.h @@ -0,0 +1,141 @@ +/** + * \file timing.h + * + * \brief Portable interface to the CPU cycle counter + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct +{ + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset if set to 1, the timer is restarted + */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm( int seconds ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0) + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/external_libs/mbedtls/include/mbedtls/version.h b/external_libs/mbedtls/include/mbedtls/version.h new file mode 100644 index 00000000..6c0cc9b0 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/version.h @@ -0,0 +1,111 @@ +/** + * \file version.h + * + * \brief Run-time version information + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * This set of compile-time defines and run-time variables can be used to + * determine the version number of the mbed TLS library used. + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 4 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x02040000 +#define MBEDTLS_VERSION_STRING "2.4.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.4.0" + +#if defined(MBEDTLS_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int mbedtls_version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void mbedtls_version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void mbedtls_version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * \note only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") + * + * \return 0 if the feature is present, + * -1 if the feature is not present and + * -2 if support for feature checking as a whole was not + * compiled in. + */ +int mbedtls_version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_VERSION_C */ + +#endif /* version.h */ diff --git a/external_libs/mbedtls/include/mbedtls/x509.h b/external_libs/mbedtls/include/mbedtls/x509.h new file mode 100644 index 00000000..54dac166 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/x509.h @@ -0,0 +1,331 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#if defined(MBEDTLS_RSA_C) +#include "rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +/* \} 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) /* Parsed (and then ?) */ + +/* + * 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/external_libs/mbedtls/include/mbedtls/x509_crl.h b/external_libs/mbedtls/include/mbedtls/x509_crl.h new file mode 100644 index 00000000..79884399 --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/x509_crl.h @@ -0,0 +1,173 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_X509_CRL_H +#define MBEDTLS_X509_CRL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct mbedtls_x509_crl_entry +{ + mbedtls_x509_buf raw; + + mbedtls_x509_buf serial; + + mbedtls_x509_time revocation_date; + + mbedtls_x509_buf entry_ext; + + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct mbedtls_x509_crl +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + mbedtls_x509_buf sig_oid2; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ diff --git a/external_libs/mbedtls/include/mbedtls/x509_crt.h b/external_libs/mbedtls/include/mbedtls/x509_crt.h new file mode 100644 index 00000000..383e484f --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/x509_crt.h @@ -0,0 +1,654 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_X509_CRT_H +#define MBEDTLS_X509_CRT_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" +#include "x509_crl.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct mbedtls_x509_crt +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ +} +mbedtls_x509_crt; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +typedef struct +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything 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/external_libs/mbedtls/include/mbedtls/x509_csr.h b/external_libs/mbedtls/include/mbedtls/x509_csr.h new file mode 100644 index 00000000..fe9843cb --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/x509_csr.h @@ -0,0 +1,298 @@ +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_X509_CSR_H +#define MBEDTLS_X509_CSR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct mbedtls_x509_csr +{ + mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ + mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf sig_oid; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ +} +mbedtls_x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct mbedtls_x509write_csr +{ + mbedtls_pk_context *key; + mbedtls_asn1_named_data *subject; + mbedtls_md_type_t md_alg; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_csr; + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \note CSR attributes (if any) are currently silently ignored. + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \note See notes for \c mbedtls_x509_csr_parse_der() + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \note See notes for \c mbedtls_x509_csr_parse() + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ); + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymetric key to include + */ +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_csr.h */ diff --git a/external_libs/mbedtls/include/mbedtls/xtea.h b/external_libs/mbedtls/include/mbedtls/xtea.h new file mode 100644 index 00000000..b073f84e --- /dev/null +++ b/external_libs/mbedtls/include/mbedtls/xtea.h @@ -0,0 +1,139 @@ +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_XTEA_H +#define MBEDTLS_XTEA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_XTEA_ENCRYPT 1 +#define MBEDTLS_XTEA_DECRYPT 0 + +#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ + +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief XTEA context structure + */ +typedef struct +{ + uint32_t k[4]; /*!< key */ +} +mbedtls_xtea_context; + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* MBEDTLS_XTEA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_xtea_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ diff --git a/external_libs/mbedtls/library/Makefile b/external_libs/mbedtls/library/Makefile new file mode 100644 index 00000000..bd6abcd7 --- /dev/null +++ b/external_libs/mbedtls/library/Makefile @@ -0,0 +1,168 @@ +include ../../../tools/build_scripts/internal_make_funcs.mk +# 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) + $(call AR_Log) + $(AR) -rc $@ $(OBJS_TLS) + $(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) + $(call AR_Log) + $(AR) -rc $@ $(OBJS_X509) + $(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) + $(call AR_Log) + $(AR) -rc $@ $(OBJS_CRYPTO) + $(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 $@ $<" + $(call CC_Log) + @ \ + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c $< + +clean: +ifndef WINDOWS + rm -f *.o libmbed* +else + del /Q /F *.o libmbed* +endif diff --git a/external_libs/mbedtls/library/aes.c b/external_libs/mbedtls/library/aes.c new file mode 100644 index 00000000..a186dee9 --- /dev/null +++ b/external_libs/mbedtls/library/aes.c @@ -0,0 +1,1492 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_AES_C) + +#include + +#include "mbedtls/aes.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); + } +} + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + + } +#endif + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free( &cty ); + + return( ret ); +} +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +} + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +void mbedtls_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 ); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +void mbedtls_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 ); +} +#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 ) + mbedtls_aes_encrypt( ctx, input, output ); + else + mbedtls_aes_decrypt( ctx, input, output ); + + return( 0 ); +} + +#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/external_libs/mbedtls/library/aesni.c b/external_libs/mbedtls/library/aesni.c new file mode 100644 index 00000000..1ca3c3ef --- /dev/null +++ b/external_libs/mbedtls/library/aesni.c @@ -0,0 +1,464 @@ +/* + * AES-NI support functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set + * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_AESNI_C) + +#include "mbedtls/aesni.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +/* + * AES-NI support detection routine + */ +int mbedtls_aesni_has_support( unsigned int what ) +{ + static int done = 0; + static unsigned int c = 0; + + if( ! done ) + { + asm( "movl $1, %%eax \n\t" + "cpuid \n\t" + : "=c" (c) + : + : "eax", "ebx", "edx" ); + done = 1; + } + + return( ( c & what ) != 0 ); +} + +/* + * Binutils needs to be at least 2.19 to support AES-NI instructions. + * Unfortunately, a lot of users have a lower version now (2014-04). + * Emit bytecode directly in order to support "old" version of gas. + * + * Opcodes from the Intel architecture reference manual, vol. 3. + * We always use registers, so we don't need prefixes for memory operands. + * Operand macros are in gas order (src, dst) as opposed to Intel order + * (dst, src) in order to blend better into the surrounding assembly code. + */ +#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," +#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," +#define AESENC ".byte 0x66,0x0F,0x38,0xDC," +#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," +#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," +#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," +#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," + +#define xmm0_xmm0 "0xC0" +#define xmm0_xmm1 "0xC8" +#define xmm0_xmm2 "0xD0" +#define xmm0_xmm3 "0xD8" +#define xmm0_xmm4 "0xE0" +#define xmm1_xmm0 "0xC1" +#define xmm1_xmm2 "0xD1" + +/* + * AES-NI AES-ECB block en(de)cryption + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + asm( "movdqu (%3), %%xmm0 \n\t" // load input + "movdqu (%1), %%xmm1 \n\t" // load round key 0 + "pxor %%xmm1, %%xmm0 \n\t" // round 0 + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // normal rounds = nr - 1 + "test %2, %2 \n\t" // mode? + "jz 2f \n\t" // 0 = decrypt + + "1: \n\t" // encryption loop + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // loop + "jnz 1b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENCLAST xmm1_xmm0 "\n\t" // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" + "subl $1, %0 \n\t" + "jnz 2b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESDECLAST xmm1_xmm0 "\n\t" // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output + : + : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) + : "memory", "cc", "xmm0", "xmm1" ); + + + return( 0 ); +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ) +{ + unsigned char aa[16], bb[16], cc[16]; + size_t i; + + /* The inputs are in big-endian order, so byte-reverse them */ + for( i = 0; i < 16; i++ ) + { + aa[i] = a[15 - i]; + bb[i] = b[15 - i]; + } + + asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 + "movdqu (%1), %%xmm1 \n\t" // b1:b0 + + /* + * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 + * using [CLMUL-WP] algorithm 1 (p. 13). + */ + "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 + "movdqa %%xmm1, %%xmm3 \n\t" // same + "movdqa %%xmm1, %%xmm4 \n\t" // same + PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 + PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 + PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 + PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 + "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 + "movdqa %%xmm4, %%xmm3 \n\t" // same + "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 + "pslldq $8, %%xmm3 \n\t" // e0+f0:0 + "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 + "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 + + /* + * Now shift the result one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 20) + */ + "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 + "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 + "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 + "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 + "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 + "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 + "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 + "pslldq $8, %%xmm3 \n\t" // r0>>63:0 + "pslldq $8, %%xmm4 \n\t" // r2>>63:0 + "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 + "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 + "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 + "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 + + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 20). + * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). + */ + /* Step 2 (1) */ + "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 + "movdqa %%xmm1, %%xmm4 \n\t" // same + "movdqa %%xmm1, %%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a + "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b + "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c + + /* Step 2 (2) */ + "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b + "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c + "pslldq $8, %%xmm3 \n\t" // a+b+c:0 + "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 + + /* Steps 3 and 4 */ + "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' + "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' + "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' + "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' + "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' + // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing + // bits carried from d. Now get those\t bits back in. + "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // d<<63:stuff + "psllq $62, %%xmm4 \n\t" // d<<62:stuff + "psllq $57, %%xmm5 \n\t" // d<<57:stuff + "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff + "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff + "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d + "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 + "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 + "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 + + "movdqu %%xmm0, (%2) \n\t" // done + : + : "r" (aa), "r" (bb), "r" (cc) + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); + + /* Now byte-reverse the outputs */ + for( i = 0; i < 16; i++ ) + c[i] = cc[15 - i]; + + return; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ) +{ + unsigned char *ik = invkey; + const unsigned char *fk = fwdkey + 16 * nr; + + memcpy( ik, fk, 16 ); + + for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) + asm( "movdqu (%0), %%xmm0 \n\t" + AESIMC xmm0_xmm0 "\n\t" + "movdqu %%xmm0, (%1) \n\t" + : + : "r" (fk), "r" (ik) + : "memory", "xmm0" ); + + memcpy( ik, fk, 16 ); +} + +/* + * Key expansion, 128-bit case + */ +static void aesni_setkey_enc_128( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key + "movdqu %%xmm0, (%0) \n\t" // as round key 0 + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next round key. + * + * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 + "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm1 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! + "add $16, %0 \n\t" // point to next round key + "movdqu %%xmm0, (%0) \n\t" // write it + "ret \n\t" + + /* Main "loop" */ + "2: \n\t" + AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_setkey_enc_192( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movq 16(%1), %%xmm1 \n\t" + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next 6 quarter-keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 + * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 + "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 + "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 + "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "ret \n\t" + + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" + + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_setkey_enc_256( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movdqu 16(%1), %%xmm1 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next two round keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and + * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * + * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 + * and those have been written to the output buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + + /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + AESKEYGENA xmm0_xmm2 ",0x00 \n\t" + "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm2, %%xmm1 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "ret \n\t" + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of mbedtls_aes_context.buf + */ + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ) +{ + switch( bits ) + { + case 128: aesni_setkey_enc_128( rk, key ); break; + case 192: aesni_setkey_enc_192( rk, key ); break; + case 256: aesni_setkey_enc_256( rk, key ); break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_C */ diff --git a/external_libs/mbedtls/library/arc4.c b/external_libs/mbedtls/library/arc4.c new file mode 100644 index 00000000..05b33d3f --- /dev/null +++ b/external_libs/mbedtls/library/arc4.c @@ -0,0 +1,205 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ARC4_C) + +#include "mbedtls/arc4.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARC4_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); +} + +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); +} + +/* + * ARC4 key schedule + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ) +{ + int i, j, a; + unsigned int k; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ) +{ + int x, y, a, b; + size_t i; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < length; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + output[i] = (unsigned char) + ( input[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; + + return( 0 ); +} + +#endif /* !MBEDTLS_ARC4_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: + * + * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 + */ +static const unsigned char arc4_test_key[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_pt[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_ct[3][8] = +{ + { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, + { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, + { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } +}; + +/* + * Checkup routine + */ +int mbedtls_arc4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char ibuf[8]; + unsigned char obuf[8]; + mbedtls_arc4_context ctx; + + mbedtls_arc4_init( &ctx ); + + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ARC4 test #%d: ", i + 1 ); + + memcpy( ibuf, arc4_test_pt[i], 8 ); + + mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); + mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); + + if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_arc4_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARC4_C */ diff --git a/external_libs/mbedtls/library/asn1parse.c b/external_libs/mbedtls/library/asn1parse.c new file mode 100644 index 00000000..4dd65c03 --- /dev/null +++ b/external_libs/mbedtls/library/asn1parse.c @@ -0,0 +1,393 @@ +/* + * Generic ASN.1 parsing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#include "mbedtls/asn1.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 16 ) | + ( (size_t)(*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | + ( (size_t)(*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( (*len)-- < 2 || *(*p)++ != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + + + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + int ret; + size_t len; + mbedtls_asn1_buf *buf; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + buf = &(cur->buf); + buf->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) + return( ret ); + + buf->p = *p; + *p += buf->len; + + /* Allocate and assign next pointer */ + if( *p < end ) + { + cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, + sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/external_libs/mbedtls/library/asn1write.c b/external_libs/mbedtls/library/asn1write.c new file mode 100644 index 00000000..69b61b20 --- /dev/null +++ b/external_libs/mbedtls/library/asn1write.c @@ -0,0 +1,390 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ASN1_WRITE_C) + +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( len <= 0xFFFF ) + { + if( *p - start < 3 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = 0x82; + return( 3 ); + } + + if( len <= 0xFFFFFF ) + { + if( *p - start < 4 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = 0x83; + return( 4 ); + } + + if( len <= 0xFFFFFFFF ) + { + if( *p - start < 5 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = ( len >> 24 ) & 0xFF; + *--(*p) = 0x84; + return( 5 ); + } + + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +} + +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) +{ + int ret; + size_t len = 0; + + // Write the MPI + // + len = mbedtls_mpi_size( X ); + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); + + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( X->s ==1 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) +{ + int ret; + size_t len = 0; + + // Write NULL + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ) +{ + int ret; + size_t len = 0; + + if( par_len == 0 ) + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); + else + len += par_len; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 255 : 0; + len++; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) +{ + int ret; + size_t len = 0; + + // TODO negative values and values larger than 128 + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len += 1; + *--(*p) = val; + + if( val > 0 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret; + size_t len = 0, size; + + size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); + + // Calculate byte length + // + if( *p < start || (size_t)( *p - start ) < size + 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size + 1; + (*p) -= size; + memcpy( *p, buf, size ); + + // Write unused bits + // + *--(*p) = (unsigned char) (size * 8 - bits); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, + sizeof(mbedtls_asn1_named_data) ); + if( cur == NULL ) + return( NULL ); + + cur->oid.len = oid_len; + cur->oid.p = mbedtls_calloc( 1, oid_len ); + if( cur->oid.p == NULL ) + { + mbedtls_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->val.len = val_len; + cur->val.p = mbedtls_calloc( 1, val_len ); + if( cur->val.p == NULL ) + { + mbedtls_free( cur->oid.p ); + mbedtls_free( cur ); + return( NULL ); + } + + cur->next = *head; + *head = cur; + } + else if( cur->val.len < val_len ) + { + /* + * Enlarge existing value buffer if needed + * Preserve old data until the allocation succeeded, to leave list in + * a consistent state in case allocation fails. + */ + void *p = mbedtls_calloc( 1, val_len ); + if( p == NULL ) + return( NULL ); + + mbedtls_free( cur->val.p ); + cur->val.p = p; + cur->val.len = val_len; + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* MBEDTLS_ASN1_WRITE_C */ diff --git a/external_libs/mbedtls/library/base64.c b/external_libs/mbedtls/library/base64.c new file mode 100644 index 00000000..5cb12cba --- /dev/null +++ b/external_libs/mbedtls/library/base64.c @@ -0,0 +1,289 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BASE64_C) + +#include "mbedtls/base64.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( ( i + 1 ) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + uint32_t j, x; + unsigned char *p; + + /* First pass: check for validity and get output length */ + for( i = n = j = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + x = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + ++x; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( x != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' && ++j > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = ( ( n * 6 ) + 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/external_libs/mbedtls/library/bignum.c b/external_libs/mbedtls/library/bignum.c new file mode 100644 index 00000000..4c99e04d --- /dev/null +++ b/external_libs/mbedtls/library/bignum.c @@ -0,0 +1,2442 @@ +/* + * Multi-precision integer library + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { + volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; +} + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + + /* Actually resize up in this case */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret; + size_t i; + + if( X == Y ) + return( 0 ); + + if( Y->p == NULL ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + for( i = 0; i < Y->n; i++ ) + X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; + + for( ; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) +{ + int ret; + mbedtls_mpi_uint r; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + + if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + n += 3; + + 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/external_libs/mbedtls/library/blowfish.c b/external_libs/mbedtls/library/blowfish.c new file mode 100644 index 00000000..9003f0df --- /dev/null +++ b/external_libs/mbedtls/library/blowfish.c @@ -0,0 +1,656 @@ +/* + * Blowfish implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The Blowfish block cipher was designed by Bruce Schneier in 1993. + * http://www.schneier.com/blowfish.html + * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + +#include "mbedtls/blowfish.h" + +#include + +#if !defined(MBEDTLS_BLOWFISH_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +/* declarations of data at the end of this file */ +static const uint32_t S[4][256]; + +static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) +{ + unsigned short a, b, c, d; + uint32_t y; + + d = (unsigned short)(x & 0xFF); + x >>= 8; + c = (unsigned short)(x & 0xFF); + x >>= 8; + b = (unsigned short)(x & 0xFF); + x >>= 8; + a = (unsigned short)(x & 0xFF); + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return( y ); +} + +static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; + Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; + + *xl = Xl; + *xr = Xr; +} + +static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); +} + +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); +} + +/* + * Blowfish key schedule + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i, j, k; + uint32_t data, datal, datar; + + if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || + ( keybits % 8 ) ) + { + return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH ); + } + + keybits >>= 3; + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j++ ) + ctx->S[i][j] = S[i][j]; + } + + j = 0; + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) + { + data = 0x00000000; + for( k = 0; k < 4; ++k ) + { + data = ( data << 8 ) | key[j++]; + if( j >= keybits ) + j = 0; + } + ctx->P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } + return( 0 ); +} + +/* + * Blowfish-ECB block encryption/decryption + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) +{ + uint32_t X0, X1; + + GET_UINT32_BE( X0, input, 0 ); + GET_UINT32_BE( X1, input, 4 ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + blowfish_dec( ctx, &X0, &X1 ); + } + else /* MBEDTLS_BLOWFISH_ENCRYPT */ + { + blowfish_enc( ctx, &X0, &X1 ); + } + + PUT_UINT32_BE( X0, output, 0 ); + PUT_UINT32_BE( X1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Blowfish-CBC buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; + + if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) + return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); + mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Blowfish CFB buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Blowfish CTR buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, + stream_block ); + + for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static const uint32_t S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + +#endif /* !MBEDTLS_BLOWFISH_ALT */ +#endif /* MBEDTLS_BLOWFISH_C */ diff --git a/external_libs/mbedtls/library/camellia.c b/external_libs/mbedtls/library/camellia.c new file mode 100644 index 00000000..ac6f96a8 --- /dev/null +++ b/external_libs/mbedtls/library/camellia.c @@ -0,0 +1,1072 @@ +/* + * Camellia implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The Camellia block cipher was designed by NTT and Mitsubishi Electric + * Corporation. + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + +#include "mbedtls/camellia.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const unsigned char SIGMA_CHARS[6][8] = +{ + { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, + { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, + { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, + { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, + { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, + { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } +}; + +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + +static const unsigned char FSb[256] = +{ + 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, + 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, + 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, + 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, + 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, + 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, + 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, + 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, + 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, + 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, + 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) +#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) +#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] + +#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char FSb[256] = +{ + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 +}; + +static const unsigned char FSb2[256] = +{ + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 +}; + +static const unsigned char FSb3[256] = +{ + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 +}; + +static const unsigned char FSb4[256] = +{ + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) FSb2[(n)] +#define SBOX3(n) FSb3[(n)] +#define SBOX4(n) FSb4[(n)] + +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char shifts[2][4][4] = +{ + { + { 1, 1, 1, 1 }, /* KL */ + { 0, 0, 0, 0 }, /* KR */ + { 1, 1, 1, 1 }, /* KA */ + { 0, 0, 0, 0 } /* KB */ + }, + { + { 1, 0, 1, 1 }, /* KL */ + { 1, 1, 0, 1 }, /* KR */ + { 1, 1, 1, 0 }, /* KA */ + { 1, 1, 0, 1 } /* KB */ + } +}; + +static const signed char indexes[2][4][20] = +{ + { + { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, + 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ + { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, + 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ + }, + { + { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, + -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ + { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ + { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ + { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, + 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ + } +}; + +static const signed char transposes[2][20] = +{ + { + 21, 22, 23, 20, + -1, -1, -1, -1, + 18, 19, 16, 17, + 11, 8, 9, 10, + 15, 12, 13, 14 + }, + { + 25, 26, 27, 24, + 29, 30, 31, 28, + 18, 19, 16, 17, + -1, -1, -1, -1, + -1, -1, -1, -1 + } +}; + +/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ +#define ROTL(DEST, SRC, SHIFT) \ +{ \ + (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ + (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ + (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ + (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ +} + +#define FL(XL, XR, KL, KR) \ +{ \ + (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ + (XL) = ((XR) | (KR)) ^ (XL); \ +} + +#define FLInv(YL, YR, KL, KR) \ +{ \ + (YL) = ((YR) | (KR)) ^ (YL); \ + (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ +} + +#define SHIFT_AND_PLACE(INDEX, OFFSET) \ +{ \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ + \ + for( i = 1; i <= 4; i++ ) \ + if( shifts[(INDEX)][(OFFSET)][i -1] ) \ + ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ + \ + for( i = 0; i < 20; i++ ) \ + if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ + RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ + } \ +} + +static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], + uint32_t z[2]) +{ + uint32_t I0, I1; + I0 = x[0] ^ k[0]; + I1 = x[1] ^ k[1]; + + I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX4((I0 ) & 0xFF) ); + I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX1((I1 ) & 0xFF) ); + + I0 ^= (I1 << 8) | (I1 >> 24); + I1 ^= (I0 << 16) | (I0 >> 16); + I0 ^= (I1 >> 8) | (I1 << 24); + I1 ^= (I0 >> 8) | (I0 << 24); + + z[0] ^= I1; + z[1] ^= I0; +} + +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); +} + +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int idx; + size_t i; + uint32_t *RK; + unsigned char t[64]; + uint32_t SIGMA[6][2]; + uint32_t KC[16]; + uint32_t TK[20]; + + RK = ctx->rk; + + memset( t, 0, 64 ); + memset( RK, 0, sizeof(ctx->rk) ); + + switch( keybits ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH ); + } + + for( i = 0; i < keybits / 8; ++i ) + t[i] = key[i]; + + if( keybits == 192 ) { + for( i = 0; i < 8; i++ ) + t[24 + i] = ~t[16 + i]; + } + + /* + * Prepare SIGMA values + */ + for( i = 0; i < 6; i++ ) { + GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); + GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); + } + + /* + * Key storage in KC + * Order: KL, KR, KA, KB + */ + memset( KC, 0, sizeof(KC) ); + + /* Store KL, KR */ + for( i = 0; i < 8; i++ ) + GET_UINT32_BE( KC[i], t, i * 4 ); + + /* Generate KA */ + for( i = 0; i < 4; ++i ) + KC[8 + i] = KC[i] ^ KC[4 + i]; + + camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); + + for( i = 0; i < 4; ++i ) + KC[8 + i] ^= KC[i]; + + camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); + + if( keybits > 128 ) { + /* Generate KB */ + for( i = 0; i < 4; ++i ) + KC[12 + i] = KC[4 + i] ^ KC[8 + i]; + + camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); + camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); + } + + /* + * Generating subkeys + */ + + /* Manipulating KL */ + SHIFT_AND_PLACE( idx, 0 ); + + /* Manipulating KR */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 3 ); + } + + /* Do transpositions */ + for( i = 0; i < 20; i++ ) { + if( transposes[idx][i] != -1 ) { + RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; + } + } + + return( 0 ); +} + +/* + * Camellia key schedule (decryption) + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int idx, ret; + size_t i; + mbedtls_camellia_context cty; + uint32_t *RK; + uint32_t *SK; + + mbedtls_camellia_init( &cty ); + + /* Also checks keybits */ + if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + idx = ( ctx->nr == 4 ); + + RK = ctx->rk; + SK = cty.rk + 24 * 2 + 8 * idx * 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) + { + *RK++ = *SK++; + *RK++ = *SK++; + } + + SK -= 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int NR; + uint32_t *RK, X[4]; + + ( (void) mode ); + + NR = ctx->nr; + RK = ctx->rk; + + GET_UINT32_BE( X[0], input, 0 ); + GET_UINT32_BE( X[1], input, 4 ); + GET_UINT32_BE( X[2], input, 8 ); + GET_UINT32_BE( X[3], input, 12 ); + + X[0] ^= *RK++; + X[1] ^= *RK++; + X[2] ^= *RK++; + X[3] ^= *RK++; + + while( NR ) { + --NR; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + + if( NR ) { + FL(X[0], X[1], RK[0], RK[1]); + RK += 2; + FLInv(X[2], X[3], RK[0], RK[1]); + RK += 2; + } + } + + X[2] ^= *RK++; + X[3] ^= *RK++; + X[0] ^= *RK++; + X[1] ^= *RK++; + + PUT_UINT32_BE( X[2], output, 0 ); + PUT_UINT32_BE( X[3], output, 4 ); + PUT_UINT32_BE( X[0], output, 8 ); + PUT_UINT32_BE( X[1], output, 12 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, + stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_CAMELLIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Camellia test vectors from: + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt + * (For each bitlength: Key 0, Nr 39) + */ +#define CAMELLIA_TESTS_ECB 2 + +static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = +{ + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, +}; + +static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = +{ + { + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, + { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, + 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } + }, + { + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, + { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, + 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } + }, + { + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, + { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, + 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } + } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define CAMELLIA_TESTS_CBC 3 + +static const unsigned char camellia_test_cbc_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + , + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } + , + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char camellia_test_cbc_iv[16] = + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } +; + +static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = +{ + { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, + { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, + { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } + +}; + +static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = +{ + { + { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, + 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, + { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, + 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, + { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, + 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } + }, + { + { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, + 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, + { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, + 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, + { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, + 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } + }, + { + { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, + 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, + { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, + 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, + { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, + 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc5528.html + */ + +static const unsigned char camellia_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char camellia_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char camellia_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char camellia_test_ctr_ct[3][48] = +{ + { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, + 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, + { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, + 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, + 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, + 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, + { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, + 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, + 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, + 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, + 0xDF, 0x50, 0x86, 0x96 } +}; + +static const int camellia_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_camellia_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char src[16]; + unsigned char dst[16]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + + mbedtls_camellia_context ctx; + + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); + + for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { + memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); + memcpy( dst, camellia_test_ecb_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_plain[i], 16 ); + memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + mbedtls_camellia_setkey_enc( &ctx, key, 128 ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CAMELLIA_C */ diff --git a/external_libs/mbedtls/library/ccm.c b/external_libs/mbedtls/library/ccm.c new file mode 100644 index 00000000..13a8fd1a --- /dev/null +++ b/external_libs/mbedtls/library/ccm.c @@ -0,0 +1,464 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CCM_C) + +#include "mbedtls/ccm.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +/* + * Initialize context + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); +} + +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); +} + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * Update the CBC-MAC state in y using a block in b + * (Always using b as the source helps the compiler optimise a bit better.) + */ +#define UPDATE_CBC_MAC \ + for( i = 0; i < 16; i++ ) \ + y[i] ^= b[i]; \ + \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ + return( ret ); + +/* + * Encrypt or decrypt a partial block with CTR + * Warning: using b for temporary storage! src and dst must not be b! + * This avoids allocating one more 16 bytes buffer while allowing src == dst. + */ +#define CTR_CRYPT( dst, src, len ) \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \ + return( ret ); \ + \ + for( i = 0; i < len; i++ ) \ + dst[i] = src[i] ^ b[i]; + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char i; + unsigned char q; + size_t len_left, olen; + unsigned char b[16]; + unsigned char y[16]; + unsigned char ctr[16]; + const unsigned char *src; + unsigned char *dst; + + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + */ + if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + /* Also implies q is within bounds */ + if( iv_len < 7 || iv_len > 13 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( add_len > 0xFF00 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + q = 16 - 1 - (unsigned char) iv_len; + + /* + * First block B_0: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + b[0] = 0; + b[0] |= ( add_len > 0 ) << 6; + b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; + b[0] |= q - 1; + + memcpy( b + 1, iv, iv_len ); + + for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) + b[15-i] = (unsigned char)( len_left & 0xFF ); + + if( len_left > 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + + /* Start CBC-MAC with first block */ + memset( y, 0, 16 ); + UPDATE_CBC_MAC; + + /* + * If there is additional data, update CBC-MAC with + * add_len, add, 0 (padding to a block boundary) + */ + if( add_len > 0 ) + { + size_t use_len; + len_left = add_len; + src = add; + + memset( b, 0, 16 ); + b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); + b[1] = (unsigned char)( ( add_len ) & 0xFF ); + + use_len = len_left < 16 - 2 ? len_left : 16 - 2; + memcpy( b + 2, src, use_len ); + len_left -= use_len; + src += use_len; + + UPDATE_CBC_MAC; + + while( len_left > 0 ) + { + use_len = len_left > 16 ? 16 : len_left; + + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + + len_left -= use_len; + src += use_len; + } + } + + /* + * Prepare counter block for encryption: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 counter (initially 1) + * + * With flags as (bits): + * 7 .. 3 0 + * 2 .. 0 q - 1 + */ + ctr[0] = q - 1; + memcpy( ctr + 1, iv, iv_len ); + memset( ctr + 1 + iv_len, 0, q ); + ctr[15] = 1; + + /* + * Authenticate and {en,de}crypt the message. + * + * The only difference between encryption and decryption is + * the respective order of authentication and {en,de}cryption. + */ + len_left = length; + src = input; + dst = output; + + while( len_left > 0 ) + { + size_t use_len = len_left > 16 ? 16 : len_left; + + if( mode == CCM_ENCRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + } + + CTR_CRYPT( dst, src, use_len ); + + if( mode == CCM_DECRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, dst, use_len ); + UPDATE_CBC_MAC; + } + + dst += use_len; + src += use_len; + len_left -= use_len; + + /* + * Increment counter. + * No need to check for overflow thanks to the length check above. + */ + for( i = 0; i < q; i++ ) + if( ++ctr[15-i] != 0 ) + break; + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for( i = 0; i < q; i++ ) + ctr[15-i] = 0; + + CTR_CRYPT( y, y, 16 ); + memcpy( tag, y, tag_len ); + + return( 0 ); +} + +/* + * Authenticated encryption + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_zeroize( output, length ); + return( MBEDTLS_ERR_CCM_AUTH_FAILED ); + } + + return( 0 ); +} + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * Examples 1 to 3 from SP800-38C Appendix C + */ + +#define NB_TESTS 3 + +/* + * The data is the same for all tests, only the used length changes + */ +static const unsigned char key[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; + +static const unsigned char iv[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b +}; + +static const unsigned char ad[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char msg[] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +}; + +static const size_t iv_len [NB_TESTS] = { 7, 8, 12 }; +static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; +static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; +static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; + +static const unsigned char res[NB_TESTS][32] = { + { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, + { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, + 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, + 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, + { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, + 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, + 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, + 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } +}; + +int mbedtls_ccm_self_test( int verbose ) +{ + mbedtls_ccm_context ctx; + unsigned char out[32]; + size_t i; + int ret; + + mbedtls_ccm_init( &ctx ); + + if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM: setup failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + msg, out, + out + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + res[i], out, + res[i] + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( out, msg, msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + mbedtls_ccm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_CCM_C */ diff --git a/external_libs/mbedtls/library/certs.c b/external_libs/mbedtls/library/certs.c new file mode 100644 index 00000000..ffe6bc98 --- /dev/null +++ b/external_libs/mbedtls/library/certs.c @@ -0,0 +1,351 @@ +/* + * X.509 test certificates + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/certs.h" + +#if defined(MBEDTLS_CERTS_C) + +#if defined(MBEDTLS_ECDSA_C) +#define TEST_CA_CRT_EC \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n" \ +"ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n" \ +"aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n" \ +"JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n" \ +"NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n" \ +"AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n" \ +"CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n" \ +"t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n" \ +"uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ +"-----END CERTIFICATE-----\r\n" +const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; + +const char mbedtls_test_ca_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" +"\r\n" +"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" +"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" +"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" +"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" +"-----END EC PRIVATE KEY-----\r\n"; + +const char mbedtls_test_ca_pwd_ec[] = "PolarSSLTest"; + +const char mbedtls_test_srv_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" +"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" +"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" +"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" +"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" +"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" +"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" +"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" +"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" +"-----END CERTIFICATE-----\r\n"; + +const char mbedtls_test_srv_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" +"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" +"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; + +const char mbedtls_test_cli_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n" +"WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n" +"9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n" +"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n" +"IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n" +"CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n" +"lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" +"LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" +"-----END CERTIFICATE-----\r\n"; + +const char mbedtls_test_cli_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" +"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" +"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; + +const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); +const size_t mbedtls_test_ca_key_ec_len = sizeof( mbedtls_test_ca_key_ec ); +const size_t mbedtls_test_ca_pwd_ec_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; +const size_t mbedtls_test_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); +const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); +const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); +const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); +#else +#define TEST_CA_CRT_EC +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_RSA_C) +#define TEST_CA_CRT_RSA \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" \ +"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" \ +"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" \ +"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" \ +"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" \ +"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" \ +"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" \ +"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ +"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ +"-----END CERTIFICATE-----\r\n" +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; + +const char mbedtls_test_ca_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" +"\r\n" +"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" +"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" +"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" +"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" +"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" +"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" +"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" +"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" +"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" +"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" +"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" +"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" +"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" +"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" +"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" +"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" +"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" +"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" +"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" +"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" +"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" +"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" +"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" +"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" +"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; + +const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; + +const char mbedtls_test_srv_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" +"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" +"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" +"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" +"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" +"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" +"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" +"zhuYwjVuX6JHG0c=\r\n" +"-----END CERTIFICATE-----\r\n"; + +const char mbedtls_test_srv_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" +"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" +"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" +"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" +"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" +"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" +"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" +"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" +"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" +"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" +"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" +"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" +"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" +"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" +"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" +"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" +"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" +"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" +"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" +"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" +"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" +"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" +"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" +"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" +"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; + +const char mbedtls_test_cli_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" +"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" +"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" +"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" +"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" +"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" +"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" +"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" +"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n" +"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n" +"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n" +"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n" +"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n" +"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n" +"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n" +"-----END CERTIFICATE-----\r\n"; + +const char mbedtls_test_cli_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" +"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" +"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" +"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" +"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" +"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" +"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" +"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" +"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" +"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" +"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" +"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" +"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" +"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" +"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" +"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" +"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" +"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" +"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" +"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" +"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" +"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" +"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" +"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" +"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; + +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); +const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); +const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); +const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); +const size_t mbedtls_test_cli_key_rsa_len = sizeof( mbedtls_test_cli_key_rsa ); +#else +#define TEST_CA_CRT_RSA +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all available CA certificates */ +const char mbedtls_test_cas_pem[] = TEST_CA_CRT_RSA TEST_CA_CRT_EC; +const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); +#endif + +/* List of all available CA certificates */ +const char * mbedtls_test_cas[] = { +#if defined(MBEDTLS_RSA_C) + mbedtls_test_ca_crt_rsa, +#endif +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec, +#endif + NULL +}; +const size_t mbedtls_test_cas_len[] = { +#if defined(MBEDTLS_RSA_C) + sizeof( mbedtls_test_ca_crt_rsa ), +#endif +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec ), +#endif + 0 +}; + +#if defined(MBEDTLS_RSA_C) +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; +const char *mbedtls_test_ca_key = mbedtls_test_ca_key_rsa; +const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_rsa; +const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_rsa; +const char *mbedtls_test_srv_key = mbedtls_test_srv_key_rsa; +const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_rsa; +const char *mbedtls_test_cli_key = mbedtls_test_cli_key_rsa; +const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_rsa ); +const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_rsa ); +const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_rsa ); +const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_rsa ); +const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_rsa ); +const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_rsa ); +#else /* ! MBEDTLS_RSA_C, so MBEDTLS_ECDSA_C */ +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_ec; +const char *mbedtls_test_ca_key = mbedtls_test_ca_key_ec; +const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_ec; +const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_ec; +const char *mbedtls_test_srv_key = mbedtls_test_srv_key_ec; +const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_ec; +const char *mbedtls_test_cli_key = mbedtls_test_cli_key_ec; +const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_ec ); +const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_ec ); +const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; +const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_ec ); +const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_ec ); +const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_ec ); +const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_ec ); +#endif /* MBEDTLS_RSA_C */ + +#endif /* MBEDTLS_CERTS_C */ diff --git a/external_libs/mbedtls/library/cipher.c b/external_libs/mbedtls/library/cipher.c new file mode 100644 index 00000000..a8834386 --- /dev/null +++ b/external_libs/mbedtls/library/cipher.c @@ -0,0 +1,917 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher.h" +#include "mbedtls/cipher_internal.h" + +#include +#include + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) +{ + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + } + + if( MBEDTLS_DECRYPT == operation ) + return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ) +{ + size_t actual_iv_size; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ); + } + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret; + size_t block_size = 0; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + *olen = ilen; + return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ); + } +#endif + + if ( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && + ilen + ctx->unprocessed_len <= block_size ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen + ctx->unprocessed_len < block_size ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + if( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + copy_len = ilen % block_size; + if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) + copy_len = block_size; + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0xFF; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done ); + } + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in mbedtls_cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *olen = 0; + + if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode || + MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( MBEDTLS_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( MBEDTLS_DECRYPT == ctx->operation ) + return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ); + + /* Set output size for encryption */ + *olen = mbedtls_cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) +{ + if( NULL == ctx || + MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + switch( mode ) + { +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + case MBEDTLS_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + case MBEDTLS_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + case MBEDTLS_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + case MBEDTLS_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case MBEDTLS_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +#if defined(MBEDTLS_GCM_C) +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_ENCRYPT != ctx->operation ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); + + return( 0 ); +} + +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + + if( NULL == ctx || NULL == ctx->cipher_info || + MBEDTLS_DECRYPT != ctx->operation ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + unsigned char check_tag[16]; + size_t i; + int diff; + + if( tag_len > sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret; + size_t finish_olen; + + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, + iv, iv_len, ad, ad_len, input, output, + tag_len, tag ) ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* MBEDTLS_CCM_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CCM_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/external_libs/mbedtls/library/cipher_wrap.c b/external_libs/mbedtls/library/cipher_wrap.c new file mode 100644 index 00000000..dc76af8f --- /dev/null +++ b/external_libs/mbedtls/library/cipher_wrap.c @@ -0,0 +1,1451 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher_internal.h" + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); + + if( ctx != NULL ) + mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); + + return( ctx ); +} + +static void gcm_ctx_free( void *ctx ) +{ + mbedtls_gcm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); + + if( ctx != NULL ) + mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); + + return( ctx ); +} + +static void ccm_ctx_free( void *ctx ) +{ + mbedtls_ccm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static void * aes_ctx_alloc( void ) +{ + mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aes_info = { + MBEDTLS_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_ecb_info = { + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "AES-128-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ecb_info = { + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "AES-192-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ecb_info = { + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "AES-256-ECB", + 16, + 0, + 16, + &aes_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aes_128_cbc_info = { + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cbc_info = { + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cbc_info = { + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aes_128_cfb128_info = { + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cfb128_info = { + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cfb128_info = { + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aes_128_ctr_info = { + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ctr_info = { + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ctr_info = { + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_gcm_info = { + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "AES-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_gcm_info = { + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "AES-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_gcm_info = { + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "AES-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_ccm_info = { + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "AES-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_info = { + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "AES-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_info = { + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "AES-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static void * camellia_ctx_alloc( void ) +{ + mbedtls_camellia_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +static const mbedtls_cipher_info_t camellia_128_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 16, + 0, + 16, + &camellia_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t camellia_128_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t camellia_128_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t camellia_128_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); + + if( des == NULL ) + return( NULL ); + + mbedtls_des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + mbedtls_des_free( (mbedtls_des_context *) ctx ); + mbedtls_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + mbedtls_des3_context *des3; + des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + mbedtls_des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + mbedtls_des3_free( (mbedtls_des3_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t des_info = { + MBEDTLS_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +static const mbedtls_cipher_info_t des_ecb_info = { + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES, + "DES-ECB", + 8, + 0, + 8, + &des_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_cbc_info = { + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede_info = { + MBEDTLS_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede_ecb_info = { + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 8, + 0, + 8, + &des_ede_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede_cbc_info = { + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede3_info = { + MBEDTLS_CIPHER_ID_3DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede3_ecb_info = { + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 8, + 0, + 8, + &des_ede3_info +}; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede3_cbc_info = { + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); +} + +static void * blowfish_ctx_alloc( void ) +{ + mbedtls_blowfish_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t blowfish_info = { + MBEDTLS_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + blowfish_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + blowfish_crypt_cfb64_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + blowfish_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_free +}; + +static const mbedtls_cipher_info_t blowfish_ecb_info = { + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_MODE_ECB, + 128, + "BLOWFISH-ECB", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t blowfish_cbc_info = { + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t blowfish_cfb64_info = { + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t blowfish_ctr_info = { + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + /* we get key_bitlen in bits, arc4 expects it in bytes */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + mbedtls_arc4_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_free( void *ctx ) +{ + mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t arc4_base_info = { + MBEDTLS_CIPHER_ID_ARC4, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + arc4_crypt_stream_wrap, +#endif + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_free +}; + +static const mbedtls_cipher_info_t arc4_128_info = { + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) ctx); + ((void) key); + ((void) key_bitlen); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const mbedtls_cipher_base_t null_base_info = { + MBEDTLS_CIPHER_ID_NULL, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +static const mbedtls_cipher_info_t null_cipher_info = { + MBEDTLS_CIPHER_NULL, + MBEDTLS_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ + +const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = +{ +#if defined(MBEDTLS_AES_C) + { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) + { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + { MBEDTLS_CIPHER_NULL, &null_cipher_info }, +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + + { MBEDTLS_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] +int mbedtls_cipher_supported[NUM_CIPHERS]; + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/external_libs/mbedtls/library/cmac.c b/external_libs/mbedtls/library/cmac.c new file mode 100644 index 00000000..ee2fe056 --- /dev/null +++ b/external_libs/mbedtls/library/cmac.c @@ -0,0 +1,1033 @@ +/* + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The + * CMAC Mode for Authentication + * http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38b.pdf + * + * - RFC 4493 - The AES-CMAC Algorithm + * https://tools.ietf.org/html/rfc4493 + * + * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message + * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) + * Algorithm for the Internet Key Exchange Protocol (IKE) + * https://tools.ietf.org/html/rfc4615 + * + * Additional test vectors: ISO/IEC 9797-1 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CMAC_C) + +#include "mbedtls/cmac.h" + +#include + + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#if defined(MBEDTLS_SELF_TEST) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C || MBEDTLS_DES_C */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * Multiplication by u in the Galois field of GF(2^n) + * + * As explained in NIST SP 800-38B, this can be computed: + * + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ R_n + * with R_64 = 0x1B and R_128 = 0x87 + * + * Input and output MUST NOT point to the same buffer + * Block size must be 8 byes or 16 bytes - the block sizes for DES and AES. + */ +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize ) +{ + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i; + + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) + { + R_n = R_128; + } + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) + { + R_n = R_64; + } + else + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + for( i = blocksize - 1; i >= 0; i-- ) + { + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; + } + + /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 + * using bit operations to avoid branches */ + + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( input[0] >> 7 ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + output[ blocksize - 1 ] ^= R_n & mask; + + return( 0 ); +} + +/* + * Generate subkeys + * + * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm + */ +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) +{ + int ret; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + size_t olen, block_size; + + mbedtls_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; + + /* Calculate Ek(0) */ + if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) + goto exit; + + /* + * Generate K1 and K2 + */ + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) + goto exit; + + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_zeroize( L, sizeof( L ) ); + + return( ret ); +} + +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) +{ + size_t index; + + for( index = 0; index < block_size; index++ ) + output[ index ] = input1[ index ] ^ input2[ index ]; +} + +/* + * Create padded last block from (partial) last block. + * + * We can't use the padding option from the cipher layer, as it only works for + * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. + */ +static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], + size_t padded_block_len, + const unsigned char *last_block, + size_t last_block_len ) +{ + size_t j; + + for( j = 0; j < padded_block_len; j++ ) + { + if( j < last_block_len ) + padded_block[j] = last_block[j]; + else if( j == last_block_len ) + padded_block[j] = 0x80; + else + padded_block[j] = 0x00; + } +} + +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ) +{ + mbedtls_cipher_type_t type; + mbedtls_cmac_context_t *cmac_ctx; + int retval; + + if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( retval = mbedtls_cipher_setkey( ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + + return 0; +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + int n, j, ret = 0; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; + + /* Is there data still to process from the last call, that's greater in + * size than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen > block_size - cmac_ctx->unprocessed_len ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; + cmac_ctx->unprocessed_len = 0; + } + + /* n is the number of blocks including any final partial block */ + n = ( ilen + block_size - 1 ) / block_size; + + /* Iterate across the input data in block sized chunks */ + for( j = 0; j < n - 1; j++ ) + { + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + } + + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state, *last_block; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + int ret; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || + output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = cmac_ctx->state; + + mbedtls_zeroize( K1, sizeof( K1 ) ); + mbedtls_zeroize( K2, sizeof( K2 ) ); + cmac_generate_subkeys( ctx, K1, K2 ); + + last_block = cmac_ctx->unprocessed_block; + + /* Calculate last block */ + if( cmac_ctx->unprocessed_len < block_size ) + { + cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); + cmac_xor_block( M_last, M_last, K2, block_size ); + } + else + { + /* Last block is complete block */ + cmac_xor_block( M_last, last_block, K1, block_size ); + } + + + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + memcpy( output, state, block_size ); + +exit: + /* Wipe the generated keys on the stack, and any other transients to avoid + * side channel leakage */ + mbedtls_zeroize( K1, sizeof( K1 ) ); + mbedtls_zeroize( K2, sizeof( K2 ) ); + + cmac_ctx->unprocessed_len = 0; + mbedtls_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + + mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + return( ret ); +} + +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) +{ + mbedtls_cmac_context_t* cmac_ctx; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); + + return( 0 ); +} + +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_cipher_context_t ctx; + int ret; + + if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_finish( &ctx, output ); + +exit: + mbedtls_cipher_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +/* + * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char *output ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; + + if( key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) + { + /* Use key as is */ + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); + } + else + { + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); + + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); + +exit: + mbedtls_zeroize( int_key, sizeof( int_key ) ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * CMAC test data from SP800-38B Appendix D.1 (corrected) + * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf + * + * AES-CMAC-PRF-128 test data from RFC 4615 + * https://tools.ietf.org/html/rfc4615#page-4 + */ + +#define NB_CMAC_TESTS_PER_KEY 4 +#define NB_PRF_TESTS 3 + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) +/* All CMAC test inputs are truncated from the same 64 byte buffer. */ +static const unsigned char test_message[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* Truncation point of message for AES CMAC tests */ +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 40, + 64 +}; + +/* AES 128 CMAC Test Data */ +static const unsigned char aes_128_key[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde + }, + { + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b + } +}; +static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }, + { + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }, + { + 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 + }, + { + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + } +}; + +/* AES 192 CMAC Test Data */ +static const unsigned char aes_192_key[24] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; +static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 + }, + { + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c + } +}; +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }, + { + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }, + { + 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad, + 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e + }, + { + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + } +}; + +/* AES 256 CMAC Test Data */ +static const unsigned char aes_256_key[32] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; +static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f + }, + { + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 + } +}; +static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }, + { + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }, + { + 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2, + 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6 + }, + { + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + } +}; +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) +/* Truncation point of message for 3DES CMAC tests */ +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 8, + 20, + 32 +}; + +/* 3DES 2 Key CMAC Test Data */ +static const unsigned char des3_2key_key[24] = { + 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5, + 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38, + 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5 +}; +static const unsigned char des3_2key_subkeys[2][8] = { + { + 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef + }, + { + 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5 + } +}; +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61 + }, + { + 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83 + }, + { + 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e + }, + { + 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8 + } +}; + +/* 3DES 3 Key CMAC Test Data */ +static const unsigned char des3_3key_key[24] = { + 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62, + 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58, + 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5 +}; +static const unsigned char des3_3key_subkeys[2][8] = { + { + 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f + }, + { + 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5 + } +}; +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95 + }, + { + 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97 + }, + { + 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed + }, + { + 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5 + } +}; + +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* AES AES-CMAC-PRF-128 Test Data */ +static const unsigned char PRFK[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xed, 0xcb +}; + +/* Sizes in bytes */ +static const size_t PRFKlen[NB_PRF_TESTS] = { + 18, + 16, + 10 +}; + +/* PRF M */ +static const unsigned char PRFM[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char PRFT[NB_PRF_TESTS][16] = { + { + 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, + 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a + }, + { + 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, + 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d + }, + { + 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, + 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d + } +}; +#endif /* MBEDTLS_AES_C */ + +static int cmac_test_subkeys( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* subkeys, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + int i, ret; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_cipher_free( &ctx ); + } + + goto exit; + +cleanup: + mbedtls_cipher_free( &ctx ); + +exit: + return( ret ); +} + +static int cmac_test_wth_cipher( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* expected_result, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret; + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); + + if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, + message_lengths[i], output ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + +exit: + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) +{ + int i; + int ret; + unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); + if( ret != 0 || + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) + { + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +int mbedtls_cmac_self_test( int verbose ) +{ + int ret; + +#if defined(MBEDTLS_AES_C) + /* AES-128 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 128", + aes_128_key, + 128, + (const unsigned char*)aes_128_subkeys, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*)aes_128_expected_result, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-192 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 192", + aes_192_key, + 192, + (const unsigned char*)aes_192_subkeys, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*)aes_192_expected_result, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-256 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 256", + aes_256_key, + 256, + (const unsigned char*)aes_256_subkeys, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*)aes_256_expected_result, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) + /* 3DES 2 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 2 key", + des3_2key_key, + 192, + (const unsigned char*)des3_2key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_2key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* 3DES 3 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 3 key", + des3_3key_key, + 192, + (const unsigned char*)des3_3key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_3key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_AES_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CMAC_C */ diff --git a/external_libs/mbedtls/library/ctr_drbg.c b/external_libs/mbedtls/library/ctr_drbg.c new file mode 100644 index 00000000..386f8adb --- /dev/null +++ b/external_libs/mbedtls/library/ctr_drbg.c @@ -0,0 +1,593 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The NIST SP 800-90 DRBGs are described in the following publucation. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow + * NIST tests to succeed (which require known length fixed entropy) + */ +int mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len, + size_t entropy_len ) +{ + int ret; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->entropy_len = entropy_len; + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + + /* + * Initialize with an empty key + */ + mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); + + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, + MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); +} + +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); +} + +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + mbedtls_aes_context aes_ctx; + + int i, j; + size_t buf_len, use_len; + + if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); + mbedtls_aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; + *p++ = ( data_len >> 24 ) & 0xff; + *p++ = ( data_len >> 16 ) & 0xff; + *p++ = ( data_len >> 8 ) & 0xff; + *p++ = ( data_len ) & 0xff; + p += 3; + *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); + + /* + * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? + MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; + + mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ); + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + mbedtls_aes_free( &aes_ctx ); + + return( 0 ); +} + +static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + + memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ); + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + return( 0 ); +} + +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + + if( add_len > 0 ) + { + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + + block_cipher_df( add_input, additional, add_len ); + ctr_drbg_update_internal( ctx, add_input ); + } +} + +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + + if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + 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/external_libs/mbedtls/library/debug.c b/external_libs/mbedtls/library/debug.c new file mode 100644 index 00000000..a9cd814b --- /dev/null +++ b/external_libs/mbedtls/library/debug.c @@ -0,0 +1,368 @@ +/* + * Debugging routines + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time_t time_t +#define mbedtls_snprintf snprintf +#endif + +#include "mbedtls/debug.h" + +#include +#include +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define DEBUG_BUF_SIZE 512 + +static int debug_threshold = 0; + +void mbedtls_debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +/* + * All calls to f_dbg must be made via this function + */ +static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *str ) +{ + /* + * If in a threaded environment, we need a thread identifier. + * Since there is no portable way to get one, use the address of the ssl + * context instead, as it shouldn't be shared between threads. + */ +#if defined(MBEDTLS_THREADING_C) + char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ + mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", ssl, str ); + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); +#else + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); +#endif +} + +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) +{ + va_list argp; + char str[DEBUG_BUF_SIZE]; + int ret; + + if( NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold ) + return; + + va_start( argp, format ); +#if defined(_WIN32) +#if defined(_TRUNCATE) + ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp ); +#else + ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); + if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE ) + { + str[DEBUG_BUF_SIZE-1] = '\0'; + ret = -1; + } +#endif +#else + ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); +#endif + va_end( argp ); + + if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) + { + str[ret] = '\n'; + str[ret + 1] = '\0'; + } + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ) +{ + char str[DEBUG_BUF_SIZE]; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) + return; + + /* + * With non-blocking I/O and examples that just retry immediately, + * the logs would be quickly flooded with WANT_READ, so ignore that. + * Don't ignore WANT_WRITE however, since is is usually rare. + */ + if( ret == MBEDTLS_ERR_SSL_WANT_READ ) + return; + + mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", + text, ret, -ret ); + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ) +{ + char str[DEBUG_BUF_SIZE]; + char txt[17]; + size_t i, idx = 0; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) + return; + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", + text, (unsigned int) len ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + for( i = 0; i < len; i++ ) + { + if( i >= 4096 ) + break; + + if( i % 16 == 0 ) + { + if( i > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", + (unsigned int) i ); + + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", + (unsigned int) buf[i] ); + txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; + } + + if( len > 0 ) + { + for( /* i = i */; i % 16 != 0; i++ ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + } +} + +#if defined(MBEDTLS_ECP_C) +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ) +{ + char str[DEBUG_BUF_SIZE]; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) + return; + + mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); + + mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_BIGNUM_C) +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ) +{ + char str[DEBUG_BUF_SIZE]; + int j, k, zeros = 1; + size_t i, n, idx = 0; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold ) + return; + + for( n = X->n - 1; n > 0; n-- ) + if( X->p[n] != 0 ) + break; + + for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- ) + if( ( ( X->p[n] >> j ) & 1 ) != 0 ) + break; + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n", + text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + for( i = n + 1, j = 0; i > 0; i-- ) + { + if( zeros && X->p[i - 1] == 0 ) + continue; + + for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- ) + { + if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) + continue; + else + zeros = 0; + + if( j % 16 == 0 ) + { + if( j > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); + idx = 0; + } + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int) + ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); + + j++; + } + + } + + if( zeros == 1 ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_pk_context *pk ) +{ + size_t i; + mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset( items, 0, sizeof( items ) ); + + if( mbedtls_pk_debug( pk, items ) != 0 ) + { + debug_send_line( ssl, level, file, line, + "invalid PK context\n" ); + return; + } + + for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) + { + if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) + return; + + mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); + name[sizeof( name ) - 1] = '\0'; + + if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) + mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); + else +#if defined(MBEDTLS_ECP_C) + if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) + mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); + else +#endif + debug_send_line( ssl, level, file, line, + "should not happen\n" ); + } +} + +static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text ) +{ + char str[DEBUG_BUF_SIZE]; + const char *start, *cur; + + start = text; + for( cur = text; *cur != '\0'; cur++ ) + { + if( *cur == '\n' ) + { + size_t len = cur - start + 1; + if( len > DEBUG_BUF_SIZE - 1 ) + len = DEBUG_BUF_SIZE - 1; + + memcpy( str, start, len ); + str[len] = '\0'; + + debug_send_line( ssl, level, file, line, str ); + + start = cur + 1; + } + } +} + +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ) +{ + char str[DEBUG_BUF_SIZE]; + int i = 0; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold ) + return; + + while( crt != NULL ) + { + char buf[1024]; + + mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); + debug_send_line( ssl, level, file, line, str ); + + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + debug_print_line_by_line( ssl, level, file, line, buf ); + + debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); + + crt = crt->next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#endif /* MBEDTLS_DEBUG_C */ diff --git a/external_libs/mbedtls/library/des.c b/external_libs/mbedtls/library/des.c new file mode 100644 index 00000000..09f95cfc --- /dev/null +++ b/external_libs/mbedtls/library/des.c @@ -0,0 +1,1061 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DES_C) + +#include "mbedtls/des.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_DES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const uint32_t SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const uint32_t SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const uint32_t SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const uint32_t SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const uint32_t SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const uint32_t SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const uint32_t SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const uint32_t SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const uint32_t LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const uint32_t RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ +{ \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ + X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ +} + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ +{ \ + X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ + Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ +} + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ +{ \ + T = *SK++ ^ X; \ + Y ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ ((X << 28) | (X >> 4)); \ + Y ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ +} + +#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; } + +void mbedtls_des_init( mbedtls_des_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des_free( mbedtls_des_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des3_init( mbedtls_des3_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des3_context ) ); +} + +void mbedtls_des3_free( mbedtls_des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_des3_context ) ); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + key[i] = odd_parity_table[key[i] / 2]; +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DES_SETKEY_ALT) +void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + uint32_t X, Y, T; + + GET_UINT32_BE( X, key, 0 ); + GET_UINT32_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} +#endif /* !MBEDTLS_DES_SETKEY_ALT */ + +/* + * DES key schedule (56-bit, encryption) + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + mbedtls_des_setkey( ctx->sk, key ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + mbedtls_des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } + + return( 0 ); +} + +static void des3_set2key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[30 - i]; + dsk[i + 1] = esk[31 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + esk[i + 64] = esk[i ]; + esk[i + 65] = esk[i + 1]; + + dsk[i + 64] = dsk[i ]; + dsk[i + 65] = dsk[i + 1]; + } +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( ctx->sk, sk, key ); + mbedtls_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( sk, ctx->sk, key ); + mbedtls_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +static void des3_set3key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[24] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + mbedtls_des_setkey( esk + 64, key + 16 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[94 - i]; + dsk[i + 1] = esk[95 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + dsk[i + 64] = esk[30 - i]; + dsk[i + 65] = esk[31 - i]; + } +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( ctx->sk, sk, key ); + mbedtls_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( sk, ctx->sk, key ); + mbedtls_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( X, Y ); + DES_ROUND( Y, X ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des3_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des3_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#endif /* !MBEDTLS_DES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * DES and 3DES test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip + */ +static const unsigned char des3_test_keys[24] = +{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 +}; + +static const unsigned char des3_test_buf[8] = +{ + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 +}; + +static const unsigned char des3_test_ecb_dec[3][8] = +{ + { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, + { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, + { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } +}; + +static const unsigned char des3_test_ecb_enc[3][8] = +{ + { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, + { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, + { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char des3_test_iv[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, +}; + +static const unsigned char des3_test_cbc_dec[3][8] = +{ + { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, + { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, + { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } +}; + +static const unsigned char des3_test_cbc_enc[3][8] = +{ + { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, + { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, + { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int mbedtls_des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + mbedtls_des_context ctx; + mbedtls_des3_context ctx3; + unsigned char buf[8]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + mbedtls_des_init( &ctx ); + mbedtls_des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_ecb( &ctx, buf, buf ); + else + mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, des3_test_iv, 8 ); + memcpy( prv, des3_test_iv, 8 ); + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + if( v == MBEDTLS_DES_DECRYPT ) + { + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + } + } + else + { + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + + memcpy( tmp, prv, 8 ); + memcpy( prv, buf, 8 ); + memcpy( buf, tmp, 8 ); + } + + memcpy( buf, prv, 8 ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_des_free( &ctx ); + mbedtls_des3_free( &ctx3 ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DES_C */ diff --git a/external_libs/mbedtls/library/dhm.c b/external_libs/mbedtls/library/dhm.c new file mode 100644 index 00000000..a4715d17 --- /dev/null +++ b/external_libs/mbedtls/library/dhm.c @@ -0,0 +1,627 @@ +/* + * Diffie-Hellman-Merkle key exchange + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The following sources were referenced in the design of this implementation + * of the Diffie-Hellman-Merkle algorithm: + * + * [1] Handbook of Applied Cryptography - 1997, Chapter 12 + * Menezes, van Oorschot and Vanstone + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DHM_C) + +#include "mbedtls/dhm.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * helper to validate the mbedtls_mpi size and import it + */ +static int dhm_read_bignum( mbedtls_mpi *X, + unsigned char **p, + const unsigned char *end ) +{ + int ret, n; + + if( end - *p < 2 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + n = ( (*p)[0] << 8 ) | (*p)[1]; + (*p) += 2; + + if( (int)( end - *p ) < n ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); + + (*p) += n; + + return( 0 ); +} + +/* + * Verify sanity of parameter with regards to P + * + * Parameter should be: 2 <= public_param <= P - 2 + * + * For more information on the attack, see: + * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf + * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 + */ +static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) +{ + mbedtls_mpi L, U; + int ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + + mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); + + if( mbedtls_mpi_cmp_mpi( param, &L ) >= 0 && + mbedtls_mpi_cmp_mpi( param, &U ) <= 0 ) + { + ret = 0; + } + +cleanup: + mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); + return( ret ); +} + +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ) +{ + int ret; + + if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) + return( ret ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + ctx->len = mbedtls_mpi_size( &ctx->P ); + + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + size_t n1, n2, n3; + unsigned char *p; + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * Generate X as large as possible ( < P ) + */ + do + { + mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + /* + * Calculate GX = G^X mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + /* + * export P, G, GX + */ +#define DHM_MPI_EXPORT(X,n) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, p + 2, n ) ); \ + *p++ = (unsigned char)( n >> 8 ); \ + *p++ = (unsigned char)( n ); p += n; + + n1 = mbedtls_mpi_size( &ctx->P ); + n2 = mbedtls_mpi_size( &ctx->G ); + n3 = mbedtls_mpi_size( &ctx->GX ); + + p = output; + DHM_MPI_EXPORT( &ctx->P , n1 ); + DHM_MPI_EXPORT( &ctx->G , n2 ); + DHM_MPI_EXPORT( &ctx->GX, n3 ); + + *olen = p - output; + + ctx->len = n1; + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); + + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret; + + if( ctx == NULL || ilen < 1 || ilen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + + if( ctx == NULL || olen < 1 || olen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * generate X and calculate GX = G^X mod P + */ + do + { + mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Use the blinding method and optimisation suggested in section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int dhm_update_blinding( mbedtls_dhm_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count; + + /* + * Don't use any blinding the first time a particular X is used, + * but remember it to use blinding next time. + */ + if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); + + return( 0 ); + } + + /* + * Ok, we need blinding. Can we re-use existing values? + * If yes, just update them by squaring them. + */ + if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + return( 0 ); + } + + /* + * We need to generate blinding values from scratch + */ + + /* Vi = random( 2, P-1 ) */ + count = 0; + do + { + mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ); + + while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); + + /* Vf = Vi^-X mod P */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + return( ret ); +} + +/* + * Derive and export the shared secret (G^Y)^X mod P + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi GYb; + + if( ctx == NULL || output_size < ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mbedtls_mpi_init( &GYb ); + + /* Blind peer's value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); + + /* Do modular exponentiation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + } + + *olen = mbedtls_mpi_size( &ctx->K ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mbedtls_mpi_free( &GYb ); + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) +{ + mbedtls_mpi_free( &ctx->pX); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); mbedtls_mpi_free( &ctx->G ); + mbedtls_mpi_free( &ctx->P ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); +} + +#if defined(MBEDTLS_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret; + size_t len; + unsigned char *p, *end; +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN DH PARAMETERS-----", + "-----END DH PARAMETERS-----", + dhmin, NULL, 0, &dhminlen ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + dhminlen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* MBEDTLS_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * privateValueLength INTEGER OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + if( p != end ) + { + /* This might be the optional privateValueLength. + * If so, we can cleanly discard it */ + mbedtls_mpi rec; + mbedtls_mpi_init( &rec ); + ret = mbedtls_asn1_get_mpi( &p, end, &rec ); + mbedtls_mpi_free( &rec ); + if ( ret != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + if ( p != end ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto exit; + } + } + + ret = 0; + + dhm->len = mbedtls_mpi_size( &dhm->P ); + +exit: +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + if( ret != 0 ) + mbedtls_dhm_free( dhm ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + mbedtls_free( *buf ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse DHM parameters + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_SELF_TEST) + +static const char mbedtls_test_dhm_params[] = +"-----BEGIN DH PARAMETERS-----\r\n" +"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" +"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" +"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" +"-----END DH PARAMETERS-----\r\n"; + +static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); + +/* + * Checkup routine + */ +int mbedtls_dhm_self_test( int verbose ) +{ + int ret; + mbedtls_dhm_context dhm; + + mbedtls_dhm_init( &dhm ); + + if( verbose != 0 ) + mbedtls_printf( " DHM parameter load: " ); + + if( ( ret = mbedtls_dhm_parse_dhm( &dhm, + (const unsigned char *) mbedtls_test_dhm_params, + mbedtls_test_dhm_params_len ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + +exit: + mbedtls_dhm_free( &dhm ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DHM_C */ diff --git a/external_libs/mbedtls/library/ecdh.c b/external_libs/mbedtls/library/ecdh.c new file mode 100644 index 00000000..c0a81473 --- /dev/null +++ b/external_libs/mbedtls/library/ecdh.c @@ -0,0 +1,264 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/ecdh.h" + +#include + +/* + * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); +} + +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point P; + + mbedtls_ecp_point_init( &P ); + + /* + * Make sure Q is a valid pubkey before using it + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); + + if( mbedtls_ecp_is_zero( &P ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); + +cleanup: + mbedtls_ecp_point_free( &P ); + + return( ret ); +} + +/* + * Initialize context + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); +} + +/* + * Free context + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_ecp_point_free( &ctx->Q ); + mbedtls_ecp_point_free( &ctx->Qp ); + mbedtls_ecp_point_free( &ctx->Vi ); + mbedtls_ecp_point_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->d ); + mbedtls_mpi_free( &ctx->z ); + mbedtls_mpi_free( &ctx->_d ); +} + +/* + * Setup and write the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t grp_len, pt_len; + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) + != 0 ) + return( ret ); + + if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) + != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, + &pt_len, buf, blen ) ) != 0 ) + return( ret ); + + *olen = grp_len + pt_len; + return( 0 ); +} + +/* + * Read the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ) +{ + int ret; + + if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) + != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Get parameters from a keypair + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) + return( ret ); + + /* If it's not our key, just import the public part as Qp */ + if( side == MBEDTLS_ECDH_THEIRS ) + return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); + + /* Our key: import public (as Q) and private parts */ + if( side != MBEDTLS_ECDH_OURS ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Setup and export the client public value + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) + != 0 ) + return( ret ); + + return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, + olen, buf, blen ); +} + +/* + * Parse and import the client's public value + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + int ret; + const unsigned char *p = buf; + + if( ctx == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 ) + return( ret ); + + if( (size_t)( p - buf ) != blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Derive and export the shared secret + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + if( ctx == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_mpi_size( &ctx->z ) > blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); + return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); +} + +#endif /* MBEDTLS_ECDH_C */ diff --git a/external_libs/mbedtls/library/ecdsa.c b/external_libs/mbedtls/library/ecdsa.c new file mode 100644 index 00000000..4156f3c3 --- /dev/null +++ b/external_libs/mbedtls/library/ecdsa.c @@ -0,0 +1,448 @@ +/* + * Elliptic curve DSA + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#include "mbedtls/ecdsa.h" +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#include "mbedtls/hmac_drbg.h" +#endif + +/* + * Derive a suitable integer for group grp from a buffer of length len + * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 + */ +static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, + const unsigned char *buf, size_t blen ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + size_t use_size = blen > n_size ? n_size : blen; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); + +cleanup: + return( ret ); +} + +/* + * Compute ECDSA signature of a hashed message (SEC1 4.1.3) + * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, key_tries, sign_tries, blind_tries; + mbedtls_ecp_point R; + mbedtls_mpi k, e, t; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); + + sign_tries = 0; + do + { + /* + * Steps 1-3: generate a suitable ephemeral keypair + * and set r = xR mod n + */ + key_tries = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); + + if( key_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); + + /* + * Step 5: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Generate a random value to blind inv_mod in next step, + * avoiding a potential timing leak. + */ + blind_tries = 0; + do + { + size_t n_size = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); + + /* See mbedtls_ecp_gen_keypair() */ + if( ++blind_tries > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); + + if( sign_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + + return( ret ); +} + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + int ret; + mbedtls_hmac_drbg_context rng_ctx; + unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const mbedtls_md_info_t *md_info; + mbedtls_mpi h; + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &h ); + mbedtls_hmac_drbg_init( &rng_ctx ); + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); + MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); + mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); + + ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, &rng_ctx ); + +cleanup: + mbedtls_hmac_drbg_free( &rng_ctx ); + mbedtls_mpi_free( &h ); + + return( ret ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/* + * Verify ECDSA signature of hashed message (SEC1 4.1.4) + * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) +{ + int ret; + mbedtls_mpi e, s_inv, u1, u2; + mbedtls_ecp_point R; + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || + mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Additional precaution: make sure Q is valid + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); + + /* + * Step 3: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); + + /* + * Step 5: R = u1 G + u2 Q + * + * Since we're not using any secret data, no need to pass a RNG to + * mbedtls_ecp_mul() for countermesures. + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); + + if( mbedtls_ecp_is_zero( &R ) ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + return( ret ); +} + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen ) +{ + int ret; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi r, s; + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + (void) f_rng; + (void) p_rng; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg ) ); +#else + (void) md_alg; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng ) ); +#endif + + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ + defined(MBEDTLS_ECDSA_DETERMINISTIC) +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) +{ + return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, + NULL, NULL ) ); +} +#endif + +/* + * Read and check signature + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ) +{ + int ret; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + mbedtls_mpi r, s; + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( p + len != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto cleanup; + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s ) ) != 0 ) + goto cleanup; + + if( p != end ) + ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +/* + * Generate key pair + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecp_group_load( &ctx->grp, gid ) || + mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); +} + +/* + * Set context from an mbedtls_ecp_keypair + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + mbedtls_ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) +{ + mbedtls_ecp_keypair_init( ctx ); +} + +/* + * Free context + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) +{ + mbedtls_ecp_keypair_free( ctx ); +} + +#endif /* MBEDTLS_ECDSA_C */ diff --git a/external_libs/mbedtls/library/ecjpake.c b/external_libs/mbedtls/library/ecjpake.c new file mode 100644 index 00000000..1fa1c2d8 --- /dev/null +++ b/external_libs/mbedtls/library/ecjpake.c @@ -0,0 +1,1103 @@ +/* + * Elliptic curve J-PAKE + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References in the code are to the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECJPAKE_C) + +#include "mbedtls/ecjpake.h" + +#include + +/* + * Convert a mbedtls_ecjpake_role to identifier string + */ +static const char * const ecjpake_id[] = { + "client", + "server" +}; + +#define ID_MINE ( ecjpake_id[ ctx->role ] ) +#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) + +/* + * Initialize context + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->md_info = NULL; + mbedtls_ecp_group_init( &ctx->grp ); + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + + mbedtls_ecp_point_init( &ctx->Xm1 ); + mbedtls_ecp_point_init( &ctx->Xm2 ); + mbedtls_ecp_point_init( &ctx->Xp1 ); + mbedtls_ecp_point_init( &ctx->Xp2 ); + mbedtls_ecp_point_init( &ctx->Xp ); + + mbedtls_mpi_init( &ctx->xm1 ); + mbedtls_mpi_init( &ctx->xm2 ); + mbedtls_mpi_init( &ctx->s ); +} + +/* + * Free context + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->md_info = NULL; + mbedtls_ecp_group_free( &ctx->grp ); + + mbedtls_ecp_point_free( &ctx->Xm1 ); + mbedtls_ecp_point_free( &ctx->Xm2 ); + mbedtls_ecp_point_free( &ctx->Xp1 ); + mbedtls_ecp_point_free( &ctx->Xp2 ); + mbedtls_ecp_point_free( &ctx->Xp ); + + mbedtls_mpi_free( &ctx->xm1 ); + mbedtls_mpi_free( &ctx->xm2 ); + mbedtls_mpi_free( &ctx->s ); +} + +/* + * Setup context + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ) +{ + int ret; + + ctx->role = role; + + if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); + +cleanup: + if( ret != 0 ) + mbedtls_ecjpake_free( ctx ); + + return( ret ); +} + +/* + * Check if context is ready for use + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) +{ + if( ctx->md_info == NULL || + ctx->grp.id == MBEDTLS_ECP_DP_NONE || + ctx->s.p == NULL ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Write a point plus its length to a buffer + */ +static int ecjpake_write_len_point( unsigned char **p, + const unsigned char *end, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *P ) +{ + int ret; + size_t len; + + /* Need at least 4 for length plus 1 for point */ + if( end < *p || end - *p < 5 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + ret = mbedtls_ecp_point_write_binary( grp, P, pf, + &len, *p + 4, end - ( *p + 4 ) ); + if( ret != 0 ) + return( ret ); + + (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF ); + (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF ); + (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF ); + (*p)[3] = (unsigned char)( ( len ) & 0xFF ); + + *p += 4 + len; + + return( 0 ); +} + +/* + * Size of the temporary buffer for ecjpake_hash: + * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) + */ +#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) + +/* + * Compute hash for ZKP (7.4.2.2.2.1) + */ +static int ecjpake_hash( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *V, + const mbedtls_ecp_point *X, + const char *id, + mbedtls_mpi *h ) +{ + int ret; + unsigned char buf[ECJPAKE_HASH_BUF_LEN]; + unsigned char *p = buf; + const unsigned char *end = buf + sizeof( buf ); + const size_t id_len = strlen( id ); + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + /* Write things to temporary buffer */ + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); + + if( end - p < 4 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len ) & 0xFF ); + + if( end < p || (size_t)( end - p ) < id_len ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( p, id, id_len ); + p += id_len; + + /* Compute hash */ + mbedtls_md( md_info, buf, p - buf, hash ); + + /* Turn it into an integer mod n */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, + mbedtls_md_get_size( md_info ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); + +cleanup: + return( ret ); +} + +/* + * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) + */ +static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret; + mbedtls_ecp_point V, VV; + mbedtls_mpi r, h; + size_t r_len; + + mbedtls_ecp_point_init( &V ); + mbedtls_ecp_point_init( &VV ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &h ); + + /* + * struct { + * ECPoint V; + * opaque r<1..2^8-1>; + * } ECSchnorrZKP; + */ + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); + + if( end < *p || (size_t)( end - *p ) < 1 ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + r_len = *(*p)++; + + if( end < *p || (size_t)( end - *p ) < r_len ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); + *p += r_len; + + /* + * Verification + */ + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, + &VV, &h, X, &r, G ) ); + + if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_ecp_point_free( &VV ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) + */ +static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_mpi *x, + const mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point V; + mbedtls_mpi v; + mbedtls_mpi h; /* later recycled to hold r */ + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &V ); + mbedtls_mpi_init( &v ); + mbedtls_mpi_init( &h ); + + /* Compute signature */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, + G, &v, &V, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ + + /* Write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, + pf, &len, *p, end - *p ) ); + *p += len; + + len = mbedtls_mpi_size( &h ); /* actually r */ + if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + + *(*p)++ = (unsigned char)( len & 0xFF ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ + *p += len; + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_mpi_free( &v ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof + * Output: verified public key X + */ +static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * struct { + * ECPoint X; + * ECSchnorrZKP zkp; + * } ECJPAKEKeyKP; + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); + if( mbedtls_ecp_is_zero( X ) ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); + +cleanup: + return( ret ); +} + +/* + * Generate an ECJPAKEKeyKP + * Output: the serialized structure, plus private/public key pair + */ +static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *x, + mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* Generate key (7.4.2.3.1) and write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, + pf, &len, *p, end - *p ) ); + *p += len; + + /* Generate and write proof */ + MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, + p, end, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs + * Ouputs: verified peer public keys Xa, Xb + */ +static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *Xa, + mbedtls_ecp_point *Xb, + const char *id, + const unsigned char *buf, + size_t len ) +{ + int ret; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + + /* + * struct { + * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; + * } ECJPAKEKeyKPPairList; + */ + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); + + if( p != end ) + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + +cleanup: + return( ret ); +} + +/* + * Generate a ECJPAKEKeyKPPairList + * Outputs: the serialized structure, plus two private/public key pairs + */ +static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *xm1, + mbedtls_ecp_point *Xa, + mbedtls_mpi *xm2, + mbedtls_ecp_point *Xb, + const char *id, + unsigned char *buf, + size_t len, + size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = buf + len; + + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, + &p, end, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + return( ret ); +} + +/* + * Read and process the first round message + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->Xp1, &ctx->Xp2, ID_PEER, + buf, len ) ); +} + +/* + * Generate and write the first round message + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, + ID_MINE, buf, len, olen, f_rng, p_rng ) ); +} + +/* + * Compute the sum of three points R = A + B + C + */ +static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *A, + const mbedtls_ecp_point *B, + const mbedtls_ecp_point *C ) +{ + int ret; + mbedtls_mpi one; + + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); + +cleanup: + mbedtls_mpi_free( &one ); + + return( ret ); +} + +/* + * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + int ret; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + mbedtls_ecp_group grp; + mbedtls_ecp_point G; /* C: GB, S: GA */ + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &G ); + + /* + * Server: GA = X3 + X4 + X1 (7.4.2.6.1) + * Client: GB = X1 + X2 + X3 (7.4.2.5.1) + * Unified: G = Xm1 + Xm2 + Xp1 + * We need that before parsing in order to check Xp as we read it + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); + + /* + * struct { + * ECParameters curve_params; // only client reading server msg + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); + if( grp.id != ctx->grp.id ) + { + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &ctx->Xp, ID_PEER, &p, end ) ); + + if( p != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &G ); + + return( ret ); +} + +/* + * Compute R = +/- X * S mod N, taking care not to leak S + */ +static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, + const mbedtls_mpi *X, + const mbedtls_mpi *S, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi b; /* Blinding value, then s + N * blinding */ + + mbedtls_mpi_init( &b ); + + /* b = s + rnd-128-bit * N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); + + /* R = sign * X * b mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); + R->s *= sign; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); + +cleanup: + mbedtls_mpi_free( &b ); + + return( ret ); +} + +/* + * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point G; /* C: GA, S: GB */ + mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ + mbedtls_mpi xm; /* C: xc, S: xs */ + unsigned char *p = buf; + const unsigned char *end = buf + len; + size_t ec_len; + + mbedtls_ecp_point_init( &G ); + mbedtls_ecp_point_init( &Xm ); + mbedtls_mpi_init( &xm ); + + /* + * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) + * + * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA + * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB + * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); + + /* + * Now write things out + * + * struct { + * ECParameters curve_params; // only server writing its message + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) + { + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, + p, end - p ) ); + p += ec_len; + } + + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, + ctx->point_format, &ec_len, p, end - p ) ); + p += ec_len; + + MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &xm, &Xm, ID_MINE, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + mbedtls_ecp_point_free( &G ); + mbedtls_ecp_point_free( &Xm ); + mbedtls_mpi_free( &xm ); + + return( ret ); +} + +/* + * Derive PMS (7.4.2.7 / 7.4.2.8) + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point K; + mbedtls_mpi m_xm2_s, one; + unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; + size_t x_bytes; + + *olen = mbedtls_md_get_size( ctx->md_info ); + if( len < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &K ); + mbedtls_mpi_init( &m_xm2_s ); + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + + /* + * Client: K = ( Xs - X4 * x2 * s ) * x2 + * Server: K = ( Xc - X2 * x4 * s ) * x4 + * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 + */ + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, + &one, &ctx->Xp, + &m_xm2_s, &ctx->Xp2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, + f_rng, p_rng ) ); + + /* PMS = SHA-256( K.X ) */ + x_bytes = ( ctx->grp.pbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); + +cleanup: + mbedtls_ecp_point_free( &K ); + mbedtls_mpi_free( &m_xm2_s ); + mbedtls_mpi_free( &one ); + + return( ret ); +} + +#undef ID_MINE +#undef ID_PEER + + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + !defined(MBEDTLS_SHA256_C) +int mbedtls_ecjpake_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +static const unsigned char ecjpake_test_password[] = { + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, + 0x65, 0x73, 0x74 +}; + +static const unsigned char ecjpake_test_x1[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 +}; + +static const unsigned char ecjpake_test_x2[] = { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 +}; + +static const unsigned char ecjpake_test_x3[] = { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 +}; + +static const unsigned char ecjpake_test_x4[] = { + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, + 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, + 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 +}; + +static const unsigned char ecjpake_test_cli_one[] = { + 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, + 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, + 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, + 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, + 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, + 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, + 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, + 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, + 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, + 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, + 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, + 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, + 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, + 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, + 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, + 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, + 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, + 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, + 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, + 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, + 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, + 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, + 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, + 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, + 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, + 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, + 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, + 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 +}; + +static const unsigned char ecjpake_test_srv_one[] = { + 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, + 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, + 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, + 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, + 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, + 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, + 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, + 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, + 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, + 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, + 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, + 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, + 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, + 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, + 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, + 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, + 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, + 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, + 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, + 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, + 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, + 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, + 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, + 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, + 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, + 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, + 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, + 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 +}; + +static const unsigned char ecjpake_test_srv_two[] = { + 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, + 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, + 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, + 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, + 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, + 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, + 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, + 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, + 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, + 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, + 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, + 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, + 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, + 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c +}; + +static const unsigned char ecjpake_test_cli_two[] = { + 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, + 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, + 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, + 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, + 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, + 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, + 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, + 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, + 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, + 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, + 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, + 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, + 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, + 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c +}; + +static const unsigned char ecjpake_test_pms[] = { + 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, + 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, + 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 +}; + +/* Load my private keys and generate the correponding public keys */ +static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, + const unsigned char *xm1, size_t len1, + const unsigned char *xm2, size_t len2 ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, + &ctx->grp.G, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, + &ctx->grp.G, NULL, NULL ) ); + +cleanup: + return( ret ); +} + +/* For tests we don't need a secure RNG; + * use the LGC from Numerical Recipes for simplicity */ +static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) +{ + static uint32_t x = 42; + (void) p; + + while( len > 0 ) + { + size_t use_len = len > 4 ? 4 : len; + x = 1664525 * x + 1013904223; + memcpy( out, &x, use_len ); + out += use_len; + len -= use_len; + } + + return( 0 ); +} + +#define TEST_ASSERT( x ) \ + do { \ + if( x ) \ + ret = 0; \ + else \ + { \ + ret = 1; \ + goto cleanup; \ + } \ + } while( 0 ) + +/* + * Checkup routine + */ +int mbedtls_ecjpake_self_test( int verbose ) +{ + int ret; + mbedtls_ecjpake_context cli; + mbedtls_ecjpake_context srv; + unsigned char buf[512], pms[32]; + size_t len, pmslen; + + mbedtls_ecjpake_init( &cli ); + mbedtls_ecjpake_init( &srv ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #0 (setup): " ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == pmslen ); + TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); + + /* Simulate generation of round one */ + MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, + ecjpake_test_x1, sizeof( ecjpake_test_x1 ), + ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); + + MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, + ecjpake_test_x3, sizeof( ecjpake_test_x3 ), + ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); + + /* Read round one */ + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, + ecjpake_test_cli_one, + sizeof( ecjpake_test_cli_one ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, + ecjpake_test_srv_one, + sizeof( ecjpake_test_srv_one ) ) == 0 ); + + /* Skip generation of round two, read round two */ + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, + ecjpake_test_srv_two, + sizeof( ecjpake_test_srv_two ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, + ecjpake_test_cli_two, + sizeof( ecjpake_test_cli_two ) ) == 0 ); + + /* Server derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + memset( buf, 0, len ); /* Avoid interferences with next step */ + + /* Client derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_ecjpake_free( &cli ); + mbedtls_ecjpake_free( &srv ); + + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#undef TEST_ASSERT + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ECJPAKE_C */ diff --git a/external_libs/mbedtls/library/ecp.c b/external_libs/mbedtls/library/ecp.c new file mode 100644 index 00000000..f51f2251 --- /dev/null +++ b/external_libs/mbedtls/library/ecp.c @@ -0,0 +1,2092 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * + * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define ECP_SHORTWEIERSTRASS +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define ECP_MONTGOMERY +#endif + +/* + * Curve types: internal for now, might be exposed later + */ +typedef enum +{ + ECP_TYPE_NONE = 0, + ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} ecp_curve_type; + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. This provides the default order for the SSL module. + * + * Reminder: update profiles in x509_crt.c when adding a new curves! + */ +static const mbedtls_ecp_curve_info ecp_supported_curves[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif + { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( strcmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( ECP_TYPE_MONTGOMERY ); + else + return( ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_init( &pt->X ); + mbedtls_mpi_init( &pt->Y ); + mbedtls_mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) +{ + if( grp == NULL ) + return; + + memset( grp, 0, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Initialize (the components of) a key pair + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_init( &key->grp ); + mbedtls_mpi_init( &key->d ); + mbedtls_ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_free( &( pt->X ) ); + mbedtls_mpi_free( &( pt->Y ) ); + mbedtls_mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mbedtls_mpi_free( &grp->P ); + mbedtls_mpi_free( &grp->A ); + mbedtls_mpi_free( &grp->B ); + mbedtls_ecp_point_free( &grp->G ); + mbedtls_mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + + mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_free( &key->grp ); + mbedtls_mpi_free( &key->d ); + mbedtls_ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) +{ + return mbedtls_ecp_group_load( dst, src->id ); +} + +/* + * Set point to zero + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) +{ + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Compare two points lazyly + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3) + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = 0; + size_t plen; + + if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && + format != MBEDTLS_ECP_PF_COMPRESSED ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Common case: P == 0 + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == MBEDTLS_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + } + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret; + size_t plen; + + if( ilen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( mbedtls_ecp_set_zero( pt ) ); + else + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( buf[0] != 0x04 ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret; + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const mbedtls_ecp_curve_info *curve_info; + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + return mbedtls_ecp_group_load( grp, curve_info->grp_id ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_ecp_curve_info *curve_info; + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + buf[0] = curve_info->tls_id >> 8; + buf[1] = curve_info->tls_id & 0xFF; + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. + * See the documentation of struct mbedtls_ecp_group. + * + * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) +{ + int ret; + + if( grp->modp == NULL ) + return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || + mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + MBEDTLS_MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); + + while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi + */ +#if defined(MBEDTLS_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ + while( 0 ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) ) + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with coutermeasueres against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi Zi, ZZi; + + if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); + + /* + * Y = Y / Z^3 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); + + /* + * Z = 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + + return( ret ); +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ) +{ + int ret; + size_t i; + mbedtls_mpi *c, u, Zi, ZZi; + + if( t_len < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + + if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < t_len; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); + MOD_MUL( c[i] ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); + + for( i = t_len - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); + } + + /* + * proceed as in normalize() + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + for( i = 0; i < t_len; i++ ) + mbedtls_mpi_free( &c[i] ); + mbedtls_free( c ); + + return( ret ); +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *Q, + unsigned char inv ) +{ + int ret; + unsigned char nonzero; + mbedtls_mpi mQY; + + mbedtls_mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mbedtls_mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . + * + * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR + * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. + * + * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + */ +static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ + int ret; + mbedtls_mpi M, S, T, U; + +#if defined(MBEDTLS_SELF_TEST) + dbl_count++; +#endif + + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); + } + } + + /* S = 4.X.Y^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); + + /* U = 8.Y^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + /* T = M^2 - 2.S */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + + /* S = M(S - T) - U */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); + + /* U = 2.Y.Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); + +cleanup: + mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); + + return( ret ); +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + +#if defined(MBEDTLS_SELF_TEST) + add_count++; +#endif + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); + + /* Special cases (2) and (3) */ + if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = mbedtls_ecp_set_zero( R ); + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + + return( ret ); +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l, ll; + size_t p_size = ( grp->pbits + 7 ) / 8; + int count = 0; + + mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + do + { + mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + /* Z = l * Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); + + /* X = l^2 * X */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); + + /* Y = l^3 * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); + +cleanup: + mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); + + return( ret ); +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 +#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries. + * + * Also, for the sake of compactness, only the seven low-order bits of x[i] + * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in + * the paper): it is set if and only if if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_fixed( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the comb method + * + * If i = i_{w-1} ... i_1 is the binary representation of i, then + * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P + * + * T must be able to hold 2^{w - 1} elements + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + */ +static int ecp_precompute_comb( const mbedtls_ecp_group *grp, + mbedtls_ecp_point T[], const mbedtls_ecp_point *P, + unsigned char w, size_t d ) +{ + int ret; + unsigned char i, k; + size_t j; + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); + + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + cur = T + i; + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + for( j = 0; j < d; j++ ) + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + + TT[k++] = cur; + } + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + j = i; + while( j-- ) + { + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + TT[k++] = &T[i + j]; + } + } + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + +cleanup: + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + */ +static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char t_len, + unsigned char i ) +{ + int ret; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < t_len; j++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char t_len, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point Txi; + size_t i; + + mbedtls_ecp_point_init( &Txi ); + + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + + while( i-- != 0 ) + { + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + mbedtls_ecp_point_free( &Txi ); + + return( ret ); +} + +/* + * Multiplication using the comb method, + * for curves in short Weierstrass form + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char w, m_is_odd, p_eq_g, pre_len, i; + size_t d; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *T; + mbedtls_mpi M, mm; + + mbedtls_mpi_init( &M ); + mbedtls_mpi_init( &mm ); + + /* we need N to be odd to trnaform m in an odd number, check now */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); + if( p_eq_g ) + w++; +#else + p_eq_g = 0; +#endif + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ + if( w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; + if( w >= grp->nbits ) + w = 2; + + /* Other sizes that depend on w */ + pre_len = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* + * Prepare precomputed points: if P == G we want to + * use grp->T if already initialized, or initialize it. + */ + T = p_eq_g ? grp->T : NULL; + + if( T == NULL ) + { + T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); + if( T == NULL ) + { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); + + if( p_eq_g ) + { + grp->T = T; + grp->T_size = pre_len; + } + } + + /* + * Make sure M is odd (M = m or M = N - m, since N is odd) + * using the fact that m * P = - (N - m) * P + */ + m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + + /* + * Go for comb multiplication, R = M * P + */ + ecp_comb_fixed( k, d, w, &M ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); + + /* + * Now get m * P from M * P and normalize it + */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + + if( T != NULL && ! p_eq_g ) + { + for( i = 0; i < pre_len; i++ ) + mbedtls_ecp_point_free( &T[i] ); + mbedtls_free( T ); + } + + mbedtls_mpi_free( &M ); + mbedtls_mpi_free( &mm ); + + if( ret != 0 ) + mbedtls_ecp_point_free( R ); + + return( ret ); +} + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) +/* + * For Montgomery curves, we do all the internal arithmetic in projective + * coordinates. Import/export of points uses only the x coordinates, which is + * internaly represented as X / Z. + * + * For scalar multiplication, we'll use a Montgomery ladder. + */ + +/* + * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 + * Cost: 1M + 1I + */ +static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l; + size_t p_size = ( grp->pbits + 7 ) / 8; + int count = 0; + + mbedtls_mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + do + { + mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); + +cleanup: + mbedtls_mpi_free( &l ); + + return( ret ); +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + const mbedtls_mpi *d ) +{ + int ret; + mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); + mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); + +cleanup: + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); + mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); + + return( ret ); +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t i; + unsigned char b; + mbedtls_ecp_point RP; + mbedtls_mpi PX; + + mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); + + /* Save PX and read from P before writing to R, in case P == R */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); + mbedtls_mpi_free( &R->Y ); + + /* RP.X might be sligtly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ + if( f_rng != NULL ) + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mbedtls_mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); + + return( ret ); +} + +#endif /* ECP_MONTGOMERY */ + +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + /* Common sanity checks */ + if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || + ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) + return( ret ); + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + return( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || + mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || + mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); + + if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + +cleanup: + + mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); + + return( ret ); +} +#endif /* ECP_SHORTWEIERSTRASS */ + +/* + * R = m * P with shortcuts for m == 1 and m == -1 + * NOT constant-time - ONLY for short Weierstrass! + */ +static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *P ) +{ + int ret; + + if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + } + else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + } + +cleanup: + return( ret ); +} + +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_ecp_point mP; + + if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); + + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + mbedtls_ecp_point_free( &mP ); + + return( ret ); +} + + +#if defined(ECP_MONTGOMERY) +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); +} +#endif /* ECP_MONTGOMERY */ + +/* + * Check that a point is valid as a public key + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mbedtls_mpi is valid as a private key + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) +{ +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* see [Curve25519] page 5 */ + if( mbedtls_mpi_get_bit( d, 0 ) != 0 || + mbedtls_mpi_get_bit( d, 1 ) != 0 || + mbedtls_mpi_get_bit( d, 2 ) != 0 || + mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* ECP_SHORTWEIERSTRASS */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* [M225] page 5 */ + size_t b; + + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + } while( mbedtls_mpi_bitlen( d ) == 0); + + /* Make sure the most significant bit is nbits */ + b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ + if( b > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); + + /* Make sure the last three bits are unset */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } + else +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* SEC1 3.2.1: Generate d such that 1 <= n < N */ + int count = 0; + unsigned char rnd[MBEDTLS_ECP_MAX_BYTES]; + + /* + * Match the procedure given in RFC 6979 (deterministic ECDSA): + * - use the same byte ordering; + * - keep the leftmost nbits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any biais, which is especially important for ECDSA. + */ + do + { + MBEDTLS_MPI_CHK( f_rng( p_rng, rnd, n_size ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); + + /* + * Each try has at worst a probability 1/2 of failing (the msb has + * a probability 1/2 of being 0, and then the result will be < N), + * so after 30 tries failure probability is a most 2**(-30). + * + * For most curves, 1 try is enough with overwhelming probability, + * since N starts with a lot of 1s in binary, but some curves + * such as secp224k1 are actually very close to the worst case. + */ + if( ++count > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); + } + else +#endif /* ECP_SHORTWEIERSTRASS */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +cleanup: + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); +} + +/* + * Generate key pair, wrapper for conventional base point + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +/* + * Check a public-private key pair + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) +{ + int ret; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + + if( pub->grp.id == MBEDTLS_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + mbedtls_ecp_point_init( &Q ); + mbedtls_ecp_group_init( &grp ); + + /* mbedtls_ecp_mul() needs a non-const group... */ + mbedtls_ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); + + if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &Q ); + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Checkup routine + */ +int mbedtls_ecp_self_test( int verbose ) +{ + int ret; + size_t i; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, P; + mbedtls_mpi m; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + /* exponents especially adapted for secp192r1 */ + const char *exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &P ); + mbedtls_mpi_init( &m ); + + /* Use secp192r1 if available, or any available curve */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); +#else + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); + + /* Do a dummy multiplication first to trigger precomputation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret < 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &P ); + mbedtls_mpi_free( &m ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/external_libs/mbedtls/library/ecp_curves.c b/external_libs/mbedtls/library/ecp_curves.c new file mode 100644 index 00000000..9a6e8eb1 --- /dev/null +++ b/external_libs/mbedtls/library/ecp_curves.c @@ -0,0 +1,1325 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) a << 0 ) | \ + ( (mbedtls_mpi_uint) b << 8 ) | \ + ( (mbedtls_mpi_uint) c << 16 ) | \ + ( (mbedtls_mpi_uint) d << 24 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_4( a, b, c, d ), \ + BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) a << 0 ) | \ + ( (mbedtls_mpi_uint) b << 8 ) | \ + ( (mbedtls_mpi_uint) c << 16 ) | \ + ( (mbedtls_mpi_uint) d << 24 ) | \ + ( (mbedtls_mpi_uint) e << 32 ) | \ + ( (mbedtls_mpi_uint) f << 40 ) | \ + ( (mbedtls_mpi_uint) g << 48 ) | \ + ( (mbedtls_mpi_uint) h << 56 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in mbedtls_mpi_uint */ + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + */ +static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( mbedtls_mpi_uint ); + X->p = (mbedtls_mpi_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mbedtls_mpi *X ) +{ + static mbedtls_mpi_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + grp->h = 1; + + return( 0 ); +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mbedtls_mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mbedtls_mpi * ); +#endif + +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( mbedtls_ecp_group *grp ) +{ + int ret; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); + + /* P = 2^255 - 19 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionaly not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) +{ + mbedtls_ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + + default: + mbedtls_ecp_group_free( grp ); + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) +#define A( i ) N->p + i * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi_uint c = 0; + mbedtls_mpi_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (mbedtls_mpi_uint) cur; \ + } + +#endif /* sizeof( mbedtls_mpi_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +/* + * Helpers for the main 'loop' + * (see fix_negative for the motivation of C) + */ +#define INIT( b ) \ + int ret; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = b; \ + mbedtls_mpi C; \ + mbedtls_mpi_uint Cp[ b / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ + \ + C.s = 1; \ + C.n = b / 8 / sizeof( mbedtls_mpi_uint) + 1; \ + C.p = Cp; \ + memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ + \ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, b * 2 / 8 / sizeof( mbedtls_mpi_uint ) ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) fix_negative( N, c, &C, bits ); + +/* + * If the result is negative, we get it in the form + * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' + */ +static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) +{ + int ret; + + /* C = - c * 2^(bits + 32) */ +#if !defined(MBEDTLS_HAVE_INT64) + ((void) bits); +#else + if( bits == 224 ) + C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; + else +#endif + C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; + + /* N = - ( C - N ) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); + N->s = -1; + +cleanup: + + return( ret ); +} + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mbedtls_mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mbedtls_mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mbedtls_mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + M.n = P255_WIDTH + 1; + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, mbedtls_mpi_uint mask ) +{ + int ret; + size_t i; + mbedtls_mpi M, R; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n - adjust; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n - adjust; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(MBEDTLS_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/external_libs/mbedtls/library/entropy.c b/external_libs/mbedtls/library/entropy.c new file mode 100644 index 00000000..d4d1b27b --- /dev/null +++ b/external_libs/mbedtls/library/entropy.c @@ -0,0 +1,655 @@ +/* + * Entropy accumulator implementation + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ENTROPY_C) + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " +#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " +#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + memset( ctx, 0, sizeof(mbedtls_entropy_context) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_starts( &ctx->accumulator, 0 ); +#else + mbedtls_sha256_starts( &ctx->accumulator, 0 ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, + 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + +#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_TIMING_C) + mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDCLOCK, + MBEDTLS_ENTROPY_SOURCE_WEAK ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, + MBEDTLS_ENTROPY_MIN_HAVEGE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) +{ +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_free( &ctx->havege_data ); +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ) +{ + int 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/external_libs/mbedtls/library/entropy_poll.c b/external_libs/mbedtls/library/entropy_poll.c new file mode 100644 index 00000000..a116e605 --- /dev/null +++ b/external_libs/mbedtls/library/entropy_poll.c @@ -0,0 +1,268 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#if defined(MBEDTLS_TIMING_C) +#include +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} + +#include +/* Check if version is at least 3.17.0 */ +static int check_version_3_17_plus( void ) +{ + int minor; + struct utsname un; + const char *ver; + + /* Get version information */ + uname(&un); + ver = un.release; + + /* Check major version; assume a single digit */ + if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) + return( -1 ); + + if( ver[0] - '0' > 3 ) + return( 0 ); + + /* Ok, so now we know major == 3, check minor. + * Assume 1 or 2 digits. */ + if( ver[2] < '0' || ver[2] > '9' ) + return( -1 ); + + minor = ver[2] - '0'; + + if( ver[3] >= '0' && ver[3] <= '9' ) + minor = 10 * minor + ver[3] - '0'; + else if( ver [3] != '.' ) + return( -1 ); + + if( minor < 17 ) + return( -1 ); + + return( 0 ); +} +static int has_getrandom = -1; +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#include + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + ((void) data); + +#if defined(HAVE_GETRANDOM) + if( has_getrandom == -1 ) + has_getrandom = ( check_version_3_17_plus() == 0 ); + + if( has_getrandom ) + { + int ret; + + if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); + } +#endif /* HAVE_GETRANDOM */ + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/external_libs/mbedtls/library/error.c b/external_libs/mbedtls/library/error.c new file mode 100644 index 00000000..dd2db0c4 --- /dev/null +++ b/external_libs/mbedtls/library/error.c @@ -0,0 +1,707 @@ +/* + * Error message information + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) +#include "mbedtls/error.h" +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#define mbedtls_time_t time_t +#endif + +#if defined(MBEDTLS_ERROR_C) + +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "mbedtls/base64.h" +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ENTROPY_C) +#include "mbedtls/entropy.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + +#if defined(MBEDTLS_OID_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#endif + +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#endif + + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // High level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_CIPHER_C) + if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid, eg because it was free()ed" ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_DHM_C) + if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the public value failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); + if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "DHM - Read/write of file failed" ); +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECP_C) + if( use_ret == -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ECP - Requested curve not available" ); + if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); + if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) + mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); + if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) + if( use_ret == -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "MD - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_MD_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "MD - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MD_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + if( use_ret == -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) + mbedtls_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PEM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_ENC_IV) ) + mbedtls_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); + if( use_ret == -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG) ) + mbedtls_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + if( use_ret == -(MBEDTLS_ERR_PK_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PK - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PK_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "PK - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "PK - Unsupported key version" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PK - Invalid key tag or value" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PK - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_PUBKEY) ) + mbedtls_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE) ) + mbedtls_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PKCS12_C) + if( use_ret == -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PKCS5_C) + if( use_ret == -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_RSA_C) + if( use_ret == -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_RSA_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the library's validity check" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The private key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); + if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) + mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) + mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) + mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) + mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); + if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) + { + mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); + return; + } + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) + mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) + mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) + mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) + mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) + mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) + mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) + mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) + mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) + mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) + mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) + mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) + mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) + mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) + mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) + mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); + if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); + if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); +#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/external_libs/mbedtls/library/gcm.c b/external_libs/mbedtls/library/gcm.c new file mode 100644 index 00000000..f1210c52 --- /dev/null +++ b/external_libs/mbedtls/library/gcm.c @@ -0,0 +1,952 @@ +/* + * NIST SP800-38D compliant GCM implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + * + * See also: + * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + * + * We use the algorithm described as Shoup's method with 4-bit tables in + * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_GCM_C) + +#include "mbedtls/gcm.h" + +#include + +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Initialize a context + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); +} + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( mbedtls_gcm_context *ctx ) +{ + int ret, i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char h[16]; + size_t olen = 0; + + memset( h, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); + + /* pack h as two 64-bits ints, big-endian */ + GET_UINT32_BE( hi, h, 0 ); + GET_UINT32_BE( lo, h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + GET_UINT32_BE( hi, h, 8 ); + GET_UINT32_BE( lo, h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) + return( 0 ); +#endif + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for( i = 4; i > 0; i >>= 1 ) + { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for( i = 2; i <= 8; i *= 2 ) + { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for( j = 1; j < i; j++ ) + { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return( 0 ); +} + +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = +{ + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { + unsigned char h[16]; + + PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); + PUT_UINT32_BE( ctx->HH[8], h, 4 ); + PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); + PUT_UINT32_BE( ctx->HL[8], h, 12 ); + + mbedtls_aesni_gcm_mult( output, x, h ); + return; + } +#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ + + lo = x[15] & 0xf; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + for( i = 15; i >= 0; i-- ) + { + lo = x[i] & 0xf; + hi = x[i] >> 4; + + if( i != 15 ) + { + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + } + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + PUT_UINT32_BE( zh >> 32, output, 0 ); + PUT_UINT32_BE( zh, output, 4 ); + PUT_UINT32_BE( zl >> 32, output, 8 ); + PUT_UINT32_BE( zl, output, 12 ); +} + +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ) +{ + int ret; + unsigned char work_buf[16]; + size_t i; + const unsigned char *p; + size_t use_len, olen = 0; + + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + if( ( (uint64_t) iv_len ) >> 61 != 0 || + ( (uint64_t) add_len ) >> 61 != 0 ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + memset( ctx->y, 0x00, sizeof(ctx->y) ); + memset( ctx->buf, 0x00, sizeof(ctx->buf) ); + + ctx->mode = mode; + ctx->len = 0; + ctx->add_len = 0; + + if( iv_len == 12 ) + { + memcpy( ctx->y, iv, iv_len ); + ctx->y[15] = 1; + } + else + { + memset( work_buf, 0x00, 16 ); + PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); + + p = iv; + while( iv_len > 0 ) + { + use_len = ( iv_len < 16 ) ? iv_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->y[i] ^= p[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + + iv_len -= use_len; + p += use_len; + } + + for( i = 0; i < 16; i++ ) + ctx->y[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + } + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + ctx->add_len = add_len; + p = add; + while( add_len > 0 ) + { + use_len = ( add_len < 16 ) ? add_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->buf[i] ^= p[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + add_len -= use_len; + p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char ectr[16]; + size_t i; + const unsigned char *p; + unsigned char *out_p = output; + size_t use_len, olen = 0; + + if( output > input && (size_t) ( output - input ) < length ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if( ctx->len + length < ctx->len || + (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + ctx->len += length; + + p = input; + while( length > 0 ) + { + use_len = ( length < 16 ) ? length : 16; + + for( i = 16; i > 12; i-- ) + if( ++ctx->y[i - 1] != 0 ) + break; + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == MBEDTLS_GCM_DECRYPT ) + ctx->buf[i] ^= p[i]; + out_p[i] = ectr[i] ^ p[i]; + if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) + ctx->buf[i] ^= out_p[i]; + } + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + length -= use_len; + p += use_len; + out_p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ) +{ + unsigned char work_buf[16]; + size_t i; + uint64_t orig_len = ctx->len * 8; + uint64_t orig_add_len = ctx->add_len * 8; + + if( tag_len > 16 || tag_len < 4 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + memcpy( tag, ctx->base_ectr, tag_len ); + + if( orig_len || orig_add_len ) + { + memset( work_buf, 0x00, 16 ); + + PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); + PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); + PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); + PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); + + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + for( i = 0; i < tag_len; i++ ) + tag[i] ^= ctx->buf[i]; + } + + return( 0 ); +} + +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret; + + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_zeroize( output, length ); + return( MBEDTLS_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); +} + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * AES-GCM test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip + */ +#define MAX_TESTS 6 + +static const int key_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char key[MAX_TESTS][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, +}; + +static const size_t iv_len[MAX_TESTS] = + { 12, 12, 12, 12, 8, 60 }; + +static const int iv_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 2 }; + +static const unsigned char iv[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 }, + { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b }, +}; + +static const size_t add_len[MAX_TESTS] = + { 0, 0, 0, 20, 20, 20 }; + +static const int add_index[MAX_TESTS] = + { 0, 0, 0, 1, 1, 1 }; + +static const unsigned char additional[MAX_TESTS][64] = +{ + { 0x00 }, + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 }, +}; + +static const size_t pt_len[MAX_TESTS] = + { 0, 16, 64, 60, 60, 60 }; + +static const int pt_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char pt[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, +}; + +static const unsigned char ct[MAX_TESTS * 3][64] = +{ + { 0x00 }, + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91 }, + { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, + 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, + 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, + 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, + 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, + 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, + 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, + 0xc2, 0x3f, 0x45, 0x98 }, + { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, + 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, + 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, + 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, + 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, + 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, + 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, + 0x4c, 0x34, 0xae, 0xe5 }, + { 0x00 }, + { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10 }, + { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7 }, + { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b }, + { 0x00 }, + { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 }, + { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f }, + { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f }, +}; + +static const unsigned char tag[MAX_TESTS * 3][16] = +{ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, + { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, + { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, + { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, + { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, + { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, + { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, + { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, + { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, + { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, + { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, + { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, + { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, +}; + +int mbedtls_gcm_self_test( int verbose ) +{ + mbedtls_gcm_context ctx; + unsigned char buf[64]; + unsigned char tag_buf[16]; + int i, j, ret; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + + mbedtls_gcm_init( &ctx ); + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + pt[pt_index[i]], buf, 16, tag_buf ); + + if( ret != 0 || + memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + ct[j * 6 + i], buf, 16, tag_buf ); + + if( ret != 0 || + memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, + buf + 32 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 || + memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, + buf + 32 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 || + memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + } + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_GCM_C */ diff --git a/external_libs/mbedtls/library/havege.c b/external_libs/mbedtls/library/havege.c new file mode 100644 index 00000000..2b75ef7b --- /dev/null +++ b/external_libs/mbedtls/library/havege.c @@ -0,0 +1,245 @@ +/** + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The HAVEGE RNG was designed by Andre Seznec in 2002. + * + * http://www.irisa.fr/caps/projects/hipsor/publi.php + * + * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVEGE_C) + +#include "mbedtls/havege.h" +#include "mbedtls/timing.h" + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* ------------------------------------------------------------------------ + * On average, one iteration accesses two 8-word blocks in the havege WALK + * table, and generates 16 words in the RES array. + * + * The data read in the WALK table is updated and permuted after each use. + * The result of the hardware clock counter read is used for this update. + * + * 25 conditional tests are present. The conditional tests are grouped in + * two nested groups of 12 conditional tests and 1 test that controls the + * permutation; on average, there should be 6 tests executed and 3 of them + * should be mispredicted. + * ------------------------------------------------------------------------ + */ + +#define SWAP(X,Y) { int *T = X; X = Y; Y = T; } + +#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; +#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; + +#define TST1_LEAVE U1++; } +#define TST2_LEAVE U2++; } + +#define ONE_ITERATION \ + \ + PTEST = PT1 >> 20; \ + \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + \ + PTX = (PT1 >> 18) & 7; \ + PT1 &= 0x1FFF; \ + PT2 &= 0x1FFF; \ + CLK = (int) mbedtls_timing_hardclock(); \ + \ + i = 0; \ + A = &WALK[PT1 ]; RES[i++] ^= *A; \ + B = &WALK[PT2 ]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ + \ + IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ + *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ + *B = IN ^ U1; \ + *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ + *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ + \ + if( PTEST & 1 ) SWAP( A, C ); \ + \ + IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ + *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ + *B = IN; CLK = (int) mbedtls_timing_hardclock(); \ + *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ + *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 4]; \ + B = &WALK[PT2 ^ 1]; \ + \ + PTEST = PT2 >> 1; \ + \ + PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ + PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ + PTY = (PT2 >> 10) & 7; \ + \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + \ + C = &WALK[PT1 ^ 5]; \ + D = &WALK[PT2 ^ 5]; \ + \ + RES[i++] ^= *A; \ + RES[i++] ^= *B; \ + RES[i++] ^= *C; \ + RES[i++] ^= *D; \ + \ + IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ + *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ + *B = IN ^ U2; \ + *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ + *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ + \ + IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ + *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ + *B = IN; \ + *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ + *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ + \ + PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ + WALK[PT1 ^ PTX ^ 7] ) & (~1); \ + PT1 ^= (PT2 ^ 0x10) & 0x10; \ + \ + for( n++, i = 0; i < 16; i++ ) \ + hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( mbedtls_havege_state *hs ) +{ + int i, n = 0; + int U1, U2, *A, *B, *C, *D; + int PT1, PT2, *WALK, RES[16]; + int PTX, PTY, CLK, PTEST, IN; + + WALK = hs->WALK; + PT1 = hs->PT1; + PT2 = hs->PT2; + + PTX = U1 = 0; + PTY = U2 = 0; + + (void)PTX; + + memset( RES, 0, sizeof( RES ) ); + + while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) + { + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + } + + hs->PT1 = PT1; + hs->PT2 = PT2; + + hs->offset[0] = 0; + hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; +} + +/* + * HAVEGE initialization + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ) +{ + memset( hs, 0, sizeof( mbedtls_havege_state ) ); + + havege_fill( hs ); +} + +void mbedtls_havege_free( mbedtls_havege_state *hs ) +{ + if( hs == NULL ) + return; + + mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) ); +} + +/* + * HAVEGE rand function + */ +int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) +{ + int val; + size_t use_len; + mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; + unsigned char *p = buf; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof(int) ) + use_len = sizeof(int); + + if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) + havege_fill( hs ); + + val = hs->pool[hs->offset[0]++]; + val ^= hs->pool[hs->offset[1]++]; + + memcpy( p, &val, use_len ); + + len -= use_len; + p += use_len; + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVEGE_C */ diff --git a/external_libs/mbedtls/library/hmac_drbg.c b/external_libs/mbedtls/library/hmac_drbg.c new file mode 100644 index 00000000..bf5f9b5b --- /dev/null +++ b/external_libs/mbedtls/library/hmac_drbg.c @@ -0,0 +1,529 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The NIST SP 800-90A DRBGs are described in the following publication. + * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + * References below are based on rev. 1 (January 2012). + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + +#include "mbedtls/hmac_drbg.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * HMAC_DRBG context initialization + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[MBEDTLS_MD_MAX_SIZE]; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + mbedtls_md_hmac_reset( &ctx->md_ctx ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); + if( rounds == 2 ) + mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, K ); + + /* Step 2 or 5 */ + mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + } +} + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); + memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); + + mbedtls_hmac_drbg_update( ctx, data, data_len ); + + return( 0 ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen; + + /* III. Check input length */ + if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || + ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); + + /* IV. Gather entropy_len bytes of entropy for the seed */ + if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + + seedlen = ctx->entropy_len; + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + mbedtls_hmac_drbg_update( ctx, seed, seedlen ); + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + + /* 4. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret; + size_t entropy_len, md_size; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + md_size = mbedtls_md_get_size( md_info ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); + memset( ctx->V, 0x01, md_size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; + + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + + /* + * For initialisation, use more entropy to emulate a nonce + * (Again, matches test vectors.) + */ + ctx->entropy_len = entropy_len * 3 / 2; + + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + ctx->entropy_len = entropy_len; + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for reseeds + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +/* + * HMAC_DRBG random function with optional additional data: + * 10.1.2.5 (arabic) + 9.3 (Roman) + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t out_len, + const unsigned char *additional, size_t add_len ) +{ + int ret; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + + /* 1. (aka VII and IX) Check reseed counter and PR */ + if( ctx->f_entropy != NULL && /* For no-reseeding instances */ + ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; /* VII.4 */ + } + + /* 2. Use additional data if any */ + if( additional != NULL && add_len != 0 ) + mbedtls_hmac_drbg_update( ctx, additional, add_len ); + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + mbedtls_md_hmac_reset( &ctx->md_ctx ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + mbedtls_hmac_drbg_update( ctx, additional, add_len ); + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + + /* 8. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG random function + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + int ret; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free an HMAC_DRBG context + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_md_free( &ctx->md_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret; + FILE *f; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + { + fclose( f ); + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + } + + fclose( f ); + + mbedtls_hmac_drbg_update( ctx, buf, n ); + + return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +/* Dummy checkup routine */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +#define OUTPUT_LEN 80 + +/* From a NIST PR=true test vector */ +static const unsigned char entropy_pr[] = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, + 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, + 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, + 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; +static const unsigned char result_pr[OUTPUT_LEN] = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, + 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, + 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, + 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, + 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, + 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; + +/* From a NIST PR=false test vector */ +static const unsigned char entropy_nopr[] = { + 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, + 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, + 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, + 0xe9, 0x9d, 0xfe, 0xdf }; +static const unsigned char result_nopr[OUTPUT_LEN] = { + 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, + 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, + 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, + 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, + 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, + 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, + 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; + +/* "Entropy" from buffer */ +static size_t test_offset; +static int hmac_drbg_self_test_entropy( void *data, + unsigned char *buf, size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + mbedtls_hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + + mbedtls_hmac_drbg_init( &ctx ); + + /* + * PR = True + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_pr, + NULL, 0 ) ); + mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = False) : " ); + + mbedtls_hmac_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_nopr, + NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/external_libs/mbedtls/library/md.c b/external_libs/mbedtls/library/md.c new file mode 100644 index 00000000..eda98f63 --- /dev/null +++ b/external_libs/mbedtls/library/md.c @@ -0,0 +1,471 @@ +/** + * \file mbedtls_md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD4_C) + MBEDTLS_MD_MD4, +#endif + +#if defined(MBEDTLS_MD2_C) + MBEDTLS_MD_MD2, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD2_C) + if( !strcmp( "MD2", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + if( !strcmp( "MD4", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + ctx->md_info->ctx_free_func( ctx->md_ctx ); + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) +{ + return mbedtls_md_setup( ctx, md_info, 1 ); +} +#endif + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + md_info->ctx_free_func( ctx->md_ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + ctx->md_info = md_info; + + return( 0 ); +} + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->starts_func( ctx->md_ctx ); + + return( 0 ); +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->update_func( ctx->md_ctx, input, ilen ); + + return( 0 ); +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->finish_func( ctx->md_ctx, output ); + + return( 0 ); +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + md_info->digest_func( input, ilen, output ); + + return( 0 ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + md_info->starts_func( ctx.md_ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + md_info->update_func( ctx.md_ctx, buf, n ); + + if( ferror( f ) != 0 ) + { + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + goto cleanup; + } + + md_info->finish_func( ctx.md_ctx, output ); + +cleanup: + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + ctx->md_info->starts_func( ctx->md_ctx ); + ctx->md_info->update_func( ctx->md_ctx, key, keylen ); + ctx->md_info->finish_func( ctx->md_ctx, sum ); + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + mbedtls_zeroize( sum, sizeof( sum ) ); + + ctx->md_info->starts_func( ctx->md_ctx ); + ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); + + return( 0 ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->update_func( ctx->md_ctx, input, ilen ); + + return( 0 ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + ctx->md_info->finish_func( ctx->md_ctx, tmp ); + ctx->md_info->starts_func( ctx->md_ctx ); + ctx->md_info->update_func( ctx->md_ctx, opad, ctx->md_info->block_size ); + ctx->md_info->update_func( ctx->md_ctx, tmp, ctx->md_info->size ); + ctx->md_info->finish_func( ctx->md_ctx, output ); + + return( 0 ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + ctx->md_info->starts_func( ctx->md_ctx ); + ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); + + return( 0 ); +} + +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &ctx, key, keylen ); + mbedtls_md_hmac_update( &ctx, input, ilen ); + mbedtls_md_hmac_finish( &ctx, output ); + + mbedtls_md_free( &ctx ); + + return( 0 ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->process_func( ctx->md_ctx, data ); + + return( 0 ); +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ diff --git a/external_libs/mbedtls/library/md2.c b/external_libs/mbedtls/library/md2.c new file mode 100644 index 00000000..89767013 --- /dev/null +++ b/external_libs/mbedtls/library/md2.c @@ -0,0 +1,288 @@ +/* + * RFC 1115/1319 compliant MD2 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The MD2 algorithm was designed by Ron Rivest in 1989. + * + * http://www.ietf.org/rfc/rfc1115.txt + * http://www.ietf.org/rfc/rfc1319.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD2_C) + +#include "mbedtls/md2.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD2_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +static const unsigned char PI_SUBST[256] = +{ + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, + 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, + 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, + 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, + 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, + 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, + 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, + 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, + 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, + 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, + 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, + 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, + 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, + 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, + 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, + 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, + 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, + 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, + 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, + 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +void mbedtls_md2_init( mbedtls_md2_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_free( mbedtls_md2_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ) +{ + *dst = *src; +} + +/* + * MD2 context setup + */ +void mbedtls_md2_starts( mbedtls_md2_context *ctx ) +{ + memset( ctx->cksum, 0, 16 ); + memset( ctx->state, 0, 46 ); + memset( ctx->buffer, 0, 16 ); + ctx->left = 0; +} + +#if !defined(MBEDTLS_MD2_PROCESS_ALT) +void mbedtls_md2_process( mbedtls_md2_context *ctx ) +{ + int i, j; + unsigned char t = 0; + + for( i = 0; i < 16; i++ ) + { + ctx->state[i + 16] = ctx->buffer[i]; + ctx->state[i + 32] = + (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); + } + + for( i = 0; i < 18; i++ ) + { + for( j = 0; j < 48; j++ ) + { + ctx->state[j] = (unsigned char) + ( ctx->state[j] ^ PI_SUBST[t] ); + t = ctx->state[j]; + } + + t = (unsigned char)( t + i ); + } + + t = ctx->cksum[15]; + + for( i = 0; i < 16; i++ ) + { + ctx->cksum[i] = (unsigned char) + ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); + t = ctx->cksum[i]; + } +} +#endif /* !MBEDTLS_MD2_PROCESS_ALT */ + +/* + * MD2 process buffer + */ +void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + + while( ilen > 0 ) + { + if( ctx->left + ilen > 16 ) + fill = 16 - ctx->left; + else + fill = ilen; + + memcpy( ctx->buffer + ctx->left, input, fill ); + + ctx->left += fill; + input += fill; + ilen -= fill; + + if( ctx->left == 16 ) + { + ctx->left = 0; + mbedtls_md2_process( ctx ); + } + } +} + +/* + * MD2 final digest + */ +void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) +{ + size_t i; + unsigned char x; + + x = (unsigned char)( 16 - ctx->left ); + + for( i = ctx->left; i < 16; i++ ) + ctx->buffer[i] = x; + + mbedtls_md2_process( ctx ); + + memcpy( ctx->buffer, ctx->cksum, 16 ); + mbedtls_md2_process( ctx ); + + memcpy( output, ctx->state, 16 ); +} + +#endif /* !MBEDTLS_MD2_ALT */ + +/* + * output = MD2( input buffer ) + */ +void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + mbedtls_md2_context ctx; + + mbedtls_md2_init( &ctx ); + mbedtls_md2_starts( &ctx ); + mbedtls_md2_update( &ctx, input, ilen ); + mbedtls_md2_finish( &ctx, output ); + mbedtls_md2_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1319 test vectors + */ +static const char md2_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890" } +}; + +static const unsigned char md2_test_sum[7][16] = +{ + { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, + 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, + { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, + 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, + { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, + 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, + { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, + 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, + { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, + 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, + { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, + 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, + { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, + 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } +}; + +/* + * Checkup routine + */ +int mbedtls_md2_self_test( int verbose ) +{ + int i; + unsigned char md2sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD2 test #%d: ", i + 1 ); + + mbedtls_md2( (unsigned char *) md2_test_str[i], + strlen( md2_test_str[i] ), md2sum ); + + if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD2_C */ diff --git a/external_libs/mbedtls/library/md4.c b/external_libs/mbedtls/library/md4.c new file mode 100644 index 00000000..11a77e3a --- /dev/null +++ b/external_libs/mbedtls/library/md4.c @@ -0,0 +1,384 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD4_C) + +#include "mbedtls/md4.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD4_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md4_init( mbedtls_md4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_free( mbedtls_md4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ) +{ + *dst = *src; +} + +/* + * MD4 context setup + */ +void mbedtls_md4_starts( mbedtls_md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +#if !defined(MBEDTLS_MD4_PROCESS_ALT) +void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) ((x & y) | ((~x) & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 1], 7 ); + P( C, D, A, B, X[ 2], 11 ); + P( B, C, D, A, X[ 3], 19 ); + P( A, B, C, D, X[ 4], 3 ); + P( D, A, B, C, X[ 5], 7 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[ 7], 19 ); + P( A, B, C, D, X[ 8], 3 ); + P( D, A, B, C, X[ 9], 7 ); + P( C, D, A, B, X[10], 11 ); + P( B, C, D, A, X[11], 19 ); + P( A, B, C, D, X[12], 3 ); + P( D, A, B, C, X[13], 7 ); + P( C, D, A, B, X[14], 11 ); + P( B, C, D, A, X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) ((x & y) | (x & z) | (y & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 4], 5 ); + P( C, D, A, B, X[ 8], 9 ); + P( B, C, D, A, X[12], 13 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 5], 5 ); + P( C, D, A, B, X[ 9], 9 ); + P( B, C, D, A, X[13], 13 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[ 6], 5 ); + P( C, D, A, B, X[10], 9 ); + P( B, C, D, A, X[14], 13 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[ 7], 5 ); + P( C, D, A, B, X[11], 9 ); + P( B, C, D, A, X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 8], 9 ); + P( C, D, A, B, X[ 4], 11 ); + P( B, C, D, A, X[12], 15 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[10], 9 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[14], 15 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 9], 9 ); + P( C, D, A, B, X[ 5], 11 ); + P( B, C, D, A, X[13], 15 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[11], 9 ); + P( C, D, A, B, X[ 7], 11 ); + P( B, C, D, A, X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} +#endif /* !MBEDTLS_MD4_PROCESS_ALT */ + +/* + * MD4 process buffer + */ +void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + mbedtls_md4_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_md4_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } +} + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn ); + mbedtls_md4_update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); +} + +#endif /* !MBEDTLS_MD4_ALT */ + +/* + * output = MD4( input buffer ) + */ +void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + mbedtls_md4_context ctx; + + mbedtls_md4_init( &ctx ); + mbedtls_md4_starts( &ctx ); + mbedtls_md4_update( &ctx, input, ilen ); + mbedtls_md4_finish( &ctx, output ); + mbedtls_md4_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1320 test vectors + */ +static const char md4_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890" } +}; + +static const unsigned char md4_test_sum[7][16] = +{ + { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, + 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, + { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, + 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, + { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, + 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, + { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, + 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, + { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, + 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, + { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, + 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, + { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, + 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } +}; + +/* + * Checkup routine + */ +int mbedtls_md4_self_test( int verbose ) +{ + int i; + unsigned char md4sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD4 test #%d: ", i + 1 ); + + mbedtls_md4( (unsigned char *) md4_test_str[i], + strlen( md4_test_str[i] ), md4sum ); + + if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD4_C */ diff --git a/external_libs/mbedtls/library/md5.c b/external_libs/mbedtls/library/md5.c new file mode 100644 index 00000000..5d972dc9 --- /dev/null +++ b/external_libs/mbedtls/library/md5.c @@ -0,0 +1,404 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD5_C) + +#include "mbedtls/md5.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD5_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md5_init( mbedtls_md5_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_free( mbedtls_md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + mbedtls_md5_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_md5_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } +} + +static const unsigned char md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + mbedtls_md5_update( ctx, md5_padding, padn ); + mbedtls_md5_update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); +} + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + mbedtls_md5_starts( &ctx ); + mbedtls_md5_update( &ctx, input, ilen ); + mbedtls_md5_finish( &ctx, output ); + mbedtls_md5_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890" } +}; + +static const int md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test( int verbose ) +{ + int i; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + mbedtls_md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ diff --git a/external_libs/mbedtls/library/md_wrap.c b/external_libs/mbedtls/library/md_wrap.c new file mode 100644 index 00000000..2cfcae20 --- /dev/null +++ b/external_libs/mbedtls/library/md_wrap.c @@ -0,0 +1,575 @@ +/** + * \file md_wrap.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md_internal.h" + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_MD2_C) + +static void md2_starts_wrap( void *ctx ) +{ + mbedtls_md2_starts( (mbedtls_md2_context *) ctx ); +} + +static void md2_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_md2_update( (mbedtls_md2_context *) ctx, input, ilen ); +} + +static void md2_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_md2_finish( (mbedtls_md2_context *) ctx, output ); +} + +static void *md2_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); + + if( ctx != NULL ) + mbedtls_md2_init( (mbedtls_md2_context *) ctx ); + + return( ctx ); +} + +static void md2_ctx_free( void *ctx ) +{ + mbedtls_md2_free( (mbedtls_md2_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md2_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md2_clone( (mbedtls_md2_context *) dst, + (const mbedtls_md2_context *) src ); +} + +static void md2_process_wrap( void *ctx, const unsigned char *data ) +{ + ((void) data); + + mbedtls_md2_process( (mbedtls_md2_context *) ctx ); +} + +const mbedtls_md_info_t mbedtls_md2_info = { + MBEDTLS_MD_MD2, + "MD2", + 16, + 16, + md2_starts_wrap, + md2_update_wrap, + md2_finish_wrap, + mbedtls_md2, + md2_ctx_alloc, + md2_ctx_free, + md2_clone_wrap, + md2_process_wrap, +}; + +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + +static void md4_starts_wrap( void *ctx ) +{ + mbedtls_md4_starts( (mbedtls_md4_context *) ctx ); +} + +static void md4_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_md4_update( (mbedtls_md4_context *) ctx, input, ilen ); +} + +static void md4_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_md4_finish( (mbedtls_md4_context *) ctx, output ); +} + +static void *md4_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); + + if( ctx != NULL ) + mbedtls_md4_init( (mbedtls_md4_context *) ctx ); + + return( ctx ); +} + +static void md4_ctx_free( void *ctx ) +{ + mbedtls_md4_free( (mbedtls_md4_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md4_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md4_clone( (mbedtls_md4_context *) dst, + (const mbedtls_md4_context *) src ); +} + +static void md4_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_md4_process( (mbedtls_md4_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_md4_info = { + MBEDTLS_MD_MD4, + "MD4", + 16, + 64, + md4_starts_wrap, + md4_update_wrap, + md4_finish_wrap, + mbedtls_md4, + md4_ctx_alloc, + md4_ctx_free, + md4_clone_wrap, + md4_process_wrap, +}; + +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + +static void md5_starts_wrap( void *ctx ) +{ + mbedtls_md5_starts( (mbedtls_md5_context *) ctx ); +} + +static void md5_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update( (mbedtls_md5_context *) ctx, input, ilen ); +} + +static void md5_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_md5_finish( (mbedtls_md5_context *) ctx, output ); +} + +static void *md5_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); + + if( ctx != NULL ) + mbedtls_md5_init( (mbedtls_md5_context *) ctx ); + + return( ctx ); +} + +static void md5_ctx_free( void *ctx ) +{ + mbedtls_md5_free( (mbedtls_md5_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md5_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md5_clone( (mbedtls_md5_context *) dst, + (const mbedtls_md5_context *) src ); +} + +static void md5_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_md5_process( (mbedtls_md5_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_md5_info = { + MBEDTLS_MD_MD5, + "MD5", + 16, + 64, + md5_starts_wrap, + md5_update_wrap, + md5_finish_wrap, + mbedtls_md5, + md5_ctx_alloc, + md5_ctx_free, + md5_clone_wrap, + md5_process_wrap, +}; + +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + +static void ripemd160_starts_wrap( void *ctx ) +{ + mbedtls_ripemd160_starts( (mbedtls_ripemd160_context *) ctx ); +} + +static void ripemd160_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update( (mbedtls_ripemd160_context *) ctx, input, ilen ); +} + +static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_ripemd160_finish( (mbedtls_ripemd160_context *) ctx, output ); +} + +static void *ripemd160_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); + + if( ctx != NULL ) + mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); + + return( ctx ); +} + +static void ripemd160_ctx_free( void *ctx ) +{ + mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); + mbedtls_free( ctx ); +} + +static void ripemd160_clone_wrap( void *dst, const void *src ) +{ + mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, + (const mbedtls_ripemd160_context *) src ); +} + +static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_ripemd160_process( (mbedtls_ripemd160_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_ripemd160_info = { + MBEDTLS_MD_RIPEMD160, + "RIPEMD160", + 20, + 64, + ripemd160_starts_wrap, + ripemd160_update_wrap, + ripemd160_finish_wrap, + mbedtls_ripemd160, + ripemd160_ctx_alloc, + ripemd160_ctx_free, + ripemd160_clone_wrap, + ripemd160_process_wrap, +}; + +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + +static void sha1_starts_wrap( void *ctx ) +{ + mbedtls_sha1_starts( (mbedtls_sha1_context *) ctx ); +} + +static void sha1_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update( (mbedtls_sha1_context *) ctx, input, ilen ); +} + +static void sha1_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_sha1_finish( (mbedtls_sha1_context *) ctx, output ); +} + +static void *sha1_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); + + if( ctx != NULL ) + mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); + + return( ctx ); +} + +static void sha1_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, + (const mbedtls_sha1_context *) src ); +} + +static void sha1_ctx_free( void *ctx ) +{ + mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha1_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_sha1_process( (mbedtls_sha1_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_sha1_info = { + MBEDTLS_MD_SHA1, + "SHA1", + 20, + 64, + sha1_starts_wrap, + sha1_update_wrap, + sha1_finish_wrap, + mbedtls_sha1, + sha1_ctx_alloc, + sha1_ctx_free, + sha1_clone_wrap, + sha1_process_wrap, +}; + +#endif /* MBEDTLS_SHA1_C */ + +/* + * Wrappers for generic message digests + */ +#if defined(MBEDTLS_SHA256_C) + +static void sha224_starts_wrap( void *ctx ) +{ + mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 1 ); +} + +static void sha224_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update( (mbedtls_sha256_context *) ctx, input, ilen ); +} + +static void sha224_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); +} + +static void sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_sha256( input, ilen, output, 1 ); +} + +static void *sha224_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); + + if( ctx != NULL ) + mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); + + return( ctx ); +} + +static void sha224_ctx_free( void *ctx ) +{ + mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha224_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, + (const mbedtls_sha256_context *) src ); +} + +static void sha224_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_sha256_process( (mbedtls_sha256_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_sha224_info = { + MBEDTLS_MD_SHA224, + "SHA224", + 28, + 64, + sha224_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha224_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +static void sha256_starts_wrap( void *ctx ) +{ + mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 0 ); +} + +static void sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_sha256( input, ilen, output, 0 ); +} + +const mbedtls_md_info_t mbedtls_sha256_info = { + MBEDTLS_MD_SHA256, + "SHA256", + 32, + 64, + sha256_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha256_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + +static void sha384_starts_wrap( void *ctx ) +{ + mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 1 ); +} + +static void sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update( (mbedtls_sha512_context *) ctx, input, ilen ); +} + +static void sha384_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_sha512_finish( (mbedtls_sha512_context *) ctx, output ); +} + +static void sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_sha512( input, ilen, output, 1 ); +} + +static void *sha384_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); + + if( ctx != NULL ) + mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); + + return( ctx ); +} + +static void sha384_ctx_free( void *ctx ) +{ + mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha384_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, + (const mbedtls_sha512_context *) src ); +} + +static void sha384_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_sha512_process( (mbedtls_sha512_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_sha384_info = { + MBEDTLS_MD_SHA384, + "SHA384", + 48, + 128, + sha384_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha384_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +static void sha512_starts_wrap( void *ctx ) +{ + mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 0 ); +} + +static void sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_sha512( input, ilen, output, 0 ); +} + +const mbedtls_md_info_t mbedtls_sha512_info = { + MBEDTLS_MD_SHA512, + "SHA512", + 64, + 128, + sha512_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha512_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +#endif /* MBEDTLS_SHA512_C */ + +#endif /* MBEDTLS_MD_C */ diff --git a/external_libs/mbedtls/library/memory_buffer_alloc.c b/external_libs/mbedtls/library/memory_buffer_alloc.c new file mode 100644 index 00000000..545d5a2c --- /dev/null +++ b/external_libs/mbedtls/library/memory_buffer_alloc.c @@ -0,0 +1,745 @@ +/* + * Buffer-based memory allocator + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" + +/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C + is dependent upon MBEDTLS_PLATFORM_C */ +#include "mbedtls/platform.h" + +#include + +#if defined(MBEDTLS_MEMORY_BACKTRACE) +#include +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#define MAGIC1 0xFF00AA55 +#define MAGIC2 0xEE119966 +#define MAX_BT 20 + +typedef struct _memory_header memory_header; +struct _memory_header +{ + size_t magic1; + size_t size; + size_t alloc; + memory_header *prev; + memory_header *next; + memory_header *prev_free; + memory_header *next_free; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + char **trace; + size_t trace_count; +#endif + size_t magic2; +}; + +typedef struct +{ + unsigned char *buf; + size_t len; + memory_header *first; + memory_header *first_free; + int verify; +#if defined(MBEDTLS_MEMORY_DEBUG) + size_t alloc_count; + size_t free_count; + size_t total_used; + size_t maximum_used; + size_t header_count; + size_t maximum_header_count; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +buffer_alloc_ctx; + +static buffer_alloc_ctx heap; + +#if defined(MBEDTLS_MEMORY_DEBUG) +static void debug_header( memory_header *hdr ) +{ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + size_t i; +#endif + + mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " + "ALLOC(%zu), SIZE(%10zu)\n", + (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, + hdr->alloc, hdr->size ); + mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", + (size_t) hdr->prev_free, (size_t) hdr->next_free ); + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + mbedtls_fprintf( stderr, "TRACE: \n" ); + for( i = 0; i < hdr->trace_count; i++ ) + mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); + mbedtls_fprintf( stderr, "\n" ); +#endif +} + +static void debug_chain() +{ + memory_header *cur = heap.first; + + mbedtls_fprintf( stderr, "\nBlock list\n" ); + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next; + } + + mbedtls_fprintf( stderr, "Free list\n" ); + cur = heap.first_free; + + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next_free; + } +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +static int verify_header( memory_header *hdr ) +{ + if( hdr->magic1 != MAGIC1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->magic2 != MAGIC2 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->alloc > 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); +#endif + return( 1 ); + } + + if( hdr->prev != NULL && hdr->prev == hdr->next ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); +#endif + return( 1 ); + } + + if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); +#endif + return( 1 ); + } + + return( 0 ); +} + +static int verify_chain() +{ + memory_header *prv = heap.first, *cur = heap.first->next; + + if( verify_header( heap.first ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of first header " + "failed\n" ); +#endif + return( 1 ); + } + + if( heap.first->prev != NULL ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "first->prev != NULL\n" ); +#endif + return( 1 ); + } + + while( cur != NULL ) + { + if( verify_header( cur ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of header " + "failed\n" ); +#endif + return( 1 ); + } + + if( cur->prev != prv ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "cur->prev != prv\n" ); +#endif + return( 1 ); + } + + prv = cur; + cur = cur->next; + } + + return( 0 ); +} + +static void *buffer_alloc_calloc( size_t n, size_t size ) +{ + memory_header *new, *cur = heap.first_free; + unsigned char *p; + void *ret; + size_t original_len, len; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + void *trace_buffer[MAX_BT]; + size_t trace_cnt; +#endif + + if( heap.buf == NULL || heap.first == NULL ) + return( NULL ); + + original_len = len = n * size; + + if( n != 0 && len / n != size ) + return( NULL ); + + if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + // Find block that fits + // + while( cur != NULL ) + { + if( cur->size >= len ) + break; + + cur = cur->next_free; + } + + if( cur == NULL ) + return( NULL ); + + if( cur->alloc != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.alloc_count++; +#endif + + // Found location, split block if > memory_header + 4 room left + // + if( cur->size - len < sizeof(memory_header) + + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + cur->alloc = 1; + + // Remove from free_list + // + if( cur->prev_free != NULL ) + cur->prev_free->next_free = cur->next_free; + else + heap.first_free = cur->next_free; + + if( cur->next_free != NULL ) + cur->next_free->prev_free = cur->prev_free; + + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); + } + + p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; + new = (memory_header *) p; + + new->size = cur->size - len - sizeof(memory_header); + new->alloc = 0; + new->prev = cur; + new->next = cur->next; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + new->trace = NULL; + new->trace_count = 0; +#endif + new->magic1 = MAGIC1; + new->magic2 = MAGIC2; + + if( new->next != NULL ) + new->next->prev = new; + + // Replace cur with new in free_list + // + new->prev_free = cur->prev_free; + new->next_free = cur->next_free; + if( new->prev_free != NULL ) + new->prev_free->next_free = new; + else + heap.first_free = new; + + if( new->next_free != NULL ) + new->next_free->prev_free = new; + + cur->alloc = 1; + cur->size = len; + cur->next = new; + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count++; + if( heap.header_count > heap.maximum_header_count ) + heap.maximum_header_count = heap.header_count; + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); +} + +static void buffer_alloc_free( void *ptr ) +{ + memory_header *hdr, *old = NULL; + unsigned char *p = (unsigned char *) ptr; + + if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) + return; + + if( p < heap.buf || p > heap.buf + heap.len ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " + "space\n" ); +#endif + mbedtls_exit( 1 ); + } + + p -= sizeof(memory_header); + hdr = (memory_header *) p; + + if( verify_header( hdr ) != 0 ) + mbedtls_exit( 1 ); + + if( hdr->alloc != 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + + hdr->alloc = 0; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.free_count++; + heap.total_used -= hdr->size; +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + free( hdr->trace ); + hdr->trace = NULL; + hdr->trace_count = 0; +#endif + + // Regroup with block before + // + if( hdr->prev != NULL && hdr->prev->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->prev->size += sizeof(memory_header) + hdr->size; + hdr->prev->next = hdr->next; + old = hdr; + hdr = hdr->prev; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Regroup with block after + // + if( hdr->next != NULL && hdr->next->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->size += sizeof(memory_header) + hdr->next->size; + old = hdr->next; + hdr->next = hdr->next->next; + + if( hdr->prev_free != NULL || hdr->next_free != NULL ) + { + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr->next_free; + else + heap.first_free = hdr->next_free; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr->prev_free; + } + + hdr->prev_free = old->prev_free; + hdr->next_free = old->next_free; + + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr; + else + heap.first_free = hdr; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Prepend to free_list if we have not merged + // (Does not have to stay in same order as prev / next list) + // + if( old == NULL ) + { + hdr->next_free = heap.first_free; + if( heap.first_free != NULL ) + heap.first_free->prev_free = hdr; + heap.first_free = hdr; + } + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); +} + +void mbedtls_memory_buffer_set_verify( int verify ) +{ + heap.verify = verify; +} + +int mbedtls_memory_buffer_alloc_verify() +{ + return verify_chain(); +} + +#if defined(MBEDTLS_MEMORY_DEBUG) +void mbedtls_memory_buffer_alloc_status() +{ + mbedtls_fprintf( stderr, + "Current use: %zu blocks / %zu bytes, max: %zu blocks / " + "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", + heap.header_count, heap.total_used, + heap.maximum_header_count, heap.maximum_used, + heap.maximum_header_count * sizeof( memory_header ) + + heap.maximum_used, + heap.alloc_count, heap.free_count ); + + if( heap.first->next == NULL ) + mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + else + { + mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); + debug_chain(); + } +} + +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) +{ + *max_used = heap.maximum_used; + *max_blocks = heap.maximum_header_count; +} + +void mbedtls_memory_buffer_alloc_max_reset( void ) +{ + heap.maximum_used = 0; + heap.maximum_header_count = 0; +} + +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) +{ + *cur_used = heap.total_used; + *cur_blocks = heap.header_count; +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +#if defined(MBEDTLS_THREADING_C) +static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) +{ + void *buf; + if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) + return( NULL ); + buf = buffer_alloc_calloc( n, size ); + if( mbedtls_mutex_unlock( &heap.mutex ) ) + return( NULL ); + return( buf ); +} + +static void buffer_alloc_free_mutexed( void *ptr ) +{ + /* We have to good option here, but corrupting the heap seems + * worse than loosing memory. */ + if( mbedtls_mutex_lock( &heap.mutex ) ) + return; + buffer_alloc_free( ptr ); + (void) mbedtls_mutex_unlock( &heap.mutex ); +} +#endif /* MBEDTLS_THREADING_C */ + +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) +{ + memset( &heap, 0, sizeof(buffer_alloc_ctx) ); + memset( buf, 0, len ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &heap.mutex ); + mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, + buffer_alloc_free_mutexed ); +#else + mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); +#endif + + if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + /* Adjust len first since buf is used in the computation */ + len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + heap.buf = buf; + heap.len = len; + + heap.first = (memory_header *) buf; + heap.first->size = len - sizeof(memory_header); + heap.first->magic1 = MAGIC1; + heap.first->magic2 = MAGIC2; + heap.first_free = heap.first; +} + +void mbedtls_memory_buffer_alloc_free() +{ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &heap.mutex ); +#endif + mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) ); +} + +#if defined(MBEDTLS_SELF_TEST) +static int check_pointer( void *p ) +{ + if( p == NULL ) + return( -1 ); + + if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) + return( -1 ); + + return( 0 ); +} + +static int check_all_free( ) +{ + if( +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used != 0 || +#endif + heap.first != heap.first_free || + (void *) heap.first != (void *) heap.buf ) + { + return( -1 ); + } + + return( 0 ); +} + +#define TEST_ASSERT( condition ) \ + if( ! (condition) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + \ + ret = 1; \ + goto cleanup; \ + } + +int mbedtls_memory_buffer_alloc_self_test( int verbose ) +{ + unsigned char buf[1024]; + unsigned char *p, *q, *r, *end; + int ret = 0; + + if( verbose != 0 ) + mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + /* Memorize end to compare with the next test */ + end = heap.buf + heap.len; + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #2 (buf not aligned): " ); + + mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); + + TEST_ASSERT( heap.buf + heap.len == end ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #3 (full): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); + + TEST_ASSERT( check_pointer( p ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( p ); + + p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); + q = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( q ); + + TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); + + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_memory_buffer_alloc_free( ); + + return( ret ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ diff --git a/external_libs/mbedtls/library/net_sockets.c b/external_libs/mbedtls/library/net_sockets.c new file mode 100644 index 00000000..cc06cbfa --- /dev/null +++ b/external_libs/mbedtls/library/net_sockets.c @@ -0,0 +1,585 @@ +/* + * TCP/IP or UDP/IP networking functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_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; + } + } + + /* I we ever get there, it's a success */ + 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/external_libs/mbedtls/library/oid.c b/external_libs/mbedtls/library/oid.c new file mode 100644 index 00000000..f13826ed --- /dev/null +++ b/external_libs/mbedtls/library/oid.c @@ -0,0 +1,710 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ +static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedtls_asn1_buf *oid ) \ +{ \ + const TYPE_T *p = LIST; \ + const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + *ATTR2 = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, + "uniqueIdentifier", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + MBEDTLS_X509_EXT_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, + MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + MBEDTLS_X509_EXT_NS_CERT_TYPE, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + MBEDTLS_PK_ECKEY, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + MBEDTLS_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, + MBEDTLS_CIPHER_DES_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + MBEDTLS_MD_MD2, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + MBEDTLS_MD_MD4, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%d", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ diff --git a/external_libs/mbedtls/library/padlock.c b/external_libs/mbedtls/library/padlock.c new file mode 100644 index 00000000..b85ff9cd --- /dev/null +++ b/external_libs/mbedtls/library/padlock.c @@ -0,0 +1,170 @@ +/* + * VIA PadLock support functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * This implementation is based on the VIA PadLock Programming Guide: + * + * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ + * programming_guide.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PADLOCK_C) + +#include "mbedtls/padlock.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86) + +/* + * PadLock detection routine + */ +int mbedtls_padlock_has_support( int feature ) +{ + static int flags = -1; + int ebx = 0, edx = 0; + + if( flags == -1 ) + { + asm( "movl %%ebx, %0 \n\t" + "movl $0xC0000000, %%eax \n\t" + "cpuid \n\t" + "cmpl $0xC0000001, %%eax \n\t" + "movl $0, %%edx \n\t" + "jb unsupported \n\t" + "movl $0xC0000001, %%eax \n\t" + "cpuid \n\t" + "unsupported: \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%ebx \n\t" + : "=m" (ebx), "=m" (edx) + : "m" (ebx) + : "eax", "ecx", "edx" ); + + flags = edx; + } + + return( flags & feature ); +} + +/* + * PadLock AES-ECB block en(de)cryption + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int ebx = 0; + uint32_t *rk; + uint32_t *blk; + uint32_t *ctrl; + unsigned char buf[256]; + + rk = ctx->rk; + blk = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( blk, input, 16 ); + + ctrl = blk + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl $1, %%ecx \n\t" + "movl %2, %%edx \n\t" + "movl %3, %%ebx \n\t" + "movl %4, %%esi \n\t" + "movl %4, %%edi \n\t" + ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) + : "memory", "ecx", "edx", "esi", "edi" ); + + memcpy( output, blk, 16 ); + + return( 0 ); +} + +/* + * PadLock AES-CBC buffer en(de)cryption + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ebx = 0; + size_t count; + uint32_t *rk; + uint32_t *iw; + uint32_t *ctrl; + unsigned char buf[256]; + + if( ( (long) input & 15 ) != 0 || + ( (long) output & 15 ) != 0 ) + return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); + + rk = ctx->rk; + iw = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( iw, iv, 16 ); + + ctrl = iw + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); + + count = ( length + 15 ) >> 4; + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl %2, %%ecx \n\t" + "movl %3, %%edx \n\t" + "movl %4, %%ebx \n\t" + "movl %5, %%esi \n\t" + "movl %6, %%edi \n\t" + "movl %7, %%eax \n\t" + ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (count), "m" (ctrl), + "m" (rk), "m" (input), "m" (output), "m" (iw) + : "memory", "eax", "ecx", "edx", "esi", "edi" ); + + memcpy( iv, iw, 16 ); + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86 */ + +#endif /* MBEDTLS_PADLOCK_C */ diff --git a/external_libs/mbedtls/library/pem.c b/external_libs/mbedtls/library/pem.c new file mode 100644 index 00000000..1ee3966e --- /dev/null +++ b/external_libs/mbedtls/library/pem.c @@ -0,0 +1,447 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/md5.h" +#include "mbedtls/cipher.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(MBEDTLS_PEM_PARSE_C) +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( 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( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( 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( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + 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( 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/external_libs/mbedtls/library/pk.c b/external_libs/mbedtls/library/pk.c new file mode 100644 index 00000000..10bd0a58 --- /dev/null +++ b/external_libs/mbedtls/library/pk.c @@ -0,0 +1,374 @@ +/* + * Public Key abstraction layer + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" + +#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 + +/* 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( 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 + } + + /* 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/external_libs/mbedtls/library/pk_wrap.c b/external_libs/mbedtls/library/pk_wrap.c new file mode 100644 index 00000000..712ad483 --- /dev/null +++ b/external_libs/mbedtls/library/pk_wrap.c @@ -0,0 +1,495 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk_internal.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#include + +#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 + +#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( 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 ) +{ + *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; + + *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/external_libs/mbedtls/library/pkcs11.c b/external_libs/mbedtls/library/pkcs11.c new file mode 100644 index 00000000..0ea64252 --- /dev/null +++ b/external_libs/mbedtls/library/pkcs11.c @@ -0,0 +1,240 @@ +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#include "mbedtls/pkcs11.h" + +#if defined(MBEDTLS_PKCS11_C) + +#include "mbedtls/md.h" +#include "mbedtls/oid.h" +#include "mbedtls/x509_crt.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); +} + +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + unsigned char *cert_blob = NULL; + size_t cert_blob_size = 0; + + if( cert == NULL ) + { + ret = 2; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, + &cert_blob_size ) != CKR_OK ) + { + ret = 3; + goto cleanup; + } + + cert_blob = mbedtls_calloc( 1, cert_blob_size ); + if( NULL == cert_blob ) + { + ret = 4; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, + &cert_blob_size ) != CKR_OK ) + { + ret = 5; + goto cleanup; + } + + if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) + { + ret = 6; + goto cleanup; + } + + ret = 0; + +cleanup: + if( NULL != cert_blob ) + mbedtls_free( cert_blob ); + + return( ret ); +} + + +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + mbedtls_x509_crt cert; + + mbedtls_x509_crt_init( &cert ); + + if( priv_key == NULL ) + goto cleanup; + + if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) + goto cleanup; + + priv_key->len = mbedtls_pk_get_len( &cert.pk ); + priv_key->pkcs11h_cert = pkcs11_cert; + + ret = 0; + +cleanup: + mbedtls_x509_crt_free( &cert ); + + return( ret ); +} + +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) +{ + if( NULL != priv_key ) + pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); +} + +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + size_t input_len, output_len; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + output_len = input_len = ctx->len; + + if( input_len < 16 || input_len > output_max_len ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Determine size of output buffer */ + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, NULL, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( output_len > output_max_len ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, output, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + *olen = output_len; + return( 0 ); +} + +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t sig_len = 0, asn_len = 0, oid_size = 0; + unsigned char *p = sig; + const char *oid; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->len; + if( hashlen > sig_len || asn_len > sig_len || + hashlen + asn_len > sig_len ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = hashlen; + } + + memcpy( p, hash, hashlen ); + + if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, + asn_len + hashlen, sig, &sig_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#endif /* defined(MBEDTLS_PKCS11_C) */ diff --git a/external_libs/mbedtls/library/pkcs12.c b/external_libs/mbedtls/library/pkcs12.c new file mode 100644 index 00000000..c603a135 --- /dev/null +++ b/external_libs/mbedtls/library/pkcs12.c @@ -0,0 +1,365 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 + * + * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS12_C) + +#include "mbedtls/pkcs12.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" + +#include + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations ) +{ + int ret; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + + /* + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#define PKCS12_MAX_PWDLEN 128 + +static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + unsigned char *key, size_t keylen, + unsigned char *iv, size_t ivlen ) +{ + int ret, iterations = 0; + mbedtls_asn1_buf salt; + size_t i; + unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; + + if( pwdlen > PKCS12_MAX_PWDLEN ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); + memset( &unipwd, 0, sizeof(unipwd) ); + + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, + &iterations ) ) != 0 ) + return( ret ); + + for( i = 0; i < pwdlen; i++ ) + unipwd[i * 2 + 1] = pwd[i]; + + if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +#undef PKCS12_MAX_PWDLEN + +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ +#if !defined(MBEDTLS_ARC4_C) + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) len); + ((void) output); + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); +#else + int ret; + unsigned char key[16]; + mbedtls_arc4_context ctx; + ((void) mode); + + mbedtls_arc4_init( &ctx ); + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, + pwd, pwdlen, + key, 16, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + mbedtls_arc4_setup( &ctx, key, 16 ); + if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_arc4_free( &ctx ); + + return( ret ); +#endif /* MBEDTLS_ARC4_C */ +} + +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ + int ret, keylen = 0; + unsigned char key[32]; + unsigned char iv[16]; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_cipher_context_t cipher_ctx; + size_t olen = 0; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_bitlen / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + mbedtls_cipher_init( &cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_zeroize( iv, sizeof( iv ) ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, + const unsigned char *filler, size_t fill_len ) +{ + unsigned char *p = data; + size_t use_len; + + while( data_len > 0 ) + { + use_len = ( data_len > fill_len ) ? fill_len : data_len; + memcpy( p, filler, use_len ); + p += use_len; + data_len -= use_len; + } +} + +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t md_type, int id, int iterations ) +{ + int ret; + unsigned int j; + + unsigned char diversifier[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + + size_t hlen, use_len, v, i; + + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + // This version only allows max of 64 bytes of password or salt + if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + mbedtls_md_init( &md_ctx ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + return( ret ); + hlen = mbedtls_md_get_size( md_info ); + + if( hlen <= 32 ) + v = 64; + else + v = 128; + + memset( diversifier, (unsigned char) id, v ); + + pkcs12_fill_buffer( salt_block, v, salt, saltlen ); + pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); + + p = data; + while( datalen > 0 ) + { + // Calculate hash( diversifier || salt_block || pwd_block ) + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) + goto exit; + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for( i = 1; i < (size_t) iterations; i++ ) + { + if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) + goto exit; + } + + use_len = ( datalen > hlen ) ? hlen : datalen; + memcpy( p, hash_output, use_len ); + datalen -= use_len; + p += use_len; + + if( datalen == 0 ) + break; + + // Concatenating copies of hash_output into hash_block (B) + pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); + + // B += 1 + for( i = v; i > 0; i-- ) + if( ++hash_block[i - 1] != 0 ) + break; + + // salt_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = salt_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + salt_block[i - 1] = j & 0xFF; + } + + // pwd_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = pwd_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + pwd_block[i - 1] = j & 0xFF; + } + } + + ret = 0; + +exit: + mbedtls_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_zeroize( hash_output, sizeof( hash_output ) ); + + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PKCS12_C */ diff --git a/external_libs/mbedtls/library/pkcs5.c b/external_libs/mbedtls/library/pkcs5.c new file mode 100644 index 00000000..e28d5a84 --- /dev/null +++ b/external_libs/mbedtls/library/pkcs5.c @@ -0,0 +1,406 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS5_C) + +#include "mbedtls/pkcs5.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations, + int *keylen, mbedtls_md_type_t *md_type ) +{ + int ret; + mbedtls_asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + salt->p = p; + p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_HMAC_SHA1, &prf_alg_oid ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + *md_type = MBEDTLS_MD_SHA1; + + if( p != end ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + int ret, iterations = 0, keylen = 0; + unsigned char *p, *end; + mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + mbedtls_asn1_buf salt; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const mbedtls_md_info_t *md_info; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_md_context_t md_ctx; + mbedtls_cipher_type_t cipher_alg; + mbedtls_cipher_context_t cipher_ctx; + + p = pbe_params->p; + end = p + pbe_params->len; + + /* + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} + * } + */ + if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + // Only PBKDF2 supported at the moment + // + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + /* + * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored + * since it is optional and we don't know if it was set or not + */ + keylen = cipher_info->key_bitlen / 8; + + if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); + } + + mbedtls_md_init( &md_ctx ); + mbedtls_cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + mbedtls_md_free( &md_ctx ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + int ret, j; + unsigned int i; + unsigned char md1[MBEDTLS_MD_MAX_SIZE]; + unsigned char work[MBEDTLS_MD_MAX_SIZE]; + unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4]; + + memset( counter, 0, 4 ); + counter[3] = 1; + + if( iteration_count > 0xFFFFFFFF ) + return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); + + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) + return( ret ); + + memcpy( md1, work, md_size ); + + for( i = 1; i < iteration_count; i++ ) + { + // U2 ends up in md1 + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) + return( ret ); + + // U1 xor U2 + // + for( j = 0; j < md_size; j++ ) + work[j] ^= md1[j]; + } + + use_len = ( key_length < md_size ) ? key_length : md_size; + memcpy( out_p, work, use_len ); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for( i = 4; i > 0; i-- ) + if( ++counter[i - 1] != 0 ) + break; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +int mbedtls_pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); + + return( 0 ); +} +#else + +#define MAX_TESTS 6 + +static const size_t plen[MAX_TESTS] = + { 8, 8, 8, 24, 9 }; + +static const unsigned char password[MAX_TESTS][32] = +{ + "password", + "password", + "password", + "passwordPASSWORDpassword", + "pass\0word", +}; + +static const size_t slen[MAX_TESTS] = + { 4, 4, 4, 36, 5 }; + +static const unsigned char salt[MAX_TESTS][40] = +{ + "salt", + "salt", + "salt", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + "sa\0lt", +}; + +static const uint32_t it_cnt[MAX_TESTS] = + { 1, 2, 4096, 4096, 4096 }; + +static const uint32_t key_len[MAX_TESTS] = + { 20, 20, 20, 25, 16 }; + +static const unsigned char result_key[MAX_TESTS][32] = +{ + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 }, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 }, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 }, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, +}; + +int mbedtls_pkcs5_self_test( int verbose ) +{ + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + mbedtls_md_init( &sha1_ctx ); + + info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], + slen[i], it_cnt[i], key_len[i], key ); + if( ret != 0 || + memcmp( result_key[i], key, key_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_md_free( &sha1_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_SHA1_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_PKCS5_C */ diff --git a/external_libs/mbedtls/library/pkparse.c b/external_libs/mbedtls/library/pkparse.c new file mode 100644 index 00000000..275429e6 --- /dev/null +++ b/external_libs/mbedtls/library/pkparse.c @@ -0,0 +1,1293 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_FS_IO) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + mbedtls_free( *buf ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) +{ + int ret; + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init( &ref ); + + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) +{ + int ret; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) +{ + int ret; + + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + rsa->len = mbedtls_mpi_size( &rsa->N ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) +{ + int ret; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); +} + +#if defined(MBEDTLS_RSA_C) +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( rsa->ver != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) + { + mbedtls_rsa_free( rsa ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + rsa->len = mbedtls_mpi_size( &rsa->N ); + + if( p != end ) + { + mbedtls_rsa_free( rsa ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 ) + { + mbedtls_rsa_free( rsa ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( p + len != end2 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + /* + * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char buf[2048]; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + + memset( buf, 0, sizeof( buf ) ); + + p = (unsigned char *) key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivatKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len > sizeof( buf ) ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* + * Decrypt EncryptedData with appropriate PDE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, + MBEDTLS_PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + // + if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + const mbedtls_pk_info_t *pk_info; + +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + + if( ret == 0 ) + { + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) ret); + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, + pwd, pwdlen ) ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_ECP_C */ + + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char *p; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + key = pem.buf; + keylen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_PEM_PARSE_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/external_libs/mbedtls/library/pkwrite.c b/external_libs/mbedtls/library/pkwrite.c new file mode 100644 index 00000000..83b798c1 --- /dev/null +++ b/external_libs/mbedtls/library/pkwrite.c @@ -0,0 +1,439 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->E ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->N ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_ECP_C */ + +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ) +{ + int ret; + size_t len = 0; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + const char *oid; + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ), + &oid, &oid_len ) ) != 0 ) + { + return( ret ); + } + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); + } +#endif + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c = buf + size; + size_t len = 0; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey: write as MPI then fix tag */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) ); + *c = MBEDTLS_ASN1_OCTET_STRING; + + /* version */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(MBEDTLS_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" + +/* + * Max sizes of key per types. Shown as tag + len (+ content). + */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSA public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 9 (rsa oid) + * + 1 + 1 (params null) + * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) + * RSAPublicKey ::= SEQUENCE { 1 + 3 + * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 + * } + */ +#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE + +/* + * RSA private keys: + * RSAPrivateKey ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * modulus INTEGER, 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) + * } + */ +#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 +#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 + +#else /* MBEDTLS_RSA_C */ + +#define RSA_PUB_DER_MAX_BYTES 0 +#define RSA_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 7 (ec oid) + * + 1 + 1 + 9 (namedCurve oid) + * subjectPublicKey BIT STRING 1 + 2 + 1 [1] + * + 1 (point format) [1] + * + 2 * ECP_MAX (coords) [1] + * } + */ +#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES + +/* + * EC private keys: + * ECPrivateKey ::= SEQUENCE { 1 + 2 + * version INTEGER , 1 + 1 + 1 + * privateKey OCTET STRING, 1 + 1 + ECP_MAX + * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) + * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above + * } + */ +#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES + +#else /* MBEDTLS_ECP_C */ + +#define ECP_PUB_DER_MAX_BYTES 0 +#define ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_ECP_C */ + +#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES +#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES + +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[PUB_DER_MAX_BYTES]; + size_t olen = 0; + + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[PRV_DER_MAX_BYTES]; + const char *begin, *end; + size_t olen = 0; + + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/external_libs/mbedtls/library/platform.c b/external_libs/mbedtls/library/platform.c new file mode 100644 index 00000000..2591c45d --- /dev/null +++ b/external_libs/mbedtls/library/platform.c @@ -0,0 +1,307 @@ +/* + * Platform abstraction layer + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc = calloc_func; + mbedtls_free = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY */ + +#if defined(_WIN32) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret; + va_list argp; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + + va_start( argp, fmt ); +#if defined(_TRUNCATE) + ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); +#else + ret = _vsnprintf( s, n, fmt, argp ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return -1; + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( 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( 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/external_libs/mbedtls/library/ripemd160.c b/external_libs/mbedtls/library/ripemd160.c new file mode 100644 index 00000000..cdb0a63c --- /dev/null +++ b/external_libs/mbedtls/library/ripemd160.c @@ -0,0 +1,467 @@ +/* + * RIPE MD-160 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + +#include "mbedtls/ripemd160.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ) +{ + *dst = *src; +} + +/* + * RIPEMD-160 context setup + */ +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned char data[64] ) +{ + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + + A = Ap = ctx->state[0]; + B = Bp = ctx->state[1]; + C = Cp = ctx->state[2]; + D = Dp = ctx->state[3]; + E = Ep = ctx->state[4]; + +#define F1( x, y, z ) ( x ^ y ^ z ) +#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) ) +#define F3( x, y, z ) ( ( x | ~y ) ^ z ) +#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) ) +#define F5( x, y, z ) ( x ^ ( y | ~z ) ) + +#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + a += f( b, c, d ) + X[r] + k; \ + a = S( a, s ) + e; \ + c = S( c, 10 ); + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + P( a, b, c, d, e, r, s, F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp ); + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( A, B, C, D, E, 0, 11, 5, 8 ); + P2( E, A, B, C, D, 1, 14, 14, 9 ); + P2( D, E, A, B, C, 2, 15, 7, 9 ); + P2( C, D, E, A, B, 3, 12, 0, 11 ); + P2( B, C, D, E, A, 4, 5, 9, 13 ); + P2( A, B, C, D, E, 5, 8, 2, 15 ); + P2( E, A, B, C, D, 6, 7, 11, 15 ); + P2( D, E, A, B, C, 7, 9, 4, 5 ); + P2( C, D, E, A, B, 8, 11, 13, 7 ); + P2( B, C, D, E, A, 9, 13, 6, 7 ); + P2( A, B, C, D, E, 10, 14, 15, 8 ); + P2( E, A, B, C, D, 11, 15, 8, 11 ); + P2( D, E, A, B, C, 12, 6, 1, 14 ); + P2( C, D, E, A, B, 13, 7, 10, 14 ); + P2( B, C, D, E, A, 14, 9, 3, 12 ); + P2( A, B, C, D, E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( E, A, B, C, D, 7, 7, 6, 9 ); + P2( D, E, A, B, C, 4, 6, 11, 13 ); + P2( C, D, E, A, B, 13, 8, 3, 15 ); + P2( B, C, D, E, A, 1, 13, 7, 7 ); + P2( A, B, C, D, E, 10, 11, 0, 12 ); + P2( E, A, B, C, D, 6, 9, 13, 8 ); + P2( D, E, A, B, C, 15, 7, 5, 9 ); + P2( C, D, E, A, B, 3, 15, 10, 11 ); + P2( B, C, D, E, A, 12, 7, 14, 7 ); + P2( A, B, C, D, E, 0, 12, 15, 7 ); + P2( E, A, B, C, D, 9, 15, 8, 12 ); + P2( D, E, A, B, C, 5, 9, 12, 7 ); + P2( C, D, E, A, B, 2, 11, 4, 6 ); + P2( B, C, D, E, A, 14, 7, 9, 15 ); + P2( A, B, C, D, E, 11, 13, 1, 13 ); + P2( E, A, B, C, D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( D, E, A, B, C, 3, 11, 15, 9 ); + P2( C, D, E, A, B, 10, 13, 5, 7 ); + P2( B, C, D, E, A, 14, 6, 1, 15 ); + P2( A, B, C, D, E, 4, 7, 3, 11 ); + P2( E, A, B, C, D, 9, 14, 7, 8 ); + P2( D, E, A, B, C, 15, 9, 14, 6 ); + P2( C, D, E, A, B, 8, 13, 6, 6 ); + P2( B, C, D, E, A, 1, 15, 9, 14 ); + P2( A, B, C, D, E, 2, 14, 11, 12 ); + P2( E, A, B, C, D, 7, 8, 8, 13 ); + P2( D, E, A, B, C, 0, 13, 12, 5 ); + P2( C, D, E, A, B, 6, 6, 2, 14 ); + P2( B, C, D, E, A, 13, 5, 10, 13 ); + P2( A, B, C, D, E, 11, 12, 0, 13 ); + P2( E, A, B, C, D, 5, 7, 4, 7 ); + P2( D, E, A, B, C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( C, D, E, A, B, 1, 11, 8, 15 ); + P2( B, C, D, E, A, 9, 12, 6, 5 ); + P2( A, B, C, D, E, 11, 14, 4, 8 ); + P2( E, A, B, C, D, 10, 15, 1, 11 ); + P2( D, E, A, B, C, 0, 14, 3, 14 ); + P2( C, D, E, A, B, 8, 15, 11, 14 ); + P2( B, C, D, E, A, 12, 9, 15, 6 ); + P2( A, B, C, D, E, 4, 8, 0, 14 ); + P2( E, A, B, C, D, 13, 9, 5, 6 ); + P2( D, E, A, B, C, 3, 14, 12, 9 ); + P2( C, D, E, A, B, 7, 5, 2, 12 ); + P2( B, C, D, E, A, 15, 6, 13, 9 ); + P2( A, B, C, D, E, 14, 8, 9, 12 ); + P2( E, A, B, C, D, 5, 6, 7, 5 ); + P2( D, E, A, B, C, 6, 5, 10, 15 ); + P2( C, D, E, A, B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( B, C, D, E, A, 4, 9, 12, 8 ); + P2( A, B, C, D, E, 0, 15, 15, 5 ); + P2( E, A, B, C, D, 5, 5, 10, 12 ); + P2( D, E, A, B, C, 9, 11, 4, 9 ); + P2( C, D, E, A, B, 7, 6, 1, 12 ); + P2( B, C, D, E, A, 12, 8, 5, 5 ); + P2( A, B, C, D, E, 2, 13, 8, 14 ); + P2( E, A, B, C, D, 10, 12, 7, 6 ); + P2( D, E, A, B, C, 14, 5, 6, 8 ); + P2( C, D, E, A, B, 1, 12, 2, 13 ); + P2( B, C, D, E, A, 3, 13, 13, 6 ); + P2( A, B, C, D, E, 8, 14, 14, 5 ); + P2( E, A, B, C, D, 11, 11, 0, 15 ); + P2( D, E, A, B, C, 6, 8, 3, 13 ); + P2( C, D, E, A, B, 15, 5, 9, 11 ); + P2( B, C, D, E, A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + C = ctx->state[1] + C + Dp; + ctx->state[1] = ctx->state[2] + D + Ep; + ctx->state[2] = ctx->state[3] + E + Ap; + ctx->state[3] = ctx->state[4] + A + Bp; + ctx->state[4] = ctx->state[0] + B + Cp; + ctx->state[0] = C; +} +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + mbedtls_ripemd160_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_ripemd160_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } +} + +static const unsigned char ripemd160_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + mbedtls_ripemd160_update( ctx, ripemd160_padding, padn ); + mbedtls_ripemd160_update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_UINT32_LE( ctx->state[4], output, 16 ); +} + +/* + * output = RIPEMD-160( input buffer ) + */ +void mbedtls_ripemd160( const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + mbedtls_ripemd160_context ctx; + + mbedtls_ripemd160_init( &ctx ); + mbedtls_ripemd160_starts( &ctx ); + mbedtls_ripemd160_update( &ctx, input, ilen ); + mbedtls_ripemd160_finish( &ctx, output ); + mbedtls_ripemd160_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC + */ +#define TESTS 8 +#define KEYS 2 +static const char *ripemd160_test_input[TESTS] = +{ + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", +}; + +static const unsigned char ripemd160_test_md[TESTS][20] = +{ + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, + { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, + { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, +}; + +/* + * Checkup routine + */ +int mbedtls_ripemd160_self_test( int verbose ) +{ + int i; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + mbedtls_ripemd160( (const unsigned char *) ripemd160_test_input[i], + strlen( ripemd160_test_input[i] ), + output ); + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RIPEMD160_C */ diff --git a/external_libs/mbedtls/library/rsa.c b/external_libs/mbedtls/library/rsa.c new file mode 100644 index 00000000..40ef2a94 --- /dev/null +++ b/external_libs/mbedtls/library/rsa.c @@ -0,0 +1,1730 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + */ + +#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 + +/* + * 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 ); +} + +/* + * 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; + + /* 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 ); + +#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 ) ); + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->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, &ctx->DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, &ctx->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 ); + + 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; + } +} +#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 ) + return( ret ); + + /* + * 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 ); + return( ret ); + } + + + /* 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 ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( ilen - ( p - buf ) > output_max_len ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} +#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 ) + return( ret ); + + 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 ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( ilen - ( p - buf ) > output_max_len ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} +#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 ); + 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 ); + + /* 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/external_libs/mbedtls/library/sha1.c b/external_libs/mbedtls/library/sha1.c new file mode 100644 index 00000000..2ccf2a2f --- /dev/null +++ b/external_libs/mbedtls/library/sha1.c @@ -0,0 +1,448 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA1_C) + +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA1_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + *dst = *src; +} + +/* + * SHA-1 context setup + */ +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp, W[16], A, B, C, D, E; + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ + W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + mbedtls_sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + mbedtls_sha1_update( ctx, sha1_padding, padn ); + mbedtls_sha1_update( ctx, msglen, 8 ); + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); +} + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +{ + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + mbedtls_sha1_starts( &ctx ); + mbedtls_sha1_update( &ctx, input, ilen ); + mbedtls_sha1_finish( &ctx, output ); + mbedtls_sha1_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); + + mbedtls_sha1_starts( &ctx ); + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + mbedtls_sha1_update( &ctx, buf, buflen ); + } + else + mbedtls_sha1_update( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + + mbedtls_sha1_finish( &ctx, sha1sum ); + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ diff --git a/external_libs/mbedtls/library/sha256.c b/external_libs/mbedtls/library/sha256.c new file mode 100644 index 00000000..ad25d383 --- /dev/null +++ b/external_libs/mbedtls/library/sha256.c @@ -0,0 +1,458 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA256_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + *dst = *src; +} + +/* + * SHA-256 context setup + */ +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; +} + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + unsigned int i; + + for( i = 0; i < 8; i++ ) + A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + GET_UINT32_BE( W[i], data, 4 * i ); + else + R( i ); + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + GET_UINT32_BE( W[i], data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; +} +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + mbedtls_sha256_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_sha256_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha256_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-256 final digest + */ +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + mbedtls_sha256_update( ctx, sha256_padding, padn ); + mbedtls_sha256_update( ctx, msglen, 8 ); + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); +} + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +void mbedtls_sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + mbedtls_sha256_context ctx; + + mbedtls_sha256_init( &ctx ); + mbedtls_sha256_starts( &ctx, is224 ); + mbedtls_sha256_update( &ctx, input, ilen ); + mbedtls_sha256_finish( &ctx, output ); + mbedtls_sha256_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + mbedtls_sha256_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + mbedtls_sha256_update( &ctx, buf, buflen ); + } + else + mbedtls_sha256_update( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + + mbedtls_sha256_finish( &ctx, sha256sum ); + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/external_libs/mbedtls/library/sha512.c b/external_libs/mbedtls/library/sha512.c new file mode 100644 index 00000000..724522ac --- /dev/null +++ b/external_libs/mbedtls/library/sha512.c @@ -0,0 +1,514 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA512_C) + +#include "mbedtls/sha512.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA512_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + *dst = *src; +} + +/* + * SHA-512 context setup + */ +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); + } + + ctx->is384 = is384; +} + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A, B, C, D, E, F, G, H; + +#define SHR(x,n) (x >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + i = 0; + + do + { + P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; + P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; + P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; + P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; + P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; + P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; + P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; + P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; + } + while( i < 80 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + unsigned int left; + + if( ilen == 0 ) + return; + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + mbedtls_sha512_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + mbedtls_sha512_process( ctx, input ); + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha512_padding[128] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-512 final digest + */ +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ) +{ + size_t last, padn; + uint64_t high, low; + unsigned char msglen[16]; + + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, msglen, 0 ); + PUT_UINT64_BE( low, msglen, 8 ); + + last = (size_t)( ctx->total[0] & 0x7F ); + padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); + + mbedtls_sha512_update( ctx, sha512_padding, padn ); + mbedtls_sha512_update( ctx, msglen, 16 ); + + PUT_UINT64_BE( ctx->state[0], output, 0 ); + PUT_UINT64_BE( ctx->state[1], output, 8 ); + PUT_UINT64_BE( ctx->state[2], output, 16 ); + PUT_UINT64_BE( ctx->state[3], output, 24 ); + PUT_UINT64_BE( ctx->state[4], output, 32 ); + PUT_UINT64_BE( ctx->state[5], output, 40 ); + + if( ctx->is384 == 0 ) + { + PUT_UINT64_BE( ctx->state[6], output, 48 ); + PUT_UINT64_BE( ctx->state[7], output, 56 ); + } +} + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +void mbedtls_sha512( const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ) +{ + mbedtls_sha512_context ctx; + + mbedtls_sha512_init( &ctx ); + mbedtls_sha512_starts( &ctx, is384 ); + mbedtls_sha512_update( &ctx, input, ilen ); + mbedtls_sha512_finish( &ctx, output ); + mbedtls_sha512_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const int sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[6][64] = +{ + /* + * SHA-384 test vectors + */ + { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, + { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, + + /* + * SHA-512 test vectors + */ + { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, + { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha512_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + mbedtls_sha512_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + mbedtls_sha512_update( &ctx, buf, buflen ); + } + else + mbedtls_sha512_update( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + + mbedtls_sha512_finish( &ctx, sha512sum ); + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ diff --git a/external_libs/mbedtls/library/ssl_cache.c b/external_libs/mbedtls/library/ssl_cache.c new file mode 100644 index 00000000..9b62de2d --- /dev/null +++ b/external_libs/mbedtls/library/ssl_cache.c @@ -0,0 +1,326 @@ +/* + * SSL session cache implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_CACHE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cache.h" + +#include + +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); + + cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &cache->mutex ); +#endif +} + +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ); +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *entry; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - entry->timestamp ) > cache->timeout ) + continue; +#endif + + if( session->ciphersuite != entry->session.ciphersuite || + session->compression != entry->session.compression || + session->id_len != entry->session.id_len ) + continue; + + if( memcmp( session->id, entry->session.id, + entry->session.id_len ) != 0 ) + continue; + + memcpy( session->master, entry->session.master, 48 ); + + session->verify_result = entry->session.verify_result; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Restore peer certificate (without rest of the original chain) + */ + if( entry->peer_cert.p != NULL ) + { + if( ( session->peer_cert = mbedtls_calloc( 1, + sizeof(mbedtls_x509_crt) ) ) == NULL ) + { + ret = 1; + goto exit; + } + + mbedtls_x509_crt_init( session->peer_cert ); + if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, + entry->peer_cert.len ) != 0 ) + { + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + ret = 1; + goto exit; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = 0; + goto exit; + } + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = time( NULL ), oldest = 0; + mbedtls_ssl_cache_entry *old = NULL; +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *prv; + int count = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + count++; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + cur->timestamp = t; + break; /* expired, reuse this slot, update timestamp */ + } +#endif + + if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + +#if defined(MBEDTLS_HAVE_TIME) + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } +#endif + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { +#if defined(MBEDTLS_HAVE_TIME) + /* + * Reuse oldest entry if max_entries reached + */ + if( count >= cache->max_entries ) + { + if( old == NULL ) + { + ret = 1; + goto exit; + } + + cur = old; + } +#else /* MBEDTLS_HAVE_TIME */ + /* + * Reuse first entry in chain if max_entries reached, + * but move to last place + */ + if( count >= cache->max_entries ) + { + if( cache->chain == NULL ) + { + ret = 1; + goto exit; + } + + cur = cache->chain; + cache->chain = cur->next; + cur->next = NULL; + prv->next = cur; + } +#endif /* MBEDTLS_HAVE_TIME */ + else + { + /* + * max_entries not reached, create new entry + */ + cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); + if( cur == NULL ) + { + ret = 1; + goto exit; + } + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur->timestamp = t; +#endif + } + + memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + mbedtls_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); + } + + /* + * Store peer certificate + */ + if( session->peer_cert != NULL ) + { + cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len ); + if( cur->peer_cert.p == NULL ) + { + ret = 1; + goto exit; + } + + memcpy( cur->peer_cert.p, session->peer_cert->raw.p, + session->peer_cert->raw.len ); + cur->peer_cert.len = session->peer_cert->raw.len; + + cur->session.peer_cert = NULL; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +#if defined(MBEDTLS_HAVE_TIME) +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* MBEDTLS_HAVE_TIME */ + +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) +{ + mbedtls_ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + mbedtls_ssl_session_free( &prv->session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_free( prv->peer_cert.p ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + mbedtls_free( prv ); + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &cache->mutex ); +#endif +} + +#endif /* MBEDTLS_SSL_CACHE_C */ diff --git a/external_libs/mbedtls/library/ssl_ciphersuites.c b/external_libs/mbedtls/library/ssl_ciphersuites.c new file mode 100644 index 00000000..a762bf7c --- /dev/null +++ b/external_libs/mbedtls/library/ssl_ciphersuites.c @@ -0,0 +1,1857 @@ +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for mbed TLS + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except rc4, weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK + * 2. By key length and cipher: + * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(MBEDTLS_SSL_CIPHERSUITES) + MBEDTLS_SSL_CIPHERSUITES, +#else + /* All AES-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All AES-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All remaining >= 128-bit ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + + /* The PSK ephemeral suites */ + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, + + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The ECJPAKE suite */ + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + + /* All AES-256 suites */ + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All AES-128 suites */ + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All remaining >= 128-bit suites */ + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + + /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, + + MBEDTLS_TLS_RSA_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_WITH_NULL_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_PSK_WITH_NULL_SHA, + +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + 0 +}; + +static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ + + { 0, "", + MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(MBEDTLS_SSL_CIPHERSUITES) +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 ) +#else + if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL ) +#endif + *(q++) = *p; + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +} +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( MBEDTLS_PK_ECKEY ); + + default: + return( MBEDTLS_PK_NONE ); + } +} +#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/external_libs/mbedtls/library/ssl_cli.c b/external_libs/mbedtls/library/ssl_cli.c new file mode 100644 index 00000000..223823b3 --- /dev/null +++ b/external_libs/mbedtls/library/ssl_cli.c @@ -0,0 +1,3405 @@ +/* + * SSLv3/TLSv1 client-side functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t hostname_len; + + *olen = 0; + + if( ssl->hostname == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + hostname_len = strlen( ssl->hostname ); + + if( end < p || (size_t)( end - p ) < hostname_len + 9 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len ) & 0xFF ); + + memcpy( p, ssl->hostname, hostname_len ); + + *olen = hostname_len + 9; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); + + if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Secure renegotiation + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; + *p++ = ssl->verify_data_len & 0xFF; + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t sig_alg_len = 0; + const int *md; +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + } + + if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ + sig_alg_len = 0; + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; +#endif + } + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); + + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); + + *olen = 6 + sig_alg_len; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *grp_id; +#else + ((void) ssl); +#endif + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); + +#if defined(MBEDTLS_ECP_C) + for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) + { + 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/external_libs/mbedtls/library/ssl_cookie.c b/external_libs/mbedtls/library/ssl_cookie.c new file mode 100644 index 00000000..9fb32de7 --- /dev/null +++ b/external_libs/mbedtls/library/ssl_cookie.c @@ -0,0 +1,260 @@ +/* + * DTLS cookie callbacks implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/ssl_internal.h" + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is + * available. Try SHA-256 first, 512 wastes resources since we need to stay + * with max 32 bytes of cookie for DTLS 1.0 + */ +#if defined(MBEDTLS_SHA256_C) +#define COOKIE_MD MBEDTLS_MD_SHA224 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA512_C) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA1_C) +#define COOKIE_MD MBEDTLS_MD_SHA1 +#define COOKIE_MD_OUTLEN 20 +#define COOKIE_HMAC_LEN 20 +#else +#error "DTLS hello verify needs SHA-1 or SHA-2" +#endif + +/* + * Cookies are formed of a 4-bytes timestamp (or serial number) and + * an HMAC of timestemp and client ID. + */ +#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) + +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_init( &ctx->hmac_ctx ); +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) +{ + ctx->timeout = delay; +} + +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_free( &ctx->hmac_ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &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/external_libs/mbedtls/library/ssl_srv.c b/external_libs/mbedtls/library/ssl_srv.c new file mode 100644 index 00000000..fc0d2d7b --- /dev/null +++ b/external_libs/mbedtls/library/ssl_srv.c @@ -0,0 +1,3926 @@ +/* + * SSLv3/TLSv1 server-side functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ) +{ + if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + mbedtls_free( ssl->cli_id ); + + if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->cli_id, info, ilen ); + ssl->cli_id_len = ilen; + + return( 0 ); +} + +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ) +{ + conf->f_cookie_write = f_cookie_write; + conf->f_cookie_check = f_cookie_check; + conf->p_cookie = p_cookie; +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( servername_list_size > 0 ) + { + hostname_len = ( ( p[1] << 8 ) | p[2] ); + if( hostname_len + 3 > servername_list_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl->conf->f_sni( ssl->conf->p_sni, + ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + 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 || + buf[0] != ssl->verify_data_len || + mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t sig_alg_list_size; + const unsigned char *p; + const unsigned char *end = buf + len; + const int *md_cur; + + + sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( sig_alg_list_size + 2 != len || + sig_alg_list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * For now, ignore the SignatureAlgorithm part and rely on offered + * ciphersuites only for that part. To be fixed later. + * + * So, just look at the HashAlgorithm part. + */ + for( md_cur = ssl->conf->sig_hashes; *md_cur != MBEDTLS_MD_NONE; md_cur++ ) { + for( p = buf + 2; p < end; p += 2 ) { + if( *md_cur == (int) mbedtls_ssl_md_alg_from_hash( p[0] ) ) { + ssl->handshake->sig_alg = p[0]; + goto have_sig_alg; + } + } + } + + /* Some key echanges do not need signatures at all */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no signature_algorithm in common" ) ); + return( 0 ); + +have_sig_alg: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + ssl->handshake->sig_alg ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const mbedtls_ecp_curve_info *curve_info, **curves; + + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Should never happen unless client duplicates the extension */ + if( ssl->handshake->curves != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Don't allow our peer to make us allocate too much memory, + * and leave room for a final 0 */ + our_size = list_size / 2 + 1; + if( our_size > MBEDTLS_ECP_DP_MAX ) + our_size = MBEDTLS_ECP_DP_MAX; + + if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); + + if( curve_info != NULL ) + { + *curves++ = curve_info; + our_size--; + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + return( ret ); + } + + /* Only mark the extension as OK when we're sure it is */ + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret; + mbedtls_ssl_session session; + + mbedtls_ssl_session_init( &session ); + + if( ssl->conf->f_ticket_parse == NULL || + ssl->conf->f_ticket_write == NULL ) + { + return( 0 ); + } + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); + + if( len == 0 ) + return( 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, + buf, len ) ) != 0 ) + { + mbedtls_ssl_session_free( &session ); + + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); + else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); + else + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); + + return( 0 ); + } + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform them we're accepting the ticket (RFC 5077 section 3.4) + */ + session.id_len = ssl->session_negotiate->id_len; + memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); + + mbedtls_ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); + + ssl->handshake->resume = 1; + + /* Don't send a new ticket after all, this one is OK */ + ssl->handshake->new_session_ticket = 0; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, cur_len, ours_len; + const unsigned char *theirs, *start, *end; + const char **ours; + + /* If ALPN not configured, just ignore the extension */ + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + /* + * Use our order of preference + */ + start = buf + 2; + end = buf + len; + for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) + { + ours_len = strlen( *ours ); + for( theirs = start; theirs != end; theirs += cur_len ) + { + /* If the list is well formed, we should get equality first */ + if( theirs > end ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cur_len = *theirs++; + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( cur_len == ours_len && + memcmp( theirs, *ours, cur_len ) == 0 ) + { + ssl->alpn_chosen = *ours; + return( 0 ); + } + } + } + + /* If we get there, no match was found */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise + */ +#if defined(MBEDTLS_ECDSA_C) +static int ssl_check_key_curve( mbedtls_pk_context *pk, + const mbedtls_ecp_curve_info **curves ) +{ + const mbedtls_ecp_curve_info **crv = curves; + mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 0 ); + crv++; + } + + return( -1 ); +} +#endif /* MBEDTLS_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +static int ssl_pick_cert( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) +{ + mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; + mbedtls_pk_type_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + uint32_t flags; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->conf->key_cert; + + if( pk_alg == MBEDTLS_PK_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); + + if( list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); + return( -1 ); + } + + for( cur = list; cur != NULL; cur = cur->next ) + { + MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", + cur->cert ); + + if( ! mbedtls_pk_can_do( cur->key, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); + continue; + } + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + * + * It also allows the user to provision different certificates for + * different uses based on keyUsage, eg if they want to avoid signing + * and decrypting with the same RSA key. + */ + if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, + MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " + "(extended) key usage extension" ) ); + continue; + } + +#if defined(MBEDTLS_ECDSA_C) + if( pk_alg == MBEDTLS_PK_ECDSA && + ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); + continue; + } +#endif + + /* + * Try to select a SHA-1 certificate for pre-1.2 clients, but still + * present them a SHA-higher cert rather than failing if it's the only + * one we got that satisfies the other conditions. + */ + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && + cur->cert->sig_md != MBEDTLS_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " + "sha-2 with pre-TLS 1.2 client" ) ); + continue; + } + } + + /* If we get there, we got a winner */ + break; + } + + if( cur == NULL ) + cur = fallback; + + /* Do not update ssl->handshake->key_cert unless there is a match */ + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", + ssl->handshake->key_cert->cert ); + return( 0 ); + } + + return( -1 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, + const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) +{ + const mbedtls_ssl_ciphersuite_t *suite_info; + + suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) ); + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 0 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " + "not configured or ext missing" ) ); + return( 0 ); + } +#endif + + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no common elliptic curve" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl->conf->f_psk == NULL && + ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || + ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no suitable certificate" ) ); + return( 0 ); + } +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len, chal_len; + unsigned char *buf, *p; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); + + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + buf = ssl->in_hdr; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", + buf[2] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", + ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", + buf[3], buf[4] ) ); + + /* + * SSLv2 Client Hello + * + * Record layer: + * 0 . 1 message length + * + * SSL layer: + * 2 . 2 message type + * 3 . 4 protocol version + */ + if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || + buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; + + if( n < 17 || n > 512 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) + ? buf[4] : ssl->conf->max_minor_ver; + + if( ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + ssl->handshake->max_major_ver = buf[3]; + ssl->handshake->max_minor_ver = buf[4]; + + if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->handshake->update_checksum( ssl, buf + 2, n ); + + buf = ssl->in_msg; + n = ssl->in_left - 5; + + /* + * 0 . 1 ciphersuitelist length + * 2 . 3 session id length + * 4 . 5 challenge length + * 6 . .. ciphersuitelist + * .. . .. session id + * .. . .. challenge + */ + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + ciph_len = ( buf[0] << 8 ) | buf[1]; + sess_len = ( buf[2] << 8 ) | buf[3]; + chal_len = ( buf[4] << 8 ) | buf[5]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", + ciph_len, sess_len, chal_len ) ); + + /* + * Make sure each parameter length is valid + */ + if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( sess_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( chal_len < 8 || chal_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( n != 6 + ciph_len + sess_len + chal_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 6, ciph_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 6 + ciph_len, sess_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", + buf + 6 + ciph_len + sess_len, chal_len ); + + p = buf + 6 + ciph_len; + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); + + p += sess_len; + memset( ssl->handshake->randbytes, 0, 64 ); + memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) + { + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + { + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) +#endif + { + if( p[0] != 0 || + p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite_v2; + } + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite_v2: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + + /* + * SSLv2 Client Hello relevant renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->in_left = 0; + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + size_t i, j; + size_t ciph_offset, comp_offset, ext_offset; + size_t msg_len, ciph_len, sess_len, comp_len, ext_len; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + size_t cookie_offset, cookie_len; +#endif + unsigned char *buf, *p, *ext; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int major, minor; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +read_record_header: +#endif + /* + * If renegotiating, then the input was read with mbedtls_ssl_read_record(), + * otherwise read it ourselves manually in order to support SSLv2 + * ClientHello, which doesn't use the same record layer format. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_hdr; + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) +#endif + if( ( buf[0] & 0x80 ) != 0 ) + return ssl_parse_client_hello_v2( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); + + /* + * SSLv3/TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 11 DTLS: epoch + record sequence number + * 3 . 4 message length + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", + buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", + ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", + buf[1], buf[2] ) ); + + mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); + + /* According to RFC 5246 Appendix E.1, the version here is typically + * "{03,00}, the lowest version number supported by the client, [or] the + * value of ClientHello.client_version", so the only meaningful check here + * is the major version shouldn't be less than 3 */ + if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* For DTLS if this is the initial handshake, remember the client sequence + * number to use it in our next message (RFC 6347 4.2.1) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + /* Epoch should be 0 for initial handshakes */ + if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); + ssl->next_record_offset = 0; + ssl->in_left = 0; + goto read_record_header; + } + + /* No MAC to check yet, so we can update right now */ + mbedtls_ssl_dtls_replay_update( ssl ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Set by mbedtls_ssl_read_record() */ + msg_len = ssl->in_hslen; + } + else +#endif + { + if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + } + + buf = ssl->in_msg; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); + + ssl->handshake->update_checksum( ssl, buf, msg_len ); + + /* + * Handshake layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 DTLS only: message seqence number + * 6 . 8 DTLS only: fragment offset + * 9 . 11 DTLS only: fragment length + */ + if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + + /* We don't support fragmentation of ClientHello (yet?) */ + if( buf[1] != 0 || + msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* + * Copy the client's handshake message_seq on initial handshakes, + * check sequence number on renego. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* This couldn't be done in ssl_prepare_handshake_record() */ + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + + if( cli_msg_seq != ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " + "%d (expected %d)", cli_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->in_msg_seq++; + } + else +#endif + { + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + ssl->handshake->out_msg_seq = cli_msg_seq; + ssl->handshake->in_msg_seq = cli_msg_seq + 1; + } + + /* + * For now we don't support fragmentation, so make sure + * fragment_offset == 0 and fragment_length == length + */ + if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || + memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + buf += mbedtls_ssl_hs_hdr_len( ssl ); + msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * ClientHello layer: + * 0 . 1 protocol version + * 2 . 33 random bytes (starting with 4 bytes of Unix time) + * 34 . 35 session id length (1 byte) + * 35 . 34+x session id + * 35+x . 35+x DTLS only: cookie length (1 byte) + * 36+x . .. DTLS only: cookie + * .. . .. ciphersuite list length (2 bytes) + * .. . .. ciphersuite list + * .. . .. compression alg. list length (1 byte) + * .. . .. compression alg. list + * .. . .. extensions length (2 bytes, optional) + * .. . .. extensions (optional) + */ + + /* + * Minimal length (with everything empty and extensions ommitted) is + * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can + * read at least up to session id length without worrying. + */ + if( msg_len < 38 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check and save the protocol version + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); + + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf ); + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->conf->max_major_ver ) + { + ssl->major_ver = ssl->conf->max_major_ver; + ssl->minor_ver = ssl->conf->max_minor_ver; + } + else if( ssl->minor_ver > ssl->conf->max_minor_ver ) + ssl->minor_ver = ssl->conf->max_minor_ver; + + /* + * Save client random (inc. Unix time) + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); + + memcpy( ssl->handshake->randbytes, buf + 2, 32 ); + + /* + * Check the session ID length and save session ID + */ + sess_len = buf[34]; + + if( sess_len > sizeof( ssl->session_negotiate->id ) || + sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); + + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 35, + ssl->session_negotiate->id_len ); + + /* + * Check the cookie length and content + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + cookie_offset = 35 + sess_len; + cookie_len = buf[cookie_offset]; + + if( cookie_offset + 1 + cookie_len + 2 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + buf + cookie_offset + 1, cookie_len ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->f_cookie_check != NULL +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + buf + cookie_offset + 1, cookie_len, + ssl->cli_id, ssl->cli_id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); + ssl->handshake->verify_cookie_len = 1; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); + ssl->handshake->verify_cookie_len = 0; + } + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + /* We know we didn't send a cookie, so it should be empty */ + if( cookie_len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); + } + + /* + * Check the ciphersuitelist length (will be parsed later) + */ + ciph_offset = cookie_offset + 1 + cookie_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + ciph_offset = 35 + sess_len; + + ciph_len = ( buf[ciph_offset + 0] << 8 ) + | ( buf[ciph_offset + 1] ); + + if( ciph_len < 2 || + ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ + ( ciph_len % 2 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + ciph_offset + 2, ciph_len ); + + /* + * Check the compression algorithms length and pick one + */ + comp_offset = ciph_offset + 2 + ciph_len; + + comp_len = buf[comp_offset]; + + if( comp_len < 1 || + comp_len > 16 || + comp_len + comp_offset + 1 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", + buf + comp_offset + 1, comp_len ); + + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#if defined(MBEDTLS_ZLIB_SUPPORT) + for( i = 0; i < comp_len; ++i ) + { + if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; + break; + } + } +#endif + + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#endif + + /* Do not parse the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + /* + * Check the extension length + */ + ext_offset = comp_offset + 1 + comp_len; + if( msg_len > ext_offset ) + { + if( msg_len < ext_offset + 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ext_len = ( buf[ext_offset + 0] << 8 ) + | ( buf[ext_offset + 1] ); + + if( ( ext_len > 0 && ext_len < 4 ) || + msg_len != ext_offset + 2 + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else + ext_len = 0; + + ext = buf + ext_offset + 2; + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); + + while( ext_len != 0 ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->conf->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + break; +#endif + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); + + ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); + + ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) ); + + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions + * and certificate from the SNI callback triggered by the SNI extension.) + */ + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) + { + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + { + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) +#endif + { + if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + mbedtls_ssl_send_fatal_handshake_failure( ssl ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + mbedtls_ssl_send_fatal_handshake_failure( ssl ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const mbedtls_ssl_ciphersuite_t *suite = NULL; + const mbedtls_cipher_info_t *cipher = NULL; + + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + /* + * RFC 7366: "If a server receives an encrypt-then-MAC request extension + * from a client and then selects a stream or Authenticated Encryption + * with Associated Data (AEAD) ciphersuite, it MUST NOT send an + * encrypt-then-MAC response extension back to the client." + */ + if( ( suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ) ) == NULL || + ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || + cipher->mode != MBEDTLS_MODE_CBC ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + *p++ = 0x00; + *p++ = 0x01; + *p++ = 0x00; + } + + *olen = p - buf; +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly computation if not needed */ + if( ssl->transform_negotiate->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN ) +static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); + + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + *olen = 7 + strlen( ssl->alpn_chosen ); + + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); + + memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *p = ssl->out_msg + 4; + unsigned char *cookie_len_byte; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + + /* The RFC is not clear on this point, but sending the actual negotiated + * version looks like the most interoperable thing to do. */ + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + p += 2; + + /* If we get here, f_cookie_check is not null */ + if( ssl->conf->f_cookie_write == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Skip length byte until we know the length */ + cookie_len_byte = p++; + + if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN, + ssl->cli_id, ssl->cli_id_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); + return( ret ); + } + + *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); + + ssl->out_msglen = p - ssl->out_msg; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + + ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + int ret; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie_len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ssl_write_hello_verify_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + /* + * Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). + * If not, try looking up session ID in our cache. + */ + if( ssl->handshake->resume == 0 && +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE && +#endif + ssl->session_negotiate->id_len != 0 && + ssl->conf->f_get_cache != NULL && + ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); + ssl->handshake->resume = 1; + } + + if( ssl->handshake->resume == 0 ) + { + /* + * New session, create a new session id, + * unless we're about to issue a session ticket + */ + ssl->state++; + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->id_len = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->id_len = n = 32; + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->id_len; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions + */ + *p++ = (unsigned char) ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); + *p++ = (unsigned char)( ssl->session_negotiate->compression ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + ssl->session_negotiate->compression ) ); + + /* Do not write the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; + + ret = mbedtls_ssl_write_record( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + size_t dn_size, total_dn_size; /* excluding length bytes */ + size_t ct_len, sa_len; /* including length bytes */ + unsigned char *buf, *p; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const mbedtls_x509_crt *crt; + int authmode; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; + else +#endif + authmode = ssl->conf->authmode; + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + buf = ssl->out_msg; + p = buf + 4; + + /* + * Supported certificate types + * + * ClientCertificateType certificate_types<1..2^8-1>; + * enum { (255) } ClientCertificateType; + */ + ct_len = 0; + +#if defined(MBEDTLS_RSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Add signature_algorithms for verify (TLS 1.2) + * + * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * enum { (255) } HashAlgorithm; + * enum { (255) } SignatureAlgorithm; + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + const int *cur; + + /* + * Supported signature algorithms + */ + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + { + unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); + + if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) + continue; + +#if defined(MBEDTLS_RSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif + } + + p[0] = (unsigned char)( sa_len >> 8 ); + p[1] = (unsigned char)( sa_len ); + sa_len += 2; + p += sa_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; + + total_dn_size = 0; + while( crt != NULL && crt->version != 0 ) + { + dn_size = crt->subject_raw.len; + + if( end < p || + (size_t)( end - p ) < dn_size || + (size_t)( end - p ) < 2 + dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; + ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); + ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); + + ret = mbedtls_ssl_write_record( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, + mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), + MBEDTLS_ECDH_OURS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t n = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char *p = ssl->out_msg + 4; + unsigned char *dig_signed = p; + size_t dig_signed_len = 0, len; + ((void) dig_signed); + ((void) dig_signed_len); + ((void) len); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#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 ) + { + ssl_get_ecdh_params_from_cert( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + size_t jlen; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p, &jlen, ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + p += jlen; + n += jlen; + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + /* Note: we don't support identity hints, until someone asks + * for them. */ + *(p++) = 0x00; + *(p++) = 0x00; + + n += 2; + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_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->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->conf->dhm_P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->conf->dhm_G ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_mpi_copy", ret ); + return( ret ); + } + + if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); + return( ret ); + } + + dig_signed = p; + dig_signed_len = len; + + p += len; + n += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_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_ECDHE_PSK ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const mbedtls_ecp_curve_info **curve = NULL; + const mbedtls_ecp_group_id *gid; + + /* Match our preference list against the offered curves */ + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->grp_id == *gid ) + goto curve_matching_done; + +curve_matching_done: + if( curve == NULL || *curve == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, + (*curve)->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, + p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); + return( ret ); + } + + dig_signed = p; + dig_signed_len = len; + + p += len; + n += len; + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ + +#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 signature_len = 0; + unsigned int hashlen = 0; + unsigned char hash[64]; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + + /* + * Choose hash algorithm. NONE means MD5 + SHA1 here. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + md_alg = mbedtls_ssl_md_alg_from_hash( ssl->handshake->sig_alg ); + + if( md_alg == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ciphersuite_info->key_exchange == + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif + { + md_alg = MBEDTLS_MD_NONE; + } + + /* + * Compute the hash to be signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + mbedtls_md5_context mbedtls_md5; + mbedtls_sha1_context mbedtls_sha1; + + mbedtls_md5_init( &mbedtls_md5 ); + mbedtls_sha1_init( &mbedtls_sha1 ); + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + mbedtls_md5_starts( &mbedtls_md5 ); + mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); + mbedtls_md5_update( &mbedtls_md5, dig_signed, dig_signed_len ); + mbedtls_md5_finish( &mbedtls_md5, hash ); + + mbedtls_sha1_starts( &mbedtls_sha1 ); + mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); + mbedtls_sha1_update( &mbedtls_sha1, dig_signed, dig_signed_len ); + mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); + + hashlen = 36; + + mbedtls_md5_free( &mbedtls_md5 ); + mbedtls_sha1_free( &mbedtls_sha1 ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + + mbedtls_md_init( &ctx ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + return( ret ); + } + + mbedtls_md_starts( &ctx ); + mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); + mbedtls_md_update( &ctx, dig_signed, dig_signed_len ); + mbedtls_md_finish( &ctx, hash ); + mbedtls_md_free( &ctx ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + + /* + * Make the signature + */ + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + *(p++) = ssl->handshake->sig_alg; + *(p++) = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); + + n += 2; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, + p + 2 , &signature_len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( signature_len >> 8 ); + *(p++) = (unsigned char)( signature_len ); + n += 2; + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); + + n += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + + ssl->out_msglen = 4 + n; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + + return( 0 ); +} + +static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + *p += n; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Decrypt the premaster using own private RSA key + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( *p++ != ( ( len >> 8 ) & 0xFF ) || + *p++ != ( ( len ) & 0xFF ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + } +#endif + + if( p + len != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* + * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding + * must not cause the connection to end immediately; instead, send a + * bad_record_mac later in the handshake. + * Also, avoid data-dependant branches here to protect against + * timing-based variants. + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, + peer_pms, &peer_pmslen, + sizeof( peer_pms ), + ssl->conf->f_rng, ssl->conf->p_rng ); + + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( diff != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); +#endif + + if( sizeof( ssl->handshake->premaster ) < pms_offset || + sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->handshake->pmslen = 48; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + for( i = 0; i < ssl->handshake->pmslen; i++ ) + pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + size_t n; + + if( ssl->conf->f_psk == NULL && + ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || + ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( *p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( n < 1 || n > 65535 || *p + n > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->conf->f_psk != NULL ) + { + if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + else + { + /* Identity is not a big secret since clients send it in the clear, + * but treat it carefully anyway, just in case */ + if( n != ssl->conf->psk_identity_len || + mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) + { + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 ) + { + return( ret ); + } + + return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char *p, *end; + + ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t pk_alg; +#endif + mbedtls_md_type_t md_alg; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || + ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + /* Read the message without adding it to the checksum */ + do { + + if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + return( ret ); + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + ssl->state++; + + /* Process the message contents */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * struct { + * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only + * opaque signature<0..2^16-1>; + * } DigitallySigned; + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + md_alg = MBEDTLS_MD_NONE; + hashlen = 36; + + /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ + if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Hash + */ + md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); + + if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + +#if !defined(MBEDTLS_MD_SHA1) + if( MBEDTLS_MD_SHA1 == md_alg ) + hash_start += 16; +#endif + + /* Info from md_alg will be used instead */ + hashlen = 0; + + i++; + + /* + * Signature + */ + if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i++; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; + i += 2; + + if( i + sig_len != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* Calculate hash and verify signature */ + ssl->handshake->calc_verify( ssl, hash ); + + if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash_start, hashlen, + ssl->in_msg + i, sig_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + + mbedtls_ssl_update_handshake_status( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t tlen; + uint32_t lifetime; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 4 . 7 ticket_lifetime_hint (0 = unspecified) + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + + if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, + ssl->session_negotiate, + ssl->out_msg + 10, + ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN, + &tlen, &lifetime ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); + tlen = 0; + } + + ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; + ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; + ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; + ssl->out_msg[7] = ( lifetime ) & 0xFF; + + ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); + + ssl->out_msglen = 10 + tlen; + + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +#endif + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_SRV_C */ diff --git a/external_libs/mbedtls/library/ssl_ticket.c b/external_libs/mbedtls/library/ssl_ticket.c new file mode 100644 index 00000000..4d9116d2 --- /dev/null +++ b/external_libs/mbedtls/library/ssl_ticket.c @@ -0,0 +1,489 @@ +/* + * TLS server tickets callbacks implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_ticket.h" + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Initialze context + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +#define MAX_KEY_BYTES 32 /* 256 bits */ + +/* + * Generate/update a key + */ +static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, + unsigned char index ) +{ + int ret; + unsigned char buf[MAX_KEY_BYTES]; + mbedtls_ssl_ticket_key *key = ctx->keys + index; + +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = (uint32_t) mbedtls_time( NULL ); +#endif + + if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) + return( ret ); + + if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) + return( ret ); + + /* With GCM and CCM, same context can encrypt & decrypt */ + ret = mbedtls_cipher_setkey( &key->ctx, buf, + mbedtls_cipher_get_key_bitlen( &key->ctx ), + MBEDTLS_ENCRYPT ); + + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Rotate/generate keys if necessary + */ +static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) +{ +#if !defined(MBEDTLS_HAVE_TIME) + ((void) ctx); +#else + if( ctx->ticket_lifetime != 0 ) + { + uint32_t current_time = (uint32_t) mbedtls_time( NULL ); + uint32_t key_time = ctx->keys[ctx->active].generation_time; + + if( current_time > key_time && + current_time - key_time < ctx->ticket_lifetime ) + { + return( 0 ); + } + + ctx->active = 1 - ctx->active; + + return( ssl_ticket_gen_key( ctx, ctx->active ) ); + } + else +#endif /* MBEDTLS_HAVE_TIME */ + return( 0 ); +} + +/* + * Setup context for actual use + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; + + ctx->ticket_lifetime = lifetime; + + cipher_info = mbedtls_cipher_info_from_type( cipher); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cipher_info->mode != MBEDTLS_MODE_GCM && + cipher_info->mode != MBEDTLS_MODE_CCM ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 || + ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || + ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Serialize a session in the following format: + * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) + * n . n+2 peer_cert length = m (0 if no certificate) + * n+3 . n+2+m peer cert ASN.1 + */ +static int ssl_save_session( const mbedtls_ssl_session *session, + unsigned char *buf, size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t left = buf_len; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( left < sizeof( mbedtls_ssl_session ) ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + memcpy( p, session, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + left -= sizeof( mbedtls_ssl_session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( session->peer_cert == NULL ) + cert_len = 0; + else + cert_len = session->peer_cert->raw.len; + + if( left < 3 + cert_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char)( cert_len >> 16 & 0xFF ); + *p++ = (unsigned char)( cert_len >> 8 & 0xFF ); + *p++ = (unsigned char)( cert_len & 0xFF ); + + if( session->peer_cert != NULL ) + memcpy( p, session->peer_cert->raw.p, cert_len ); + + p += cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + *olen = p - buf; + + return( 0 ); +} + +/* + * Unserialise session, see ssl_save_session() + */ +static int ssl_load_session( mbedtls_ssl_session *session, + const unsigned char *buf, size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( p + sizeof( mbedtls_ssl_session ) > end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( session, p, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( p + 3 > end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len == 0 ) + { + session->peer_cert = NULL; + } + else + { + int ret; + + if( p + cert_len > end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( session->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( session->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Create session ticket, with the following structure: + * + * struct { + * opaque key_name[4]; + * opaque iv[12]; + * opaque encrypted_state<0..2^16-1>; + * opaque tag[16]; + * } ticket; + * + * The key_name, iv, and length of encrypted_state are the additional + * authenticated data. + */ +int mbedtls_ssl_ticket_write( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *ticket_lifetime ) +{ + int ret; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = start; + unsigned char *iv = start + 4; + unsigned char *state_len_bytes = iv + 12; + unsigned char *state = state_len_bytes + 2; + unsigned char *tag; + size_t clear_len, ciph_len; + + *tlen = 0; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, + * in addition to session itself, that will be checked when writing it. */ + if( end - start < 4 + 12 + 2 + 16 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + key = &ctx->keys[ctx->active]; + + *ticket_lifetime = ctx->ticket_lifetime; + + memcpy( key_name, key->name, 4 ); + + if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 ) + goto cleanup; + + /* Dump session state */ + if( ( ret = ssl_save_session( session, + state, end - state, &clear_len ) ) != 0 || + (unsigned long) clear_len > 65535 ) + { + goto cleanup; + } + state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; + state_len_bytes[1] = ( clear_len ) & 0xff; + + /* Encrypt and authenticate */ + tag = state + clear_len; + if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, + iv, 12, key_name, 4 + 12 + 2, + state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 ) + { + goto cleanup; + } + if( ciph_len != clear_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + *tlen = 4 + 12 + 2 + 16 + ciph_len; + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Select key based on name + */ +static mbedtls_ssl_ticket_key *ssl_ticket_select_key( + mbedtls_ssl_ticket_context *ctx, + const unsigned char name[4] ) +{ + unsigned char i; + + for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) + if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) + return( &ctx->keys[i] ); + + return( NULL ); +} + +/* + * Load session ticket (see mbedtls_ssl_ticket_write for structure) + */ +int mbedtls_ssl_ticket_parse( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ) +{ + int ret; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = buf; + unsigned char *iv = buf + 4; + unsigned char *enc_len_p = iv + 12; + unsigned char *ticket = enc_len_p + 2; + unsigned char *tag; + size_t enc_len, clear_len; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* See mbedtls_ssl_ticket_write() */ + if( len < 4 + 12 + 2 + 16 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; + tag = ticket + enc_len; + + if( len != 4 + 12 + 2 + enc_len + 16 ) + { + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + goto cleanup; + } + + /* Select key */ + if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) + { + /* We can't know for sure but this is a likely option unless we're + * under attack - this is only informative anyway */ + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + + /* Decrypt and authenticate */ + if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12, + key_name, 4 + 12 + 2, ticket, enc_len, + ticket, &clear_len, tag, 16 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + ret = MBEDTLS_ERR_SSL_INVALID_MAC; + + goto cleanup; + } + if( clear_len != enc_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + /* Actually load session */ + if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 ) + goto cleanup; + +#if defined(MBEDTLS_HAVE_TIME) + { + /* Check for expiration */ + mbedtls_time_t current_time = mbedtls_time( NULL ); + + if( current_time < session->start || + (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) + { + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + } +#endif + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free context + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) +{ + mbedtls_cipher_free( &ctx->keys[0].ctx ); + mbedtls_cipher_free( &ctx->keys[1].ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); +} + +#endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/external_libs/mbedtls/library/ssl_tls.c b/external_libs/mbedtls/library/ssl_tls.c new file mode 100644 index 00000000..84a04ae5 --- /dev/null +++ b/external_libs/mbedtls/library/ssl_tls.c @@ -0,0 +1,7679 @@ +/* + * SSLv3/TLSv1 shared functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* Length of the "epoch" field in the record header */ +static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 2 ); +#else + ((void) ssl); +#endif + return( 0 ); +} + +/* + * Start a timer. + * Passing millisecs = 0 cancels a running timer. + */ +static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) +{ + if( ssl->f_set_timer == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); + ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); +} + +/* + * Return -1 is timer is expired, 0 if it isn't. + */ +static int ssl_check_timer( mbedtls_ssl_context *ssl ) +{ + if( ssl->f_get_timer == NULL ) + return( 0 ); + + if( ssl->f_get_timer( ssl->p_timer ) == 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); + return( -1 ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Double the retransmit timeout value, within the allowed range, + * returning -1 if the maximum value has already been reached. + */ +static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + uint32_t new_timeout; + + if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) + return( -1 ); + + new_timeout = 2 * ssl->handshake->retransmit_timeout; + + /* Avoid arithmetic overflow and range overflow */ + if( new_timeout < ssl->handshake->retransmit_timeout || + new_timeout > ssl->conf->hs_timeout_max ) + { + new_timeout = ssl->conf->hs_timeout_max; + } + + ssl->handshake->retransmit_timeout = new_timeout; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); + + return( 0 ); +} + +static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = +{ + MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ + 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ + 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ + 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ + 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ +}; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_CLI_C) +static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src ) +{ + mbedtls_ssl_session_free( dst ); + memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( src->peer_cert != NULL ) + { + int ret; + + dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); + if( dst->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( dst->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + mbedtls_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( src->ticket != NULL ) + { + dst->ticket = mbedtls_calloc( 1, src->ticket_len ); + if( dst->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen ) = NULL; +int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; +int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/* + * Key material generation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static int ssl3_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t i; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padding[16]; + unsigned char sha1sum[20]; + ((void)label); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + /* + * SSLv3: + * block = + * MD5( secret + SHA1( 'A' + secret + random ) ) + + * MD5( secret + SHA1( 'BB' + secret + random ) ) + + * MD5( secret + SHA1( 'CCC' + secret + random ) ) + + * ... + */ + for( i = 0; i < dlen / 16; i++ ) + { + memset( padding, (unsigned char) ('A' + i), 1 + i ); + + mbedtls_sha1_starts( &sha1 ); + mbedtls_sha1_update( &sha1, padding, 1 + i ); + mbedtls_sha1_update( &sha1, secret, slen ); + mbedtls_sha1_update( &sha1, random, rlen ); + mbedtls_sha1_finish( &sha1, sha1sum ); + + mbedtls_md5_starts( &md5 ); + mbedtls_md5_update( &md5, secret, slen ); + mbedtls_md5_update( &md5, sha1sum, 20 ); + mbedtls_md5_finish( &md5, dstbuf + i * 16 ); + } + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_zeroize( padding, sizeof( padding ) ); + mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static int tls1_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb, hs; + size_t i, j, k; + const unsigned char *S1, *S2; + unsigned char tmp[128]; + unsigned char h_i[20]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init( &md_ctx ); + + if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hs = ( slen + 1 ) / 2; + S1 = secret; + S2 = secret + slen - hs; + + nb = strlen( label ); + memcpy( tmp + 20, label, nb ); + memcpy( tmp + 20 + nb, random, rlen ); + nb += rlen; + + /* + * First compute P_md5(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, S1, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + for( i = 0; i < dlen; i += 16 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + k = ( i + 16 > dlen ) ? dlen % 16 : 16; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + /* + * XOR out with P_sha1(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, S2, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += 20 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + 20 > dlen ) ? dlen % 20 : 20; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); + } + + mbedtls_md_free( &md_ctx ); + + mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k, md_len; + unsigned char tmp[128]; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init( &md_ctx ); + + if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + md_len = mbedtls_md_get_size( md_info ); + + if( sizeof( tmp ) < md_len + strlen( label ) + rlen ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + md_len, label, nb ); + memcpy( tmp + md_len + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, secret, slen ); + mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += md_len ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + md_len > dlen ) ? dlen % md_len : md_len; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SHA256_C) +static int tls_prf_sha256( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +static int tls_prf_sha384( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * ); +static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + unsigned char tmp[64]; + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t iv_copy_len; + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; + + mbedtls_ssl_session *session = ssl->session_negotiate; + mbedtls_ssl_transform *transform = ssl->transform_negotiate; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + cipher_info = mbedtls_cipher_info_from_type( transform->ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", + transform->ciphersuite_info->cipher ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( transform->ciphersuite_info->mac ); + if( md_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found", + transform->ciphersuite_info->mac ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * SSLv3: + * master = + * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) + * + * TLSv1+: + * master = PRF( premaster, "master secret", randbytes )[0..47] + */ + if( handshake->resume == 0 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, + handshake->pmslen ); + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + unsigned char session_hash[48]; + size_t hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + + ssl->handshake->calc_verify( ssl, session_hash ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { +#if defined(MBEDTLS_SHA512_C) + if( ssl->transform_negotiate->ciphersuite_info->mac == + MBEDTLS_MD_SHA384 ) + { + hash_len = 48; + } + else +#endif + hash_len = 32; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + hash_len = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); + + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + "extended master secret", + session_hash, hash_len, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + } + else +#endif + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + "master secret", + handshake->randbytes, 64, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + mbedtls_zeroize( handshake->premaster, sizeof(handshake->premaster) ); + } + else + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + + /* + * Swap the client and server random values. + */ + memcpy( tmp, handshake->randbytes, 64 ); + memcpy( handshake->randbytes, tmp + 32, 32 ); + memcpy( handshake->randbytes + 32, tmp, 32 ); + mbedtls_zeroize( tmp, sizeof( tmp ) ); + + /* + * SSLv3: + * key block = + * MD5( master + SHA1( 'A' + master + randbytes ) ) + + * MD5( master + SHA1( 'BB' + master + randbytes ) ) + + * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + + * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + + * ... + * + * TLSv1: + * key block = PRF( master, "key expansion", randbytes ) + */ + ret = handshake->tls_prf( session->master, 48, "key expansion", + handshake->randbytes, 64, keyblk, 256 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + transform->keylen = cipher_info->key_bitlen / 8; + + if( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->mode == MBEDTLS_MODE_CCM ) + { + transform->maclen = 0; + + transform->ivlen = 12; + transform->fixed_ivlen = 4; + + /* Minimum length is expicit IV + tag */ + transform->minlen = transform->ivlen - transform->fixed_ivlen + + ( transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); + } + else + { + /* Initialize HMAC contexts */ + if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || + ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + return( ret ); + } + + /* Get MAC length */ + transform->maclen = mbedtls_md_get_size( md_info ); + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + /* + * If HMAC is to be truncated, we shall keep the leftmost bytes, + * (rfc 6066 page 13 or rfc 2104 section 4), + * so we only need to adjust the length here. + */ + if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( cipher_info->mode == MBEDTLS_MODE_STREAM ) + transform->minlen = transform->maclen; + else + { + /* + * GenericBlockCipher: + * 1. if EtM is in use: one block plus MAC + * otherwise: * first multiple of blocklen greater than maclen + * 2. IV except for SSL3 and TLS 1.0 + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + transform->minlen = transform->maclen + + cipher_info->block_size; + } + else +#endif + { + transform->minlen = transform->maclen + + cipher_info->block_size + - transform->maclen % cipher_info->block_size; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) + ; /* No need to adjust minlen */ + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", + transform->keylen, transform->minlen, transform->ivlen, + transform->maclen ) ); + + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + key1 = keyblk + transform->maclen * 2; + key2 = keyblk + transform->maclen * 2 + transform->keylen; + + mac_enc = keyblk; + mac_dec = keyblk + transform->maclen; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + key1 = keyblk + transform->maclen * 2 + transform->keylen; + key2 = keyblk + transform->maclen * 2; + + mac_enc = keyblk + transform->maclen; + mac_dec = keyblk; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( transform->maclen > sizeof transform->mac_enc ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( transform->mac_enc, mac_enc, transform->maclen ); + memcpy( transform->mac_dec, mac_dec, transform->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen ); + mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_init != NULL ) + { + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); + + if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen, + transform->iv_enc, transform->iv_dec, + iv_copy_len, + mac_enc, mac_dec, + transform->maclen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + if( ssl->conf->f_export_keys != NULL ) + { + ssl->conf->f_export_keys( ssl->conf->p_export_keys, + session->master, keyblk, + transform->maclen, transform->keylen, + iv_copy_len ); + } +#endif + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_bitlen, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_bitlen, + MBEDTLS_DECRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( cipher_info->mode == MBEDTLS_MODE_CBC ) + { + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + mbedtls_zeroize( keyblk, sizeof( keyblk ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + // Initialize compression + // + if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_BUFFER_LEN ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); + + memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); + memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); + + if( deflateInit( &transform->ctx_deflate, + Z_DEFAULT_COMPRESSION ) != Z_OK || + inflateInit( &transform->ctx_inflate ) != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char pad_1[48]; + unsigned char pad_2[48]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + memset( pad_1, 0x36, 48 ); + memset( pad_2, 0x5C, 48 ); + + mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update( &md5, pad_1, 48 ); + mbedtls_md5_finish( &md5, hash ); + + mbedtls_md5_starts( &md5 ); + mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update( &md5, pad_2, 48 ); + mbedtls_md5_update( &md5, hash, 16 ); + mbedtls_md5_finish( &md5, hash ); + + mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update( &sha1, pad_1, 40 ); + mbedtls_sha1_finish( &sha1, hash + 16 ); + + mbedtls_sha1_starts( &sha1 ); + mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update( &sha1, pad_2, 40 ); + mbedtls_sha1_update( &sha1, hash + 16, 20 ); + mbedtls_sha1_finish( &sha1, hash + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + mbedtls_md5_finish( &md5, hash ); + mbedtls_sha1_finish( &sha1, hash + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] ) +{ + mbedtls_sha256_context sha256; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + mbedtls_sha256_finish( &sha256, hash ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha256_free( &sha256 ); + + return; +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] ) +{ + mbedtls_sha512_context sha512; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + mbedtls_sha512_finish( &sha512, hash ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha512_free( &sha512 ); + + return; +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + const unsigned char *psk = ssl->conf->psk; + size_t psk_len = ssl->conf->psk_len; + + /* If the psk callback was called, use its result */ + if( ssl->handshake->psk != NULL ) + { + psk = ssl->handshake->psk; + psk_len = ssl->handshake->psk_len; + } + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memset( p, 0, psk_len ); + p += psk_len; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + int ret; + size_t len; + + /* Write length only when we know the actual value */ + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, end - ( p + 2 ), &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + *(p++) = (unsigned char)( len >> 8 ); + *(p++) = (unsigned char)( len ); + p += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret; + size_t zlen; + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( zlen >> 8 ); + *(p++) = (unsigned char)( zlen ); + p += zlen; + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( p, psk, psk_len ); + p += psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +/* + * SSLv3.0 MAC functions + */ +static void ssl_mac( mbedtls_md_context_t *md_ctx, unsigned char *secret, + unsigned char *buf, size_t len, + unsigned char *ctr, int type ) +{ + unsigned char header[11]; + unsigned char padding[48]; + int padlen; + int md_size = mbedtls_md_get_size( md_ctx->md_info ); + int md_type = mbedtls_md_get_type( md_ctx->md_info ); + + /* Only MD5 and SHA-1 supported */ + if( md_type == MBEDTLS_MD_MD5 ) + padlen = 48; + else + padlen = 40; + + memcpy( header, ctr, 8 ); + header[ 8] = (unsigned char) type; + header[ 9] = (unsigned char)( len >> 8 ); + header[10] = (unsigned char)( len ); + + memset( padding, 0x36, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, header, 11 ); + mbedtls_md_update( md_ctx, buf, len ); + mbedtls_md_finish( md_ctx, buf + len ); + + memset( padding, 0x5C, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, buf + len, md_size ); + mbedtls_md_finish( md_ctx, buf + len ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + ( defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) ) +#define SSL_SOME_MODES_USE_MAC +#endif + +/* + * Encryption/decryption functions + */ +static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( ssl->session_out == NULL || ssl->transform_out == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_msg, ssl->out_msglen ); + + /* + * Add MAC before if needed + */ +#if defined(SSL_SOME_MODES_USE_MAC) + if( mode == MBEDTLS_MODE_STREAM || + ( mode == MBEDTLS_MODE_CBC +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + && ssl->session_out->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED +#endif + ) ) + { +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl_mac( &ssl->transform_out->md_ctx_enc, + ssl->transform_out->mac_enc, + ssl->out_msg, ssl->out_msglen, + ssl->out_ctr, ssl->out_msgtype ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_msg, ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, + ssl->out_msg + ssl->out_msglen ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", + ssl->out_msg + ssl->out_msglen, + ssl->transform_out->maclen ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* AEAD not the only option */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + ssl->out_msg, ssl->out_msglen, + ssl->out_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( ssl->out_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM ) + { + int ret; + size_t enc_msglen, olen; + unsigned char *enc_msg; + unsigned char add_data[13]; + unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + memcpy( add_data, ssl->out_ctr, 8 ); + add_data[8] = ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, add_data + 9 ); + add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->out_msglen & 0xFF; + + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + /* + * Generate IV + */ + if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, + ssl->out_ctr, 8 ); + memcpy( ssl->out_iv, ssl->out_ctr, 8 ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + /* + * Encrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + add_data, 13, + enc_msg, enc_msglen, + enc_msg, &olen, + enc_msg + enc_msglen, taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); + return( ret ); + } + + if( olen != enc_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen += taglen; + auth_done++; + + MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + if( mode == MBEDTLS_MODE_CBC ) + { + int ret; + unsigned char *enc_msg; + size_t enc_msglen, padlen, olen = 0, i; + + padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % + ssl->transform_out->ivlen; + if( padlen == ssl->transform_out->ivlen ) + padlen = 0; + + for( i = 0; i <= padlen; i++ ) + ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; + + ssl->out_msglen += padlen + 1; + + enc_msglen = ssl->out_msglen; + enc_msg = ssl->out_msg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Generate IV + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( ssl->out_iv, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of IV and %d bytes of padding", + ssl->out_msglen, ssl->transform_out->ivlen, + padlen + 1 ) ); + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + enc_msg, enc_msglen, + enc_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( enc_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_out->iv_enc, + ssl->transform_out->cipher_ctx_enc.iv, + ssl->transform_out->ivlen ); + } +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( auth_done == 0 ) + { + /* + * MAC(MAC_write_key, seq_num + + * TLSCipherText.type + + * TLSCipherText.version + + * length_of( (IV +) ENC(...) ) + + * IV + // except for TLS 1.0 + * ENC(content + padding + padding_length)); + */ + unsigned char pseudo_hdr[13]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 ); + memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 ); + pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_iv, ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, + ssl->out_iv + ssl->out_msglen ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +#define SSL_MAX_MAC_SIZE 48 + +static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) +{ + size_t i; + mbedtls_cipher_mode_t mode; + int auth_done = 0; +#if defined(SSL_SOME_MODES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + + if( ssl->session_in == NULL || ssl->transform_in == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec ); + + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", + ssl->in_msglen, ssl->transform_in->minlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + padlen = 0; + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + ssl->in_msg, ssl->in_msglen, + ssl->in_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( ssl->in_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM ) + { + int ret; + size_t dec_msglen, olen; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + unsigned char add_data[13]; + unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + size_t explicit_iv_len = ssl->transform_in->ivlen - + ssl->transform_in->fixed_ivlen; + + if( ssl->in_msglen < explicit_iv_len + taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " + "+ taglen (%d)", ssl->in_msglen, + explicit_iv_len, taglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + dec_msglen = ssl->in_msglen - explicit_iv_len - taglen; + + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + ssl->in_msglen = dec_msglen; + + memcpy( add_data, ssl->in_ctr, 8 ); + add_data[8] = ssl->in_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, add_data + 9 ); + add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->in_msglen & 0xFF; + + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, + ssl->in_iv, + ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + add_data, 13, + dec_msg, dec_msglen, + dec_msg_result, &olen, + dec_msg + dec_msglen, taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); + + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + if( olen != dec_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + if( mode == MBEDTLS_MODE_CBC ) + { + /* + * Decrypt and check the padding + */ + int ret; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + size_t dec_msglen; + size_t minlen = 0; + size_t olen = 0; + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + minlen += ssl->transform_in->ivlen; +#endif + + if( ssl->in_msglen < minlen + ssl->transform_in->ivlen || + ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " + "+ 1 ) ( + expl IV )", ssl->in_msglen, + ssl->transform_in->ivlen, + ssl->transform_in->maclen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + dec_msglen = ssl->in_msglen; + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + + /* + * Authenticate before decrypt if enabled + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + unsigned char computed_mac[SSL_MAX_MAC_SIZE]; + unsigned char pseudo_hdr[13]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + dec_msglen -= ssl->transform_in->maclen; + ssl->in_msglen -= ssl->transform_in->maclen; + + memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 ); + memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 ); + pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, + ssl->in_iv, ssl->in_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac ); + mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, + ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", computed_mac, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac, + ssl->transform_in->maclen ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", + ssl->in_msglen, ssl->transform_in->ivlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + dec_msglen -= ssl->transform_in->ivlen; + ssl->in_msglen -= ssl->transform_in->ivlen; + + for( i = 0; i < ssl->transform_in->ivlen; i++ ) + ssl->transform_in->iv_dec[i] = ssl->in_iv[i]; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + dec_msg, dec_msglen, + dec_msg_result, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( dec_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_in->iv_dec, + ssl->transform_in->cipher_ctx_dec.iv, + ssl->transform_in->ivlen ); + } +#endif + + padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; + + if( ssl->in_msglen < ssl->transform_in->maclen + padlen && + auth_done == 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", + ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); +#endif + padlen = 0; + correct = 0; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( padlen > ssl->transform_in->ivlen ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " + "should be no more than %d", + padlen, ssl->transform_in->ivlen ) ); +#endif + correct = 0; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * TLSv1+: always check the padding up to the first failure + * and fake check up to 256 bytes of padding + */ + size_t pad_count = 0, real_count = 1; + size_t padding_idx = ssl->in_msglen - padlen - 1; + + /* + * Padding is guaranteed to be incorrect if: + * 1. padlen >= ssl->in_msglen + * + * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN + + * ssl->transform_in->maclen + * + * In both cases we reset padding_idx to a safe value (0) to + * prevent out-of-buffer reads. + */ + correct &= ( ssl->in_msglen >= padlen + 1 ); + correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + + ssl->transform_in->maclen ); + + padding_idx *= correct; + + for( i = 1; i <= 256; i++ ) + { + real_count &= ( i <= padlen ); + pad_count += real_count * + ( ssl->in_msg[padding_idx + i] == padlen - 1 ); + } + + correct &= ( pad_count == padlen ); /* Only 1 on correct padding */ + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= correct * 0x1FF; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_msglen -= padlen; + } + else +#endif /* MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + ssl->in_msg, ssl->in_msglen ); + + /* + * Authenticate if not done yet. + * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). + */ +#if defined(SSL_SOME_MODES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char tmp[SSL_MAX_MAC_SIZE]; + + ssl->in_msglen -= ssl->transform_in->maclen; + + ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); + ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); + + memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl_mac( &ssl->transform_in->md_ctx_dec, + ssl->transform_in->mac_dec, + ssl->in_msg, ssl->in_msglen, + ssl->in_ctr, ssl->in_msgtype ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * Process MAC and always update for padlen afterwards to make + * total time independent of padlen + * + * extra_run compensates MAC check for padlen + * + * Known timing attacks: + * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) + * + * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values + * correctly. (We round down instead of up, so -56 is the correct + * value for our calculations instead of -55) + */ + size_t j, extra_run = 0; + extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - + ( 13 + ssl->in_msglen + 8 ) / 64; + + extra_run &= correct * 0xFF; + + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 8 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_hdr, 3 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, + ssl->in_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, + ssl->in_msg + ssl->in_msglen ); + /* Call mbedtls_md_process at least once due to cache attacks */ + for( j = 0; j < extra_run + 1; j++ ) + mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); + + mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ) != 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif /* SSL_SOME_MODES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ssl->in_msglen == 0 ) + { + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ; /* in_ctr read from peer, not maintained internally */ + } + else +#endif + { + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +#if defined(MBEDTLS_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +static int ssl_compress_buf( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->out_msg; + size_t len_pre = ssl->out_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN - + ssl->transform_out->ctx_deflate.avail_out; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->in_msg; + size_t len_pre = ssl->in_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_MAX_CONTENT_LEN; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = MBEDTLS_SSL_MAX_CONTENT_LEN - + ssl->transform_in->ctx_inflate.avail_out; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) +{ + /* If renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if( ssl->conf->renego_max_records < 0 ) + { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; + + while( ratio != 0 ) + { + ++doublings; + ratio >>= 1; + } + + if( ++ssl->renego_records_seen > doublings ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); + return( 0 ); + } + } + + return( ssl_write_hello_request( ssl ) ); +} +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. + */ +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) +{ + int ret; + size_t len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + uint32_t timeout; + + /* Just to be sure */ + if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " + "mbedtls_ssl_set_timer_cb() for DTLS" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ + + /* + * Move to the next record in the already read datagram if applicable + */ + if( ssl->next_record_offset != 0 ) + { + if( ssl->in_left < ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left -= ssl->next_record_offset; + + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", + ssl->next_record_offset ) ); + memmove( ssl->in_hdr, + ssl->in_hdr + ssl->next_record_offset, + ssl->in_left ); + } + + ssl->next_record_offset = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + /* + * Done if we already have enough data. + */ + if( nb_want <= ssl->in_left) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + return( 0 ); + } + + /* + * A record can't be split accross datagrams. If we need to read but + * are not at the beginning of a new record, the caller did something + * wrong. + */ + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Don't even try to read if time's out already. + * This avoids by-passing the timer when repeatedly receiving messages + * that will end up being dropped. + */ + if( ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + timeout = ssl->handshake->retransmit_timeout; + else + timeout = ssl->conf->read_timeout; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); + + if( ssl->f_recv_timeout != NULL ) + ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, + timeout ); + else + ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + } + + if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); + ssl_set_timer( ssl, 0 ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl_double_retransmit_timeout( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); + return( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + } + + if( ret < 0 ) + return( ret ); + + ssl->in_left = ret; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + + if( ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + if( ssl->f_recv_timeout != NULL ) + { + ret = ssl->f_recv_timeout( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len, + ssl->conf->read_timeout ); + } + else + { + ret = ssl->f_recv( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + ssl->in_left += ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf, i; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + if( ssl->f_send == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Avoid incrementing counter if data is flushed */ + if( ssl->out_left == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + return( 0 ); + } + + while( ssl->out_left > 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", + mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) + + ssl->out_msglen - ssl->out_left; + ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + ssl->out_left -= ret; + } + + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Functions to handle the DTLS retransmission state machine + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Append current handshake message to current outgoing flight + */ +static int ssl_flight_append( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_flight_item *msg; + + /* Allocate space for current message */ + if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", + sizeof( mbedtls_ssl_flight_item ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); + mbedtls_free( msg ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Copy current handshake message with headers */ + memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); + msg->len = ssl->out_msglen; + msg->type = ssl->out_msgtype; + msg->next = NULL; + + /* Append to the current flight */ + if( ssl->handshake->flight == NULL ) + ssl->handshake->flight = msg; + else + { + mbedtls_ssl_flight_item *cur = ssl->handshake->flight; + while( cur->next != NULL ) + cur = cur->next; + cur->next = msg; + } + + return( 0 ); +} + +/* + * Free the current flight of handshake messages + */ +static void ssl_flight_free( mbedtls_ssl_flight_item *flight ) +{ + mbedtls_ssl_flight_item *cur = flight; + mbedtls_ssl_flight_item *next; + + while( cur != NULL ) + { + next = cur->next; + + mbedtls_free( cur->p ); + mbedtls_free( cur ); + + cur = next; + } +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); +#endif + +/* + * Swap transform_out and out_ctr with the alternative ones + */ +static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[8]; + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); + + /* Swap transforms */ + tmp_transform = ssl->transform_out; + ssl->transform_out = ssl->handshake->alt_transform_out; + ssl->handshake->alt_transform_out = tmp_transform; + + /* Swap epoch + sequence_number */ + memcpy( tmp_out_ctr, ssl->out_ctr, 8 ); + memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); + + /* Adjust to the newly activated transform */ + if( ssl->transform_out != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif +} + +/* + * Retransmit the current flight of messages. + * + * Need to remember the current message in case flush_output returns + * WANT_WRITE, causing us to exit this function and come back later. + * This function must be called until state is no longer SENDING. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) ); + + ssl->handshake->cur_msg = ssl->handshake->flight; + ssl_swap_epochs( ssl ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + int ret; + mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg; + + /* Swap epochs before sending Finished: we can't do it after + * sending ChangeCipherSpec, in case write returns WANT_READ. + * Must be done before copying, may change out_msg pointer */ + if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl_swap_epochs( ssl ); + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + ssl->handshake->cur_msg = cur->next; + + MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 ); + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + else + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( 0 ); +} + +/* + * To be called when the last message of an incoming flight is received. + */ +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) +{ + /* We won't need to resend that one any more */ + ssl_flight_free( ssl->handshake->flight ); + ssl->handshake->flight = NULL; + ssl->handshake->cur_msg = NULL; + + /* The next incoming flight will start with this msg_seq */ + ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + + /* Cancel timer */ + ssl_set_timer( ssl, 0 ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; +} + +/* + * To be called when the last message of an outgoing flight is send. + */ +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) +{ + ssl_reset_retransmit_timeout( ssl ); + ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Record layer functions + */ + +/* + * Write current record. + * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg. + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) +{ + int ret, done = 0, out_msg_type; + size_t len = ssl->out_msglen; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + ; /* Skip special handshake treatment when resending */ + } + else +#endif + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + out_msg_type = ssl->out_msg[0]; + + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); + ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); + ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); + + /* + * DTLS has additional fields in the Handshake layer, + * between the length field and the actual payload: + * uint16 message_seq; + * uint24 fragment_offset; + * uint24 fragment_length; + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Make room for the additional DTLS fields */ + memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); + ssl->out_msglen += 8; + len += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; + ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* We don't fragment, so frag_offset = 0 and frag_len = len */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); + } + + /* Save handshake and CCS messages for resending */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING && + ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || + ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_write != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); + + ret = mbedtls_ssl_hw_record_write( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + } + + ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], + ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Reassemble fragmented DTLS handshake messages. + * + * Use a temporary buffer for reassembly, divided in two parts: + * - the first holds the reassembled message (including handshake header), + * - the second holds a bitmask indicating which parts of the message + * (excluding headers) have been received so far. + */ +static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) +{ + unsigned char *msg, *bitmask; + size_t frag_len, frag_off; + size_t msg_len = ssl->in_hslen - 12; /* Without headers */ + + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * For first fragment, check size and allocate buffer + */ + if( ssl->handshake->hs_msg == NULL ) + { + size_t alloc_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* The bitmask needs one bit per byte of message excluding header */ + alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); + + ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); + if( ssl->handshake->hs_msg == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); + memset( ssl->handshake->hs_msg + 6, 0, 3 ); + memcpy( ssl->handshake->hs_msg + 9, + ssl->handshake->hs_msg + 1, 3 ); + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + + msg = ssl->handshake->hs_msg + 12; + bitmask = msg + msg_len; + + /* + * Check and copy current fragment + */ + frag_off = ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8]; + frag_len = ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11]; + + if( frag_off + frag_len > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", + frag_off, frag_len, msg_len ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( frag_len + 12 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", + frag_len, ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + ssl_bitmask_set( bitmask, frag_off, frag_len ); + + /* + * Do we have the complete message by now? + * If yes, finalize it, else ask to read the next record. + */ + if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); + + if( frag_len + 12 < ssl->in_msglen ) + { + /* + * We'got more handshake messages in the same record. + * This case is not handled now because no know implementation does + * that and it's hard to test, so we prefer to fail cleanly for now. + */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( ssl->in_left > ssl->next_record_offset ) + { + /* + * We've got more data in the buffer after the current record, + * that we don't want to overwrite. Move it before writing the + * reassembled message, and adjust in_left and next_record_offset. + */ + unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; + unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; + size_t remain_len = ssl->in_left - ssl->next_record_offset; + + /* First compute and check new lengths */ + ssl->next_record_offset = new_remain - ssl->in_hdr; + ssl->in_left = ssl->next_record_offset + remain_len; + + if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - + (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + memmove( new_remain, cur_remain, remain_len ); + } + + memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); + + mbedtls_free( ssl->handshake->hs_msg ); + ssl->handshake->hs_msg = NULL; + + MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", + ssl->in_msg, ssl->in_hslen ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ( + ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + /* ssl->handshake is NULL when receiving ClientHello for renego */ + if( ssl->handshake != NULL && + recv_msg_seq != ssl->handshake->in_msg_seq ) + { + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %d, start_of_flight = %d", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %d, expected = %d", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Reassemble if current message is fragmented or reassembly is + * already in progress */ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 || + ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + + if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); + return( ret ); + } + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->handshake != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + ssl->handshake->in_msg_seq++; + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* Forward declaration */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + if( f_cookie_write == NULL || f_cookie_check == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); + obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); + obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); + + obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); + obuf[12] = (unsigned char)( ( *olen - 13 ) ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * mbedtls_ssl_read_record() will ignore the record if anything else than + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function + * cannot not return 0. + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t len; + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + ssl->conf->p_cookie, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + /* Dont 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; + + /* + * "Empty strings MUST NOT be included and byte strings MUST NOT be + * truncated". 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_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 ) +{ + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + if( memcmp( ssl->in_ctr, ssl->conf->renego_period, 8 ) <= 0 && + memcmp( ssl->out_ctr, ssl->conf->renego_period, 8 ) <= 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_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, 0xFF, 7 ); + conf->renego_period[7] = 0x00; +#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 one 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: + ssl->handshake->calc_verify = ssl_calc_verify_tls; + break; +#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/external_libs/mbedtls/library/threading.c b/external_libs/mbedtls/library/threading.c new file mode 100644 index 00000000..83ec01a4 --- /dev/null +++ b/external_libs/mbedtls/library/threading.c @@ -0,0 +1,137 @@ +/* + * Threading abstraction layer + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_THREADING_C) + +#include "mbedtls/threading.h" + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || mutex->is_valid ) + return; + + mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; +} + +static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || !mutex->is_valid ) + return; + + (void) pthread_mutex_destroy( &mutex->mutex ); + mutex->is_valid = 0; +} + +static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; + +/* + * With phtreads we can statically initialize mutexes + */ +#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } + +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_THREADING_ALT) +static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); +} +static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return; +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; + +/* + * Set functions pointers and initialize global mutexes + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) +{ + mbedtls_mutex_init = mutex_init; + mbedtls_mutex_free = mutex_free; + mbedtls_mutex_lock = mutex_lock; + mbedtls_mutex_unlock = mutex_unlock; + + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; + +#endif /* MBEDTLS_THREADING_C */ diff --git a/external_libs/mbedtls/library/timing.c b/external_libs/mbedtls/library/timing.c new file mode 100644 index 00000000..a7c7ff02 --- /dev/null +++ b/external_libs/mbedtls/library/timing.c @@ -0,0 +1,525 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_TIMING_C) + +#include "mbedtls/timing.h" + +#if !defined(MBEDTLS_TIMING_ALT) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" +#endif + +#ifndef asm +#define asm __asm +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +#include +#include + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +/* some versions of mingw-64 have 32-bit longs even on x84_64 */ +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__i386__) || ( \ + ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm volatile( "mftbu %0" : "=r" (tbu0) ); + asm volatile( "mftb %0" : "=r" (tbl ) ); + asm volatile( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) + +#define HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long mbedtls_timing_hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { + gettimeofday( &tv_init, NULL ); + hardclock_init = 1; + } + + gettimeofday( &tv_cur, NULL ); + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} +#endif /* !HAVE_HARDCLOCK */ + +volatile int mbedtls_timing_alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + unsigned long delta; + LARGE_INTEGER offset, hfreq; + struct _hr_time *t = (struct _hr_time *) val; + + QueryPerformanceCounter( &offset ); + QueryPerformanceFrequency( &hfreq ); + + delta = (unsigned long)( ( 1000 * + ( offset.QuadPart - t->start.QuadPart ) ) / + hfreq.QuadPart ); + + if( reset ) + QueryPerformanceCounter( &t->start ); + + return( delta ); +} + +/* It's OK to use a global because alarm() is supposed to be global anyway */ +static DWORD alarmMs; + +static DWORD WINAPI TimerProc( LPVOID TimerContext ) +{ + ((void) TimerContext); + Sleep( alarmMs ); + mbedtls_timing_alarmed = 1; + return( TRUE ); +} + +void mbedtls_set_alarm( int seconds ) +{ + DWORD ThreadId; + + mbedtls_timing_alarmed = 0; + alarmMs = seconds * 1000; + CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + unsigned long delta; + struct timeval offset; + struct _hr_time *t = (struct _hr_time *) val; + + gettimeofday( &offset, NULL ); + + if( reset ) + { + t->start.tv_sec = offset.tv_sec; + t->start.tv_usec = offset.tv_usec; + return( 0 ); + } + + delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 + + ( offset.tv_usec - t->start.tv_usec ) / 1000; + + return( delta ); +} + +static void sighandler( int signum ) +{ + mbedtls_timing_alarmed = 1; + signal( signum, sighandler ); +} + +void mbedtls_set_alarm( int seconds ) +{ + mbedtls_timing_alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); +} + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->fin_ms == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); + + if( elapsed_ms >= ctx->fin_ms ) + return( 2 ); + + if( elapsed_ms >= ctx->int_ms ) + return( 1 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_TIMING_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing mbedtls_timing_hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct mbedtls_timing_hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +#define FAIL do \ +{ \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + \ + return( 1 ); \ +} while( 0 ) + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int mbedtls_timing_self_test( int verbose ) +{ + unsigned long cycles, ratio; + unsigned long millisecs, secs; + int hardfail; + struct mbedtls_timing_hr_time hires; + uint32_t a, b; + mbedtls_timing_delay_context ctx; + + if( verbose != 0 ) + mbedtls_printf( " TIMING tests note: will take some time!\n" ); + + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) mbedtls_timing_get_timer( &hires, 1 ); + + mbedtls_set_alarm( (int) secs ); + while( !mbedtls_timing_alarmed ) + ; + + millisecs = mbedtls_timing_get_timer( &hires, 0 ); + + /* For some reason on Windows it looks like alarm has an extra delay + * (maybe related to creating a new thread). Allow some room here. */ + if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); + + for( a = 200; a <= 400; a += 200 ) + { + for( b = 200; b <= 400; b += 200 ) + { + mbedtls_timing_set_delay( &ctx, a, a + b ); + + busy_msleep( a - a / 8 ); + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; + + busy_msleep( a / 4 ); + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b - a / 8 - b / 8 ); + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b / 4 ); + if( mbedtls_timing_get_delay( &ctx ) != 2 ) + FAIL; + } + } + + mbedtls_timing_set_delay( &ctx, 0, 0 ); + busy_msleep( 200 ); + if( mbedtls_timing_get_delay( &ctx ) != -1 ) + FAIL; + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + hardfail = 0; + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (ignored)\n" ); + + goto hard_test_done; + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +hard_test_done: + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_TIMING_C */ diff --git a/external_libs/mbedtls/library/version.c b/external_libs/mbedtls/library/version.c new file mode 100644 index 00000000..6ca80d46 --- /dev/null +++ b/external_libs/mbedtls/library/version.c @@ -0,0 +1,50 @@ +/* + * Version information + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" +#include + +unsigned int mbedtls_version_get_number() +{ + return( MBEDTLS_VERSION_NUMBER ); +} + +void mbedtls_version_get_string( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING, + sizeof( MBEDTLS_VERSION_STRING ) ); +} + +void mbedtls_version_get_string_full( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING_FULL, + sizeof( MBEDTLS_VERSION_STRING_FULL ) ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/external_libs/mbedtls/library/version_features.c b/external_libs/mbedtls/library/version_features.c new file mode 100644 index 00000000..e866e67a --- /dev/null +++ b/external_libs/mbedtls/library/version_features.c @@ -0,0 +1,647 @@ +/* + * Version feature information + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" + +#include + +static const char *features[] = { +#if defined(MBEDTLS_VERSION_FEATURES) +#if defined(MBEDTLS_HAVE_ASM) + "MBEDTLS_HAVE_ASM", +#endif /* MBEDTLS_HAVE_ASM */ +#if defined(MBEDTLS_HAVE_SSE2) + "MBEDTLS_HAVE_SSE2", +#endif /* MBEDTLS_HAVE_SSE2 */ +#if defined(MBEDTLS_HAVE_TIME) + "MBEDTLS_HAVE_TIME", +#endif /* MBEDTLS_HAVE_TIME */ +#if defined(MBEDTLS_HAVE_TIME_DATE) + "MBEDTLS_HAVE_TIME_DATE", +#endif /* MBEDTLS_HAVE_TIME_DATE */ +#if defined(MBEDTLS_PLATFORM_MEMORY) + "MBEDTLS_PLATFORM_MEMORY", +#endif /* MBEDTLS_PLATFORM_MEMORY */ +#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) + "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) + "MBEDTLS_PLATFORM_EXIT_ALT", +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) + "MBEDTLS_PLATFORM_TIME_ALT", +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) + "MBEDTLS_PLATFORM_FPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) + "MBEDTLS_PLATFORM_PRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) + "MBEDTLS_PLATFORM_SNPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) + "MBEDTLS_PLATFORM_NV_SEED_ALT", +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#if defined(MBEDTLS_DEPRECATED_WARNING) + "MBEDTLS_DEPRECATED_WARNING", +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#if defined(MBEDTLS_DEPRECATED_REMOVED) + "MBEDTLS_DEPRECATED_REMOVED", +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_TIMING_ALT) + "MBEDTLS_TIMING_ALT", +#endif /* MBEDTLS_TIMING_ALT */ +#if defined(MBEDTLS_AES_ALT) + "MBEDTLS_AES_ALT", +#endif /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_ARC4_ALT) + "MBEDTLS_ARC4_ALT", +#endif /* MBEDTLS_ARC4_ALT */ +#if defined(MBEDTLS_BLOWFISH_ALT) + "MBEDTLS_BLOWFISH_ALT", +#endif /* MBEDTLS_BLOWFISH_ALT */ +#if defined(MBEDTLS_CAMELLIA_ALT) + "MBEDTLS_CAMELLIA_ALT", +#endif /* MBEDTLS_CAMELLIA_ALT */ +#if defined(MBEDTLS_DES_ALT) + "MBEDTLS_DES_ALT", +#endif /* MBEDTLS_DES_ALT */ +#if defined(MBEDTLS_XTEA_ALT) + "MBEDTLS_XTEA_ALT", +#endif /* MBEDTLS_XTEA_ALT */ +#if defined(MBEDTLS_MD2_ALT) + "MBEDTLS_MD2_ALT", +#endif /* MBEDTLS_MD2_ALT */ +#if defined(MBEDTLS_MD4_ALT) + "MBEDTLS_MD4_ALT", +#endif /* MBEDTLS_MD4_ALT */ +#if defined(MBEDTLS_MD5_ALT) + "MBEDTLS_MD5_ALT", +#endif /* MBEDTLS_MD5_ALT */ +#if defined(MBEDTLS_RIPEMD160_ALT) + "MBEDTLS_RIPEMD160_ALT", +#endif /* MBEDTLS_RIPEMD160_ALT */ +#if defined(MBEDTLS_SHA1_ALT) + "MBEDTLS_SHA1_ALT", +#endif /* MBEDTLS_SHA1_ALT */ +#if defined(MBEDTLS_SHA256_ALT) + "MBEDTLS_SHA256_ALT", +#endif /* MBEDTLS_SHA256_ALT */ +#if defined(MBEDTLS_SHA512_ALT) + "MBEDTLS_SHA512_ALT", +#endif /* MBEDTLS_SHA512_ALT */ +#if defined(MBEDTLS_MD2_PROCESS_ALT) + "MBEDTLS_MD2_PROCESS_ALT", +#endif /* MBEDTLS_MD2_PROCESS_ALT */ +#if defined(MBEDTLS_MD4_PROCESS_ALT) + "MBEDTLS_MD4_PROCESS_ALT", +#endif /* MBEDTLS_MD4_PROCESS_ALT */ +#if defined(MBEDTLS_MD5_PROCESS_ALT) + "MBEDTLS_MD5_PROCESS_ALT", +#endif /* MBEDTLS_MD5_PROCESS_ALT */ +#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) + "MBEDTLS_RIPEMD160_PROCESS_ALT", +#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ +#if defined(MBEDTLS_SHA1_PROCESS_ALT) + "MBEDTLS_SHA1_PROCESS_ALT", +#endif /* MBEDTLS_SHA1_PROCESS_ALT */ +#if defined(MBEDTLS_SHA256_PROCESS_ALT) + "MBEDTLS_SHA256_PROCESS_ALT", +#endif /* MBEDTLS_SHA256_PROCESS_ALT */ +#if defined(MBEDTLS_SHA512_PROCESS_ALT) + "MBEDTLS_SHA512_PROCESS_ALT", +#endif /* MBEDTLS_SHA512_PROCESS_ALT */ +#if defined(MBEDTLS_DES_SETKEY_ALT) + "MBEDTLS_DES_SETKEY_ALT", +#endif /* MBEDTLS_DES_SETKEY_ALT */ +#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) + "MBEDTLS_DES_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) + "MBEDTLS_DES3_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) + "MBEDTLS_AES_SETKEY_ENC_ALT", +#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ +#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) + "MBEDTLS_AES_SETKEY_DEC_ALT", +#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ +#if defined(MBEDTLS_AES_ENCRYPT_ALT) + "MBEDTLS_AES_ENCRYPT_ALT", +#endif /* MBEDTLS_AES_ENCRYPT_ALT */ +#if defined(MBEDTLS_AES_DECRYPT_ALT) + "MBEDTLS_AES_DECRYPT_ALT", +#endif /* MBEDTLS_AES_DECRYPT_ALT */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + "MBEDTLS_TEST_NULL_ENTROPY", +#endif /* MBEDTLS_TEST_NULL_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + "MBEDTLS_ENTROPY_HARDWARE_ALT", +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#if defined(MBEDTLS_AES_ROM_TABLES) + "MBEDTLS_AES_ROM_TABLES", +#endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + "MBEDTLS_CAMELLIA_SMALL_MEMORY", +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + "MBEDTLS_CIPHER_MODE_CBC", +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_CFB) + "MBEDTLS_CIPHER_MODE_CFB", +#endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_CTR) + "MBEDTLS_CIPHER_MODE_CTR", +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + "MBEDTLS_CIPHER_NULL_CIPHER", +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + "MBEDTLS_CIPHER_PADDING_PKCS7", +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + "MBEDTLS_CIPHER_PADDING_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) + "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + "MBEDTLS_ECP_DP_SECP192R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + "MBEDTLS_ECP_DP_SECP224R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + "MBEDTLS_ECP_DP_SECP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + "MBEDTLS_ECP_DP_SECP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + "MBEDTLS_ECP_DP_SECP521R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + "MBEDTLS_ECP_DP_SECP192K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + "MBEDTLS_ECP_DP_SECP224K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + "MBEDTLS_ECP_DP_SECP256K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + "MBEDTLS_ECP_DP_BP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + "MBEDTLS_ECP_DP_BP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + "MBEDTLS_ECP_DP_BP512R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + "MBEDTLS_ECP_DP_CURVE25519_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_NIST_OPTIM) + "MBEDTLS_ECP_NIST_OPTIM", +#endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + "MBEDTLS_ECDSA_DETERMINISTIC", +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + "MBEDTLS_PK_PARSE_EC_EXTENDED", +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + "MBEDTLS_ERROR_STRERROR_DUMMY", +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ +#if defined(MBEDTLS_GENPRIME) + "MBEDTLS_GENPRIME", +#endif /* MBEDTLS_GENPRIME */ +#if defined(MBEDTLS_FS_IO) + "MBEDTLS_FS_IO", +#endif /* MBEDTLS_FS_IO */ +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) + "MBEDTLS_NO_PLATFORM_ENTROPY", +#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) + "MBEDTLS_ENTROPY_FORCE_SHA256", +#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) + "MBEDTLS_ENTROPY_NV_SEED", +#endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if defined(MBEDTLS_MEMORY_DEBUG) + "MBEDTLS_MEMORY_DEBUG", +#endif /* MBEDTLS_MEMORY_DEBUG */ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + "MBEDTLS_MEMORY_BACKTRACE", +#endif /* MBEDTLS_MEMORY_BACKTRACE */ +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + "MBEDTLS_PK_RSA_ALT_SUPPORT", +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ +#if defined(MBEDTLS_PKCS1_V15) + "MBEDTLS_PKCS1_V15", +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + "MBEDTLS_PKCS1_V21", +#endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_RSA_NO_CRT) + "MBEDTLS_RSA_NO_CRT", +#endif /* MBEDTLS_RSA_NO_CRT */ +#if defined(MBEDTLS_SELF_TEST) + "MBEDTLS_SELF_TEST", +#endif /* MBEDTLS_SELF_TEST */ +#if defined(MBEDTLS_SHA256_SMALLER) + "MBEDTLS_SHA256_SMALLER", +#endif /* MBEDTLS_SHA256_SMALLER */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + "MBEDTLS_SSL_ALL_ALERT_MESSAGES", +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_DEBUG_ALL) + "MBEDTLS_SSL_DEBUG_ALL", +#endif /* MBEDTLS_SSL_DEBUG_ALL */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + "MBEDTLS_SSL_ENCRYPT_THEN_MAC", +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + "MBEDTLS_SSL_FALLBACK_SCSV", +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + "MBEDTLS_SSL_HW_RECORD_ACCEL", +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + "MBEDTLS_SSL_CBC_RECORD_SPLITTING", +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + "MBEDTLS_SSL_RENEGOTIATION", +#endif /* MBEDTLS_SSL_RENEGOTIATION */ +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", +#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + "MBEDTLS_SSL_PROTO_SSL3", +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) + "MBEDTLS_SSL_PROTO_TLS1", +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) + "MBEDTLS_SSL_PROTO_TLS1_1", +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + "MBEDTLS_SSL_PROTO_TLS1_2", +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + "MBEDTLS_SSL_PROTO_DTLS", +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_ALPN) + "MBEDTLS_SSL_ALPN", +#endif /* MBEDTLS_SSL_ALPN */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + "MBEDTLS_SSL_DTLS_ANTI_REPLAY", +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + "MBEDTLS_SSL_DTLS_HELLO_VERIFY", +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + "MBEDTLS_SSL_SESSION_TICKETS", +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + "MBEDTLS_SSL_EXPORT_KEYS", +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + "MBEDTLS_SSL_SERVER_NAME_INDICATION", +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + "MBEDTLS_SSL_TRUNCATED_HMAC", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_THREADING_ALT) + "MBEDTLS_THREADING_ALT", +#endif /* MBEDTLS_THREADING_ALT */ +#if defined(MBEDTLS_THREADING_PTHREAD) + "MBEDTLS_THREADING_PTHREAD", +#endif /* MBEDTLS_THREADING_PTHREAD */ +#if defined(MBEDTLS_VERSION_FEATURES) + "MBEDTLS_VERSION_FEATURES", +#endif /* MBEDTLS_VERSION_FEATURES */ +#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", +#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ +#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", +#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + "MBEDTLS_X509_CHECK_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + "MBEDTLS_X509_RSASSA_PSS_SUPPORT", +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + "MBEDTLS_ZLIB_SUPPORT", +#endif /* MBEDTLS_ZLIB_SUPPORT */ +#if defined(MBEDTLS_AESNI_C) + "MBEDTLS_AESNI_C", +#endif /* MBEDTLS_AESNI_C */ +#if defined(MBEDTLS_AES_C) + "MBEDTLS_AES_C", +#endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_ARC4_C) + "MBEDTLS_ARC4_C", +#endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_ASN1_PARSE_C) + "MBEDTLS_ASN1_PARSE_C", +#endif /* MBEDTLS_ASN1_PARSE_C */ +#if defined(MBEDTLS_ASN1_WRITE_C) + "MBEDTLS_ASN1_WRITE_C", +#endif /* MBEDTLS_ASN1_WRITE_C */ +#if defined(MBEDTLS_BASE64_C) + "MBEDTLS_BASE64_C", +#endif /* MBEDTLS_BASE64_C */ +#if defined(MBEDTLS_BIGNUM_C) + "MBEDTLS_BIGNUM_C", +#endif /* MBEDTLS_BIGNUM_C */ +#if defined(MBEDTLS_BLOWFISH_C) + "MBEDTLS_BLOWFISH_C", +#endif /* MBEDTLS_BLOWFISH_C */ +#if defined(MBEDTLS_CAMELLIA_C) + "MBEDTLS_CAMELLIA_C", +#endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_CCM_C) + "MBEDTLS_CCM_C", +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CERTS_C) + "MBEDTLS_CERTS_C", +#endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CIPHER_C) + "MBEDTLS_CIPHER_C", +#endif /* MBEDTLS_CIPHER_C */ +#if defined(MBEDTLS_CMAC_C) + "MBEDTLS_CMAC_C", +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_CTR_DRBG_C) + "MBEDTLS_CTR_DRBG_C", +#endif /* MBEDTLS_CTR_DRBG_C */ +#if defined(MBEDTLS_DEBUG_C) + "MBEDTLS_DEBUG_C", +#endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_DES_C) + "MBEDTLS_DES_C", +#endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_DHM_C) + "MBEDTLS_DHM_C", +#endif /* MBEDTLS_DHM_C */ +#if defined(MBEDTLS_ECDH_C) + "MBEDTLS_ECDH_C", +#endif /* MBEDTLS_ECDH_C */ +#if defined(MBEDTLS_ECDSA_C) + "MBEDTLS_ECDSA_C", +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_ECJPAKE_C) + "MBEDTLS_ECJPAKE_C", +#endif /* MBEDTLS_ECJPAKE_C */ +#if defined(MBEDTLS_ECP_C) + "MBEDTLS_ECP_C", +#endif /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_ENTROPY_C) + "MBEDTLS_ENTROPY_C", +#endif /* MBEDTLS_ENTROPY_C */ +#if defined(MBEDTLS_ERROR_C) + "MBEDTLS_ERROR_C", +#endif /* MBEDTLS_ERROR_C */ +#if defined(MBEDTLS_GCM_C) + "MBEDTLS_GCM_C", +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_HAVEGE_C) + "MBEDTLS_HAVEGE_C", +#endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_HMAC_DRBG_C) + "MBEDTLS_HMAC_DRBG_C", +#endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_MD_C) + "MBEDTLS_MD_C", +#endif /* MBEDTLS_MD_C */ +#if defined(MBEDTLS_MD2_C) + "MBEDTLS_MD2_C", +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + "MBEDTLS_MD4_C", +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + "MBEDTLS_MD5_C", +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + "MBEDTLS_MEMORY_BUFFER_ALLOC_C", +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ +#if defined(MBEDTLS_NET_C) + "MBEDTLS_NET_C", +#endif /* MBEDTLS_NET_C */ +#if defined(MBEDTLS_OID_C) + "MBEDTLS_OID_C", +#endif /* MBEDTLS_OID_C */ +#if defined(MBEDTLS_PADLOCK_C) + "MBEDTLS_PADLOCK_C", +#endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_PEM_PARSE_C) + "MBEDTLS_PEM_PARSE_C", +#endif /* MBEDTLS_PEM_PARSE_C */ +#if defined(MBEDTLS_PEM_WRITE_C) + "MBEDTLS_PEM_WRITE_C", +#endif /* MBEDTLS_PEM_WRITE_C */ +#if defined(MBEDTLS_PK_C) + "MBEDTLS_PK_C", +#endif /* MBEDTLS_PK_C */ +#if defined(MBEDTLS_PK_PARSE_C) + "MBEDTLS_PK_PARSE_C", +#endif /* MBEDTLS_PK_PARSE_C */ +#if defined(MBEDTLS_PK_WRITE_C) + "MBEDTLS_PK_WRITE_C", +#endif /* MBEDTLS_PK_WRITE_C */ +#if defined(MBEDTLS_PKCS5_C) + "MBEDTLS_PKCS5_C", +#endif /* MBEDTLS_PKCS5_C */ +#if defined(MBEDTLS_PKCS11_C) + "MBEDTLS_PKCS11_C", +#endif /* MBEDTLS_PKCS11_C */ +#if defined(MBEDTLS_PKCS12_C) + "MBEDTLS_PKCS12_C", +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PLATFORM_C) + "MBEDTLS_PLATFORM_C", +#endif /* MBEDTLS_PLATFORM_C */ +#if defined(MBEDTLS_RIPEMD160_C) + "MBEDTLS_RIPEMD160_C", +#endif /* MBEDTLS_RIPEMD160_C */ +#if defined(MBEDTLS_RSA_C) + "MBEDTLS_RSA_C", +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_SHA1_C) + "MBEDTLS_SHA1_C", +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + "MBEDTLS_SHA256_C", +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + "MBEDTLS_SHA512_C", +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SSL_CACHE_C) + "MBEDTLS_SSL_CACHE_C", +#endif /* MBEDTLS_SSL_CACHE_C */ +#if defined(MBEDTLS_SSL_COOKIE_C) + "MBEDTLS_SSL_COOKIE_C", +#endif /* MBEDTLS_SSL_COOKIE_C */ +#if defined(MBEDTLS_SSL_TICKET_C) + "MBEDTLS_SSL_TICKET_C", +#endif /* MBEDTLS_SSL_TICKET_C */ +#if defined(MBEDTLS_SSL_CLI_C) + "MBEDTLS_SSL_CLI_C", +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + "MBEDTLS_SSL_SRV_C", +#endif /* MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_TLS_C) + "MBEDTLS_SSL_TLS_C", +#endif /* MBEDTLS_SSL_TLS_C */ +#if defined(MBEDTLS_THREADING_C) + "MBEDTLS_THREADING_C", +#endif /* MBEDTLS_THREADING_C */ +#if defined(MBEDTLS_TIMING_C) + "MBEDTLS_TIMING_C", +#endif /* MBEDTLS_TIMING_C */ +#if defined(MBEDTLS_VERSION_C) + "MBEDTLS_VERSION_C", +#endif /* MBEDTLS_VERSION_C */ +#if defined(MBEDTLS_X509_USE_C) + "MBEDTLS_X509_USE_C", +#endif /* MBEDTLS_X509_USE_C */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + "MBEDTLS_X509_CRT_PARSE_C", +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_X509_CRL_PARSE_C) + "MBEDTLS_X509_CRL_PARSE_C", +#endif /* MBEDTLS_X509_CRL_PARSE_C */ +#if defined(MBEDTLS_X509_CSR_PARSE_C) + "MBEDTLS_X509_CSR_PARSE_C", +#endif /* MBEDTLS_X509_CSR_PARSE_C */ +#if defined(MBEDTLS_X509_CREATE_C) + "MBEDTLS_X509_CREATE_C", +#endif /* MBEDTLS_X509_CREATE_C */ +#if defined(MBEDTLS_X509_CRT_WRITE_C) + "MBEDTLS_X509_CRT_WRITE_C", +#endif /* MBEDTLS_X509_CRT_WRITE_C */ +#if defined(MBEDTLS_X509_CSR_WRITE_C) + "MBEDTLS_X509_CSR_WRITE_C", +#endif /* MBEDTLS_X509_CSR_WRITE_C */ +#if defined(MBEDTLS_XTEA_C) + "MBEDTLS_XTEA_C", +#endif /* MBEDTLS_XTEA_C */ +#endif /* MBEDTLS_VERSION_FEATURES */ + NULL +}; + +int mbedtls_version_check_feature( const char *feature ) +{ + const char **idx = features; + + if( *idx == NULL ) + return( -2 ); + + if( feature == NULL ) + return( -1 ); + + while( *idx != NULL ) + { + if( !strcmp( *idx, feature ) ) + return( 0 ); + idx++; + } + return( -1 ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/external_libs/mbedtls/library/x509.c b/external_libs/mbedtls/library/x509.c new file mode 100644 index 00000000..fad390d8 --- /dev/null +++ b/external_libs/mbedtls/library/x509.c @@ -0,0 +1,1063 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_USE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#endif + + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) +#include +#include +#include +#endif +#endif + +#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) paramaters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ) +{ + int ret; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + + MBEDTLS_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + val->p = *p; + *p += val->len; + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int(unsigned char **p, unsigned 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 ); +} + +/* + * 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; + 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 ) + { + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + CHECK( x509_parse_int( p, 2, &time->year ) ); + 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 ) ); + if( len > 10 ) + CHECK( x509_parse_int( p, 2, &time->sec ) ); + if( len > 12 && *(*p)++ != 'Z' ) + return( MBEDTLS_ERR_X509_INVALID_DATE ); + + time->year += 100 * ( time->year < 50 ); + time->year += 1900; + + CHECK( x509_date_is_valid( time ) ); + + return( 0 ); + } + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + { + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + CHECK( x509_parse_int( p, 4, &time->year ) ); + 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 ) ); + if( len > 12 ) + CHECK( x509_parse_int( p, 2, &time->sec ) ); + if( len > 14 && *(*p)++ != 'Z' ) + return( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( time ) ); + + return( 0 ); + } + else + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); +} + +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/external_libs/mbedtls/library/x509_create.c b/external_libs/mbedtls/library/x509_create.c new file mode 100644 index 00000000..df20ec8e --- /dev/null +++ b/external_libs/mbedtls/library/x509_create.c @@ -0,0 +1,340 @@ +/* + * X.509 base functions for creating certificates / CSRs + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CREATE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" + +#include + +typedef struct { + const char *name; + size_t name_len; + const char*oid; +} x509_attr_descriptor_t; + +#define ADD_STRLEN( s ) s, sizeof( s ) - 1 + +static const x509_attr_descriptor_t x509_attrs[] = +{ + { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, + { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, + { ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY }, + { ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY }, + { ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION }, + { ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION }, + { ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY }, + { ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY }, + { ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL }, + { ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT }, + { ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT }, + { ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE }, + { ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE }, + { ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL }, + { ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER }, + { ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS }, + { ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE }, + { ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER }, + { ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE }, + { ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME }, + { ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME }, + { ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME }, + { ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME }, + { ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS }, + { ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM }, + { ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER }, + { ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT }, + { ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT }, + { NULL, 0, NULL } +}; + +static const char *x509_at_oid_from_name( const char *name, size_t name_len ) +{ + const x509_attr_descriptor_t *cur; + + for( cur = x509_attrs; cur->name != NULL; cur++ ) + if( cur->name_len == name_len && + strncmp( cur->name, name, name_len ) == 0 ) + break; + + return( cur->oid ); +} + +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) +{ + int ret = 0; + const char *s = name, *c = s; + const char *end = s + strlen( s ); + const char *oid = NULL; + int in_tag = 1; + char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + char *d = data; + + /* Clear existing chain if present */ + mbedtls_asn1_free_named_data_list( head ); + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) + { + ret = MBEDTLS_ERR_X509_UNKNOWN_OID; + goto exit; + } + + s = c + 1; + in_tag = 0; + d = data; + } + + if( !in_tag && *c == '\\' && c != end ) + { + c++; + + /* Check for valid escaped characters */ + if( c == end || *c != ',' ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + else if( !in_tag && ( *c == ',' || c == end ) ) + { + if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + while( c < end && *(c + 1) == ' ' ) + c++; + + s = c + 1; + in_tag = 1; + } + + if( !in_tag && s != c + 1 ) + { + *(d++) = *c; + + if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + + c++; + } + +exit: + + return( ret ); +} + +/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved + * to store the critical boolean for us + */ +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + cur->val.p[0] = critical; + memcpy( cur->val.p + 1, val, val_len ); + + return( 0 ); +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_write_name( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + const unsigned char *name, size_t name_len ) +{ + int ret; + size_t len = 0; + + // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL + // + if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len && + memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start, + (const char *) name, + name_len ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start, + (const char *) name, + name_len ) ); + } + + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret; + size_t len = 0; + mbedtls_asn1_named_data *cur = first; + + while( cur != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, + cur->oid.len, + cur->val.p, cur->val.len ) ); + cur = cur->next; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ) +{ + int ret; + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, sig, len ); + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, + oid_len, 0 ) ); + + return( (int) len ); +} + +static int x509_write_extension( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *ext ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +/* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + */ +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret; + size_t len = 0; + mbedtls_asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( (int) len ); +} + +#endif /* MBEDTLS_X509_CREATE_C */ diff --git a/external_libs/mbedtls/library/x509_crl.c b/external_libs/mbedtls/library/x509_crl.c new file mode 100644 index 00000000..7b2b4733 --- /dev/null +++ b/external_libs/mbedtls/library/x509_crl.c @@ -0,0 +1,722 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + +#include "mbedtls/x509_crl.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Version ::= INTEGER { v1(0), v2(1) } + */ +static int x509_crl_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * X.509 CRL v2 extensions (no extensions parsed yet.) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + size_t len = 0; + + /* Get explicit tag */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL v2 entry extensions (no extensions parsed yet.) + */ +static int x509_get_crl_entry_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + size_t len = 0; + + /* OPTIONAL */ + if( end <= *p ) + return( 0 ); + + ext->tag = **p; + ext->p = *p; + + /* + * Get CRL-entry extension sequence header + * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crl_entry *entry ) +{ + int ret; + size_t entry_len; + mbedtls_x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + cur_entry->raw.tag = **p; + cur_entry->raw.p = *p; + cur_entry->raw.len = len2; + end2 = *p + len2; + + if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end2, + &cur_entry->revocation_date ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_crl_entry_ext( p, end2, + &cur_entry->entry_ext ) ) != 0 ) + return( ret ); + + if( *p < end ) + { + cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur_entry = cur_entry->next; + } + } + + return( 0 ); +} + +/* + * Parse one CRLs in DER format and append it to the chained list + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + mbedtls_x509_crl *crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Add new CRL on the end of the chain if needed. + */ + while( crl->version != 0 && crl->next != NULL ) + crl = crl->next; + + if( crl->version != 0 && crl->next == NULL ) + { + crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); + + if( crl->next == NULL ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + mbedtls_x509_crl_init( crl->next ); + crl = crl->next; + } + + /* + * Copy raw DER-encoded CRL + */ + if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crl->raw.p = p; + crl->raw.len = buflen; + + end = p + buflen; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->version++; + + if( crl->version > 2 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && + ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid.len != sig_oid2.len || + memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret; + size_t use_len; + mbedtls_pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + do + { + mbedtls_pem_init( &pem ); + + // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated + // string + if( buflen == 0 || buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + is_pem = 1; + + buflen -= use_len; + buf += use_len; + + if( ( ret = mbedtls_x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + return( ret ); + } + + mbedtls_pem_free( &pem ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + } + /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. + * And a valid CRL cannot be less than 1 byte anyway. */ + while( is_pem && buflen > 1 ); + + if( is_pem ) + return( 0 ); + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crl_parse( chain, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ) +{ + int ret; + size_t n; + char *p; + const mbedtls_x509_crl_entry *entry; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = &crl->entry; + + ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%sserial number: ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = entry->next; + } + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) +{ + memset( crl, 0, sizeof(mbedtls_x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) +{ + mbedtls_x509_crl *crl_cur = crl; + mbedtls_x509_crl *crl_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + if( crl_prv != crl ) + mbedtls_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/external_libs/mbedtls/library/x509_crt.c b/external_libs/mbedtls/library/x509_crt.c new file mode 100644 index 00000000..60e14f90 --- /dev/null +++ b/external_libs/mbedtls/library/x509_crt.c @@ -0,0 +1,2394 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#include +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ + /* 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 ) +{ + int success = 0, first_error = 0, total_failed = 0; +#if defined(MBEDTLS_PEM_PARSE_C) + 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, 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; + + 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_x509_time_is_past( &trust_ca->valid_to ) ) + { + continue; + } + + if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) + { + 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; + } + + /* + * 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; + + break; + } + + /* + * 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( 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/external_libs/mbedtls/library/x509_csr.c b/external_libs/mbedtls/library/x509_csr.c new file mode 100644 index 00000000..603d06b6 --- /dev/null +++ b/external_libs/mbedtls/library/x509_csr.c @@ -0,0 +1,423 @@ +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + mbedtls_x509_buf sig_params; + + memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + mbedtls_x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = mbedtls_calloc( 1, len = buflen ); + + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + csr->version++; + + if( csr->version != 1 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + * + * The list of possible attributes is open-ended, though RFC 2985 + * (PKCS#9) defines a few in section 5.4. We currently don't support any, + * so we just ignore them. This is a safe thing to do as the worst thing + * that could happen is that we issue a certificate that does not match + * the requester's expectations - this cannot cause a violation of our + * signature policies. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ + int ret; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t use_len; + mbedtls_pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) + return( ret ); + + mbedtls_pem_free( &pem ); + return( 0 ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load a CSR into the structure + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_csr_parse( csr, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &csr->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CSR + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) +{ + memset( csr, 0, sizeof(mbedtls_x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if( csr == NULL ) + return; + + mbedtls_pk_free( &csr->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + mbedtls_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_free( csr->raw.p ); + } + + mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) ); +} + +#endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/external_libs/mbedtls/library/x509write_crt.c b/external_libs/mbedtls/library/x509write_crt.c new file mode 100644 index 00000000..d1d9a22a --- /dev/null +++ b/external_libs/mbedtls/library/x509write_crt.c @@ -0,0 +1,459 @@ +/* + * X.509 certificate writing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * References: + * - certificates: RFC 5280, updated by RFC 6818 + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif /* MBEDTLS_PEM_WRITE_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof(mbedtls_x509write_cert) ); + + mbedtls_mpi_init( &ctx->serial ); + ctx->version = MBEDTLS_X509_CRT_VERSION_3; +} + +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) +{ + mbedtls_mpi_free( &ctx->serial ); + + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->issuer ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_cert) ); +} + +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) +{ + ctx->version = version; +} + +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) +{ + ctx->subject_key = key; +} + +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) +{ + ctx->issuer_key = key; +} + +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ) +{ + return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); +} + +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ) +{ + int ret; + + if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ) +{ + if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || + strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ); +} + +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ) +{ + int ret; + unsigned char buf[9]; + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + + if( is_ca && max_pathlen > 127 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) ); + } + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, + MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), + 0, buf + sizeof(buf) - len, len ); +} + +#if defined(MBEDTLS_SHA1_C) +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); + + mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); + c = buf + sizeof(buf) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); + + return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + + mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); + c = buf + sizeof(buf) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} +#endif /* MBEDTLS_SHA1_C */ + +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ) +{ + unsigned char buf[4], ku; + unsigned char *c; + int ret; + + /* We currently only support 7 bits, from 0x80 to 0x02 */ + if( ( key_usage & ~0xfe ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + + c = buf + 4; + ku = (unsigned char) key_usage; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *time, size_t size ) +{ + int ret; + size_t len = 0; + + /* + * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) time + 2, + size - 2 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) time, + size ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char tmp_buf[2048]; + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed in tmp_buf + */ + c = tmp_buf + sizeof( tmp_buf ); + + /* Signature algorithm needed in TBS, and later for actual signature */ + pk_alg = mbedtls_pk_get_type( ctx->issuer_key ); + if( pk_alg == MBEDTLS_PK_ECKEY ) + pk_alg = MBEDTLS_PK_ECDSA; + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + + /* + * SubjectPublicKeyInfo + */ + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, + tmp_buf, c - tmp_buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Issuer ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, + sig_oid, strlen( sig_oid ), 0 ) ); + + /* + * Serial ::= INTEGER + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + sub_len = 0; + MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Make signature + */ + mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + + if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + /* + * Write data to output buffer + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); + + if( len > (size_t)( c2 - buf ) ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char output_buf[4096]; + size_t olen = 0; + + if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CRT_WRITE_C */ diff --git a/external_libs/mbedtls/library/x509write_csr.c b/external_libs/mbedtls/library/x509write_csr.c new file mode 100644 index 00000000..8fd856b2 --- /dev/null +++ b/external_libs/mbedtls/library/x509write_csr.c @@ -0,0 +1,259 @@ +/* + * X.509 Certificate Signing Request writing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1write.h" + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) +{ + memset( ctx, 0, sizeof(mbedtls_x509write_csr) ); +} + +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) +{ + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_csr) ); +} + +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) +{ + ctx->key = key; +} + +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + 0, val, val_len ); +} + +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char tmp_buf[2048]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed in tmp_buf + */ + c = tmp_buf + sizeof( tmp_buf ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + + if( len ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, + MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, + tmp_buf, c - tmp_buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Prepare signature + */ + mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + + pk_alg = mbedtls_pk_get_type( ctx->key ); + if( pk_alg == MBEDTLS_PK_ECKEY ) + pk_alg = MBEDTLS_PK_ECDSA; + + if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 || + ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Write data to output buffer + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); + + if( len > (size_t)( c2 - buf ) ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char output_buf[4096]; + size_t olen = 0; + + if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CSR_WRITE_C */ diff --git a/external_libs/mbedtls/library/xtea.c b/external_libs/mbedtls/library/xtea.c new file mode 100644 index 00000000..fe0a3509 --- /dev/null +++ b/external_libs/mbedtls/library/xtea.c @@ -0,0 +1,281 @@ +/* + * An 32-bit implementation of the XTEA algorithm + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_XTEA_C) + +#include "mbedtls/xtea.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_XTEA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_xtea_context ) ); +} + +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); +} + +/* + * XTEA key schedule + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ) +{ + int i; + + memset( ctx, 0, sizeof(mbedtls_xtea_context) ); + + for( i = 0; i < 4; i++ ) + { + GET_UINT32_BE( ctx->k[i], key, i << 2 ); + } +} + +/* + * XTEA encrypt function + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode, + const unsigned char input[8], unsigned char output[8]) +{ + uint32_t *k, v0, v1, i; + + k = ctx->k; + + GET_UINT32_BE( v0, input, 0 ); + GET_UINT32_BE( v1, input, 4 ); + + if( mode == MBEDTLS_XTEA_ENCRYPT ) + { + uint32_t sum = 0, delta = 0x9E3779B9; + + for( i = 0; i < 32; i++ ) + { + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + sum += delta; + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + } + } + else /* MBEDTLS_XTEA_DECRYPT */ + { + uint32_t delta = 0x9E3779B9, sum = delta * 32; + + for( i = 0; i < 32; i++ ) + { + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + sum -= delta; + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + } + } + + PUT_UINT32_BE( v0, output, 0 ); + PUT_UINT32_BE( v1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * XTEA-CBC buffer encryption/decryption + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length, + unsigned char iv[8], const unsigned char *input, + unsigned char *output) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_XTEA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_xtea_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_xtea_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* !MBEDTLS_XTEA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * XTEA tests vectors (non-official) + */ + +static const unsigned char xtea_test_key[6][16] = +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char xtea_test_pt[6][8] = +{ + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } +}; + +static const unsigned char xtea_test_ct[6][8] = +{ + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } +}; + +/* + * Checkup routine + */ +int mbedtls_xtea_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char buf[8]; + mbedtls_xtea_context ctx; + + mbedtls_xtea_init( &ctx ); + for( i = 0; i < 6; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " XTEA test #%d: ", i + 1 ); + + memcpy( buf, xtea_test_pt[i], 8 ); + + mbedtls_xtea_setup( &ctx, xtea_test_key[i] ); + mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf ); + + if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_xtea_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_XTEA_C */ diff --git a/include/config.h b/include/config.h new file mode 100755 index 00000000..8c4dd673 --- /dev/null +++ b/include/config.h @@ -0,0 +1,20 @@ +/* #undef AUTH_MODE_CERT */ +#define AUTH_MODE_KEY +/* #undef AUTH_WITH_NOTLS */ +#define GATEWAY_ENABLED +/* #undef COAP_COMM_ENABLED */ +#define OTA_MQTT_CHANNEL +#define SYSTEM_COMM +#define DEV_DYN_REG_ENABLED +/* #undef LOG_UPLOAD */ +/* #undef IOT_DEBUG */ +/* #undef DEBUG_DEV_INFO_USED */ +/* #undef AT_TCP_ENABLED */ +/* #undef AT_UART_RECV_IRQ */ +/* #undef AT_OS_USED */ +/* #undef AT_DEBUG */ +#define OTA_USE_HTTPS +#define MULTITHREAD_ENABLED +#define BROADCAST_ENABLED +#define RRPC_ENABLED +#define REMOTE_CONFIG_MQTT diff --git a/include/exports/qcloud_iot_export_broadcast.h b/include/exports/qcloud_iot_export_broadcast.h new file mode 100755 index 00000000..63cd429d --- /dev/null +++ b/include/exports/qcloud_iot_export_broadcast.h @@ -0,0 +1,47 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_BROADCAST_H_ +#define QCLOUD_IOT_EXPORT_BROADCAST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef BROADCAST_ENABLED + +/** + * @brief broadcast message callback + */ +typedef void (*OnBroadcastMessageCallback)(void *pClient, const char *msg, uint32_t msgLen); + +/** + * @brief Subscribe broadcast topic with message callback + * + * @param pClient pointer of handle to MQTT client + * @param callback Broadcast message callback + * @return QCLOUD_RET_SUCCESS when success, otherwise fail + */ +int IOT_Broadcast_Subscribe(void *pClient, OnBroadcastMessageCallback callback); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // QCLOUD_IOT_EXPORT_BROADCAST_H_ diff --git a/include/exports/qcloud_iot_export_coap.h b/include/exports/qcloud_iot_export_coap.h new file mode 100755 index 00000000..097e7c9e --- /dev/null +++ b/include/exports/qcloud_iot_export_coap.h @@ -0,0 +1,187 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_COAP_H_ +#define QCLOUD_IOT_EXPORT_COAP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/** + * @brief CoAP needResp message callback function define + * + * @param message CoAP message + * @param userContext User context when sending message + */ +typedef void (*OnRespCallback)(void *message, void *userContext); + +/** + * CoAP EVENT TYPE + */ +typedef enum { + COAP_EVENT_RECEIVE_ACK = 0, // MSG ACK received + COAP_EVENT_RECEIVE_RESPCONTENT = 1, // MSG response received + COAP_EVENT_UNAUTHORIZED = -1, // Device auth failed or token expired + COAP_EVENT_FORBIDDEN = -2, // CoAP URI invalid or without permission + COAP_EVENT_INTERNAL_SERVER_ERROR = -3, // CoAP server error + COAP_EVENT_ACK_TIMEOUT = -4, // MSG ACK timeout + COAP_EVENT_SEPRESP_TIMEOUT = -5, // MSG response timeout +} CoAPEventType; + +typedef struct { + /* event type */ + CoAPEventType event_type; + /* message content */ + void *message; + +} CoAPEventMessage; + +typedef void (*CoAPEventHandleFunc)(void *pcontext, CoAPEventMessage *message); + +/* The structure of COAP event handle */ +typedef struct { + CoAPEventHandleFunc h_fp; + void * context; +} CoAPEventHandler; + +/** + * @brief CoAP data structure when sending msg + */ +typedef struct { + bool need_resp; // Need response from peer (true), or not (false). Currently only false is supported + char * pay_load; // COAP msg payload + size_t pay_load_len; // COAP msg payload length + void * user_context; // user context for callback + OnRespCallback resp_callback; // function callback when recv msg response, valid only when need_resp is true +} SendMsgParams; + +#define DEFAULT_SENDMSG_PARAMS \ + { \ + false, NULL, 0, NULL, NULL \ + } + +/** + * CoAP data structure when constructing client + */ +typedef struct { + /* device info */ + char *product_id; // product ID + char *device_name; // device name + +#ifdef AUTH_MODE_CERT + char cert_file[FILE_PATH_MAX_LEN]; // full path of device cert file + char key_file[FILE_PATH_MAX_LEN]; // full path of device key file +#else + char *device_secret; // device secret +#endif + + uint32_t command_timeout; // coap timeout value when waiting for ACK/response + unsigned char max_retry_count; // CoAP max sending retry count + CoAPEventHandler event_handle; // event callback + +} CoAPInitParams; + +#ifdef AUTH_MODE_CERT +#define DEFAULT_COAPINIT_PARAMS \ + { \ + NULL, NULL, {0}, {0}, 2000, 5, { 0 } \ + } +#else +#define DEFAULT_COAPINIT_PARAMS \ + { \ + NULL, NULL, NULL, 2000, 5, { 0 } \ + } +#endif + +/** + * @brief Construct CoAP Client and connect to server + * + * @param pParams CoAP Client construct and connect parameters + * + * @return COAPClient pointer, NULL when fail + */ +void *IOT_COAP_Construct(CoAPInitParams *pParams); + +/** + * @brief Disconnect with COAP server and destroy COAPClient + * + * @param pClient COAPClient pointer + * + */ +void IOT_COAP_Destroy(void **pClient); + +/** + * @brief Read and handle CoAP msg in synchronized way + * + * @param pClient COAPClient pointer + * @param timeout_ms timeout value (unit: ms) for this Yielding + * @return QCLOUD_RET_SUCCESS when success, otherwise fail + */ +int IOT_COAP_Yield(void *pClient, uint32_t timeout_ms); + +/** + * @brief Send/publish CoAP msg + * + * @param pClient COAPClient pointer + * @param topicName CoAP URI (msg topic) + * @param sendParams Tx msg parameters + * @return value > 0 for msg Id; value < 0 for failure + */ +int IOT_COAP_SendMessage(void *pClient, char *topicName, SendMsgParams *sendParams); + +/** + * @brief Get COAP Response msgId + * + * @param pMessage COAP Response msg + * @return value > 0 for msg Id; value < 0 for failure + */ +int IOT_COAP_GetMessageId(void *pMessage); + +/** + * @brief Get COAP Response payload + * + * @param pMessage COAP Response msg + * @param payload msg payload + * @param payloadLen msg payload length + * @return QCLOUD_RET_SUCCESS when success, otherwise fail + */ +int IOT_COAP_GetMessagePayload(void *pMessage, char **payload, int *payloadLen); + +/** + * @brief Get COAP Response msg error code + * + * @param pMessage COAP Response msg + * @return COAPEventType converted from msg error code + */ +int IOT_COAP_GetMessageCode(void *pMessage); + +/** + * @brief Get the device Info of the dedicated COAP client + * + * @param pClient handle to COAP client + * @return pointer to the device Info + */ +DeviceInfo *IOT_COAP_GetDeviceInfo(void *pClient); + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_COAP_H_ */ diff --git a/include/exports/qcloud_iot_export_dynreg.h b/include/exports/qcloud_iot_export_dynreg.h new file mode 100755 index 00000000..9c715ca5 --- /dev/null +++ b/include/exports/qcloud_iot_export_dynreg.h @@ -0,0 +1,39 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QLCOUD_IOT_EXPORT_DYNREG_H_ +#define QLCOUD_IOT_EXPORT_DYNREG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_export.h" + +/** + * @brief Do dynamic register/create device + * + * @param pDevInfo In: device info with [ProductId, ProductKey, DeviceName] + * Out: device info with [ProductId, DeviceName, DeviceSecret or Device cert/key file] + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_DynReg_Device(DeviceInfo *pDevInfo); + +#ifdef __cplusplus +} +#endif + +#endif // QLCOUD_IOT_EXPORT_DYNREG_H_ \ No newline at end of file diff --git a/include/exports/qcloud_iot_export_error.h b/include/exports/qcloud_iot_export_error.h new file mode 100755 index 00000000..be06c8d2 --- /dev/null +++ b/include/exports/qcloud_iot_export_error.h @@ -0,0 +1,118 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_ERROR_H_ +#define QCLOUD_IOT_EXPORT_ERROR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * IOT SDK return/error code + * Enumeration of return code in QCloud IoT C-SDK. + * Values less than 0 are specific error codes + * Value of 0 is successful return + * Values greater than 0 are specific non-error return codes + */ +typedef enum { + QCLOUD_RET_MQTT_ALREADY_CONNECTED = 4, // Already connected with MQTT server + QCLOUD_RET_MQTT_CONNACK_CONNECTION_ACCEPTED = 3, // MQTT connection accepted by server + QCLOUD_RET_MQTT_MANUALLY_DISCONNECTED = 2, // Manually disconnected with MQTT server + QCLOUD_RET_MQTT_RECONNECTED = 1, // Reconnected with MQTT server successfully + QCLOUD_RET_SUCCESS = 0, // Successful return + QCLOUD_ERR_FAILURE = -1001, // Generic failure return + QCLOUD_ERR_INVAL = -1002, // Invalid parameter + QCLOUD_ERR_DEV_INFO = -1003, // Fail to get device info + QCLOUD_ERR_MALLOC = -1004, // Fail to malloc memory + QCLOUD_ERR_HTTP_CLOSED = -3, // HTTP server close the connection + QCLOUD_ERR_HTTP = -4, // HTTP unknown error + QCLOUD_ERR_HTTP_PRTCL = -5, // HTTP protocol error + QCLOUD_ERR_HTTP_UNRESOLVED_DNS = -6, // HTTP DNS resolve failed + QCLOUD_ERR_HTTP_PARSE = -7, // HTTP URL parse failed + QCLOUD_ERR_HTTP_CONN = -8, // HTTP connect failed + QCLOUD_ERR_HTTP_AUTH = -9, // HTTP auth failed + QCLOUD_ERR_HTTP_NOT_FOUND = -10, // HTTP 404 + QCLOUD_ERR_HTTP_TIMEOUT = -11, // HTTP timeout + QCLOUD_ERR_MQTT_PUSH_TO_LIST_FAILED = -102, // Fail to push node to MQTT waiting list + QCLOUD_ERR_MQTT_NO_CONN = -103, // Not connected with MQTT server + QCLOUD_ERR_MQTT_UNKNOWN = -104, // MQTT unknown error + QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT = -105, // Reconnecting with MQTT server + QCLOUD_ERR_MQTT_RECONNECT_TIMEOUT = -106, // MQTT reconnect timeout + QCLOUD_ERR_MQTT_MAX_SUBSCRIPTIONS = -107, // MQTT topic subscription out of range + QCLOUD_ERR_MQTT_SUB = -108, // MQTT topic subscription fail + QCLOUD_ERR_MQTT_NOTHING_TO_READ = -109, // MQTT nothing to read + QCLOUD_ERR_MQTT_PACKET_READ = -110, // Something wrong when reading MQTT packet + QCLOUD_ERR_MQTT_REQUEST_TIMEOUT = -111, // MQTT request timeout + QCLOUD_ERR_MQTT_CONNACK_UNKNOWN = -112, // MQTT connection refused: unknown error + QCLOUD_ERR_MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION = -113, // MQTT connection refused: protocol version invalid + QCLOUD_ERR_MQTT_CONNACK_IDENTIFIER_REJECTED = -114, // MQTT connection refused: identifier rejected + QCLOUD_ERR_MQTT_CONNACK_SERVER_UNAVAILABLE = -115, // MQTT connection refused: service not available + QCLOUD_ERR_MQTT_CONNACK_BAD_USERDATA = -116, // MQTT connection refused: bad user name or password + QCLOUD_ERR_MQTT_CONNACK_NOT_AUTHORIZED = -117, // MQTT connection refused: not authorized + QCLOUD_ERR_RX_MESSAGE_INVAL = -118, // MQTT received invalid msg + QCLOUD_ERR_BUF_TOO_SHORT = -119, // MQTT recv buffer not enough + QCLOUD_ERR_MQTT_QOS_NOT_SUPPORT = -120, // MQTT QoS level not supported + QCLOUD_ERR_MQTT_UNSUB_FAIL = -121, // MQTT unsubscribe failed + QCLOUD_ERR_JSON_PARSE = -132, // JSON parsing error + QCLOUD_ERR_JSON_BUFFER_TRUNCATED = -133, // JSON buffer truncated + QCLOUD_ERR_JSON_BUFFER_TOO_SMALL = -134, // JSON parsing buffer not enough + QCLOUD_ERR_JSON = -135, // JSON generation error + QCLOUD_ERR_MAX_JSON_TOKEN = -136, // JSON token out of range + QCLOUD_ERR_MAX_APPENDING_REQUEST = -137, // appending request out of range + QCLOUD_ERR_MAX_TOPIC_LENGTH = -138, // Topic length oversize + QCLOUD_ERR_COAP_NULL = -150, // COAP null pointer + QCLOUD_ERR_COAP_DATA_SIZE = -151, // COAP data size out of range + QCLOUD_ERR_COAP_INTERNAL = -152, // COAP interval error + QCLOUD_ERR_COAP_BADMSG = -153, // COAP bad msg + QCLOUD_ERR_DTLS_PEER_CLOSE_NOTIFY = -160, // DTLS connection is closed + QCLOUD_ERR_SHADOW_PROPERTY_EXIST = -201, // Shadow property already exist + QCLOUD_ERR_SHADOW_NOT_PROPERTY_EXIST = -202, // Shadow property not exist + QCLOUD_ERR_SHADOW_UPDATE_TIMEOUT = -203, // Shadow update timeout + QCLOUD_ERR_SHADOW_UPDATE_REJECTED = -204, // Shadow update rejected by server + QCLOUD_ERR_SHADOW_GET_TIMEOUT = -205, // Shadow get timeout + QCLOUD_ERR_SHADOW_GET_REJECTED = -206, // Shadow get rejected by server + QCLOUD_ERR_GATEWAY_CREATE_SESSION_FAIL = -221, // Gateway fail to create sub-device session + QCLOUD_ERR_GATEWAY_SESSION_NO_EXIST = -222, // Gateway sub-device session not exist + QCLOUD_ERR_GATEWAY_SESSION_TIMEOUT = -223, // Gateway sub-device session timeout + QCLOUD_ERR_GATEWAY_SUBDEV_ONLINE = -224, // Gateway sub-device online + QCLOUD_ERR_GATEWAY_SUBDEV_OFFLINE = -225, // Gateway sub-device offline + QCLOUD_ERR_RRPC_REPLY_TIMEOUT = -230, // RRPC reply timeout + QCLOUD_ERR_RRPC_REPLY_ERR = -231, // RRPC reply error + QCLOUD_ERR_TCP_SOCKET_FAILED = -601, // TLS TCP socket connect fail + QCLOUD_ERR_TCP_UNKNOWN_HOST = -602, // TCP unknown host (DNS fail) + QCLOUD_ERR_TCP_CONNECT = -603, // TCP/UDP socket connect fail + QCLOUD_ERR_TCP_READ_TIMEOUT = -604, // TCP read timeout + QCLOUD_ERR_TCP_WRITE_TIMEOUT = -605, // TCP write timeout + QCLOUD_ERR_TCP_READ_FAIL = -606, // TCP read error + QCLOUD_ERR_TCP_WRITE_FAIL = -607, // TCP write error + QCLOUD_ERR_TCP_PEER_SHUTDOWN = -608, // TCP server close connection + QCLOUD_ERR_TCP_NOTHING_TO_READ = -609, // TCP socket nothing to read + QCLOUD_ERR_SSL_INIT = -701, // TLS/SSL init fail + QCLOUD_ERR_SSL_CERT = -702, // TLS/SSL certificate issue + QCLOUD_ERR_SSL_CONNECT = -703, // TLS/SSL connect fail + QCLOUD_ERR_SSL_CONNECT_TIMEOUT = -704, // TLS/SSL connect timeout + QCLOUD_ERR_SSL_WRITE_TIMEOUT = -705, // TLS/SSL write timeout + QCLOUD_ERR_SSL_WRITE = -706, // TLS/SSL write error + QCLOUD_ERR_SSL_READ_TIMEOUT = -707, // TLS/SSL read timeout + QCLOUD_ERR_SSL_READ = -708, // TLS/SSL read error + QCLOUD_ERR_SSL_NOTHING_TO_READ = -709, // TLS/SSL nothing to read +} IoT_Return_Code; + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_ERROR_H_ */ diff --git a/include/exports/qcloud_iot_export_gateway.h b/include/exports/qcloud_iot_export_gateway.h new file mode 100755 index 00000000..89ecfc29 --- /dev/null +++ b/include/exports/qcloud_iot_export_gateway.h @@ -0,0 +1,224 @@ + +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_GATEWAY_H_ +#define QCLOUD_IOT_EXPORT_GATEWAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_export_mqtt.h" + +/* Gateway and sub-device parameter */ +typedef struct { + /*gateway device info */ + char *product_id; + char *device_name; + /*sub-device device info */ + char *subdev_product_id; + char *subdev_device_name; + +} GatewayParam; + +#define DEFAULT_GATEWAY_PARAMS \ + { \ + NULL, NULL, NULL, NULL \ + } + +/** + * @brief Define a callback to be invoked when gatway event happen + * + * @param context, the program context + * @param client, the gateway client + * @param msg, the event message. + * + * @return none + */ +typedef void (*GatewayEventHandleFun)(void *client, void *context, void *msg); + +/* The structure of gateway init param */ +typedef struct { + MQTTInitParams init_param; /* MQTT params */ + void * event_context; /* the user context */ + GatewayEventHandleFun event_handler; /* event handler for gateway user*/ +} GatewayInitParam; + +#define DEFAULT_GATEWAY_INIT_PARAMS \ + { \ + DEFAULT_MQTTINIT_PARAMS, NULL, NULL \ + } + +/** + * @brief Create gateway client and connect to MQTT server + * + * @param init_param Gateway MQTT init parameters + * + * @return a valid gateway client handle when success, or NULL otherwise + */ +void *IOT_Gateway_Construct(GatewayInitParam *init_param); + +/** + * @brief Close connection and destroy gateway client + * + * @param client handle to gateway client + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_Gateway_Destroy(void *client); + +/** + * @brief Make sub-device online + * + * @param client handle to gateway client + * @param param sub-device parameters + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_Gateway_Subdev_Online(void *client, GatewayParam *param); + +/** + * @brief Make sub-device offline + * + * @param client handle to gateway client + * @param param sub-device parameters + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_Gateway_Subdev_Offline(void *client, GatewayParam *param); + +/** + * @brief Bind a sub-device + * + * @param client handle to gateway client + * @param param gateway parameters + * @param pBindSubDevInfo sub dev info to bind + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_Gateway_Subdev_Bind(void *client, GatewayParam *param, DeviceInfo *pBindSubDevInfo); + +/** + * @brief Unbind a sub-device + * + * @param client handle to gateway client + * @param param gateway parameters + * @param pBindSubDevInfo sub dev info to unbind + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_Gateway_Subdev_Unbind(void *client, GatewayParam *param, DeviceInfo *pSubDevInfo); + +/** + * @brief Publish gateway MQTT message + * + * @param client handle to gateway client + * @param topic_name MQTT topic name + * @param params publish parameters + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_Gateway_Publish(void *client, char *topic_name, PublishParams *params); + +/** + * @brief Subscribe gateway MQTT topic + * + * @param client handle to gateway client + * @param topic_filter MQTT topic filter + * @param params subscribe parameters + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_Gateway_Subscribe(void *client, char *topic_filter, SubscribeParams *params); + +/** + * @brief unsubscribe gateway MQTT topic + * + * @param client handle to gateway client + * @param topic_filter MQTT topic filter + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_Gateway_Unsubscribe(void *client, char *topic_filter); + +/** + * @brief check if MQTT topic has been subscribed or not + * + * @param pClient handle to MQTT client + * @param topicFilter MQTT topic filter + * + * @return true when successfully subscribed, or false if not yet + */ +int IOT_Gateway_IsSubReady(void *client, char *topic_filter); + +/** + * @brief Check connection and keep alive state, read/handle MQTT message in synchronized way + * + * @param client handle to gateway client + * @param timeout_ms timeout value (unit: ms) for this operation + * + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Gateway_Yield(void *client, uint32_t timeout_ms); + +/** + * @brief Return the MQTT client dedicated to this gateway handle + * + * @param pClient handle to gateway client + * + * @return a valid mqtt client handle when success, or NULL otherwise + */ +void *IOT_Gateway_Get_Mqtt_Client(void *handle); + +/* The structure of subdevice bindinfo */ +typedef struct _SubdevBindInfo { + char product_id[MAX_SIZE_OF_PRODUCT_ID + 1]; + char device_name[MAX_SIZE_OF_DEVICE_NAME + 1]; + struct _SubdevBindInfo *next; +} SubdevBindInfo; + +/* The structure of subdevice bindlist */ +typedef struct _SubdevBindList { + SubdevBindInfo *bindlist_head; + int bind_num; +} SubdevBindList; + +/** + * @brief get sub-device bind list from cloud platform + * + * @param client handle to gateway client + * @param param gateway parameters + * @param subdev_bindlist output subdev bind list + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_Gateway_Subdev_GetBindList(void *client, GatewayParam *param, SubdevBindList *subdev_bindlist); + +/** + * @brief destory sub dev bind list + * + * @param subdev_bindlist input subdev bind list pointer, ref IOT_Gateway_Subdev_GetBindList + * output param subdev_bindlist + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +void IOT_Gateway_Subdev_DestoryBindList(SubdevBindList *subdev_bindlist); + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_GATEWAY_H_ */ diff --git a/include/exports/qcloud_iot_export_log.h b/include/exports/qcloud_iot_export_log.h new file mode 100755 index 00000000..e51171eb --- /dev/null +++ b/include/exports/qcloud_iot_export_log.h @@ -0,0 +1,204 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_LOG_H_ +#define QCLOUD_IOT_EXPORT_LOG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include "qcloud_iot_export_variables.h" + +/** + * SDK log print/upload level + */ +typedef enum { + eLOG_DISABLE = 0, // disable log print/upload + eLOG_ERROR = 1, // error log level + eLOG_WARN = 2, // warning log level + eLOG_INFO = 3, // info log level + eLOG_DEBUG = 4, // debug log level +} LOG_LEVEL; + +/** + * log print level control, only print logs with level less or equal to this variable + */ +extern LOG_LEVEL g_log_print_level; + +/** + * log upload level control, only upload logs with level less or equal to this variable + */ +extern LOG_LEVEL g_log_upload_level; + +/* user's self defined log handler callback */ +typedef bool (*LogMessageHandler)(const char *message); + +/** + * @brief user callback for saving/reading logs into/from NVS(files/FLASH) after upload fail/recover + */ +// callback for saving logs into NVS(files/FLASH) after upload fail +typedef size_t (*LogSaveFunc)(const char *msg, size_t wLen); +// callback for reading logs from NVS(files/FLASH) when upload ready +typedef size_t (*LogReadFunc)(char *buff, size_t rLen); +// callback for deleting logs in NVS(files/FLASH). return 0 when success +typedef int (*LogDelFunc)(); +// callback for reading the size of logs in NVS(files/FLASH). return 0 when nothing exist +typedef size_t (*LogGetSizeFunc)(); + +/** + * @brief data structure to init feature of log upload + */ +typedef struct { + /* device info */ + const char *product_id; + const char *device_name; + /* auth key, use device secret for PSK device and cert file path for cert device */ + const char *sign_key; + /* user callback saving/reading logs into/from NVS(files/FLASH) */ + LogSaveFunc save_func; + LogReadFunc read_func; + LogDelFunc del_func; + LogGetSizeFunc get_size_func; +} LogUploadInitParams; + +/** + * @brief Set the global log level of print + * + * @param level + */ +void IOT_Log_Set_Level(LOG_LEVEL level); + +/** + * @brief Get the global log level of print + * + * @return + */ +LOG_LEVEL IOT_Log_Get_Level(void); + +/** + * @brief Set the global log level of upload + * + * @param level + */ +void IOT_Log_Set_Upload_Level(LOG_LEVEL level); + +/** + * @brief Get the global log level of upload + * + * @return + */ +LOG_LEVEL IOT_Log_Get_Upload_Level(void); + +/** + * @brief Set user callback to print log into whereever you want + * + * @param handler function pointer of callback + * + */ +void IOT_Log_Set_MessageHandler(LogMessageHandler handler); + +/** + * @brief Init the resource for log upload + * + * @param init_params init parameter + * @return QCLOUD_RET_SUCCESS when success, or error code when fail + * + */ +int IOT_Log_Init_Uploader(LogUploadInitParams *init_params); + +/** + * @brief Stop log upload and release the resource + * + * @return + */ +void IOT_Log_Fini_Uploader(void); + +/** + * @brief Do one log upload + * + * @param force_upload true = upload log at once, false = upload in defined time interval + * @return QCLOUD_RET_SUCCESS when success, or error code when fail + */ +int IOT_Log_Upload(bool force_upload); + +/** + * @brief Generate log for print/upload, call LogMessageHandler if defined + * + * When LOG_UPLOAD is enabled, the log will be uploaded to cloud server + * + * @param file + * @param func + * @param line + * @param level + */ +void IOT_Log_Gen(const char *file, const char *func, const int line, const int level, const char *fmt, ...); + +/* Simple APIs for log generation in different level */ +#define Log_d(fmt, ...) IOT_Log_Gen(__FILE__, __FUNCTION__, __LINE__, eLOG_DEBUG, fmt, ##__VA_ARGS__) +#define Log_i(fmt, ...) IOT_Log_Gen(__FILE__, __FUNCTION__, __LINE__, eLOG_INFO, fmt, ##__VA_ARGS__) +#define Log_w(fmt, ...) IOT_Log_Gen(__FILE__, __FUNCTION__, __LINE__, eLOG_WARN, fmt, ##__VA_ARGS__) +#define Log_e(fmt, ...) IOT_Log_Gen(__FILE__, __FUNCTION__, __LINE__, eLOG_ERROR, fmt, ##__VA_ARGS__) + +/* check pointer before printf/snprintf */ +#define STRING_PTR_PRINT_SANITY_CHECK(s) ((s) ? (s) : "null") + +/* Macro for debug mode */ +#ifdef IOT_DEBUG +#define IOT_FUNC_ENTRY \ + { \ + printf("FUNC_ENTRY: %s L#%d \n", __FUNCTION__, __LINE__); \ + } +#define IOT_FUNC_EXIT \ + { \ + printf("FUNC_EXIT: %s L#%d \n", __FUNCTION__, __LINE__); \ + return; \ + } +#define IOT_FUNC_EXIT_RC(x) \ + { \ + printf("FUNC_EXIT: %s L#%d Return Code : %ld \n", __FUNCTION__, __LINE__, (long)(x)); \ + return x; \ + } +#else +#define IOT_FUNC_ENTRY +#define IOT_FUNC_EXIT \ + { \ + return; \ + } +#define IOT_FUNC_EXIT_RC(x) \ + { \ + return x; \ + } +#endif + +/* Macro for interval debug */ +//#define LOG_UPLOAD_DEBUG +#ifdef LOG_UPLOAD_DEBUG +#define UPLOAD_DBG(fmt, ...) HAL_Printf(">>LOG-DBG>>%s(%d): " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define UPLOAD_DBG(...) +#endif +#define UPLOAD_ERR(fmt, ...) HAL_Printf(">>LOG-ERR>>%s(%d): " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_LOG_H_ */ diff --git a/include/exports/qcloud_iot_export_mqtt.h b/include/exports/qcloud_iot_export_mqtt.h new file mode 100644 index 00000000..719f191d --- /dev/null +++ b/include/exports/qcloud_iot_export_mqtt.h @@ -0,0 +1,323 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_MQTT_H_ +#define QCLOUD_IOT_EXPORT_MQTT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/** + * @brief MQTT Quality of Service level + * + * Check MQTT spec for QoS define + */ +typedef enum _QoS { + QOS0 = 0, // At most once delivery + QOS1 = 1, // At least once delivery, PUBACK is required + QOS2 = 2 // Exactly once delivery. NOT supported currently +} QoS; + +/** + * @brief MQTT message parameter for pub/sub + */ +typedef struct { + QoS qos; // MQTT QoS level + uint8_t retained; // RETAIN flag + uint8_t dup; // DUP flag + uint16_t id; // MQTT Id + const char *ptopic; // MQTT topic + size_t topic_len; // topic length + void * payload; // MQTT msg payload + size_t payload_len; // MQTT length of msg payload +} MQTTMessage; + +typedef MQTTMessage PublishParams; + +#define DEFAULT_PUB_PARAMS \ + { \ + QOS0, 0, 0, 0, NULL, 0, NULL, 0 \ + } + +typedef enum { + + /* MQTT undefined event */ + MQTT_EVENT_UNDEF = 0, + + /* MQTT disconnect */ + MQTT_EVENT_DISCONNECT = 1, + + /* MQTT reconnect */ + MQTT_EVENT_RECONNECT = 2, + + /* MQTT subscribe success */ + MQTT_EVENT_SUBCRIBE_SUCCESS = 3, + + /* MQTT subscribe timeout */ + MQTT_EVENT_SUBCRIBE_TIMEOUT = 4, + + /* MQTT subscribe fail */ + MQTT_EVENT_SUBCRIBE_NACK = 5, + + /* MQTT unsubscribe success */ + MQTT_EVENT_UNSUBCRIBE_SUCCESS = 6, + + /* MQTT unsubscribe timeout */ + MQTT_EVENT_UNSUBCRIBE_TIMEOUT = 7, + + /* MQTT unsubscribe fail */ + MQTT_EVENT_UNSUBCRIBE_NACK = 8, + + /* MQTT publish success */ + MQTT_EVENT_PUBLISH_SUCCESS = 9, + + /* MQTT publish timeout */ + MQTT_EVENT_PUBLISH_TIMEOUT = 10, + + /* MQTT publish fail */ + MQTT_EVENT_PUBLISH_NACK = 11, + + /* MQTT received msg from server */ + MQTT_EVENT_PUBLISH_RECVEIVED = 12, + + /* MQTT client destroy */ + MQTT_EVENT_CLIENT_DESTROY = 13, + + /* MQTT unsubscribe */ + MQTT_EVENT_UNSUBSCRIBE = 14, + +} MQTTEventType; + +/** + * @brief Define MQTT SUBSCRIBE callback when message arrived + */ +typedef void (*OnMessageHandler)(void *pClient, MQTTMessage *message, void *pUserData); + +/** + * @brief Define MQTT SUBSCRIBE callback when event happened + */ +typedef void (*OnSubEventHandler)(void *pClient, MQTTEventType event_type, void *pUserData); + +/** + * @brief Define structure to do MQTT subscription + */ +typedef struct { + QoS qos; // MQTT QoS level + OnMessageHandler on_message_handler; // callback when message arrived + OnSubEventHandler on_sub_event_handler; // callback when event happened + void * user_data; // user context for callback +} SubscribeParams; + +/** + * Default MQTT subscription parameters + */ +#define DEFAULT_SUB_PARAMS \ + { \ + QOS0, NULL, NULL, NULL \ + } + +typedef struct { + /* MQTT event type */ + MQTTEventType event_type; + void * msg; +} MQTTEventMsg; + +/** + * @brief Define MQTT callback when MQTT event happen + * + * @param pclient, the MQTT client + * @param context, user callback context + * @param msg, the event message. + * + * @return none + */ +typedef void (*MQTTEventHandleFun)(void *pclient, void *context, MQTTEventMsg *msg); + +/* The structure of MQTT event handle */ +typedef struct { + MQTTEventHandleFun h_fp; + void * context; +} MQTTEventHandler; + +/* The structure of MQTT init parameters */ +typedef struct { + /* device info */ + char *product_id; // product ID + char *device_name; // device name + +#ifdef AUTH_MODE_CERT + char cert_file[FILE_PATH_MAX_LEN]; // full path of device cert file + char key_file[FILE_PATH_MAX_LEN]; // full path of device key file +#else + char *device_secret; // device secret +#endif + + uint32_t command_timeout; // timeout value (unit: ms) for MQTT connect/pub/sub/yield + uint32_t keep_alive_interval_ms; // MQTT keep alive time interval in millisecond + uint8_t clean_session; // flag of clean session, 1 clean, 0 not clean + uint8_t auto_connect_enable; // flag of auto reconnection, 1 is enable and recommended + MQTTEventHandler event_handle; // event callback + + int err_code; + +} MQTTInitParams; + +/** + * Default MQTT init parameters + */ +#ifdef AUTH_MODE_CERT +#define DEFAULT_MQTTINIT_PARAMS \ + { \ + NULL, NULL, {0}, {0}, 5000, 240 * 1000, 1, 1, {0}, 0 \ + } +#else +#define DEFAULT_MQTTINIT_PARAMS \ + { \ + NULL, NULL, NULL, 5000, 240 * 1000, 1, 1, {0}, 0 \ + } +#endif + +/** + * @brief Create MQTT client and connect to MQTT server + * + * @param pParams MQTT init parameters + * + * @return a valid MQTT client handle when success, or NULL otherwise + */ +void *IOT_MQTT_Construct(MQTTInitParams *pParams); + +/** + * @brief Close connection and destroy MQTT client + * + * @param pClient pointer of handle to MQTT client + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_MQTT_Destroy(void **pClient); + +/** + * @brief Check connection and keep alive state, read/handle MQTT message in synchronized way + * + * @param pClient handle to MQTT client + * @param timeout_ms timeout value (unit: ms) for this operation + * + * @return QCLOUD_RET_SUCCESS when success, QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT when try reconnecing, or err code for + * failure + */ +int IOT_MQTT_Yield(void *pClient, uint32_t timeout_ms); + +/** + * @brief Publish MQTT message + * + * @param pClient handle to MQTT client + * @param topicName MQTT topic name + * @param pParams publish parameters + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_MQTT_Publish(void *pClient, char *topicName, PublishParams *pParams); + +/** + * @brief Subscribe MQTT topic + * + * @param pClient handle to MQTT client + * @param topicFilter MQTT topic filter + * @param pParams subscribe parameters + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_MQTT_Subscribe(void *pClient, char *topicFilter, SubscribeParams *pParams); + +/** + * @brief Unsubscribe MQTT topic + * + * @param pClient handle to MQTT client + * @param topicFilter MQTT topic filter + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_MQTT_Unsubscribe(void *pClient, char *topicFilter); + +/** + * @brief check if MQTT topic has been subscribed or not + * + * @param pClient handle to MQTT client + * @param topicFilter MQTT topic filter + * + * @return true when successfully subscribed, or false if not yet + */ +bool IOT_MQTT_IsSubReady(void *pClient, char *topicFilter); + +/** + * @brief Check if MQTT is connected + * + * @param pClient handle to MQTT client + * @return true= connected, false = unconnected + */ +bool IOT_MQTT_IsConnected(void *pClient); + +/** + * @brief Get error code of last IOT_MQTT_Construct operation + * + * @return error code of last IOT_MQTT_Construct operation + */ +int IOT_MQTT_GetErrCode(void); + +/** + * @brief Get the device Info of the dedicated MQTT client + * + * @param pClient handle to MQTT client + * @return pointer to the device Info + */ +DeviceInfo *IOT_MQTT_GetDeviceInfo(void *pClient); + +#ifdef MULTITHREAD_ENABLED +/** + * @brief Start the default loop thread to read and handle MQTT packet + * + * @param pClient handle to MQTT client + * @return QCLOUD_RET_SUCCESS when success, err code for failure + */ +int IOT_MQTT_StartLoop(void *pClient); + +/** + * @brief Stop the default loop thread to read and handle MQTT packet + * + * @param pClient handle to MQTT client + */ +void IOT_MQTT_StopLoop(void *pClient); + +/** + * @brief Get the status of loop thread + * + * @param pClient handle to MQTT client + * @param exit_code exit code of the thread + * @return true= thread running, false = thread quit + */ +bool IOT_MQTT_GetLoopStatus(void *pClient, int *exit_code); + +void IOT_MQTT_SetLoopStatus(void *pClient, bool loop_status); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_MQTT_H_ */ diff --git a/include/exports/qcloud_iot_export_ota.h b/include/exports/qcloud_iot_export_ota.h new file mode 100755 index 00000000..317d808a --- /dev/null +++ b/include/exports/qcloud_iot_export_ota.h @@ -0,0 +1,252 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_OTA_H_ +#define QCLOUD_IOT_EXPORT_OTA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_import.h" + +typedef enum { + + IOT_OTA_ERR_FAIL = -1, + IOT_OTA_ERR_INVALID_PARAM = -2, + IOT_OTA_ERR_INVALID_STATE = -3, + IOT_OTA_ERR_STR_TOO_LONG = -4, + IOT_OTA_ERR_FETCH_FAILED = -5, + IOT_OTA_ERR_FETCH_NOT_EXIST = -6, + IOT_OTA_ERR_FETCH_AUTH_FAIL = -7, + IOT_OTA_ERR_FETCH_TIMEOUT = -8, + IOT_OTA_ERR_NOMEM = -9, + IOT_OTA_ERR_OSC_FAILED = -10, + IOT_OTA_ERR_REPORT_VERSION = -11, + IOT_OTA_ERR_NONE = 0 + +} IOT_OTA_Error_Code; + +/* type of OTA state */ +typedef enum { + IOT_OTAS_UNINITED = 0, /* un-inited */ + IOT_OTAS_INITED, /* inited */ + IOT_OTAS_FETCHING, /* fetching */ + IOT_OTAS_FETCHED, /* fetched */ + IOT_OTAS_DISCONNECTED /* disconnected */ +} IOT_OTA_State_Code; + +/* type of OTA progress */ +typedef enum { + + /* firmware upgrade failed */ + IOT_OTAP_BURN_FAILED = -4, + + /* firmware checksum failed */ + IOT_OTAP_CHECK_FALIED = -3, + + /* firmware download failed */ + IOT_OTAP_FETCH_FAILED = -2, + + /* init failed */ + IOT_OTAP_GENERAL_FAILED = -1, + + /* [0, 100], progress percentage */ + + /* minimal of progress percentage */ + IOT_OTAP_FETCH_PERCENTAGE_MIN = 0, + + /* maximal of progress percentage */ + IOT_OTAP_FETCH_PERCENTAGE_MAX = 100 + +} IOT_OTA_Progress_Code; + +typedef enum { + + IOT_OTAG_FETCHED_SIZE, /* Size of firmware fetched */ + IOT_OTAG_FILE_SIZE, /* Total size of firmware */ + IOT_OTAG_MD5SUM, /* firmware md5 checksum (string) */ + IOT_OTAG_VERSION, /* firmware version (string) */ + IOT_OTAG_CHECK_FIRMWARE /* check firmware */ + +} IOT_OTA_CmdType; + +typedef enum { + + IOT_OTAR_DOWNLOAD_TIMEOUT = -1, + IOT_OTAR_FILE_NOT_EXIST = -2, + IOT_OTAR_AUTH_FAIL = -3, + IOT_OTAR_MD5_NOT_MATCH = -4, + IOT_OTAR_UPGRADE_FAIL = -5, + IOT_OTAR_NONE = 0, + IOT_OTAR_DOWNLOAD_BEGIN = 1, + IOT_OTAR_DOWNLOADING = 2, + IOT_OTAR_UPGRADE_BEGIN = 3, + IOT_OTAR_UPGRADE_SUCCESS = 4, + +} IOT_OTAReportType; + +/** + * @brief Init OTA module and resources + * MQTT/COAP Client should be constructed beforehand + * + * @param product_id: product Id + * @param device_name: device name + * @param ch_signal: channel: MQTT or COAP + * + * @return a valid OTA module handle when success, or NULL otherwise + */ +void *IOT_OTA_Init(const char *product_id, const char *device_name, void *ch_signal); + +/** + * @brief Destroy OTA module and resources + * + * @param handle: OTA module handle + * + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_OTA_Destroy(void *handle); + +/** + * @brief Setup HTTP connection and prepare OTA download + * + * @param handle: OTA module handle + * @param offset: offset of firmware downloaded + * @param size: size of firmware + * + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_OTA_StartDownload(void *handle, uint32_t offset, uint32_t size); + +/** + * @brief Update MD5 of local firmware + * + * @param handle: OTA module handle + * @param buff: buffer to firmware + * @param size: size of buffer + * + */ +void IOT_OTA_UpdateClientMd5(void *handle, char *buff, uint32_t size); + +int IOT_OTA_ResetClientMD5(void *handle); + +/** + * @brief Report local firmware version to server + * NOTE: do this report before real download + * + * @param handle: OTA module handle + * @param version: local firmware version string + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_OTA_ReportVersion(void *handle, const char *version); + +/** + * @brief Report upgrade begin to server + * + * @param handle: OTA module handle + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_OTA_ReportUpgradeBegin(void *handle); + +/** + * @brief Report upgrade success to server + * + * @param handle: OTA module handle + * @param version: version string of firmware to upgrade + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_OTA_ReportUpgradeSuccess(void *handle, const char *version); + +/** + * @brief Report upgrade fail to server + * + * @param handle: OTA module handle + * @param version: version string of firmware to upgrade + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_OTA_ReportUpgradeFail(void *handle, const char *version); + +/** + * @brief Check if firmware is fetching/downloading + * + * @param handle: OTA module handle + * + * @retval 1 : Yes. + * @retval 0 : No. + */ +int IOT_OTA_IsFetching(void *handle); + +/** + * @brief Check if firmware fetching/downloading is finished + * + * @param handle: OTA module handle + * + * @retval 1 : Yes. + * @retval 0 : No. + */ +int IOT_OTA_IsFetchFinish(void *handle); + +/** + * @brief Download firmware from HTTP server and save to buffer + * + * @param handle: OTA module handle + * @param buf: buffer to store firmware + * @param buf_len: length of buffer + * @param timeout_s: timeout value in second + * + * @retval < 0 : error code + * @retval 0 : no data is downloaded in this period and timeout happen + * @retval (0, len] : size of the downloaded data + */ +int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s); + +/** + * @brief Get OTA info (version, file_size, MD5, download state) from OTA module + * + * @param handle: OTA module handle + * @param type: type of info to get, refer to IOT_OTA_CmdType + * @param buf: buffer for the data + * @param buf_len: length of buffer + * @return + NOTE: + 1) if type==IOT_OTAG_FETCHED_SIZE, 'buf' = uint32_t pointer, 'buf_len' = 4 + 2) if type==IOT_OTAG_FILE_SIZE, 'buf' = uint32_t pointer, 'buf_len' = 4 + 3) if type==IOT_OTAG_MD5SUM, 'buf' = char array buffer, 'buf_len = 33 + 4) if type==IOT_OTAG_VERSION, 'buf'= char array buffer, 'buf_len = OTA_VERSION_LEN_MAX + 5) if type==IOT_OTAG_CHECK_FIRMWARE, 'buf' = uint32_t pointer, 'buf_len' = 4 + * + * @retval 0 : success + * @retval < 0 : error code for failure + */ +int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len); + +/** + * @brief Get error code of last operation + * + * @param handle: OTA module handle + * + * @return error code + */ +int IOT_OTA_GetLastError(void *handle); + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_OTA_H_ */ diff --git a/include/exports/qcloud_iot_export_remote_config.h b/include/exports/qcloud_iot_export_remote_config.h new file mode 100644 index 00000000..fb4f293f --- /dev/null +++ b/include/exports/qcloud_iot_export_remote_config.h @@ -0,0 +1,75 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_REMOTE_CONFIG_H_ +#define QCLOUD_IOT_EXPORT_REMOTE_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define REMOTE_CONFIG_ERRCODE_SUCCESS 0 // get config success +#define REMOTE_CONFIG_ERRCODE_DISABLE 1001 // Cloud platform has been disabled remote config + +#define REMOTE_CONFIG_JSON_BUFFER_MIN_LEN 60 // config json buffer sys need len + +/** + * @brief proc config data, subscribe set struct ConfigSubscirbeUserData + * + * @param client MQTTClient pointer + * @param config_reply_errcode Config ErrCode; ERRCODE_REMOTE_CONFIG_SUCCESS can proc config_json other config_json is + invalid + * @param config_json config json data string, format is {xxxx}; user config data at cloud platform, pointer is + struct ConfigSubscirbeUserData json_buffer member + * @param config_json_len config json data length, + * @return void + */ +typedef void (*OnConfigProcHandler)(void *client, int config_reply_errcode, char *config_json, int config_json_len); + +typedef struct { + OnConfigProcHandler on_config_proc; // config proc callback when message arrived + int json_buffer_len; // sys json data need 60 B + config json data max len + char * json_buffer; // save json buffer [sys json data + config json data] ,sdk proc recv buff + // save config json data as OnConfigProcHandler functions config_json parameter +} ConfigSubscirbeUserData; + +/** + * @brief subscribe config topic $config/operation/result/${productID}/${deviceName} + * + * @param client MQTTClient pointer + * @param config_sub_userdata Config topic subscribe userdata + * @param subscribe_timeout wait cloud platform reply max time, ms + * @return >= QCLOUD_RET_SUCCESS for success + * otherwise, failure + */ +int IOT_Subscribe_Config(void *client, ConfigSubscirbeUserData *config_sub_userdata, int subscribe_timeout); + +/** + * @brief get config from MQTT server $config/operation/${productID}/${deviceName} + * + * @param client MQTTClient pointer + * @param json_buffer store create json string + * @param buffer_size pJsonBuffer len min 20B + * @param reply_timeout wait cloud platform reply max time, ms + * @return QCLOUD_RET_SUCCESS for success + * otherwise, failure + */ +int IOT_Get_Config(void *client, char *json_buffer, int buffer_size, int reply_timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_CONFIG_H_ */ \ No newline at end of file diff --git a/include/exports/qcloud_iot_export_rrpc.h b/include/exports/qcloud_iot_export_rrpc.h new file mode 100755 index 00000000..2601161d --- /dev/null +++ b/include/exports/qcloud_iot_export_rrpc.h @@ -0,0 +1,82 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_RRPC_H_ +#define QCLOUD_IOT_EXPORT_RRPC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "qcloud_iot_import.h" + +#ifdef RRPC_ENABLED + +/* Max len of status in reply msg*/ +#define MAX_RRPC_REPLY_STATUS_LEN 64 + +/* Max len of process id*/ +#define MAX_RRPC_PROCESS_ID_LEN 16 + +typedef enum _eRRPCReplyCode_ { + eRRPC_SUCCESS = 0, + eRRPC_FAIL = -1, +} eRRPCReplyCode; + +/** + * @brief rrpc msg reply parameter + */ +typedef struct _sRRPCReplyPara { + eRRPCReplyCode code; // reply code. 0:success, ~0:failed + char status_msg[MAX_RRPC_REPLY_STATUS_LEN]; // reply message + char * user_data; // content of user reply + size_t user_data_len; // length of user data +} sRRPCReplyPara; + +/** + * @brief RRPC message callback + */ +typedef void (*OnRRPCMessageCallback)(void *pClient, const char *msg, uint32_t msgLen); + +/** + * @brief Subscribe rrpc topic with message callback + * + * @param pClient pointer of handle to MQTT client + * @param callback rrpc message callback + * @return QCLOUD_RET_SUCCESS when success, otherwise fail + */ +int IOT_RRPC_Init(void *pClient, OnRRPCMessageCallback callback); + +/** + * @brief reply to the rrpc msg + * @param pClient handle to mqtt client + * @param processId process id + * @param pJsonDoc data buffer for reply + * @param sizeOfBuffer length of data buffer + * @param replyPara rrpc reply info + * @return QCLOUD_RET_SUCCESS when success, or err code + * for failure + */ +int IOT_RRPC_Reply(void *pClient, char *pJsonDoc, size_t sizeOfBuffer, sRRPCReplyPara *replyPara); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // QCLOUD_IOT_EXPORT_RRPC_H_ diff --git a/include/exports/qcloud_iot_export_shadow.h b/include/exports/qcloud_iot_export_shadow.h new file mode 100755 index 00000000..b1093a09 --- /dev/null +++ b/include/exports/qcloud_iot_export_shadow.h @@ -0,0 +1,356 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_SHADOW_H_ +#define QCLOUD_IOT_EXPORT_SHADOW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_export_mqtt.h" + +typedef enum _eShadowType_ { + eSHADOW = 0, // normal shadow + eTEMPLATE = 1, // data template +} eShadowType; + +/* The structure of MQTT shadow init parameters */ +typedef struct { + /* device info */ + char *product_id; // product ID + char *device_name; // device name + +#ifdef AUTH_MODE_CERT + char cert_file[FILE_PATH_MAX_LEN]; // full path of device cert file + char key_file[FILE_PATH_MAX_LEN]; // full path of device key file +#else + char *device_secret; // device secret +#endif + + uint32_t command_timeout; // timeout value (unit: ms) for MQTT connect/pub/sub/yield + uint32_t keep_alive_interval_ms; // MQTT keep alive time interval in millisecond + uint8_t clean_session; // flag of clean session, 1 clean, 0 not clean + uint8_t auto_connect_enable; // flag of auto reconnection, 1 is enable and recommended + MQTTEventHandler event_handle; // event callback + eShadowType shadow_type; // shadow type +} ShadowInitParams; + +#ifdef AUTH_MODE_CERT +#define DEFAULT_SHAWDOW_INIT_PARAMS \ + { \ + NULL, NULL, {0}, {0}, 5000, 240 * 1000, 1, 1, {0}, 0 \ + } +#else +#define DEFAULT_SHAWDOW_INIT_PARAMS \ + { \ + NULL, NULL, NULL, 5000, 240 * 1000, 1, 1, {0}, 0 \ + } +#endif + +/** + * @brief Type of shadow request ACK + */ +typedef enum { + ACK_NONE = -3, // ACK is init state + ACK_TIMEOUT = -2, // received ACK timeout + ACK_REJECTED = -1, // ACK is rejected + ACK_ACCEPTED = 0, // ACK is accepted +} RequestAck; + +/** + * @brief Type of interaction with server + */ +typedef enum { + GET, // Get device document from server + UPDATE, // Update or create device document in server +} Method; + +/** + * @brief JSON data type + */ +typedef enum { JINT32, JINT16, JINT8, JUINT32, JUINT16, JUINT8, JFLOAT, JDOUBLE, JBOOL, JSTRING, JOBJECT } JsonDataType; + +/** + * @brief Define a device property, as a JSON document node + */ +typedef struct _JSONNode { + char * key; // Key of this JSON node + void * data; // Value of this JSON node + JsonDataType type; // Data type of this JSON node + bool delta_arrived; +} DeviceProperty; + +/** + * @brief Data type of template + */ + +#define TYPE_TEMPLATE_INT JINT32 +#define TYPE_TEMPLATEENUM JINT32 +#define TYPE_TEMPLATE_FLOAT JFLOAT +#define TYPE_TEMPLATE_BOOL JINT8 +#define TYPE_TEMPLATE_STRING JSTRING +#define TYPE_TEMPLATE_TIME JUINT32 +#define TYPE_TEMPLATE_JOBJECT JOBJECT + +typedef int32_t TYPE_DEF_TEMPLATE_INT; +typedef int32_t TYPE_DEF_TEMPLATE_ENUM; +typedef float TYPE_DEF_TEMPLATE_FLOAT; +typedef char TYPE_DEF_TEMPLATE_BOOL; +typedef char TYPE_DEF_TEMPLATE_STRING; +typedef uint32_t TYPE_DEF_TEMPLATE_TIME; +typedef void * TYPE_DEF_TEMPLATE_OBJECT; + +/** + * @brief Define property status in data template + */ +typedef enum _eDataState_ { + eNOCHANGE = 0, + eCHANGED = 1, +} eDataState; + +/** + * @brief Define data point in data template + */ +typedef struct { + DeviceProperty data_property; + eDataState state; +} sDataPoint; + +/** + * @brief Define MQTT shadow callback when request response arrived + * + * @param method type of request + * @param requestAck response type + * @param pJsonDocument JSON document from server + * @param userContext User context + * + */ +typedef void (*OnRequestCallback)(void *pClient, Method method, RequestAck requestAck, const char *pJsonDocument, + void *userContext); + +/** + * @brief Define callback when device property change + * + * @param pJsonValueBuffer property JSON buffer + * @param valueLength property length + * @param DeviceProperty reference to device property + */ +typedef void (*OnPropRegCallback)(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength, + DeviceProperty *pProperty); + +/** + * @brief Create MQTT Shadow client and connect to MQTT server + * + * @param pParams Shadow init parameters + * + * @return a valid Shadow client handle when success, or NULL otherwise + */ +void *IOT_Shadow_Construct(ShadowInitParams *pParams); + +/** + * @brief Return the MQTT client dedicated to this shadow handle + * + * @param pClient handle to shadow client + * + * @return a valid mqtt client handle when success, or NULL otherwise + */ +void *IOT_Shadow_Get_Mqtt_Client(void *handle); + +/** + * @brief Publish MQTT message + * + * @param pClient handle to shadow client + * @param topicName MQTT topic name + * @param pParams publish parameters + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_Shadow_Publish(void *pClient, char *topicName, PublishParams *pParams); + +/** + * @brief Subscribe MQTT message + * + * @param pClient handle to shadow client + * @param topicFilter MQTT topic filter + * @param pParams subscribe parameters + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_Shadow_Subscribe(void *pClient, char *topicFilter, SubscribeParams *pParams); + +/** + * @brief Unsubscribe MQTT message + * + * @param pClient handle to shadow client + * @param topicFilter MQTT topic filter + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int IOT_Shadow_Unsubscribe(void *pClient, char *topicFilter); + +/** + * @brief Check if MQTT shadow is connected + * + * @param pClient handle to shadow client + * @return true= connected, false = unconnected + */ +bool IOT_Shadow_IsConnected(void *pClient); + +/** + * @brief Close connection and destroy MQTT shadow client + * + * @param pClient pointer of handle to shadow client + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int IOT_Shadow_Destroy(void *pClient); + +/** + * @brief Check connection and keep alive state, read/handle MQTT message in synchronized way + * + * @param pClient handle to shadow client + * @param timeout_ms timeout value (unit: ms) for this operation + * + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_Yield(void *pClient, uint32_t timeout_ms); + +/** + * @brief Update device shadow document in asynchronized way + * + * @param pClient handle to shadow client + * @param pJsonDoc source JSON document for update + * @param sizeOfBuffer length of JSON document + * @param callback callback when response arrive + * @param userContext user data for callback + * @param timeout_ms timeout value for this operation (unit: ms) + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_Update(void *pClient, char *pJsonDoc, size_t sizeOfBuffer, OnRequestCallback callback, void *userContext, + uint32_t timeout_ms); + +/** + * @brief Update device shadow document in synchronized way + * + * @param pClient handle to shadow client + * @param pJsonDoc source JSON document for update + * @param sizeOfBuffer length of JSON document + * @param timeout_ms timeout value for this operation (unit: ms) + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + + */ +int IOT_Shadow_Update_Sync(void *pClient, char *pJsonDoc, size_t sizeOfBuffer, uint32_t timeout_ms); + +/** + * @brief Get device shadow document in asynchronized way + * + * @param pClient handle to shadow client + * @param callback callback when response arrive + * @param userContext user data for callback + * @param timeout_ms timeout value for this operation (unit: ms) + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_Get(void *pClient, OnRequestCallback callback, void *userContext, uint32_t timeout_ms); + +/** + * @brief Get device shadow document in asynchronized way + * + * @param pClient handle to shadow client + * @param timeout_ms timeout value for this operation (unit: ms) + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_Get_Sync(void *pClient, uint32_t timeout_ms); + +/** + * @brief Register device property + * + * @param pClient handle to shadow client + * @param pProperty reference to device property + * @param callback callback when property changes + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_Register_Property(void *pClient, DeviceProperty *pProperty, OnPropRegCallback callback); + +/** + * @brief UnRegister device property + * + * @param pClient handle to shadow client + * @param pProperty reference to device property + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_UnRegister_Property(void *pClient, DeviceProperty *pProperty); + +/** + * @brief Add reported fields in JSON document, don't overwrite + * + * @param pClient handle to shadow client + * @param jsonBuffer string buffer to store JSON document + * @param sizeOfBuffer size of string buffer + * @param count number of properties + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_JSON_ConstructReport(void *pClient, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...); + +/** + * @brief Add reported fields array in JSON document, don't overwrite + * + * @param pClient handle to shadow client + * @param jsonBuffer string buffer to store JSON document + * @param sizeOfBuffer size of string buffer + * @param count number of properties + * @param pDeviceProperties array of properties + * @return QCLOUD_RET_SUCCESS when success, or err code for failure */ + +int IOT_Shadow_JSON_ConstructReportArray(void *pClient, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, + DeviceProperty *pDeviceProperties[]); + +/** + * @brief Add reported fields in JSON document, overwrite + * + * @param pClient handle to shadow client + * @param jsonBuffer string buffer to store JSON document + * @param sizeOfBuffer size of string buffer + * @param count number of properties + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_JSON_Construct_OverwriteReport(void *pClient, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...); + +/** + * @brief Add reported fields array in JSON document and set desire field as null + * + * @param pClient handle to shadow client + * @param jsonBuffer string buffer to store JSON document + * @param sizeOfBuffer size of string buffer + * @param count number of properties + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_JSON_ConstructReportAndDesireAllNull(void *pClient, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, + ...); + +/** + * @brief Set desire field as null + * + * @param jsonBuffer string buffer to store JSON document + * @param sizeOfBuffer size of string buffer + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int IOT_Shadow_JSON_ConstructDesireAllNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer); + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_SHADOW_H_ */ diff --git a/src/sdk-impl/exports/qcloud_iot_export_system.h b/include/exports/qcloud_iot_export_system.h old mode 100644 new mode 100755 similarity index 55% rename from src/sdk-impl/exports/qcloud_iot_export_system.h rename to include/exports/qcloud_iot_export_system.h index 2b92fa48..ca489727 --- a/src/sdk-impl/exports/qcloud_iot_export_system.h +++ b/include/exports/qcloud_iot_export_system.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -21,15 +21,23 @@ extern "C" { #endif /** - * @brief 获取系统时间 + * @brief Get system timestamp from MQTT server * - * @param pClient Client结构体 - * @param time 返回IoT后台的时间 - * @return 返回QCLOUD_ERR_SUCCESS, 表示请求成功 - * 返回QCLOUD_ERR_FAILURE, 表示请求失败 + * @param pClient MQTTClient pointer + * @param time timestamp value return from server + * @return QCLOUD_RET_SUCCESS for success + * otherwise, failure */ -int IOT_SYSTEM_GET_TIME(void* pClient, long* time); +int IOT_Get_SysTime(void* pClient, long* time); +/** + * @brief sync ntp timestamp from MQTT server + * + * @param pClient MQTTClient pointer + * @return QCLOUD_RET_SUCCESS for success + * otherwise, failure + */ +int IOT_Sync_NTPTime(void* pClient); #ifdef __cplusplus } diff --git a/src/utils/lite/lite-list.h b/include/lite-list.h old mode 100644 new mode 100755 similarity index 73% rename from src/utils/lite/lite-list.h rename to include/lite-list.h index 0a5639c2..a9c455cf --- a/src/utils/lite/lite-list.h +++ b/include/lite-list.h @@ -1,23 +1,17 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. * */ -/** - * Edit by shockcao@tencent.com 2018/3/15 - */ #ifndef _LINUX_LIST_H #define _LINUX_LIST_H @@ -40,10 +34,12 @@ struct list_head { * using the generic single-entry routines. */ -#define LIST_HEAD_INIT(name) { &(name), &(name) } +#define LIST_HEAD_INIT(name) \ + { \ + &(name), &(name) \ + } -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) +#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) static inline void INIT_LIST_HEAD(struct list_head *list) { @@ -57,14 +53,12 @@ static inline void INIT_LIST_HEAD(struct list_head *list) * This is only for internal list manipulation where we know * the prev/next entries already! */ -static inline void __list_add(struct list_head *new_ptr, - struct list_head *prev, - struct list_head *next) +static inline void __list_add(struct list_head *new_ptr, struct list_head *prev, struct list_head *next) { - next->prev = new_ptr; + next->prev = new_ptr; new_ptr->next = next; new_ptr->prev = prev; - prev->next = new_ptr; + prev->next = new_ptr; } /** @@ -80,7 +74,6 @@ static inline void list_add(struct list_head *new_ptr, struct list_head *head) __list_add(new_ptr, head, head->next); } - /** * list_add_tail - add a new_ptr entry * @new_ptr: new_ptr entry to be added @@ -130,17 +123,15 @@ static inline void list_del(struct list_head *entry) * * If @old was empty, it will be overwritten. */ -static inline void list_replace(struct list_head *old, - struct list_head *new_ptr) +static inline void list_replace(struct list_head *old, struct list_head *new_ptr) { - new_ptr->next = old->next; + new_ptr->next = old->next; new_ptr->next->prev = new_ptr; - new_ptr->prev = old->prev; + new_ptr->prev = old->prev; new_ptr->prev->next = new_ptr; } -static inline void list_replace_init(struct list_head *old, - struct list_head *new_ptr) +static inline void list_replace_init(struct list_head *old, struct list_head *new_ptr) { list_replace(old, new_ptr); INIT_LIST_HEAD(old); @@ -172,8 +163,7 @@ static inline void list_move(struct list_head *list, struct list_head *head) * @list: the entry to move * @head: the head that will follow our entry */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) +static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del_entry(list); list_add_tail(list, head); @@ -184,8 +174,7 @@ static inline void list_move_tail(struct list_head *list, * @list: the entry to test * @head: the head of the list */ -static inline int list_is_last(const struct list_head *list, - const struct list_head *head) +static inline int list_is_last(const struct list_head *list, const struct list_head *head) { return list->next == head; } @@ -247,8 +236,7 @@ static inline int list_is_singular(const struct list_head *head) * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) +#define list_entry(ptr, type, member) container_of(ptr, type, member) /** * list_first_entry - get the first element from a list @@ -258,8 +246,7 @@ static inline int list_is_singular(const struct list_head *head) * * Note, that list is expected to be not empty. */ -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) +#define list_first_entry(ptr, type, member) list_entry((ptr)->next, type, member) /** * list_last_entry - get the last element from a list @@ -269,8 +256,7 @@ static inline int list_is_singular(const struct list_head *head) * * Note, that list is expected to be not empty. */ -#define list_last_entry(ptr, type, member) \ - list_entry((ptr)->prev, type, member) +#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member) /** * list_first_entry_or_null - get the first element from a list @@ -280,32 +266,28 @@ static inline int list_is_singular(const struct list_head *head) * * Note that if the list is empty, it returns NULL. */ -#define list_first_entry_or_null(ptr, type, member) \ - (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) +#define list_first_entry_or_null(ptr, type, member) (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) /** * list_next_entry - get the next element in list * @pos: the type * to cursor * @member: the name of the list_struct within the struct. */ -#define list_next_entry(pos, member, type) \ - list_entry((pos)->member.next, type, member) +#define list_next_entry(pos, member, type) list_entry((pos)->member.next, type, member) /** * list_prev_entry - get the prev element in list * @pos: the type * to cursor * @member: the name of the list_struct within the struct. */ -#define list_prev_entry(pos, member, type) \ - list_entry((pos)->member.prev, type, member) +#define list_prev_entry(pos, member, type) list_entry((pos)->member.prev, type, member) /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) +#define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next) /** * __list_for_each - iterate over a list @@ -315,16 +297,14 @@ static inline int list_is_singular(const struct list_head *head) * This variant doesn't differ from list_for_each() any more. * We don't do prefetching in either case. */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) +#define __list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next) /** * list_for_each_prev - iterate over a list backwards * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); pos = pos->prev) +#define list_for_each_prev(pos, head) for (pos = (head)->prev; pos != (head); pos = pos->prev) /** * list_for_each_safe - iterate over a list safe against removal of list entry @@ -332,9 +312,7 @@ static inline int list_is_singular(const struct list_head *head) * @n: another &struct list_head to use as temporary storage * @head: the head for your list. */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) +#define list_for_each_safe(pos, n, head) for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next) /** * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry @@ -343,9 +321,7 @@ static inline int list_is_singular(const struct list_head *head) * @head: the head for your list. */ #define list_for_each_prev_safe(pos, n, head) \ - for (pos = (head)->prev, n = pos->prev; \ - pos != (head); \ - pos = n, n = pos->prev) + for (pos = (head)->prev, n = pos->prev; pos != (head); pos = n, n = pos->prev) /** * list_for_each_entry - iterate over list of given type @@ -353,9 +329,8 @@ static inline int list_is_singular(const struct list_head *head) * @head: the head for your list. * @member: the name of the list_struct within the struct. */ -#define list_for_each_entry(pos, head, member, type) \ - for (pos = list_entry((head)->next, type, member); \ - &pos->member != (head); \ +#define list_for_each_entry(pos, head, member, type) \ + for (pos = list_entry((head)->next, type, member); &pos->member != (head); \ pos = list_entry(pos->member.next, type, member)) /** @@ -364,9 +339,8 @@ static inline int list_is_singular(const struct list_head *head) * @head: the head for your list. * @member: the name of the list_struct within the struct. */ -#define list_for_each_entry_reverse(pos, head, member, type) \ - for (pos = list_entry((head)->prev, type, member); \ - &pos->member != (head); \ +#define list_for_each_entry_reverse(pos, head, member, type) \ + for (pos = list_entry((head)->prev, type, member); &pos->member != (head); \ pos = list_entry(pos->member.prev, type, member)) /** @@ -377,8 +351,7 @@ static inline int list_is_singular(const struct list_head *head) * * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). */ -#define list_prepare_entry(pos, head, member, type) \ - ((pos) ? : list_entry(head, type, member)) +#define list_prepare_entry(pos, head, member, type) ((pos) ?: list_entry(head, type, member)) /** * list_for_each_entry_continue - continue iteration over list of given type @@ -389,9 +362,8 @@ static inline int list_is_singular(const struct list_head *head) * Continue to iterate over list of given type, continuing after * the current position. */ -#define list_for_each_entry_continue(pos, head, member, type) \ - for (pos = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ +#define list_for_each_entry_continue(pos, head, member, type) \ + for (pos = list_entry(pos->member.next, type, member); &pos->member != (head); \ pos = list_entry(pos->member.next, type, member)) /** @@ -403,9 +375,8 @@ static inline int list_is_singular(const struct list_head *head) * Start to iterate over list of given type backwards, continuing after * the current position. */ -#define list_for_each_entry_continue_reverse(pos, head, member, type) \ - for (pos = list_entry(pos->member.prev, type, member); \ - &pos->member != (head); \ +#define list_for_each_entry_continue_reverse(pos, head, member, type) \ + for (pos = list_entry(pos->member.prev, type, member); &pos->member != (head); \ pos = list_entry(pos->member.prev, type, member)) /** @@ -416,9 +387,8 @@ static inline int list_is_singular(const struct list_head *head) * * Iterate over list of given type, continuing from current position. */ -#define list_for_each_entry_from(pos, head, member, type) \ - for (; &pos->member != (head); \ - pos = list_entry(pos->member.next, type, member)) +#define list_for_each_entry_from(pos, head, member, type) \ + for (; &pos->member != (head); pos = list_entry(pos->member.next, type, member)) /** * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry @@ -427,11 +397,9 @@ static inline int list_is_singular(const struct list_head *head) * @head: the head for your list. * @member: the name of the list_struct within the struct. */ -#define list_for_each_entry_safe(pos, n, head, member, type) \ - for (pos = list_entry((head)->next, type, member), \ - n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, type, member)) +#define list_for_each_entry_safe(pos, n, head, member, type) \ + for (pos = list_entry((head)->next, type, member), n = list_entry(pos->member.next, type, member); \ + &pos->member != (head); pos = n, n = list_entry(n->member.next, type, member)) /** * list_for_each_entry_safe_continue - continue list iteration safe against removal @@ -443,11 +411,9 @@ static inline int list_is_singular(const struct list_head *head) * Iterate over list of given type, continuing after current point, * safe against removal of list entry. */ -#define list_for_each_entry_safe_continue(pos, n, head, member, type) \ - for (pos = list_entry(pos->member.next, type, member), \ - n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, type, member)) +#define list_for_each_entry_safe_continue(pos, n, head, member, type) \ + for (pos = list_entry(pos->member.next, type, member), n = list_entry(pos->member.next, type, member); \ + &pos->member != (head); pos = n, n = list_entry(n->member.next, type, member)) /** * list_for_each_entry_safe_from - iterate over list from current point safe against removal @@ -459,9 +425,8 @@ static inline int list_is_singular(const struct list_head *head) * Iterate over list of given type from current point, safe against * removal of list entry. */ -#define list_for_each_entry_safe_from(pos, n, head, member, type) \ - for (n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ +#define list_for_each_entry_safe_from(pos, n, head, member, type) \ + for (n = list_entry(pos->member.next, type, member); &pos->member != (head); \ pos = n, n = list_entry(n->member.next, type, member)) /** @@ -474,11 +439,9 @@ static inline int list_is_singular(const struct list_head *head) * Iterate backwards over list of given type, safe against removal * of list entry. */ -#define list_for_each_entry_safe_reverse(pos, n, head, member, type) \ - for (pos = list_entry((head)->prev, type, member), \ - n = list_entry(pos->member.prev, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.prev, type, member)) +#define list_for_each_entry_safe_reverse(pos, n, head, member, type) \ + for (pos = list_entry((head)->prev, type, member), n = list_entry(pos->member.prev, type, member); \ + &pos->member != (head); pos = n, n = list_entry(n->member.prev, type, member)) /** * list_safe_reset_next - reset a stale list_for_each_entry_safe loop @@ -492,7 +455,6 @@ static inline int list_is_singular(const struct list_head *head) * and list_safe_reset_next is called after re-taking the lock and before * completing the current iteration of the loop body. */ -#define list_safe_reset_next(pos, n, member, type) \ - n = list_entry(pos->member.next, type, member) +#define list_safe_reset_next(pos, n, member, type) n = list_entry(pos->member.next, type, member) #endif diff --git a/include/lite-utils.h b/include/lite-utils.h new file mode 100755 index 00000000..79230f5d --- /dev/null +++ b/include/lite-utils.h @@ -0,0 +1,85 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __LITE_UTILS_H__ +#define __LITE_UTILS_H__ + +#include +#include +#include +#include +#include +#include +#if defined(_PLATFORM_IS_LINUX_) +#include +#endif + +#include "lite-list.h" +#include "qcloud_iot_import.h" + +#define LITE_TRUE (1) +#define LITE_FALSE (0) + +#ifndef container_of +#define container_of(ptr, type, member) ((type *)((char *)(ptr)-offsetof(type, member))) +#endif + +#define LITE_MINIMUM(a, b) (((a) <= (b)) ? (a) : (b)) +#define LITE_MAXIMUM(a, b) (((a) >= (b)) ? (a) : (b)) +#define LITE_isdigit(c) (((c) <= '9' && (c) >= '0') ? (LITE_TRUE) : (LITE_FALSE)) + +#if defined(_PLATFORM_IS_LINUX_) +#define LITE_ASSERT(expr) assert(expr) +#else +#define LITE_ASSERT(expr) \ + do { \ + if (!(expr)) { \ + HAL_Printf("### %s | %s(%d): ASSERT FAILED ###: %s is FALSE\r\n", __FILE__, __func__, __LINE__, #expr); \ + } \ + } while (0) +#endif + +char *LITE_strdup(const char *src); +char *LITE_format_string(const char *fmt, ...); +char *LITE_format_nstring(const int len, const char *fmt, ...); +void LITE_hexbuf_convert(unsigned char *digest, char *out, int buflen, int uppercase); +void LITE_hexstr_convert(char *hexstr, uint8_t *out_buf, int len); + +char * LITE_json_value_of(char *key, char *src); +list_head_t *LITE_json_keys_of(char *src, char *prefix); +void LITE_json_keys_release(list_head_t *keylist); +char * LITE_json_string_value_strip_transfer(char *key, char *src); + +int LITE_get_int32(int32_t *value, char *src); +int LITE_get_int16(int16_t *value, char *src); +int LITE_get_int8(int8_t *value, char *src); +int LITE_get_uint32(uint32_t *value, char *src); +int LITE_get_uint16(uint16_t *value, char *src); +int LITE_get_uint8(uint8_t *value, char *src); +int LITE_get_float(float *value, char *src); +int LITE_get_double(double *value, char *src); +int LITE_get_boolean(bool *value, char *src); + +typedef struct _json_key_t { + char * key; + list_head_t list; +} json_key_t; + +#define foreach_json_keys_in(src, iter_key, keylist, pos) \ + for (keylist = (void *)LITE_json_keys_of((char *)src, ""), \ + pos = (void *)list_first_entry((list_head_t *)keylist, json_key_t, list), iter_key = ((json_key_t *)pos)->key; \ + (iter_key = ((json_key_t *)pos)->key); pos = list_next_entry((json_key_t *)pos, list, json_key_t)) + +#endif /* __LITE_UTILS_H__ */ diff --git a/include/platform.h b/include/platform.h new file mode 100755 index 00000000..b5ad29ca --- /dev/null +++ b/include/platform.h @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef PLATFORM_H_ +#define PLATFORM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PATH_MAX 4096 +/* Max size of cert/key file full path */ +#define FILE_PATH_MAX_LEN 256 + +#ifdef WIN32 +#include +#include +#include +#include +typedef unsigned long ssize_t; +#define getcwd(buffer, len) _getcwd(buffer, len) +#endif + +#if defined(__linux__) && defined(__GLIBC__) +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PLATFORM_H_ */ diff --git a/include/qcloud_iot_export.h b/include/qcloud_iot_export.h new file mode 100755 index 00000000..10c1afb5 --- /dev/null +++ b/include/qcloud_iot_export.h @@ -0,0 +1,97 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_H_ +#define QCLOUD_IOT_EXPORT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" +#include "platform.h" + +/* IoT C-SDK version info */ +#define QCLOUD_IOT_DEVICE_SDK_VERSION "3.2.2" + +/**************** QCloud IoT C-SDK constants begin ************************/ + +/* MAX size of client ID */ +#define MAX_SIZE_OF_CLIENT_ID (80) + +/* MAX size of product ID */ +#define MAX_SIZE_OF_PRODUCT_ID (10) + +/* MAX size of product secret */ +#define MAX_SIZE_OF_PRODUCT_SECRET (32) + +/* MAX size of device name */ +#define MAX_SIZE_OF_DEVICE_NAME (48) + +/* MAX size of device secret */ +#define MAX_SIZE_OF_DEVICE_SECRET (64) + +/* MAX size of device cert file name */ +#define MAX_SIZE_OF_DEVICE_CERT_FILE_NAME (128) + +/* MAX size of device key file name */ +#define MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME (128) + +/**************** QCloud IoT C-SDK constants end *************************/ + +typedef struct { + char product_id[MAX_SIZE_OF_PRODUCT_ID + 1]; + char device_name[MAX_SIZE_OF_DEVICE_NAME + 1]; + char client_id[MAX_SIZE_OF_CLIENT_ID + 1]; + +#ifdef AUTH_MODE_CERT + char dev_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1]; + char dev_key_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1]; +#else + char device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1]; +#endif + +#ifdef DEV_DYN_REG_ENABLED + char product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1]; +#endif +} DeviceInfo; + +#ifdef GATEWAY_ENABLED +typedef struct { + DeviceInfo gw_info; + DeviceInfo* sub_dev_info; + unsigned int sub_dev_num; +} GatewayDeviceInfo; +#endif + +#include "qcloud_iot_export_rrpc.h" +#include "qcloud_iot_export_broadcast.h" +#include "qcloud_iot_export_coap.h" +#include "qcloud_iot_export_dynreg.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_gateway.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_export_mqtt.h" +#include "qcloud_iot_export_ota.h" +#include "qcloud_iot_export_shadow.h" +#include "qcloud_iot_export_system.h" +#include "qcloud_iot_export_variables.h" +#include "qcloud_iot_export_remote_config.h" + +#ifdef __cplusplus +} +#endif + +#endif /* QCLOUD_IOT_EXPORT_H_ */ diff --git a/include/qcloud_iot_export_variables.h b/include/qcloud_iot_export_variables.h new file mode 100755 index 00000000..e2cfbfab --- /dev/null +++ b/include/qcloud_iot_export_variables.h @@ -0,0 +1,74 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_EXPORT_VARIABLES_H_ +#define QCLOUD_IOT_EXPORT_VARIABLES_H_ + +/* + * Below variables are dependant on user situation (network status/device memory/application context) + * Adjust the default value to meet your requirement + */ + +/* default MQTT/CoAP timeout value when connect/pub/sub (unit: ms) */ +#define QCLOUD_IOT_MQTT_COMMAND_TIMEOUT (5 * 1000) + +/* default MQTT keep alive interval (unit: ms) */ +#define QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL (240 * 1000) + +/* default MQTT Tx buffer size, MAX: 16*1024 */ +#define QCLOUD_IOT_MQTT_TX_BUF_LEN (2048) + +/* default MQTT Rx buffer size, MAX: 16*1024 */ +#define QCLOUD_IOT_MQTT_RX_BUF_LEN (2048) + +/* default COAP Tx buffer size, MAX: 1*1024 */ +#define COAP_SENDMSG_MAX_BUFLEN (512) + +/* default COAP Rx buffer size, MAX: 1*1024 */ +#define COAP_RECVMSG_MAX_BUFLEN (512) + +/* MAX MQTT reconnect interval (unit: ms) */ +#define MAX_RECONNECT_WAIT_INTERVAL (60 * 1000) + +/* MAX valid time when connect to MQTT server. 0: always valid */ +/* Use this only if the device has accurate UTC time. Otherwise, set to 0 */ +#define MAX_ACCESS_EXPIRE_TIMEOUT (0) + +/* log print/upload related variables */ +/* MAX size of log buffer for one log item including header and content */ +#define MAX_LOG_MSG_LEN (511) + +#if defined(__linux__) +#undef MAX_LOG_MSG_LEN +#define MAX_LOG_MSG_LEN (1023) +#endif + +/* + * Log upload related params, which will affect the size of device memory/disk consumption + * the default value can be changed for different user situation + */ +// size of buffer for log upload +#define LOG_UPLOAD_BUFFER_SIZE 5000 + +// Max size of one http log upload. Should not larger than 5000 +#define MAX_HTTP_LOG_POST_SIZE 3000 + +// MAX size for saving log into NVS (files/FLASH) after upload fail +#define MAX_LOG_SAVE_SIZE (3 * LOG_UPLOAD_BUFFER_SIZE) + +// interval of log upload (unit: ms) Decrease this value if LOG_UPLOAD_BUFFER_SIZE is small +#define LOG_UPLOAD_INTERVAL_MS 2000 + +#endif /* QCLOUD_IOT_EXPORT_VARIABLES_H_ */ diff --git a/include/qcloud_iot_import.h b/include/qcloud_iot_import.h new file mode 100755 index 00000000..99dba871 --- /dev/null +++ b/include/qcloud_iot_import.h @@ -0,0 +1,583 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_IMPORT_H_ +#define QCLOUD_IOT_IMPORT_H_ +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "platform.h" + +#define _IN_ /* indicate an input parameter */ +#define _OU_ /* indicate a output parameter */ + +#define IOT_TRUE (1) /* indicate boolean value true */ +#define IOT_FALSE (0) /* indicate boolean value false */ + +#define Max(a, b) ((a) > (b) ? (a) : (b)) +#define Min(a, b) ((a) < (b) ? (a) : (b)) + +/********************************************************************** + * QCloud IoT C-SDK Hardware Abstraction Layer + * Platform/OS/IP stack/SSL dependant functions + * Check platform folder for reference implementaions + * Require porting when adapt SDK to new platform/OS + *********************************************************************/ + +typedef void (*ThreadRunFunc)(void *arg); + +typedef struct ThreadParams { + char * thread_name; + uint32_t thread_id; + ThreadRunFunc thread_func; + void * user_arg; + uint16_t priority; + uint32_t stack_size; +} ThreadParams; + +/** + * @brief Create a thread/task + * + * @param params thread parameters + * @return 0 when success, or error code otherwise + */ +int HAL_ThreadCreate(ThreadParams *params); + +/** + * @brief create semaphore + * + * @return a valid semaphore handle when success, or NULL otherwise + */ +void *HAL_SemaphoreCreate(void); + +/** + * @brief Destroy semaphore + * @param sem semaphore handle + */ +void HAL_SemaphoreDestroy(void *sem); + +/** + * @brief Post semaphore + * @param sem semaphore handle + */ +void HAL_SemaphorePost(void *sem); + +/** + * @brief Wait for semaphore + * @param sem semaphore handle + * @param timeout_ms waiting timeout value (unit: ms) + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms); + +/** + * @brief Create mutex + * + * @return a valid mutex handle when success, or NULL otherwise + */ +void *HAL_MutexCreate(void); + +/** + * @brief Destroy mutex + * + * @param mutex mutex handle + */ +void HAL_MutexDestroy(_IN_ void *mutex); + +/** + * @brief Lock a mutex in blocking way + * + * @param mutex mutex handle + */ +void HAL_MutexLock(_IN_ void *mutex); + +/** + * @brief Lock a mutex in non-blocking way + * + * @param mutex mutex handle + * @return 0 for success, or err code for failure + */ +int HAL_MutexTryLock(_IN_ void *mutex); + +/** + * @brief Unlock/release mutex + * + * @param mutex mutex handle + */ +void HAL_MutexUnlock(_IN_ void *mutex); + +/** + * @brief Malloc memory + * + * @param size Expected memory size (unit: byte) + * @return pointer to the memory + */ +void *HAL_Malloc(_IN_ uint32_t size); + +/** + * @brief Free memory + * + * @param ptr pointer to the pre-malloc memory + */ +void HAL_Free(_IN_ void *ptr); + +/** + * @brief Print data to console in format + * + * @param fmt print format + * @param ... variable number of arguments + */ +void HAL_Printf(_IN_ const char *fmt, ...); + +/** + * @brief Print data to string in format + * + * @param str destination string + * @param len Max size of the output + * @param fmt print format + * @param ... variable number of arguments + * @return number of bytes that print successfull + */ +int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...); + +/** + Print data to string in format + * + * @param str destination string + * @param len Max size of the output + * @param fmt print format + * @param ap arguments list + * @return number of bytes that print successfull + + */ +int HAL_Vsnprintf(_OU_ char *str, _IN_ const int len, _IN_ const char *fmt, _IN_ va_list ap); + +/** + * @brief Get timestamp in millisecond + * + * @return timestamp in millisecond + */ +uint32_t HAL_GetTimeMs(void); + +/** + * @brief Delay operation in blocking way + * + * @param ms sleep interval in millisecond + */ +void HAL_DelayMs(_IN_ uint32_t ms); + +/** + * @brief Sleep for a while + * + * @param ms sleep interval in millisecond + */ +void HAL_SleepMs(_IN_ uint32_t ms); + +/** + * @brief Set device info to NVS(flash/files) + * + * @param pdevInfo reference to device info + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_SetDevInfo(void *pdevInfo); + +/** + * @brief Get device info from NVS(flash/files) + * + * @param pdevInfo reference to device info + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_GetDevInfo(void *pdevInfo); + +/** + * @brief Get device info from a JSON file + * + * @param file_name JSON file path + * @param pdevInfo reference to device info + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_GetDevInfoFromFile(const char *file_name, void *dev_info); + +#ifdef GATEWAY_ENABLED +/** + * @brief Get gateway device info from NVS(flash/files) + * + * @param pgwDeviceInfo reference to gateway device info + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_GetGwDevInfo(void *pgwDeviceInfo); +#endif + +/** + * @brief Set the name of file which contain device info + * + * @param file_name the name of file which contain device info + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_SetDevInfoFile(const char *file_name); + +/** + * Define timer structure, platform dependant + */ +struct Timer { +#if defined(__linux__) && defined(__GLIBC__) + struct timeval end_time; +#else + uintptr_t end_time; +#endif +}; + +typedef struct Timer Timer; + +/** + * @brief Check if timer expires or not + * + * @param timer reference to timer + * @return true = expired, false = not expired yet + */ +bool HAL_Timer_expired(Timer *timer); + +/** + * @brief Set the countdown/expired value for the timer + * + * @param timer reference to timer + * @param timeout_ms countdown/expired value (unit: millisecond) + */ +void HAL_Timer_countdown_ms(Timer *timer, unsigned int timeout_ms); + +/** + * @brief Set the countdown/expired value for the timer + * + * @param timer reference to timer + * @param timeout countdown/expired value (unit: second) + */ +void HAL_Timer_countdown(Timer *timer, unsigned int timeout); + +/** + * @brief Check the remain time of the timer + * + * @param timer reference to timer + * @return 0 if expired, or the left time in millisecond + */ +int HAL_Timer_remain(Timer *timer); + +/** + * @brief Init the timer + * + * @param timer reference to timer + */ +void HAL_Timer_init(Timer *timer); + +#define TIME_FORMAT_STR_LEN (20) +/** + * @brief Get local time in format: %y-%m-%d %H:%M:%S + * + * @return string of formatted time + */ +char *HAL_Timer_current(char *time_str); + +/** + * @brief Get timestamp in second + * + * @return timestamp in second + */ +long HAL_Timer_current_sec(void); + +/** + * @brief Set timestamp in second to systime/rtc + * + * @return 0 is success other failed + */ +int HAL_Timer_set_systime_sec(size_t timestamp_sec); + +/** + * @brief Set timestamp in millsecond to systime/rtc + * + * @return 0 is success other failed + */ +int HAL_Timer_set_systime_ms(size_t timestamp_ms); + +#ifdef AT_TCP_ENABLED +int HAL_AT_TCP_Init(void); +uintptr_t HAL_AT_TCP_Connect(const char *host, uint16_t port); +int HAL_AT_TCP_Disconnect(uintptr_t fd); +int HAL_AT_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *written_len); +int HAL_AT_TCP_Read(uintptr_t fd, uint8_t *buf, uint32_t len, uint32_t timeout_ms, uint32_t *read_len); +int at_device_init(void); +int HAL_AT_Uart_Init(void); +int HAL_AT_Uart_Deinit(void); +int HAL_AT_Uart_Send(void *data, uint32_t size); +int HAL_AT_Uart_Recv(void *data, uint32_t expect_size, uint32_t *recv_size, uint32_t timeout); +#endif + +/********** TLS/DTLS network sturcture and operations **********/ + +#ifndef AUTH_WITH_NOTLS +/** + * @brief Define structure for TLS connection parameters + * + */ +typedef struct { + const char *ca_crt; + uint16_t ca_crt_len; + +#ifdef AUTH_MODE_CERT + /** + * Device with certificate + */ + const char *cert_file; // public certificate file + const char *key_file; // pravite certificate file +#else + /** + * Device with PSK + */ + const char *psk; // PSK string + const char *psk_id; // PSK ID +#endif + + size_t psk_length; // PSK length + + unsigned int timeout_ms; // SSL handshake timeout in millisecond + +} SSLConnectParams; + +typedef SSLConnectParams TLSConnectParams; + +/** + * @brief Setup TLS connection with server + * + * @param pConnectParams reference to TLS connection parameters + * @host server address + * @port server port + * @return TLS connect handle when success, or 0 otherwise + */ +uintptr_t HAL_TLS_Connect(TLSConnectParams *pConnectParams, const char *host, int port); + +/** + * @brief Disconnect with TLS server and release resources + * + * @param handle TLS connect handle + */ +void HAL_TLS_Disconnect(uintptr_t handle); + +/** + * @brief Write data via TLS connection + * + * @param handle TLS connect handle + * @param data source data to write + * @param totalLen length of data + * @param timeout_ms timeout value in millisecond + * @param written_len length of data written successfully + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_TLS_Write(uintptr_t handle, unsigned char *data, size_t totalLen, uint32_t timeout_ms, size_t *written_len); + +/** + * @brief Read data via TLS connection + * + * @param handle TLS connect handle + * @param data destination data buffer where to put data + * @param totalLen length of data + * @param timeout_ms timeout value in millisecond + * @param read_len length of data read successfully + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_TLS_Read(uintptr_t handle, unsigned char *data, size_t totalLen, uint32_t timeout_ms, size_t *read_len); + +/********** DTLS network **********/ +#ifdef COAP_COMM_ENABLED +typedef SSLConnectParams DTLSConnectParams; + +/** + * @brief Setup DTLS connection with server + * + * @param pConnectParams reference to DTLS connection parameters + * @host server address + * @port server port + * @return DTLS connect handle when success, or 0 otherwise + */ +uintptr_t HAL_DTLS_Connect(DTLSConnectParams *pConnectParams, const char *host, int port); + +/** + * @brief Disconnect with DTLS server and release resources + * + * @param handle DTLS connect handle + */ +void HAL_DTLS_Disconnect(uintptr_t handle); + +/** + * @brief Write data via DTLS connection + * + * @param handle DTLS connect handle + * @param data source data to write + * @param totalLen length of data + * @param timeout_ms timeout value in millisecond + * @param written_len length of data written successfully + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_DTLS_Write(uintptr_t handle, const unsigned char *data, size_t datalen, size_t *written_len); + +/** + * @brief Read data via DTLS connection + * + * @param handle DTLS connect handle + * @param data destination data buffer where to put data + * @param totalLen length of data + * @param timeout_ms timeout value in millisecond + * @param read_len length of data read successfully + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_DTLS_Read(uintptr_t handle, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len); + +#endif // COAP_COMM_ENABLED +#endif // AUTH_WITH_NOTLS + +/********** TCP network **********/ +/** + * @brief Setup TCP connection with server + * + * @host server address + * @port server port + * @return TCP socket handle (value>0) when success, or 0 otherwise + */ +uintptr_t HAL_TCP_Connect(const char *host, uint16_t port); + +/** + * @brief Disconnect with server and release resource + * + * @param fd TCP Socket handle + * @return 0 when success + */ +int HAL_TCP_Disconnect(uintptr_t fd); + +/** + * @brief Write data via TCP connection + * + * @param fd TCP socket handle + * @param data source data to write + * @param len length of data + * @param timeout_ms timeout value in millisecond + * @param written_len length of data written successfully + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_TCP_Write(uintptr_t fd, const unsigned char *data, uint32_t len, uint32_t timeout_ms, size_t *written_len); + +/** + * @brief Read data via TCP connection + * + * @param fd TCP socket handle + * @param data destination data buffer where to put data + * @param len length of data + * @param timeout_ms timeout value in millisecond + * @param read_len length of data read successfully + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int HAL_TCP_Read(uintptr_t fd, unsigned char *data, uint32_t len, uint32_t timeout_ms, size_t *read_len); + +/********** UDP network **********/ +#ifdef COAP_COMM_ENABLED +/** + * @brief Setup UDP connection with server + * + * @host server address + * @port server port + * @return UPD socket handle (value>0) when success, or 0 otherwise + */ +uintptr_t HAL_UDP_Connect(const char *host, unsigned short port); + +/** + * @brief Disconnect with server and release resource + * + * @param fd UDP Socket handle + * @return 0 when success + */ +void HAL_UDP_Disconnect(uintptr_t fd); + +/** + * @brief Write data via UDP connection + * + * @param fd UDP socket handle + * @param data source data to write + * @param len length of data + * @return length of data written when success, or err code for failure + */ +int HAL_UDP_Write(uintptr_t fd, const unsigned char *data, unsigned int len); + +/** + * @brief Read data via UDP connection + * + * @param fd UDP socket handle + * @param data destination data buffer where to put data + * @param len length of data + * @return length of data read when success, or err code for failure + */ +int HAL_UDP_Read(uintptr_t fd, unsigned char *data, unsigned int len); + +/** + * @brief Read data via UDP connection + * + * @param fd UDP socket handle + * @param data destination data buffer where to put data + * @param len length of data + * @param timeout_ms timeout value in millisecond + * @return length of data read when success, or err code for failure + */ +int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datalen, unsigned int timeout_ms); +#endif // COAP_COMM_ENABLED + +#ifdef LOG_UPLOAD +/* Functions for saving/reading logs into/from NVS(files/FLASH) after log upload fail/recover */ +/** + * @brief Functions for saving logs into NVS(files/FLASH) after log upload fail + * @param log source log buffer + * @param len length of log to save + * @return length of data save when success, or 0 for failure + */ +size_t HAL_Log_Save(const char *log, size_t len); + +/** + * @brief Functions for reading logs from NVS(files/FLASH) when log upload ready + * @param buf destination log buffer + * @param len length of log to read + * @return length of data read when success, or 0 for failure + */ +size_t HAL_Log_Read(char *buf, size_t len); + +/** + * @brief Functions for deleting logs in NVS(files/FLASH). + * @return 0 when success + */ +int HAL_Log_Del(void); + +/** + * @brief Functions for reading the size of logs in NVS(files/FLASH). + * @return 0 when nothing exist + */ +size_t HAL_Log_Get_Size(void); +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* QCLOUD_IOT_IMPORT_H_ */ diff --git a/src/utils/farra/utils_timer.c b/include/utils_getopt.h old mode 100644 new mode 100755 similarity index 51% rename from src/utils/farra/utils_timer.c rename to include/utils_getopt.h index 433ce7d8..0b5f33b1 --- a/src/utils/farra/utils_timer.c +++ b/include/utils_getopt.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,32 +13,10 @@ * */ -#ifdef __cplusplus -extern "C" { -#endif - -#include "utils_timer.h" - -bool expired(Timer *timer) { - return HAL_Timer_expired(timer); -} - -void countdown_ms(Timer *timer, unsigned int timeout_ms) { - HAL_Timer_countdown_ms(timer, timeout_ms); -} - -void countdown(Timer *timer, unsigned int timeout) { - HAL_Timer_countdown(timer, timeout); -} +#ifndef __UTILS_GETOPT_H__ +#define __UTILS_GETOPT_H__ -int left_ms(Timer *timer) { - return HAL_Timer_remain(timer); -} +extern char* utils_optarg; /* pointer to argument of current option */ +int utils_getopt(int nargc, char* const* nargv, const char* options); -void InitTimer(Timer *timer) { - HAL_Timer_init(timer); -} - -#ifdef __cplusplus -} #endif diff --git a/make.settings b/make.settings index 9f2a2aee..31a6bd7f 100755 --- a/make.settings +++ b/make.settings @@ -1,30 +1,80 @@ -BUILD_TYPE = release #release/debug +# 编译类型: release/debug +BUILD_TYPE = release +# Makefile编译打印 echo +DEBUG_MAKEFILE = n +# 编译工具链 PLATFORM_CC = gcc PLATFORM_AR = ar PLATFORM_OS = linux PLATFORM_SSL = mbedtls +PLATFORM_AT_DEV = esp8266 -# -# Uncomment below and specify PATH to your toolchain when cross-compile SDK -# -# PLATFORM_CC = /home/shock/openwrt/packages/toolchain/mipsel-linux-gcc -# PLATFORM_AR = /home/shock/openwrt/packages/toolchain/mipsel-linux-ar +# 交叉编译工具链示例 +# PLATFORM_CC = /opt/openwrt/packages/toolchain/mipsel-linux-gcc +# PLATFORM_AR = /opt/openwrt/packages/toolchain/mipsel-linux-ar # PLATFORM_CC = armcc # PLATFORM_AR = armar -FEATURE_MQTT_COMM_ENABLED = y # 是否打开MQTT通道的总开关 -FEATURE_MQTT_DEVICE_SHADOW = y # 是否打开设备影子的总开关 -FEATURE_COAP_COMM_ENABLED = y # 是否打开CoAP通道的总开关 -FEATURE_NBIOT_COMM_ENABLED = y # 是否打开NBIoT通道的消息组装 -FEATURE_GATEWAY_ENABLED = n # 是否打开MQTT通道网关功能 +# 是否打开MQTT通道的总开关 +FEATURE_MQTT_COMM_ENABLED = y -FEATURE_OTA_COMM_ENABLED = y # 是否打开OTA固件升级总开关 -FEATURE_OTA_SIGNAL_CHANNEL = MQTT # OTA信令通道类型:MQTT/COAP +# 是否打开设备影子的总开关 +FEATURE_MQTT_DEVICE_SHADOW = y -FEATURE_AUTH_MODE = CERT # MQTT/CoAP接入认证方式,使用证书认证:CERT;使用密钥认证:KEY -FEATURE_AUTH_WITH_NOTLS = n # 接入认证是否不使用TLS,证书方式必须选择使用TLS,密钥认证可选择不使用TLS +# 是否打开CoAP通道的总开关 +FEATURE_COAP_COMM_ENABLED = n -FEATURE_LOG_UPLOAD_ENABLED = y # 是否打开日志上报云端功能 -FEATURE_SYSTEM_COMM_ENABLED = y # 是否打开获取iot后台时间功能 -FEATURE_MULTITHREAD_TEST_ENABLED = n # 是否编译Linux多线程测试例程 +# 是否打开MQTT通道网关功能 +FEATURE_GATEWAY_ENABLED = y + +# 是否打开OTA固件升级总开关 +FEATURE_OTA_COMM_ENABLED = y + +# OTA信令通道类型:MQTT/COAP +FEATURE_OTA_SIGNAL_CHANNEL = MQTT + +# MQTT/CoAP接入认证方式,使用证书认证:CERT;使用密钥认证:KEY +FEATURE_AUTH_MODE = KEY + +# 接入认证是否不使用TLS,证书方式必须选择使用TLS,密钥认证可选择不使用TLS +FEATURE_AUTH_WITH_NOTLS = n + +# 是否使能设备动态注册 +FEATURE_DEV_DYN_REG_ENABLED = n + +# 是否打开日志上报云端功能 +FEATURE_LOG_UPLOAD_ENABLED = n + +# 是否打开获取iot后台时间功能 +FEATURE_SYSTEM_COMM_ENABLED = y + +# 是否打开多线程功能支持 +FEATURE_MULTITHREAD_ENABLED = y + +# 是否使用HTTPS下载固件 +FEATURE_OTA_USE_HTTPS = y + +# 是否打开代码中获取设备信息功能,设为n时将从device_info.json中读取设备信息 +FEATURE_DEBUG_DEV_INFO_USED = n + +# 是否使用AT方式实现TCP通信 +FEATURE_AT_TCP_ENABLED = n + +# 是否打开AT模组中断接收功能 +FEATURE_AT_UART_RECV_IRQ = n + +# 是否打开AT模组多线程功能 +FEATURE_AT_OS_USED = n + +# 是否打开AT模组调试功能 +FEATURE_AT_DEBUG = n + +# 是否打开广播功能 +FEATURE_BROADCAST_ENABLED = y + +# 是否打开RRPC功能 +FEATURE_RRPC_ENABLED = y + +# 是否打开MQTT远程配置功能 +FEATURE_REMOTE_CONFIG_MQTT_ENABLED = y diff --git a/packages/gtest_module.git/HEAD b/packages/gtest_module.git/HEAD deleted file mode 100644 index cb089cd8..00000000 --- a/packages/gtest_module.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/packages/gtest_module.git/config b/packages/gtest_module.git/config deleted file mode 100644 index 1f2dcf51..00000000 --- a/packages/gtest_module.git/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true - precomposeunicode = true -[remote "origin"] - url = http://git.code.oa.com/IoT_Hub/gtest_module.git - fetch = +refs/heads/*:refs/remotes/origin/* -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/packages/gtest_module.git/description b/packages/gtest_module.git/description deleted file mode 100644 index 498b267a..00000000 --- a/packages/gtest_module.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/packages/gtest_module.git/hooks/applypatch-msg.sample b/packages/gtest_module.git/hooks/applypatch-msg.sample deleted file mode 100755 index a5d7b84a..00000000 --- a/packages/gtest_module.git/hooks/applypatch-msg.sample +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message taken by -# applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. The hook is -# allowed to edit the commit message file. -# -# To enable this hook, rename this file to "applypatch-msg". - -. git-sh-setup -commitmsg="$(git rev-parse --git-path hooks/commit-msg)" -test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} -: diff --git a/packages/gtest_module.git/hooks/commit-msg.sample b/packages/gtest_module.git/hooks/commit-msg.sample deleted file mode 100755 index b58d1184..00000000 --- a/packages/gtest_module.git/hooks/commit-msg.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message. -# Called by "git commit" with one argument, the name of the file -# that has the commit message. The hook should exit with non-zero -# status after issuing an appropriate message if it wants to stop the -# commit. The hook is allowed to edit the commit message file. -# -# To enable this hook, rename this file to "commit-msg". - -# Uncomment the below to add a Signed-off-by line to the message. -# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -# hook is more suited to it. -# -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" - -# This example catches duplicate Signed-off-by lines. - -test "" = "$(grep '^Signed-off-by: ' "$1" | - sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { - echo >&2 Duplicate Signed-off-by lines. - exit 1 -} diff --git a/packages/gtest_module.git/hooks/post-update.sample b/packages/gtest_module.git/hooks/post-update.sample deleted file mode 100755 index ec17ec19..00000000 --- a/packages/gtest_module.git/hooks/post-update.sample +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare a packed repository for use over -# dumb transports. -# -# To enable this hook, rename this file to "post-update". - -exec git update-server-info diff --git a/packages/gtest_module.git/hooks/pre-applypatch.sample b/packages/gtest_module.git/hooks/pre-applypatch.sample deleted file mode 100755 index 4142082b..00000000 --- a/packages/gtest_module.git/hooks/pre-applypatch.sample +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed -# by applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-applypatch". - -. git-sh-setup -precommit="$(git rev-parse --git-path hooks/pre-commit)" -test -x "$precommit" && exec "$precommit" ${1+"$@"} -: diff --git a/packages/gtest_module.git/hooks/pre-commit.sample b/packages/gtest_module.git/hooks/pre-commit.sample deleted file mode 100755 index 68d62d54..00000000 --- a/packages/gtest_module.git/hooks/pre-commit.sample +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed. -# Called by "git commit" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message if -# it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-commit". - -if git rev-parse --verify HEAD >/dev/null 2>&1 -then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -fi - -# If you want to allow non-ASCII filenames set this variable to true. -allownonascii=$(git config --bool hooks.allownonascii) - -# Redirect output to stderr. -exec 1>&2 - -# Cross platform projects tend to avoid non-ASCII filenames; prevent -# them from being added to the repository. We exploit the fact that the -# printable range starts at the space character and ends with tilde. -if [ "$allownonascii" != "true" ] && - # Note that the use of brackets around a tr range is ok here, (it's - # even required, for portability to Solaris 10's /usr/bin/tr), since - # the square bracket bytes happen to fall in the designated range. - test $(git diff --cached --name-only --diff-filter=A -z $against | - LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 -then - cat <<\EOF -Error: Attempt to add a non-ASCII file name. - -This can cause problems if you want to work with people on other platforms. - -To be portable it is advisable to rename the file. - -If you know what you are doing you can disable this check using: - - git config hooks.allownonascii true -EOF - exit 1 -fi - -# If there are whitespace errors, print the offending file names and fail. -exec git diff-index --check --cached $against -- diff --git a/packages/gtest_module.git/hooks/pre-push.sample b/packages/gtest_module.git/hooks/pre-push.sample deleted file mode 100755 index 6187dbf4..00000000 --- a/packages/gtest_module.git/hooks/pre-push.sample +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh - -# An example hook script to verify what is about to be pushed. Called by "git -# push" after it has checked the remote status, but before anything has been -# pushed. If this script exits with a non-zero status nothing will be pushed. -# -# This hook is called with the following parameters: -# -# $1 -- Name of the remote to which the push is being done -# $2 -- URL to which the push is being done -# -# If pushing without using a named remote those arguments will be equal. -# -# Information about the commits which are being pushed is supplied as lines to -# the standard input in the form: -# -# -# -# This sample shows how to prevent push of commits where the log message starts -# with "WIP" (work in progress). - -remote="$1" -url="$2" - -z40=0000000000000000000000000000000000000000 - -while read local_ref local_sha remote_ref remote_sha -do - if [ "$local_sha" = $z40 ] - then - # Handle delete - : - else - if [ "$remote_sha" = $z40 ] - then - # New branch, examine all commits - range="$local_sha" - else - # Update to existing branch, examine new commits - range="$remote_sha..$local_sha" - fi - - # Check for WIP commit - commit=`git rev-list -n 1 --grep '^WIP' "$range"` - if [ -n "$commit" ] - then - echo >&2 "Found WIP commit in $local_ref, not pushing" - exit 1 - fi - fi -done - -exit 0 diff --git a/packages/gtest_module.git/hooks/pre-rebase.sample b/packages/gtest_module.git/hooks/pre-rebase.sample deleted file mode 100755 index 6cbef5c3..00000000 --- a/packages/gtest_module.git/hooks/pre-rebase.sample +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006, 2008 Junio C Hamano -# -# The "pre-rebase" hook is run just before "git rebase" starts doing -# its job, and can prevent the command from running by exiting with -# non-zero status. -# -# The hook is called with the following parameters: -# -# $1 -- the upstream the series was forked from. -# $2 -- the branch being rebased (or empty when rebasing the current branch). -# -# This sample shows how to prevent topic branches that are already -# merged to 'next' branch from getting rebased, because allowing it -# would result in rebasing already published history. - -publish=next -basebranch="$1" -if test "$#" = 2 -then - topic="refs/heads/$2" -else - topic=`git symbolic-ref HEAD` || - exit 0 ;# we do not interrupt rebasing detached HEAD -fi - -case "$topic" in -refs/heads/??/*) - ;; -*) - exit 0 ;# we do not interrupt others. - ;; -esac - -# Now we are dealing with a topic branch being rebased -# on top of master. Is it OK to rebase it? - -# Does the topic really exist? -git show-ref -q "$topic" || { - echo >&2 "No such branch $topic" - exit 1 -} - -# Is topic fully merged to master? -not_in_master=`git rev-list --pretty=oneline ^master "$topic"` -if test -z "$not_in_master" -then - echo >&2 "$topic is fully merged to master; better remove it." - exit 1 ;# we could allow it, but there is no point. -fi - -# Is topic ever merged to next? If so you should not be rebasing it. -only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` -only_next_2=`git rev-list ^master ${publish} | sort` -if test "$only_next_1" = "$only_next_2" -then - not_in_topic=`git rev-list "^$topic" master` - if test -z "$not_in_topic" - then - echo >&2 "$topic is already up to date with master" - exit 1 ;# we could allow it, but there is no point. - else - exit 0 - fi -else - not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` - /usr/bin/perl -e ' - my $topic = $ARGV[0]; - my $msg = "* $topic has commits already merged to public branch:\n"; - my (%not_in_next) = map { - /^([0-9a-f]+) /; - ($1 => 1); - } split(/\n/, $ARGV[1]); - for my $elem (map { - /^([0-9a-f]+) (.*)$/; - [$1 => $2]; - } split(/\n/, $ARGV[2])) { - if (!exists $not_in_next{$elem->[0]}) { - if ($msg) { - print STDERR $msg; - undef $msg; - } - print STDERR " $elem->[1]\n"; - } - } - ' "$topic" "$not_in_next" "$not_in_master" - exit 1 -fi - -<<\DOC_END - -This sample hook safeguards topic branches that have been -published from being rewound. - -The workflow assumed here is: - - * Once a topic branch forks from "master", "master" is never - merged into it again (either directly or indirectly). - - * Once a topic branch is fully cooked and merged into "master", - it is deleted. If you need to build on top of it to correct - earlier mistakes, a new topic branch is created by forking at - the tip of the "master". This is not strictly necessary, but - it makes it easier to keep your history simple. - - * Whenever you need to test or publish your changes to topic - branches, merge them into "next" branch. - -The script, being an example, hardcodes the publish branch name -to be "next", but it is trivial to make it configurable via -$GIT_DIR/config mechanism. - -With this workflow, you would want to know: - -(1) ... if a topic branch has ever been merged to "next". Young - topic branches can have stupid mistakes you would rather - clean up before publishing, and things that have not been - merged into other branches can be easily rebased without - affecting other people. But once it is published, you would - not want to rewind it. - -(2) ... if a topic branch has been fully merged to "master". - Then you can delete it. More importantly, you should not - build on top of it -- other people may already want to - change things related to the topic as patches against your - "master", so if you need further changes, it is better to - fork the topic (perhaps with the same name) afresh from the - tip of "master". - -Let's look at this example: - - o---o---o---o---o---o---o---o---o---o "next" - / / / / - / a---a---b A / / - / / / / - / / c---c---c---c B / - / / / \ / - / / / b---b C \ / - / / / / \ / - ---o---o---o---o---o---o---o---o---o---o---o "master" - - -A, B and C are topic branches. - - * A has one fix since it was merged up to "next". - - * B has finished. It has been fully merged up to "master" and "next", - and is ready to be deleted. - - * C has not merged to "next" at all. - -We would want to allow C to be rebased, refuse A, and encourage -B to be deleted. - -To compute (1): - - git rev-list ^master ^topic next - git rev-list ^master next - - if these match, topic has not merged in next at all. - -To compute (2): - - git rev-list master..topic - - if this is empty, it is fully merged to "master". - -DOC_END diff --git a/packages/gtest_module.git/hooks/pre-receive.sample b/packages/gtest_module.git/hooks/pre-receive.sample deleted file mode 100755 index a1fd29ec..00000000 --- a/packages/gtest_module.git/hooks/pre-receive.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to make use of push options. -# The example simply echoes all push options that start with 'echoback=' -# and rejects all pushes when the "reject" push option is used. -# -# To enable this hook, rename this file to "pre-receive". - -if test -n "$GIT_PUSH_OPTION_COUNT" -then - i=0 - while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" - do - eval "value=\$GIT_PUSH_OPTION_$i" - case "$value" in - echoback=*) - echo "echo from the pre-receive-hook: ${value#*=}" >&2 - ;; - reject) - exit 1 - esac - i=$((i + 1)) - done -fi diff --git a/packages/gtest_module.git/hooks/prepare-commit-msg.sample b/packages/gtest_module.git/hooks/prepare-commit-msg.sample deleted file mode 100755 index 10fa14c5..00000000 --- a/packages/gtest_module.git/hooks/prepare-commit-msg.sample +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare the commit log message. -# Called by "git commit" with the name of the file that has the -# commit message, followed by the description of the commit -# message's source. The hook's purpose is to edit the commit -# message file. If the hook fails with a non-zero status, -# the commit is aborted. -# -# To enable this hook, rename this file to "prepare-commit-msg". - -# This hook includes three examples. The first one removes the -# "# Please enter the commit message..." help message. -# -# The second includes the output of "git diff --name-status -r" -# into the message, just before the "git status" output. It is -# commented because it doesn't cope with --amend or with squashed -# commits. -# -# The third example adds a Signed-off-by line to the message, that can -# still be edited. This is rarely a good idea. - -COMMIT_MSG_FILE=$1 -COMMIT_SOURCE=$2 -SHA1=$3 - -/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" - -# case "$COMMIT_SOURCE,$SHA1" in -# ,|template,) -# /usr/bin/perl -i.bak -pe ' -# print "\n" . `git diff --cached --name-status -r` -# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; -# *) ;; -# esac - -# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" -# if test -z "$COMMIT_SOURCE" -# then -# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" -# fi diff --git a/packages/gtest_module.git/hooks/update.sample b/packages/gtest_module.git/hooks/update.sample deleted file mode 100755 index 80ba9413..00000000 --- a/packages/gtest_module.git/hooks/update.sample +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -# -# An example hook script to block unannotated tags from entering. -# Called by "git receive-pack" with arguments: refname sha1-old sha1-new -# -# To enable this hook, rename this file to "update". -# -# Config -# ------ -# hooks.allowunannotated -# This boolean sets whether unannotated tags will be allowed into the -# repository. By default they won't be. -# hooks.allowdeletetag -# This boolean sets whether deleting tags will be allowed in the -# repository. By default they won't be. -# hooks.allowmodifytag -# This boolean sets whether a tag may be modified after creation. By default -# it won't be. -# hooks.allowdeletebranch -# This boolean sets whether deleting branches will be allowed in the -# repository. By default they won't be. -# hooks.denycreatebranch -# This boolean sets whether remotely creating branches will be denied -# in the repository. By default this is allowed. -# - -# --- Command line -refname="$1" -oldrev="$2" -newrev="$3" - -# --- Safety check -if [ -z "$GIT_DIR" ]; then - echo "Don't run this script from the command line." >&2 - echo " (if you want, you could supply GIT_DIR then run" >&2 - echo " $0 )" >&2 - exit 1 -fi - -if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then - echo "usage: $0 " >&2 - exit 1 -fi - -# --- Config -allowunannotated=$(git config --bool hooks.allowunannotated) -allowdeletebranch=$(git config --bool hooks.allowdeletebranch) -denycreatebranch=$(git config --bool hooks.denycreatebranch) -allowdeletetag=$(git config --bool hooks.allowdeletetag) -allowmodifytag=$(git config --bool hooks.allowmodifytag) - -# check for no description -projectdesc=$(sed -e '1q' "$GIT_DIR/description") -case "$projectdesc" in -"Unnamed repository"* | "") - echo "*** Project description file hasn't been set" >&2 - exit 1 - ;; -esac - -# --- Check types -# if $newrev is 0000...0000, it's a commit to delete a ref. -zero="0000000000000000000000000000000000000000" -if [ "$newrev" = "$zero" ]; then - newrev_type=delete -else - newrev_type=$(git cat-file -t $newrev) -fi - -case "$refname","$newrev_type" in - refs/tags/*,commit) - # un-annotated tag - short_refname=${refname##refs/tags/} - if [ "$allowunannotated" != "true" ]; then - echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 - echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 - exit 1 - fi - ;; - refs/tags/*,delete) - # delete tag - if [ "$allowdeletetag" != "true" ]; then - echo "*** Deleting a tag is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/tags/*,tag) - # annotated tag - if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 - then - echo "*** Tag '$refname' already exists." >&2 - echo "*** Modifying a tag is not allowed in this repository." >&2 - exit 1 - fi - ;; - refs/heads/*,commit) - # branch - if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then - echo "*** Creating a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/heads/*,delete) - # delete branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/remotes/*,commit) - # tracking branch - ;; - refs/remotes/*,delete) - # delete tracking branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a tracking branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - *) - # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 - exit 1 - ;; -esac - -# --- Finished -exit 0 diff --git a/packages/gtest_module.git/index b/packages/gtest_module.git/index deleted file mode 100644 index 33755e33..00000000 Binary files a/packages/gtest_module.git/index and /dev/null differ diff --git a/packages/gtest_module.git/info/exclude b/packages/gtest_module.git/info/exclude deleted file mode 100644 index a5196d1b..00000000 --- a/packages/gtest_module.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/packages/gtest_module.git/logs/HEAD b/packages/gtest_module.git/logs/HEAD deleted file mode 100644 index b76829af..00000000 --- a/packages/gtest_module.git/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 ab77aa4106186627099bda9c218385c2dbe420fa skyztmeng 1526572808 +0800 clone: from http://git.code.oa.com/IoT_Hub/gtest_module.git diff --git a/packages/gtest_module.git/logs/refs/heads/master b/packages/gtest_module.git/logs/refs/heads/master deleted file mode 100644 index b76829af..00000000 --- a/packages/gtest_module.git/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 ab77aa4106186627099bda9c218385c2dbe420fa skyztmeng 1526572808 +0800 clone: from http://git.code.oa.com/IoT_Hub/gtest_module.git diff --git a/packages/gtest_module.git/logs/refs/remotes/origin/HEAD b/packages/gtest_module.git/logs/refs/remotes/origin/HEAD deleted file mode 100644 index b76829af..00000000 --- a/packages/gtest_module.git/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 ab77aa4106186627099bda9c218385c2dbe420fa skyztmeng 1526572808 +0800 clone: from http://git.code.oa.com/IoT_Hub/gtest_module.git diff --git a/packages/gtest_module.git/objects/02/1feb16f94bde560642cdfb56f044dabde1d3cd b/packages/gtest_module.git/objects/02/1feb16f94bde560642cdfb56f044dabde1d3cd deleted file mode 100644 index 251ebdaa..00000000 Binary files a/packages/gtest_module.git/objects/02/1feb16f94bde560642cdfb56f044dabde1d3cd and /dev/null differ diff --git a/packages/gtest_module.git/objects/02/92dc11957eaa218b358f1f761ca4a5cb2faea7 b/packages/gtest_module.git/objects/02/92dc11957eaa218b358f1f761ca4a5cb2faea7 deleted file mode 100644 index b27114b7..00000000 Binary files a/packages/gtest_module.git/objects/02/92dc11957eaa218b358f1f761ca4a5cb2faea7 and /dev/null differ diff --git a/packages/gtest_module.git/objects/03/8f9ba79eb30377f165d8a0200d4750d349b8e7 b/packages/gtest_module.git/objects/03/8f9ba79eb30377f165d8a0200d4750d349b8e7 deleted file mode 100644 index f647dea8..00000000 Binary files a/packages/gtest_module.git/objects/03/8f9ba79eb30377f165d8a0200d4750d349b8e7 and /dev/null differ diff --git a/packages/gtest_module.git/objects/06/c4fb9b2446386d5a5f11b4d8dae5efcaee02f6 b/packages/gtest_module.git/objects/06/c4fb9b2446386d5a5f11b4d8dae5efcaee02f6 deleted file mode 100644 index 2e9412e6..00000000 Binary files a/packages/gtest_module.git/objects/06/c4fb9b2446386d5a5f11b4d8dae5efcaee02f6 and /dev/null differ diff --git a/packages/gtest_module.git/objects/0a/9cee52233328b1bafdc4bc402699fa14038f73 b/packages/gtest_module.git/objects/0a/9cee52233328b1bafdc4bc402699fa14038f73 deleted file mode 100644 index 4bb15d7a..00000000 Binary files a/packages/gtest_module.git/objects/0a/9cee52233328b1bafdc4bc402699fa14038f73 and /dev/null differ diff --git a/packages/gtest_module.git/objects/0e/5c10cf7cd7d97cef420777ee64ff56ec596630 b/packages/gtest_module.git/objects/0e/5c10cf7cd7d97cef420777ee64ff56ec596630 deleted file mode 100644 index f4d1f8a1..00000000 Binary files a/packages/gtest_module.git/objects/0e/5c10cf7cd7d97cef420777ee64ff56ec596630 and /dev/null differ diff --git a/packages/gtest_module.git/objects/11/7e5bbd157684d30d5be3af14805fe1c2997250 b/packages/gtest_module.git/objects/11/7e5bbd157684d30d5be3af14805fe1c2997250 deleted file mode 100644 index 7652ea4f..00000000 Binary files a/packages/gtest_module.git/objects/11/7e5bbd157684d30d5be3af14805fe1c2997250 and /dev/null differ diff --git a/packages/gtest_module.git/objects/20/726b2cd5bfc2daab8275fa0e54e8ca911f8613 b/packages/gtest_module.git/objects/20/726b2cd5bfc2daab8275fa0e54e8ca911f8613 deleted file mode 100644 index 399cc84d..00000000 Binary files a/packages/gtest_module.git/objects/20/726b2cd5bfc2daab8275fa0e54e8ca911f8613 and /dev/null differ diff --git a/packages/gtest_module.git/objects/25/1fdf025b2c5311faf95e86e330fe921c60dadb b/packages/gtest_module.git/objects/25/1fdf025b2c5311faf95e86e330fe921c60dadb deleted file mode 100644 index 756e5d32..00000000 Binary files a/packages/gtest_module.git/objects/25/1fdf025b2c5311faf95e86e330fe921c60dadb and /dev/null differ diff --git a/packages/gtest_module.git/objects/28/2a2dac03194ad7f4d9a601e737eb95896c7fca b/packages/gtest_module.git/objects/28/2a2dac03194ad7f4d9a601e737eb95896c7fca deleted file mode 100644 index a07227f1..00000000 Binary files a/packages/gtest_module.git/objects/28/2a2dac03194ad7f4d9a601e737eb95896c7fca and /dev/null differ diff --git a/packages/gtest_module.git/objects/28/5bb2a87b4b9df902f726c564abb75d3cad35c2 b/packages/gtest_module.git/objects/28/5bb2a87b4b9df902f726c564abb75d3cad35c2 deleted file mode 100644 index a24dae90..00000000 Binary files a/packages/gtest_module.git/objects/28/5bb2a87b4b9df902f726c564abb75d3cad35c2 and /dev/null differ diff --git a/packages/gtest_module.git/objects/2a/6e4dad1d18b6507c0f6df09e45e8e3e29b4bd9 b/packages/gtest_module.git/objects/2a/6e4dad1d18b6507c0f6df09e45e8e3e29b4bd9 deleted file mode 100644 index c45a09d3..00000000 Binary files a/packages/gtest_module.git/objects/2a/6e4dad1d18b6507c0f6df09e45e8e3e29b4bd9 and /dev/null differ diff --git a/packages/gtest_module.git/objects/2b/3a78f5bf86328fc1bf58f1682c9ee44a5057c2 b/packages/gtest_module.git/objects/2b/3a78f5bf86328fc1bf58f1682c9ee44a5057c2 deleted file mode 100644 index a8c53cb4..00000000 Binary files a/packages/gtest_module.git/objects/2b/3a78f5bf86328fc1bf58f1682c9ee44a5057c2 and /dev/null differ diff --git a/packages/gtest_module.git/objects/30/78d6d2a19d7918ed3c756abcfcb49937e16eb1 b/packages/gtest_module.git/objects/30/78d6d2a19d7918ed3c756abcfcb49937e16eb1 deleted file mode 100644 index 259bd59a..00000000 Binary files a/packages/gtest_module.git/objects/30/78d6d2a19d7918ed3c756abcfcb49937e16eb1 and /dev/null differ diff --git a/packages/gtest_module.git/objects/30/ae712f50ed3d8e8446e4495af9b1abecab2e86 b/packages/gtest_module.git/objects/30/ae712f50ed3d8e8446e4495af9b1abecab2e86 deleted file mode 100644 index 82d6c467..00000000 Binary files a/packages/gtest_module.git/objects/30/ae712f50ed3d8e8446e4495af9b1abecab2e86 and /dev/null differ diff --git a/packages/gtest_module.git/objects/31/42f742a0910f77961acbf655158d142a153fa0 b/packages/gtest_module.git/objects/31/42f742a0910f77961acbf655158d142a153fa0 deleted file mode 100644 index 1a6ddeb7..00000000 Binary files a/packages/gtest_module.git/objects/31/42f742a0910f77961acbf655158d142a153fa0 and /dev/null differ diff --git a/packages/gtest_module.git/objects/33/f70563469b1b53f3397061af6ed21c9d131c20 b/packages/gtest_module.git/objects/33/f70563469b1b53f3397061af6ed21c9d131c20 deleted file mode 100644 index b56cfe34..00000000 Binary files a/packages/gtest_module.git/objects/33/f70563469b1b53f3397061af6ed21c9d131c20 and /dev/null differ diff --git a/packages/gtest_module.git/objects/36/029422174f215848681db1110bcdb23538a12e b/packages/gtest_module.git/objects/36/029422174f215848681db1110bcdb23538a12e deleted file mode 100644 index cba6c2d9..00000000 Binary files a/packages/gtest_module.git/objects/36/029422174f215848681db1110bcdb23538a12e and /dev/null differ diff --git a/packages/gtest_module.git/objects/38/b9208e30c501f939b08b169354f00db93eccd6 b/packages/gtest_module.git/objects/38/b9208e30c501f939b08b169354f00db93eccd6 deleted file mode 100644 index d71faa6a..00000000 Binary files a/packages/gtest_module.git/objects/38/b9208e30c501f939b08b169354f00db93eccd6 and /dev/null differ diff --git a/packages/gtest_module.git/objects/3a/8a166a4d987d3f3b7fcd7df5c97f0ba0670c18 b/packages/gtest_module.git/objects/3a/8a166a4d987d3f3b7fcd7df5c97f0ba0670c18 deleted file mode 100644 index f5e1fb02..00000000 Binary files a/packages/gtest_module.git/objects/3a/8a166a4d987d3f3b7fcd7df5c97f0ba0670c18 and /dev/null differ diff --git a/packages/gtest_module.git/objects/3e/d5263d077ebd1e5ec03072303fc2b7474e1d17 b/packages/gtest_module.git/objects/3e/d5263d077ebd1e5ec03072303fc2b7474e1d17 deleted file mode 100644 index 76819ccd..00000000 Binary files a/packages/gtest_module.git/objects/3e/d5263d077ebd1e5ec03072303fc2b7474e1d17 and /dev/null differ diff --git a/packages/gtest_module.git/objects/42/9ddfeecaa74e71a9d89ec568e98581b7662b07 b/packages/gtest_module.git/objects/42/9ddfeecaa74e71a9d89ec568e98581b7662b07 deleted file mode 100644 index 3cb4ea0e..00000000 Binary files a/packages/gtest_module.git/objects/42/9ddfeecaa74e71a9d89ec568e98581b7662b07 and /dev/null differ diff --git a/packages/gtest_module.git/objects/43/584a92d08df002383a73a1908c0af78583dc94 b/packages/gtest_module.git/objects/43/584a92d08df002383a73a1908c0af78583dc94 deleted file mode 100644 index b3b52d28..00000000 Binary files a/packages/gtest_module.git/objects/43/584a92d08df002383a73a1908c0af78583dc94 and /dev/null differ diff --git a/packages/gtest_module.git/objects/4d/1d81d20ffca32ba8f9577ff5bd06bfe2de7463 b/packages/gtest_module.git/objects/4d/1d81d20ffca32ba8f9577ff5bd06bfe2de7463 deleted file mode 100644 index 9315e7a0..00000000 Binary files a/packages/gtest_module.git/objects/4d/1d81d20ffca32ba8f9577ff5bd06bfe2de7463 and /dev/null differ diff --git a/packages/gtest_module.git/objects/55/29ba54415ebeee85ff08b202e83ae74fcddb1a b/packages/gtest_module.git/objects/55/29ba54415ebeee85ff08b202e83ae74fcddb1a deleted file mode 100644 index 7f1c7371..00000000 Binary files a/packages/gtest_module.git/objects/55/29ba54415ebeee85ff08b202e83ae74fcddb1a and /dev/null differ diff --git a/packages/gtest_module.git/objects/5a/6eb8730a9fa6430dabbfb32b7f1d490dbeafba b/packages/gtest_module.git/objects/5a/6eb8730a9fa6430dabbfb32b7f1d490dbeafba deleted file mode 100644 index 681481f4..00000000 Binary files a/packages/gtest_module.git/objects/5a/6eb8730a9fa6430dabbfb32b7f1d490dbeafba and /dev/null differ diff --git a/packages/gtest_module.git/objects/5c/7c47af0bb1e8898492e05425e40397a4d12f6a b/packages/gtest_module.git/objects/5c/7c47af0bb1e8898492e05425e40397a4d12f6a deleted file mode 100644 index a092e1ce..00000000 Binary files a/packages/gtest_module.git/objects/5c/7c47af0bb1e8898492e05425e40397a4d12f6a and /dev/null differ diff --git a/packages/gtest_module.git/objects/60/c1ea050b61e93bfcf146e6111bfa50315c82ee b/packages/gtest_module.git/objects/60/c1ea050b61e93bfcf146e6111bfa50315c82ee deleted file mode 100644 index af494839..00000000 Binary files a/packages/gtest_module.git/objects/60/c1ea050b61e93bfcf146e6111bfa50315c82ee and /dev/null differ diff --git a/packages/gtest_module.git/objects/77/eb844839d8927a293d25704df9b1707a4273a5 b/packages/gtest_module.git/objects/77/eb844839d8927a293d25704df9b1707a4273a5 deleted file mode 100644 index c8979b63..00000000 Binary files a/packages/gtest_module.git/objects/77/eb844839d8927a293d25704df9b1707a4273a5 and /dev/null differ diff --git a/packages/gtest_module.git/objects/7a/13b4b0de6083bbfe6963f8c0ed16e27de77012 b/packages/gtest_module.git/objects/7a/13b4b0de6083bbfe6963f8c0ed16e27de77012 deleted file mode 100644 index 6fbe8bb4..00000000 Binary files a/packages/gtest_module.git/objects/7a/13b4b0de6083bbfe6963f8c0ed16e27de77012 and /dev/null differ diff --git a/packages/gtest_module.git/objects/84/9f4c4b8102ce81dac26662db40a5e0e659042a b/packages/gtest_module.git/objects/84/9f4c4b8102ce81dac26662db40a5e0e659042a deleted file mode 100644 index 4e281f07..00000000 Binary files a/packages/gtest_module.git/objects/84/9f4c4b8102ce81dac26662db40a5e0e659042a and /dev/null differ diff --git a/packages/gtest_module.git/objects/92/dc13c6a6789ed7b86295c05c00ee4b6c39498c b/packages/gtest_module.git/objects/92/dc13c6a6789ed7b86295c05c00ee4b6c39498c deleted file mode 100644 index a008b4e5..00000000 Binary files a/packages/gtest_module.git/objects/92/dc13c6a6789ed7b86295c05c00ee4b6c39498c and /dev/null differ diff --git a/packages/gtest_module.git/objects/95/7a69c6a9e7bed7d57ebd7872fb047f97175fc1 b/packages/gtest_module.git/objects/95/7a69c6a9e7bed7d57ebd7872fb047f97175fc1 deleted file mode 100644 index 1d4660ab..00000000 Binary files a/packages/gtest_module.git/objects/95/7a69c6a9e7bed7d57ebd7872fb047f97175fc1 and /dev/null differ diff --git a/packages/gtest_module.git/objects/97/f1a7fdd2c0cc44c3a148f0f1ecdcbdfe9bac6c b/packages/gtest_module.git/objects/97/f1a7fdd2c0cc44c3a148f0f1ecdcbdfe9bac6c deleted file mode 100644 index 06a57275..00000000 Binary files a/packages/gtest_module.git/objects/97/f1a7fdd2c0cc44c3a148f0f1ecdcbdfe9bac6c and /dev/null differ diff --git a/packages/gtest_module.git/objects/a2/df412f8a20459043cdb70e5b095a72b7a1394a b/packages/gtest_module.git/objects/a2/df412f8a20459043cdb70e5b095a72b7a1394a deleted file mode 100644 index 964dd44f..00000000 Binary files a/packages/gtest_module.git/objects/a2/df412f8a20459043cdb70e5b095a72b7a1394a and /dev/null differ diff --git a/packages/gtest_module.git/objects/a7/743f4a8569359dbff549f1fad371efb6fa5fd3 b/packages/gtest_module.git/objects/a7/743f4a8569359dbff549f1fad371efb6fa5fd3 deleted file mode 100644 index a0391e27..00000000 Binary files a/packages/gtest_module.git/objects/a7/743f4a8569359dbff549f1fad371efb6fa5fd3 and /dev/null differ diff --git a/packages/gtest_module.git/objects/a7/a1c0b7d9a96e76bb3fc8f0e5128a4545bf5b5a b/packages/gtest_module.git/objects/a7/a1c0b7d9a96e76bb3fc8f0e5128a4545bf5b5a deleted file mode 100644 index fedf2dad..00000000 --- a/packages/gtest_module.git/objects/a7/a1c0b7d9a96e76bb3fc8f0e5128a4545bf5b5a +++ /dev/null @@ -1,5 +0,0 @@ -xU6y!$mRDKMT\ڭO,ѻl-ѠΣEr̼v?~w{K?|q?iBsT߼).`G}^*m1qto8Xr= l]_ϴ&ɍCǑQ:ߺkjƘP,l8ږt-.zė~?߷ |("Ù݅Y[Kq!jh{!{?NC-c\Wif_Άh?A+_.D=¶/\: #U9vܢ[ãfmp~x2>6 p+qESqiug٢ZL[l.STDwƁZpD -iƉnaH ppq'?ekKBi܋RWeqRtMf!))VRERSM)J,^/$_Rk*JRUȍzB*O*U|B0 2iI,Th)d 1U2XrLfE@V4*2QҪ*WRLL߂꒼!Y\)sYk4`*r(l)òلJ& -EQ'gX-KMwMJR.;,Te*#i^i]N%RBYQe$ -#by8쀌iUPFe2_pNEΚYQkf?b7&t'\oCId'I/rɜ -WZF (4gbUa7KjF"Lzُ)=͟&ԍ[>R^ʟBbs6{c1DG޼ԙo|:``b8[lyv=A'٧ ^"ۜ8]ln^Zݼw;"л{_f \ No newline at end of file diff --git a/packages/gtest_module.git/objects/ab/77aa4106186627099bda9c218385c2dbe420fa b/packages/gtest_module.git/objects/ab/77aa4106186627099bda9c218385c2dbe420fa deleted file mode 100644 index 026662ef..00000000 Binary files a/packages/gtest_module.git/objects/ab/77aa4106186627099bda9c218385c2dbe420fa and /dev/null differ diff --git a/packages/gtest_module.git/objects/b9/55ebf2f9110e6353c687cc3942348da797cb50 b/packages/gtest_module.git/objects/b9/55ebf2f9110e6353c687cc3942348da797cb50 deleted file mode 100644 index 6d492151..00000000 Binary files a/packages/gtest_module.git/objects/b9/55ebf2f9110e6353c687cc3942348da797cb50 and /dev/null differ diff --git a/packages/gtest_module.git/objects/ba/7ad68ad1caa5fb20838c700896a4182ba59d9f b/packages/gtest_module.git/objects/ba/7ad68ad1caa5fb20838c700896a4182ba59d9f deleted file mode 100644 index 174d67ba..00000000 Binary files a/packages/gtest_module.git/objects/ba/7ad68ad1caa5fb20838c700896a4182ba59d9f and /dev/null differ diff --git a/packages/gtest_module.git/objects/bb/206167ba26748248f0cbcb619ce08dec0b9985 b/packages/gtest_module.git/objects/bb/206167ba26748248f0cbcb619ce08dec0b9985 deleted file mode 100644 index 0e3cef18..00000000 Binary files a/packages/gtest_module.git/objects/bb/206167ba26748248f0cbcb619ce08dec0b9985 and /dev/null differ diff --git a/packages/gtest_module.git/objects/c1/cd69ab466c7c1b2e763680b3384a4eb87c98c3 b/packages/gtest_module.git/objects/c1/cd69ab466c7c1b2e763680b3384a4eb87c98c3 deleted file mode 100644 index 9c747faf..00000000 Binary files a/packages/gtest_module.git/objects/c1/cd69ab466c7c1b2e763680b3384a4eb87c98c3 and /dev/null differ diff --git a/packages/gtest_module.git/objects/c8/5f5d58477be279042ab4ffb154fb012b575e7c b/packages/gtest_module.git/objects/c8/5f5d58477be279042ab4ffb154fb012b575e7c deleted file mode 100644 index acfedb1e..00000000 Binary files a/packages/gtest_module.git/objects/c8/5f5d58477be279042ab4ffb154fb012b575e7c and /dev/null differ diff --git a/packages/gtest_module.git/objects/d7/7f676d47edeb7c46cb4ed950eb1f0bc91e04f8 b/packages/gtest_module.git/objects/d7/7f676d47edeb7c46cb4ed950eb1f0bc91e04f8 deleted file mode 100644 index 1dfb4fc8..00000000 Binary files a/packages/gtest_module.git/objects/d7/7f676d47edeb7c46cb4ed950eb1f0bc91e04f8 and /dev/null differ diff --git a/packages/gtest_module.git/objects/da/80ddc6c70ee2dc773ed6765a4f89dfa8cb38e8 b/packages/gtest_module.git/objects/da/80ddc6c70ee2dc773ed6765a4f89dfa8cb38e8 deleted file mode 100644 index e4c99381..00000000 Binary files a/packages/gtest_module.git/objects/da/80ddc6c70ee2dc773ed6765a4f89dfa8cb38e8 and /dev/null differ diff --git a/packages/gtest_module.git/objects/df/1eef4754efeb6bc066239b1ccc3bfeeb896310 b/packages/gtest_module.git/objects/df/1eef4754efeb6bc066239b1ccc3bfeeb896310 deleted file mode 100644 index f7230bdf..00000000 Binary files a/packages/gtest_module.git/objects/df/1eef4754efeb6bc066239b1ccc3bfeeb896310 and /dev/null differ diff --git a/packages/gtest_module.git/objects/e4/6f7cfcb483a9551c20ada23b77f9880405f4fe b/packages/gtest_module.git/objects/e4/6f7cfcb483a9551c20ada23b77f9880405f4fe deleted file mode 100644 index 9cbed64d..00000000 Binary files a/packages/gtest_module.git/objects/e4/6f7cfcb483a9551c20ada23b77f9880405f4fe and /dev/null differ diff --git a/packages/gtest_module.git/objects/e9/b405340a855f60258b134026be7b13612ebe1e b/packages/gtest_module.git/objects/e9/b405340a855f60258b134026be7b13612ebe1e deleted file mode 100644 index 05e3a3c4..00000000 Binary files a/packages/gtest_module.git/objects/e9/b405340a855f60258b134026be7b13612ebe1e and /dev/null differ diff --git a/packages/gtest_module.git/objects/f3/028225523306eb9648f94bcbe9e3a78016bb7e b/packages/gtest_module.git/objects/f3/028225523306eb9648f94bcbe9e3a78016bb7e deleted file mode 100644 index 6f6ea18c..00000000 Binary files a/packages/gtest_module.git/objects/f3/028225523306eb9648f94bcbe9e3a78016bb7e and /dev/null differ diff --git a/packages/gtest_module.git/objects/fa/e32cb29b61973407f7823592a706c279ae5b25 b/packages/gtest_module.git/objects/fa/e32cb29b61973407f7823592a706c279ae5b25 deleted file mode 100644 index 9821f743..00000000 Binary files a/packages/gtest_module.git/objects/fa/e32cb29b61973407f7823592a706c279ae5b25 and /dev/null differ diff --git a/packages/gtest_module.git/objects/fb/0e35425e1e6f7179d02b93945bdee431b25e4e b/packages/gtest_module.git/objects/fb/0e35425e1e6f7179d02b93945bdee431b25e4e deleted file mode 100644 index 9423540c..00000000 Binary files a/packages/gtest_module.git/objects/fb/0e35425e1e6f7179d02b93945bdee431b25e4e and /dev/null differ diff --git a/packages/gtest_module.git/objects/fc/a103556d59c2b8dca6f3930616b6682d098d5d b/packages/gtest_module.git/objects/fc/a103556d59c2b8dca6f3930616b6682d098d5d deleted file mode 100644 index 487b484c..00000000 Binary files a/packages/gtest_module.git/objects/fc/a103556d59c2b8dca6f3930616b6682d098d5d and /dev/null differ diff --git a/packages/gtest_module.git/objects/fe/879bca7927afae2499a6137ab26f4991fbbacf b/packages/gtest_module.git/objects/fe/879bca7927afae2499a6137ab26f4991fbbacf deleted file mode 100644 index cbe75e42..00000000 Binary files a/packages/gtest_module.git/objects/fe/879bca7927afae2499a6137ab26f4991fbbacf and /dev/null differ diff --git a/packages/gtest_module.git/packed-refs b/packages/gtest_module.git/packed-refs deleted file mode 100644 index 429a5e8b..00000000 --- a/packages/gtest_module.git/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled fully-peeled sorted -ab77aa4106186627099bda9c218385c2dbe420fa refs/remotes/origin/master diff --git a/packages/gtest_module.git/refs/heads/master b/packages/gtest_module.git/refs/heads/master deleted file mode 100644 index 945a67bf..00000000 --- a/packages/gtest_module.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -ab77aa4106186627099bda9c218385c2dbe420fa diff --git a/packages/gtest_module.git/refs/remotes/origin/HEAD b/packages/gtest_module.git/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28ff..00000000 --- a/packages/gtest_module.git/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/packages/mbedtls_module.git/COMMIT_EDITMSG b/packages/mbedtls_module.git/COMMIT_EDITMSG deleted file mode 100644 index 6103ee6e..00000000 --- a/packages/mbedtls_module.git/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -add mbedtls lib diff --git a/packages/mbedtls_module.git/HEAD b/packages/mbedtls_module.git/HEAD deleted file mode 100644 index cb089cd8..00000000 --- a/packages/mbedtls_module.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/packages/mbedtls_module.git/config b/packages/mbedtls_module.git/config deleted file mode 100644 index 08ef48cb..00000000 --- a/packages/mbedtls_module.git/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true - precomposeunicode = true -[remote "origin"] - url = http://git.code.oa.com/IoT_Hub/mbedtls_module.git - fetch = +refs/heads/*:refs/remotes/origin/* -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/packages/mbedtls_module.git/description b/packages/mbedtls_module.git/description deleted file mode 100644 index 498b267a..00000000 --- a/packages/mbedtls_module.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/packages/mbedtls_module.git/hooks/applypatch-msg.sample b/packages/mbedtls_module.git/hooks/applypatch-msg.sample deleted file mode 100755 index a5d7b84a..00000000 --- a/packages/mbedtls_module.git/hooks/applypatch-msg.sample +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message taken by -# applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. The hook is -# allowed to edit the commit message file. -# -# To enable this hook, rename this file to "applypatch-msg". - -. git-sh-setup -commitmsg="$(git rev-parse --git-path hooks/commit-msg)" -test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} -: diff --git a/packages/mbedtls_module.git/hooks/commit-msg.sample b/packages/mbedtls_module.git/hooks/commit-msg.sample deleted file mode 100755 index b58d1184..00000000 --- a/packages/mbedtls_module.git/hooks/commit-msg.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message. -# Called by "git commit" with one argument, the name of the file -# that has the commit message. The hook should exit with non-zero -# status after issuing an appropriate message if it wants to stop the -# commit. The hook is allowed to edit the commit message file. -# -# To enable this hook, rename this file to "commit-msg". - -# Uncomment the below to add a Signed-off-by line to the message. -# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -# hook is more suited to it. -# -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" - -# This example catches duplicate Signed-off-by lines. - -test "" = "$(grep '^Signed-off-by: ' "$1" | - sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { - echo >&2 Duplicate Signed-off-by lines. - exit 1 -} diff --git a/packages/mbedtls_module.git/hooks/post-update.sample b/packages/mbedtls_module.git/hooks/post-update.sample deleted file mode 100755 index ec17ec19..00000000 --- a/packages/mbedtls_module.git/hooks/post-update.sample +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare a packed repository for use over -# dumb transports. -# -# To enable this hook, rename this file to "post-update". - -exec git update-server-info diff --git a/packages/mbedtls_module.git/hooks/pre-applypatch.sample b/packages/mbedtls_module.git/hooks/pre-applypatch.sample deleted file mode 100755 index 4142082b..00000000 --- a/packages/mbedtls_module.git/hooks/pre-applypatch.sample +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed -# by applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-applypatch". - -. git-sh-setup -precommit="$(git rev-parse --git-path hooks/pre-commit)" -test -x "$precommit" && exec "$precommit" ${1+"$@"} -: diff --git a/packages/mbedtls_module.git/hooks/pre-commit.sample b/packages/mbedtls_module.git/hooks/pre-commit.sample deleted file mode 100755 index 68d62d54..00000000 --- a/packages/mbedtls_module.git/hooks/pre-commit.sample +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed. -# Called by "git commit" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message if -# it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-commit". - -if git rev-parse --verify HEAD >/dev/null 2>&1 -then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -fi - -# If you want to allow non-ASCII filenames set this variable to true. -allownonascii=$(git config --bool hooks.allownonascii) - -# Redirect output to stderr. -exec 1>&2 - -# Cross platform projects tend to avoid non-ASCII filenames; prevent -# them from being added to the repository. We exploit the fact that the -# printable range starts at the space character and ends with tilde. -if [ "$allownonascii" != "true" ] && - # Note that the use of brackets around a tr range is ok here, (it's - # even required, for portability to Solaris 10's /usr/bin/tr), since - # the square bracket bytes happen to fall in the designated range. - test $(git diff --cached --name-only --diff-filter=A -z $against | - LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 -then - cat <<\EOF -Error: Attempt to add a non-ASCII file name. - -This can cause problems if you want to work with people on other platforms. - -To be portable it is advisable to rename the file. - -If you know what you are doing you can disable this check using: - - git config hooks.allownonascii true -EOF - exit 1 -fi - -# If there are whitespace errors, print the offending file names and fail. -exec git diff-index --check --cached $against -- diff --git a/packages/mbedtls_module.git/hooks/pre-push.sample b/packages/mbedtls_module.git/hooks/pre-push.sample deleted file mode 100755 index 6187dbf4..00000000 --- a/packages/mbedtls_module.git/hooks/pre-push.sample +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh - -# An example hook script to verify what is about to be pushed. Called by "git -# push" after it has checked the remote status, but before anything has been -# pushed. If this script exits with a non-zero status nothing will be pushed. -# -# This hook is called with the following parameters: -# -# $1 -- Name of the remote to which the push is being done -# $2 -- URL to which the push is being done -# -# If pushing without using a named remote those arguments will be equal. -# -# Information about the commits which are being pushed is supplied as lines to -# the standard input in the form: -# -# -# -# This sample shows how to prevent push of commits where the log message starts -# with "WIP" (work in progress). - -remote="$1" -url="$2" - -z40=0000000000000000000000000000000000000000 - -while read local_ref local_sha remote_ref remote_sha -do - if [ "$local_sha" = $z40 ] - then - # Handle delete - : - else - if [ "$remote_sha" = $z40 ] - then - # New branch, examine all commits - range="$local_sha" - else - # Update to existing branch, examine new commits - range="$remote_sha..$local_sha" - fi - - # Check for WIP commit - commit=`git rev-list -n 1 --grep '^WIP' "$range"` - if [ -n "$commit" ] - then - echo >&2 "Found WIP commit in $local_ref, not pushing" - exit 1 - fi - fi -done - -exit 0 diff --git a/packages/mbedtls_module.git/hooks/pre-rebase.sample b/packages/mbedtls_module.git/hooks/pre-rebase.sample deleted file mode 100755 index 6cbef5c3..00000000 --- a/packages/mbedtls_module.git/hooks/pre-rebase.sample +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006, 2008 Junio C Hamano -# -# The "pre-rebase" hook is run just before "git rebase" starts doing -# its job, and can prevent the command from running by exiting with -# non-zero status. -# -# The hook is called with the following parameters: -# -# $1 -- the upstream the series was forked from. -# $2 -- the branch being rebased (or empty when rebasing the current branch). -# -# This sample shows how to prevent topic branches that are already -# merged to 'next' branch from getting rebased, because allowing it -# would result in rebasing already published history. - -publish=next -basebranch="$1" -if test "$#" = 2 -then - topic="refs/heads/$2" -else - topic=`git symbolic-ref HEAD` || - exit 0 ;# we do not interrupt rebasing detached HEAD -fi - -case "$topic" in -refs/heads/??/*) - ;; -*) - exit 0 ;# we do not interrupt others. - ;; -esac - -# Now we are dealing with a topic branch being rebased -# on top of master. Is it OK to rebase it? - -# Does the topic really exist? -git show-ref -q "$topic" || { - echo >&2 "No such branch $topic" - exit 1 -} - -# Is topic fully merged to master? -not_in_master=`git rev-list --pretty=oneline ^master "$topic"` -if test -z "$not_in_master" -then - echo >&2 "$topic is fully merged to master; better remove it." - exit 1 ;# we could allow it, but there is no point. -fi - -# Is topic ever merged to next? If so you should not be rebasing it. -only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` -only_next_2=`git rev-list ^master ${publish} | sort` -if test "$only_next_1" = "$only_next_2" -then - not_in_topic=`git rev-list "^$topic" master` - if test -z "$not_in_topic" - then - echo >&2 "$topic is already up to date with master" - exit 1 ;# we could allow it, but there is no point. - else - exit 0 - fi -else - not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` - /usr/bin/perl -e ' - my $topic = $ARGV[0]; - my $msg = "* $topic has commits already merged to public branch:\n"; - my (%not_in_next) = map { - /^([0-9a-f]+) /; - ($1 => 1); - } split(/\n/, $ARGV[1]); - for my $elem (map { - /^([0-9a-f]+) (.*)$/; - [$1 => $2]; - } split(/\n/, $ARGV[2])) { - if (!exists $not_in_next{$elem->[0]}) { - if ($msg) { - print STDERR $msg; - undef $msg; - } - print STDERR " $elem->[1]\n"; - } - } - ' "$topic" "$not_in_next" "$not_in_master" - exit 1 -fi - -<<\DOC_END - -This sample hook safeguards topic branches that have been -published from being rewound. - -The workflow assumed here is: - - * Once a topic branch forks from "master", "master" is never - merged into it again (either directly or indirectly). - - * Once a topic branch is fully cooked and merged into "master", - it is deleted. If you need to build on top of it to correct - earlier mistakes, a new topic branch is created by forking at - the tip of the "master". This is not strictly necessary, but - it makes it easier to keep your history simple. - - * Whenever you need to test or publish your changes to topic - branches, merge them into "next" branch. - -The script, being an example, hardcodes the publish branch name -to be "next", but it is trivial to make it configurable via -$GIT_DIR/config mechanism. - -With this workflow, you would want to know: - -(1) ... if a topic branch has ever been merged to "next". Young - topic branches can have stupid mistakes you would rather - clean up before publishing, and things that have not been - merged into other branches can be easily rebased without - affecting other people. But once it is published, you would - not want to rewind it. - -(2) ... if a topic branch has been fully merged to "master". - Then you can delete it. More importantly, you should not - build on top of it -- other people may already want to - change things related to the topic as patches against your - "master", so if you need further changes, it is better to - fork the topic (perhaps with the same name) afresh from the - tip of "master". - -Let's look at this example: - - o---o---o---o---o---o---o---o---o---o "next" - / / / / - / a---a---b A / / - / / / / - / / c---c---c---c B / - / / / \ / - / / / b---b C \ / - / / / / \ / - ---o---o---o---o---o---o---o---o---o---o---o "master" - - -A, B and C are topic branches. - - * A has one fix since it was merged up to "next". - - * B has finished. It has been fully merged up to "master" and "next", - and is ready to be deleted. - - * C has not merged to "next" at all. - -We would want to allow C to be rebased, refuse A, and encourage -B to be deleted. - -To compute (1): - - git rev-list ^master ^topic next - git rev-list ^master next - - if these match, topic has not merged in next at all. - -To compute (2): - - git rev-list master..topic - - if this is empty, it is fully merged to "master". - -DOC_END diff --git a/packages/mbedtls_module.git/hooks/pre-receive.sample b/packages/mbedtls_module.git/hooks/pre-receive.sample deleted file mode 100755 index a1fd29ec..00000000 --- a/packages/mbedtls_module.git/hooks/pre-receive.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to make use of push options. -# The example simply echoes all push options that start with 'echoback=' -# and rejects all pushes when the "reject" push option is used. -# -# To enable this hook, rename this file to "pre-receive". - -if test -n "$GIT_PUSH_OPTION_COUNT" -then - i=0 - while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" - do - eval "value=\$GIT_PUSH_OPTION_$i" - case "$value" in - echoback=*) - echo "echo from the pre-receive-hook: ${value#*=}" >&2 - ;; - reject) - exit 1 - esac - i=$((i + 1)) - done -fi diff --git a/packages/mbedtls_module.git/hooks/prepare-commit-msg.sample b/packages/mbedtls_module.git/hooks/prepare-commit-msg.sample deleted file mode 100755 index 10fa14c5..00000000 --- a/packages/mbedtls_module.git/hooks/prepare-commit-msg.sample +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare the commit log message. -# Called by "git commit" with the name of the file that has the -# commit message, followed by the description of the commit -# message's source. The hook's purpose is to edit the commit -# message file. If the hook fails with a non-zero status, -# the commit is aborted. -# -# To enable this hook, rename this file to "prepare-commit-msg". - -# This hook includes three examples. The first one removes the -# "# Please enter the commit message..." help message. -# -# The second includes the output of "git diff --name-status -r" -# into the message, just before the "git status" output. It is -# commented because it doesn't cope with --amend or with squashed -# commits. -# -# The third example adds a Signed-off-by line to the message, that can -# still be edited. This is rarely a good idea. - -COMMIT_MSG_FILE=$1 -COMMIT_SOURCE=$2 -SHA1=$3 - -/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" - -# case "$COMMIT_SOURCE,$SHA1" in -# ,|template,) -# /usr/bin/perl -i.bak -pe ' -# print "\n" . `git diff --cached --name-status -r` -# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; -# *) ;; -# esac - -# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" -# if test -z "$COMMIT_SOURCE" -# then -# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" -# fi diff --git a/packages/mbedtls_module.git/hooks/update.sample b/packages/mbedtls_module.git/hooks/update.sample deleted file mode 100755 index 80ba9413..00000000 --- a/packages/mbedtls_module.git/hooks/update.sample +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -# -# An example hook script to block unannotated tags from entering. -# Called by "git receive-pack" with arguments: refname sha1-old sha1-new -# -# To enable this hook, rename this file to "update". -# -# Config -# ------ -# hooks.allowunannotated -# This boolean sets whether unannotated tags will be allowed into the -# repository. By default they won't be. -# hooks.allowdeletetag -# This boolean sets whether deleting tags will be allowed in the -# repository. By default they won't be. -# hooks.allowmodifytag -# This boolean sets whether a tag may be modified after creation. By default -# it won't be. -# hooks.allowdeletebranch -# This boolean sets whether deleting branches will be allowed in the -# repository. By default they won't be. -# hooks.denycreatebranch -# This boolean sets whether remotely creating branches will be denied -# in the repository. By default this is allowed. -# - -# --- Command line -refname="$1" -oldrev="$2" -newrev="$3" - -# --- Safety check -if [ -z "$GIT_DIR" ]; then - echo "Don't run this script from the command line." >&2 - echo " (if you want, you could supply GIT_DIR then run" >&2 - echo " $0 )" >&2 - exit 1 -fi - -if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then - echo "usage: $0 " >&2 - exit 1 -fi - -# --- Config -allowunannotated=$(git config --bool hooks.allowunannotated) -allowdeletebranch=$(git config --bool hooks.allowdeletebranch) -denycreatebranch=$(git config --bool hooks.denycreatebranch) -allowdeletetag=$(git config --bool hooks.allowdeletetag) -allowmodifytag=$(git config --bool hooks.allowmodifytag) - -# check for no description -projectdesc=$(sed -e '1q' "$GIT_DIR/description") -case "$projectdesc" in -"Unnamed repository"* | "") - echo "*** Project description file hasn't been set" >&2 - exit 1 - ;; -esac - -# --- Check types -# if $newrev is 0000...0000, it's a commit to delete a ref. -zero="0000000000000000000000000000000000000000" -if [ "$newrev" = "$zero" ]; then - newrev_type=delete -else - newrev_type=$(git cat-file -t $newrev) -fi - -case "$refname","$newrev_type" in - refs/tags/*,commit) - # un-annotated tag - short_refname=${refname##refs/tags/} - if [ "$allowunannotated" != "true" ]; then - echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 - echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 - exit 1 - fi - ;; - refs/tags/*,delete) - # delete tag - if [ "$allowdeletetag" != "true" ]; then - echo "*** Deleting a tag is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/tags/*,tag) - # annotated tag - if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 - then - echo "*** Tag '$refname' already exists." >&2 - echo "*** Modifying a tag is not allowed in this repository." >&2 - exit 1 - fi - ;; - refs/heads/*,commit) - # branch - if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then - echo "*** Creating a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/heads/*,delete) - # delete branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/remotes/*,commit) - # tracking branch - ;; - refs/remotes/*,delete) - # delete tracking branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a tracking branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - *) - # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 - exit 1 - ;; -esac - -# --- Finished -exit 0 diff --git a/packages/mbedtls_module.git/index b/packages/mbedtls_module.git/index deleted file mode 100644 index f0e71d33..00000000 Binary files a/packages/mbedtls_module.git/index and /dev/null differ diff --git a/packages/mbedtls_module.git/info/exclude b/packages/mbedtls_module.git/info/exclude deleted file mode 100644 index a5196d1b..00000000 --- a/packages/mbedtls_module.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/packages/mbedtls_module.git/logs/HEAD b/packages/mbedtls_module.git/logs/HEAD deleted file mode 100644 index 6ffa6794..00000000 --- a/packages/mbedtls_module.git/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 aad2c14fa822faf207580e14b55e0ae818fe8409 skyztmeng 1526625242 +0800 commit (initial): add mbedtls lib diff --git a/packages/mbedtls_module.git/logs/refs/heads/master b/packages/mbedtls_module.git/logs/refs/heads/master deleted file mode 100644 index 6ffa6794..00000000 --- a/packages/mbedtls_module.git/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 aad2c14fa822faf207580e14b55e0ae818fe8409 skyztmeng 1526625242 +0800 commit (initial): add mbedtls lib diff --git a/packages/mbedtls_module.git/logs/refs/remotes/origin/master b/packages/mbedtls_module.git/logs/refs/remotes/origin/master deleted file mode 100644 index 7edad3f0..00000000 --- a/packages/mbedtls_module.git/logs/refs/remotes/origin/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 aad2c14fa822faf207580e14b55e0ae818fe8409 skyztmeng 1526625245 +0800 update by push diff --git a/packages/mbedtls_module.git/objects/01/d0f214bca3ff12c5f709f62df845fc554614cf b/packages/mbedtls_module.git/objects/01/d0f214bca3ff12c5f709f62df845fc554614cf deleted file mode 100644 index 297b1d82..00000000 Binary files a/packages/mbedtls_module.git/objects/01/d0f214bca3ff12c5f709f62df845fc554614cf and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/03/7e1c31125712912a249830e31034e42451cdeb b/packages/mbedtls_module.git/objects/03/7e1c31125712912a249830e31034e42451cdeb deleted file mode 100644 index 260e6a90..00000000 --- a/packages/mbedtls_module.git/objects/03/7e1c31125712912a249830e31034e42451cdeb +++ /dev/null @@ -1,4 +0,0 @@ -xWoHg)}D U/hc5Ud-V:pݮl߆^ zp$A`CoJKa\P$Jd'LU0덅θ W//._هne*-F#I` ,Р~Ĉ䟋[2xE\+"T튠Pj6Qg߇ dЮkebªBaH | -1 MuJBr3pƟKG,dqs'[罱65nہpE 2&efx덧3ڬJ#X@S(VD["ikf3yjv+4D#ihVTys&G>x~ތ|'oy3t>lM}/`2XS1m&ǐ:.a=VTSiXC)IXXN8KyͅR"8Xf561~tpz.cY wo 7 nZiE*NvwBU -ҁfӏvS^X{:%3A'-|ih9z]]g)KB\X x2ew9r4j"-4i;H#[`&aڧk>={͊.h yYlxFʃQS(#״IF] " UE 2~2L1[:w.I>ͬK}xN52|@:9@ >kֿwNaGɡˣxhċDƇv͚11:~ɐ>"!t֨ wRQ}Ш)'a^hv\mA44 C`{Ii_Ta98X |$_:y8 Ȱ=;"=&y e\29SXzhGHQ*-gq]Iy7 +F-;n"<˩71* ?%7b<<2ݰ(?#ŷtATu*" -/@B1ŋ4r9IӽGWY朗Gtxܞn28rP}TIw]`,h \ No newline at end of file diff --git a/packages/mbedtls_module.git/objects/04/24d623fb3e6324f2e0b7ccf6d49b1a5ffaf8a3 b/packages/mbedtls_module.git/objects/04/24d623fb3e6324f2e0b7ccf6d49b1a5ffaf8a3 deleted file mode 100644 index 534dfb34..00000000 Binary files a/packages/mbedtls_module.git/objects/04/24d623fb3e6324f2e0b7ccf6d49b1a5ffaf8a3 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/05/9d3c5c9afd7ba8c18716ae0c81561fa9e72a02 b/packages/mbedtls_module.git/objects/05/9d3c5c9afd7ba8c18716ae0c81561fa9e72a02 deleted file mode 100644 index b8d55fa1..00000000 Binary files a/packages/mbedtls_module.git/objects/05/9d3c5c9afd7ba8c18716ae0c81561fa9e72a02 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/05/b33d3fdbb921608999f3f9d6d5bd6d7fc11981 b/packages/mbedtls_module.git/objects/05/b33d3fdbb921608999f3f9d6d5bd6d7fc11981 deleted file mode 100644 index e2b09016..00000000 Binary files a/packages/mbedtls_module.git/objects/05/b33d3fdbb921608999f3f9d6d5bd6d7fc11981 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/08/2832c87fdd21e962ded0c7a65cbefd820ec036 b/packages/mbedtls_module.git/objects/08/2832c87fdd21e962ded0c7a65cbefd820ec036 deleted file mode 100644 index c4bf5625..00000000 Binary files a/packages/mbedtls_module.git/objects/08/2832c87fdd21e962ded0c7a65cbefd820ec036 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/09/f95cfc3b38e878d49ffcbfd5a5f97a23159d9a b/packages/mbedtls_module.git/objects/09/f95cfc3b38e878d49ffcbfd5a5f97a23159d9a deleted file mode 100644 index 4a1a57db..00000000 Binary files a/packages/mbedtls_module.git/objects/09/f95cfc3b38e878d49ffcbfd5a5f97a23159d9a and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/0e/a64252ee4f5a07386210387e69917c3ba349d4 b/packages/mbedtls_module.git/objects/0e/a64252ee4f5a07386210387e69917c3ba349d4 deleted file mode 100644 index c8075b92..00000000 Binary files a/packages/mbedtls_module.git/objects/0e/a64252ee4f5a07386210387e69917c3ba349d4 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/0f/93fbf427d523e608d3226dc1af203cb2470849 b/packages/mbedtls_module.git/objects/0f/93fbf427d523e608d3226dc1af203cb2470849 deleted file mode 100644 index e233ff97..00000000 Binary files a/packages/mbedtls_module.git/objects/0f/93fbf427d523e608d3226dc1af203cb2470849 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/10/bd0a5828b93ce8bfb5e94069a272e9a58a8ef5 b/packages/mbedtls_module.git/objects/10/bd0a5828b93ce8bfb5e94069a272e9a58a8ef5 deleted file mode 100644 index b6882a2e..00000000 Binary files a/packages/mbedtls_module.git/objects/10/bd0a5828b93ce8bfb5e94069a272e9a58a8ef5 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/11/a77e3ae4d0e87e2c0006fd3d1bfb0ff97ead30 b/packages/mbedtls_module.git/objects/11/a77e3ae4d0e87e2c0006fd3d1bfb0ff97ead30 deleted file mode 100644 index c22a3ba1..00000000 Binary files a/packages/mbedtls_module.git/objects/11/a77e3ae4d0e87e2c0006fd3d1bfb0ff97ead30 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/13/a8fd1a245ac2b20a6fadf62d0db660eb0b9cdd b/packages/mbedtls_module.git/objects/13/a8fd1a245ac2b20a6fadf62d0db660eb0b9cdd deleted file mode 100644 index 800aae5c..00000000 Binary files a/packages/mbedtls_module.git/objects/13/a8fd1a245ac2b20a6fadf62d0db660eb0b9cdd and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/1b/77aaedd48f9c28276ebbe064596fa7b2ab9439 b/packages/mbedtls_module.git/objects/1b/77aaedd48f9c28276ebbe064596fa7b2ab9439 deleted file mode 100644 index 6ded3a9c..00000000 Binary files a/packages/mbedtls_module.git/objects/1b/77aaedd48f9c28276ebbe064596fa7b2ab9439 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/1c/a3c3ef5b9a5f4ecf6ae322f358147c703c2344 b/packages/mbedtls_module.git/objects/1c/a3c3ef5b9a5f4ecf6ae322f358147c703c2344 deleted file mode 100644 index 3073fd9c..00000000 Binary files a/packages/mbedtls_module.git/objects/1c/a3c3ef5b9a5f4ecf6ae322f358147c703c2344 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/1e/e3966e1ef3b06ebb3e21d069b17c18b748d247 b/packages/mbedtls_module.git/objects/1e/e3966e1ef3b06ebb3e21d069b17c18b748d247 deleted file mode 100644 index 179157bd..00000000 Binary files a/packages/mbedtls_module.git/objects/1e/e3966e1ef3b06ebb3e21d069b17c18b748d247 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/1f/a1c2d80153219405d32b98c68fdd4f931cc60a b/packages/mbedtls_module.git/objects/1f/a1c2d80153219405d32b98c68fdd4f931cc60a deleted file mode 100644 index 5766089b..00000000 Binary files a/packages/mbedtls_module.git/objects/1f/a1c2d80153219405d32b98c68fdd4f931cc60a and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/20/45a5ab64279e33483aa349ca35462d0244b680 b/packages/mbedtls_module.git/objects/20/45a5ab64279e33483aa349ca35462d0244b680 deleted file mode 100644 index befbdedd..00000000 Binary files a/packages/mbedtls_module.git/objects/20/45a5ab64279e33483aa349ca35462d0244b680 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/22/3823b3cd6bb2a8a211094b44f0342dd5f378dc b/packages/mbedtls_module.git/objects/22/3823b3cd6bb2a8a211094b44f0342dd5f378dc deleted file mode 100644 index b3597067..00000000 Binary files a/packages/mbedtls_module.git/objects/22/3823b3cd6bb2a8a211094b44f0342dd5f378dc and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/25/91c45d750ffd78f379ecd6b84d6340d50ff56f b/packages/mbedtls_module.git/objects/25/91c45d750ffd78f379ecd6b84d6340d50ff56f deleted file mode 100644 index db9430c5..00000000 Binary files a/packages/mbedtls_module.git/objects/25/91c45d750ffd78f379ecd6b84d6340d50ff56f and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/26/b24a9e2ac76745d3ca295176944be1016010f4 b/packages/mbedtls_module.git/objects/26/b24a9e2ac76745d3ca295176944be1016010f4 deleted file mode 100644 index 2c0d4407..00000000 Binary files a/packages/mbedtls_module.git/objects/26/b24a9e2ac76745d3ca295176944be1016010f4 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/27/5429e603e97180dc2671bce8ae0ae443f46b36 b/packages/mbedtls_module.git/objects/27/5429e603e97180dc2671bce8ae0ae443f46b36 deleted file mode 100644 index 67778b59..00000000 Binary files a/packages/mbedtls_module.git/objects/27/5429e603e97180dc2671bce8ae0ae443f46b36 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/27/abbd97207b0e1652cfe1d5c389a15a9a598482 b/packages/mbedtls_module.git/objects/27/abbd97207b0e1652cfe1d5c389a15a9a598482 deleted file mode 100644 index 07392d0e..00000000 Binary files a/packages/mbedtls_module.git/objects/27/abbd97207b0e1652cfe1d5c389a15a9a598482 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/29/579964076121b4bb658ad192495b47c4d99d8d b/packages/mbedtls_module.git/objects/29/579964076121b4bb658ad192495b47c4d99d8d deleted file mode 100644 index a804a4e5..00000000 Binary files a/packages/mbedtls_module.git/objects/29/579964076121b4bb658ad192495b47c4d99d8d and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/2b/75ef7bd880592a95409b62efdb5d6a648268f0 b/packages/mbedtls_module.git/objects/2b/75ef7bd880592a95409b62efdb5d6a648268f0 deleted file mode 100644 index ab843caf..00000000 Binary files a/packages/mbedtls_module.git/objects/2b/75ef7bd880592a95409b62efdb5d6a648268f0 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/2c/cf2a2f524bf2adc88f5a501c57798acb7969b1 b/packages/mbedtls_module.git/objects/2c/cf2a2f524bf2adc88f5a501c57798acb7969b1 deleted file mode 100644 index eb702e61..00000000 Binary files a/packages/mbedtls_module.git/objects/2c/cf2a2f524bf2adc88f5a501c57798acb7969b1 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/2c/fcae200e226c9818164104a909b58e51a2d803 b/packages/mbedtls_module.git/objects/2c/fcae200e226c9818164104a909b58e51a2d803 deleted file mode 100644 index fe96e081..00000000 Binary files a/packages/mbedtls_module.git/objects/2c/fcae200e226c9818164104a909b58e51a2d803 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/2e/88928137cfed3aa6e30274311b9f5a380d4e0a b/packages/mbedtls_module.git/objects/2e/88928137cfed3aa6e30274311b9f5a380d4e0a deleted file mode 100644 index a77dcf77..00000000 Binary files a/packages/mbedtls_module.git/objects/2e/88928137cfed3aa6e30274311b9f5a380d4e0a and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/34/626eef4869a0b5ca399394b522aade2509d051 b/packages/mbedtls_module.git/objects/34/626eef4869a0b5ca399394b522aade2509d051 deleted file mode 100644 index c3ab3456..00000000 Binary files a/packages/mbedtls_module.git/objects/34/626eef4869a0b5ca399394b522aade2509d051 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/35/185dfda1ac36ca0e472ea9535380a93c4b46aa b/packages/mbedtls_module.git/objects/35/185dfda1ac36ca0e472ea9535380a93c4b46aa deleted file mode 100644 index 698fd2ae..00000000 Binary files a/packages/mbedtls_module.git/objects/35/185dfda1ac36ca0e472ea9535380a93c4b46aa and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/35/2c652db9ea90f6652381fbdd07ae948e4c8318 b/packages/mbedtls_module.git/objects/35/2c652db9ea90f6652381fbdd07ae948e4c8318 deleted file mode 100644 index b7a2a763..00000000 Binary files a/packages/mbedtls_module.git/objects/35/2c652db9ea90f6652381fbdd07ae948e4c8318 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/37/34bb7274ae7ddea1d430cc639e373adb797051 b/packages/mbedtls_module.git/objects/37/34bb7274ae7ddea1d430cc639e373adb797051 deleted file mode 100644 index 0a13cfa2..00000000 Binary files a/packages/mbedtls_module.git/objects/37/34bb7274ae7ddea1d430cc639e373adb797051 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/38/3e484f71cb3413c5f94496921207fd715b5f00 b/packages/mbedtls_module.git/objects/38/3e484f71cb3413c5f94496921207fd715b5f00 deleted file mode 100644 index ea3f215a..00000000 Binary files a/packages/mbedtls_module.git/objects/38/3e484f71cb3413c5f94496921207fd715b5f00 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/38/6f8adb07876f2d3d080e7eb300c281675dd83e b/packages/mbedtls_module.git/objects/38/6f8adb07876f2d3d080e7eb300c281675dd83e deleted file mode 100644 index e63106bd..00000000 Binary files a/packages/mbedtls_module.git/objects/38/6f8adb07876f2d3d080e7eb300c281675dd83e and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/3a/63a63a43fd783673e264a7002be0a1cd6e206f b/packages/mbedtls_module.git/objects/3a/63a63a43fd783673e264a7002be0a1cd6e206f deleted file mode 100644 index 9750ddb7..00000000 Binary files a/packages/mbedtls_module.git/objects/3a/63a63a43fd783673e264a7002be0a1cd6e206f and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/3a/c8306fb659b50e84d87cc082a12a21016d5b22 b/packages/mbedtls_module.git/objects/3a/c8306fb659b50e84d87cc082a12a21016d5b22 deleted file mode 100644 index 3c0e2c20..00000000 Binary files a/packages/mbedtls_module.git/objects/3a/c8306fb659b50e84d87cc082a12a21016d5b22 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/3c/4804c79d11536b729b932e611dbc5355dbf142 b/packages/mbedtls_module.git/objects/3c/4804c79d11536b729b932e611dbc5355dbf142 deleted file mode 100644 index b0c40610..00000000 Binary files a/packages/mbedtls_module.git/objects/3c/4804c79d11536b729b932e611dbc5355dbf142 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/40/ef2a9480fac22d2c506a4e9fa85184bcfe97b5 b/packages/mbedtls_module.git/objects/40/ef2a9480fac22d2c506a4e9fa85184bcfe97b5 deleted file mode 100644 index b482fe1c..00000000 Binary files a/packages/mbedtls_module.git/objects/40/ef2a9480fac22d2c506a4e9fa85184bcfe97b5 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/41/56f3c3c4c1d0ae3b650359f175df1116cc3c1b b/packages/mbedtls_module.git/objects/41/56f3c3c4c1d0ae3b650359f175df1116cc3c1b deleted file mode 100644 index 52c33eb0..00000000 Binary files a/packages/mbedtls_module.git/objects/41/56f3c3c4c1d0ae3b650359f175df1116cc3c1b and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/45/214d41d9f9c1d8f18f9dda265a28d37dac6381 b/packages/mbedtls_module.git/objects/45/214d41d9f9c1d8f18f9dda265a28d37dac6381 deleted file mode 100644 index 7cac8924..00000000 Binary files a/packages/mbedtls_module.git/objects/45/214d41d9f9c1d8f18f9dda265a28d37dac6381 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/4c/99e04d6fc6c84f1e8e0e67fff557668f3e846a b/packages/mbedtls_module.git/objects/4c/99e04d6fc6c84f1e8e0e67fff557668f3e846a deleted file mode 100644 index 62a2966a..00000000 Binary files a/packages/mbedtls_module.git/objects/4c/99e04d6fc6c84f1e8e0e67fff557668f3e846a and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/4d/9116d2148bd35bffd747a41754f90b05e1bf27 b/packages/mbedtls_module.git/objects/4d/9116d2148bd35bffd747a41754f90b05e1bf27 deleted file mode 100644 index b9a0b838..00000000 Binary files a/packages/mbedtls_module.git/objects/4d/9116d2148bd35bffd747a41754f90b05e1bf27 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/4d/d65c03c029c267acd818364683c993143d0b01 b/packages/mbedtls_module.git/objects/4d/d65c03c029c267acd818364683c993143d0b01 deleted file mode 100644 index 83d77b2d..00000000 Binary files a/packages/mbedtls_module.git/objects/4d/d65c03c029c267acd818364683c993143d0b01 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/52/46c789d31ebed51956ee136fae9410badc32d1 b/packages/mbedtls_module.git/objects/52/46c789d31ebed51956ee136fae9410badc32d1 deleted file mode 100644 index 4ef0d0eb..00000000 Binary files a/packages/mbedtls_module.git/objects/52/46c789d31ebed51956ee136fae9410badc32d1 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/52/827d8d1a59621ef66d3bd31dbc2a59ea165e44 b/packages/mbedtls_module.git/objects/52/827d8d1a59621ef66d3bd31dbc2a59ea165e44 deleted file mode 100644 index a8f8f726..00000000 Binary files a/packages/mbedtls_module.git/objects/52/827d8d1a59621ef66d3bd31dbc2a59ea165e44 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/54/5d5a2c326e1fd8e90070955acd6d7edf8931e7 b/packages/mbedtls_module.git/objects/54/5d5a2c326e1fd8e90070955acd6d7edf8931e7 deleted file mode 100644 index 295373dc..00000000 Binary files a/packages/mbedtls_module.git/objects/54/5d5a2c326e1fd8e90070955acd6d7edf8931e7 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/54/dac166b4cfd9d5873bf7350bc57e79ad00bdf0 b/packages/mbedtls_module.git/objects/54/dac166b4cfd9d5873bf7350bc57e79ad00bdf0 deleted file mode 100644 index beff24ad..00000000 Binary files a/packages/mbedtls_module.git/objects/54/dac166b4cfd9d5873bf7350bc57e79ad00bdf0 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/54/dc02d7cdc334dc6303a59583b76f87b8b52ffa b/packages/mbedtls_module.git/objects/54/dc02d7cdc334dc6303a59583b76f87b8b52ffa deleted file mode 100644 index a40e17b4..00000000 Binary files a/packages/mbedtls_module.git/objects/54/dc02d7cdc334dc6303a59583b76f87b8b52ffa and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/5a/64061aa0caca4dae93d5c2ac74b7580c77b7b6 b/packages/mbedtls_module.git/objects/5a/64061aa0caca4dae93d5c2ac74b7580c77b7b6 deleted file mode 100644 index 51d49214..00000000 Binary files a/packages/mbedtls_module.git/objects/5a/64061aa0caca4dae93d5c2ac74b7580c77b7b6 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/5c/a2ecf2e0990d83eed1476d9f174470c54b2a60 b/packages/mbedtls_module.git/objects/5c/a2ecf2e0990d83eed1476d9f174470c54b2a60 deleted file mode 100644 index 8f240a48..00000000 Binary files a/packages/mbedtls_module.git/objects/5c/a2ecf2e0990d83eed1476d9f174470c54b2a60 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/5c/af27cb686ff17ba1af44ab408eee6b81e96c62 b/packages/mbedtls_module.git/objects/5c/af27cb686ff17ba1af44ab408eee6b81e96c62 deleted file mode 100644 index e0e589cc..00000000 Binary files a/packages/mbedtls_module.git/objects/5c/af27cb686ff17ba1af44ab408eee6b81e96c62 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/5c/b12cba754b299b69e50be79bd17f40b16f6f21 b/packages/mbedtls_module.git/objects/5c/b12cba754b299b69e50be79bd17f40b16f6f21 deleted file mode 100644 index df8fb049..00000000 Binary files a/packages/mbedtls_module.git/objects/5c/b12cba754b299b69e50be79bd17f40b16f6f21 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/5d/972dc9dd36929046142224f365a8236819c2d3 b/packages/mbedtls_module.git/objects/5d/972dc9dd36929046142224f365a8236819c2d3 deleted file mode 100644 index cbd91d77..00000000 Binary files a/packages/mbedtls_module.git/objects/5d/972dc9dd36929046142224f365a8236819c2d3 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/5e/549f6b6a7824f931e24ad9ffa597639a482919 b/packages/mbedtls_module.git/objects/5e/549f6b6a7824f931e24ad9ffa597639a482919 deleted file mode 100644 index 537faf58..00000000 Binary files a/packages/mbedtls_module.git/objects/5e/549f6b6a7824f931e24ad9ffa597639a482919 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/5f/c5395a8c43e4d20aa54236bd27447781e85fbe b/packages/mbedtls_module.git/objects/5f/c5395a8c43e4d20aa54236bd27447781e85fbe deleted file mode 100644 index abffab3b..00000000 Binary files a/packages/mbedtls_module.git/objects/5f/c5395a8c43e4d20aa54236bd27447781e85fbe and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/60/3d06b64fd0269676da71cb9ebc8d8643cc33ef b/packages/mbedtls_module.git/objects/60/3d06b64fd0269676da71cb9ebc8d8643cc33ef deleted file mode 100644 index 8c3798b9..00000000 Binary files a/packages/mbedtls_module.git/objects/60/3d06b64fd0269676da71cb9ebc8d8643cc33ef and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/60/bcaf8b27f4645e267526eb94e5c3bb73f7a458 b/packages/mbedtls_module.git/objects/60/bcaf8b27f4645e267526eb94e5c3bb73f7a458 deleted file mode 100644 index be6a6881..00000000 Binary files a/packages/mbedtls_module.git/objects/60/bcaf8b27f4645e267526eb94e5c3bb73f7a458 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/60/e14f90e7bd23d1da18088b28b2e4735e5516c1 b/packages/mbedtls_module.git/objects/60/e14f90e7bd23d1da18088b28b2e4735e5516c1 deleted file mode 100644 index 70303e20..00000000 Binary files a/packages/mbedtls_module.git/objects/60/e14f90e7bd23d1da18088b28b2e4735e5516c1 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/62/5a2819234b27e0d6baa8d8008a32df7b399d12 b/packages/mbedtls_module.git/objects/62/5a2819234b27e0d6baa8d8008a32df7b399d12 deleted file mode 100644 index 3f6e7af9..00000000 Binary files a/packages/mbedtls_module.git/objects/62/5a2819234b27e0d6baa8d8008a32df7b399d12 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/62/7694f425f5b6782efcfac7175abbfe7a7f8dfa b/packages/mbedtls_module.git/objects/62/7694f425f5b6782efcfac7175abbfe7a7f8dfa deleted file mode 100644 index c3e44f6b..00000000 Binary files a/packages/mbedtls_module.git/objects/62/7694f425f5b6782efcfac7175abbfe7a7f8dfa and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/66/8c0f567cc94b0169a01fcc922bee100feb83f6 b/packages/mbedtls_module.git/objects/66/8c0f567cc94b0169a01fcc922bee100feb83f6 deleted file mode 100644 index 9983efc9..00000000 Binary files a/packages/mbedtls_module.git/objects/66/8c0f567cc94b0169a01fcc922bee100feb83f6 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/69/b61b205f13f0c83f16514e09150bc0870a3d83 b/packages/mbedtls_module.git/objects/69/b61b205f13f0c83f16514e09150bc0870a3d83 deleted file mode 100644 index c9fa23cd..00000000 Binary files a/packages/mbedtls_module.git/objects/69/b61b205f13f0c83f16514e09150bc0870a3d83 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/6c/0cc9b088bd8669adce16a05000be0ade9bed59 b/packages/mbedtls_module.git/objects/6c/0cc9b088bd8669adce16a05000be0ade9bed59 deleted file mode 100644 index e4c74c79..00000000 --- a/packages/mbedtls_module.git/objects/6c/0cc9b088bd8669adce16a05000be0ade9bed59 +++ /dev/null @@ -1,8 +0,0 @@ -xVsF3VyBNa*c6v ժ>x4ׇHRa %*[B:39Ulf+ZG#˂2p4@NH2~ Gs{l6G`x;GSz :^)d|(@J'Fec2 :w2lU*'Rf -6R3?5X&ebYؔuy^n21hJI_91-R6VߪkZ -"ePu%9AB -`$B 6 -*~rY}m1q>W,/>6^8a%<&faq3_H" "2 ,+?0ո?9G"Y$Ei'eiJ=$Wm0 ϝ0a#%3&_{?{2Y|}M4w*/ЖqHTPJd2GWT5SwnQV:zel4P)/L$Kx:^>gs̞wVpB7XN=d_,@eąU>(f0'Q"ep*jr_h Z,"rDP, -͢ssA}͙c0fM߳׳WsĚi0,fah\T|tA`gO3H"i4\ E DPǡxhe|)-7!L XqA^Uwb=C'65휹t.`~ar >1hV'/G\U!,8ެ_ƼNMm:OZ{EǻHЂ>Kn0n&!CU@[lex[gc)3@>D5uq=Y -Ic%Ilת_ oL{TտI!lȺs*,Y#SH-hT&ee¹ v]gku4=^C>H.jʒ ˺PYw"׽)4_Ucyp,kefYy}BeU_ǚ1+o[&9 Zfz҅2+l/]8T*<)\[r_;1S@4+b?_ \ No newline at end of file diff --git a/packages/mbedtls_module.git/objects/6c/58bcc52532a1098b5d1f5601053fc1dade071f b/packages/mbedtls_module.git/objects/6c/58bcc52532a1098b5d1f5601053fc1dade071f deleted file mode 100644 index 75e7c6f4..00000000 Binary files a/packages/mbedtls_module.git/objects/6c/58bcc52532a1098b5d1f5601053fc1dade071f and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/6c/a80d469557d6f036feee6a16b33734cf51d881 b/packages/mbedtls_module.git/objects/6c/a80d469557d6f036feee6a16b33734cf51d881 deleted file mode 100644 index 728c6dc2..00000000 --- a/packages/mbedtls_module.git/objects/6c/a80d469557d6f036feee6a16b33734cf51d881 +++ /dev/null @@ -1,5 +0,0 @@ -xRn0Y_u.WR4(G*ԑ NAK+L$-]Rv9N"3B7-[TK\dRmwOCYCY} LLP* jT:tu3 - EaxQ]d;gh_B%RT`ָ/"o?$4mAc/a'+ذ@p /1ҐAH,8 –#ڷ:}0g(w Aژn]Lu{EYpN@A+LaVHi \!i5o7\m23[ M6*J^?/t n 6ϳuD f g(N%Gm@H(Ĵ]vx hYP yr\>d -JTiXMa>fSddؔ6+|C&)S讽y m6o#,$^Nا -UJ;fԢHnx'XhS -JDʳ%8iˡo_X, Z'ϫ9ɦ0,i[ARTX5})4M8< ~yރj&$kUz5nQ(Nb?̎ԵeVZNHs'}uk Q \ No newline at end of file diff --git a/packages/mbedtls_module.git/objects/6e/9ed98add937957dc73cdb0996a73ebfc70212a b/packages/mbedtls_module.git/objects/6e/9ed98add937957dc73cdb0996a73ebfc70212a deleted file mode 100644 index d0dd2177..00000000 Binary files a/packages/mbedtls_module.git/objects/6e/9ed98add937957dc73cdb0996a73ebfc70212a and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/6f/c9c772aef7aed034e165f7b20aab6bb365ff13 b/packages/mbedtls_module.git/objects/6f/c9c772aef7aed034e165f7b20aab6bb365ff13 deleted file mode 100644 index 86354bba..00000000 Binary files a/packages/mbedtls_module.git/objects/6f/c9c772aef7aed034e165f7b20aab6bb365ff13 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/70/83fc8599ff583ca6c2324ff6adfaed2f2de582 b/packages/mbedtls_module.git/objects/70/83fc8599ff583ca6c2324ff6adfaed2f2de582 deleted file mode 100644 index 2caee559..00000000 Binary files a/packages/mbedtls_module.git/objects/70/83fc8599ff583ca6c2324ff6adfaed2f2de582 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/71/2ad4832378dbba430c637e03f7fbf43b285da9 b/packages/mbedtls_module.git/objects/71/2ad4832378dbba430c637e03f7fbf43b285da9 deleted file mode 100644 index e4029b12..00000000 Binary files a/packages/mbedtls_module.git/objects/71/2ad4832378dbba430c637e03f7fbf43b285da9 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/72/4522ac68f74cd019348010dc10e288e2f4d16d b/packages/mbedtls_module.git/objects/72/4522ac68f74cd019348010dc10e288e2f4d16d deleted file mode 100644 index b7cb1ed3..00000000 Binary files a/packages/mbedtls_module.git/objects/72/4522ac68f74cd019348010dc10e288e2f4d16d and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/73/ff32b669901ce1ef581218e0749ee9542ca3d7 b/packages/mbedtls_module.git/objects/73/ff32b669901ce1ef581218e0749ee9542ca3d7 deleted file mode 100644 index a8236d3a..00000000 Binary files a/packages/mbedtls_module.git/objects/73/ff32b669901ce1ef581218e0749ee9542ca3d7 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/74/7aca4dfaaab826e4e51c832c4c860a68879573 b/packages/mbedtls_module.git/objects/74/7aca4dfaaab826e4e51c832c4c860a68879573 deleted file mode 100644 index 7f53702d..00000000 Binary files a/packages/mbedtls_module.git/objects/74/7aca4dfaaab826e4e51c832c4c860a68879573 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/75/e0b97c4ad75691c9573cc87eed898a253a27ac b/packages/mbedtls_module.git/objects/75/e0b97c4ad75691c9573cc87eed898a253a27ac deleted file mode 100644 index 6c2338cb..00000000 Binary files a/packages/mbedtls_module.git/objects/75/e0b97c4ad75691c9573cc87eed898a253a27ac and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/77/4559b3cf6e6eb9c9e2de351c0b573eb5428042 b/packages/mbedtls_module.git/objects/77/4559b3cf6e6eb9c9e2de351c0b573eb5428042 deleted file mode 100644 index 8f22df29..00000000 Binary files a/packages/mbedtls_module.git/objects/77/4559b3cf6e6eb9c9e2de351c0b573eb5428042 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/79/88439900316abb035ccc95738777e2f455ef59 b/packages/mbedtls_module.git/objects/79/88439900316abb035ccc95738777e2f455ef59 deleted file mode 100644 index 712b4222..00000000 Binary files a/packages/mbedtls_module.git/objects/79/88439900316abb035ccc95738777e2f455ef59 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/7a/67c6c1fb129eb016743fa93e5de24e2be1676b b/packages/mbedtls_module.git/objects/7a/67c6c1fb129eb016743fa93e5de24e2be1676b deleted file mode 100644 index cc13c9e1..00000000 Binary files a/packages/mbedtls_module.git/objects/7a/67c6c1fb129eb016743fa93e5de24e2be1676b and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/7b/2b4733bc7610b98059408457c0888570dc2686 b/packages/mbedtls_module.git/objects/7b/2b4733bc7610b98059408457c0888570dc2686 deleted file mode 100644 index 6bc176c3..00000000 Binary files a/packages/mbedtls_module.git/objects/7b/2b4733bc7610b98059408457c0888570dc2686 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/7c/6bc61bfb7061eb1043e6f748fac69192d495a5 b/packages/mbedtls_module.git/objects/7c/6bc61bfb7061eb1043e6f748fac69192d495a5 deleted file mode 100644 index c9382eed..00000000 Binary files a/packages/mbedtls_module.git/objects/7c/6bc61bfb7061eb1043e6f748fac69192d495a5 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/81/258d5f396b98774a6fb9987adb05c0fc610aa3 b/packages/mbedtls_module.git/objects/81/258d5f396b98774a6fb9987adb05c0fc610aa3 deleted file mode 100644 index 5e47a670..00000000 Binary files a/packages/mbedtls_module.git/objects/81/258d5f396b98774a6fb9987adb05c0fc610aa3 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/83/b798c11929323123dc821d21168dfb20ad5de3 b/packages/mbedtls_module.git/objects/83/b798c11929323123dc821d21168dfb20ad5de3 deleted file mode 100644 index 91ff524d..00000000 Binary files a/packages/mbedtls_module.git/objects/83/b798c11929323123dc821d21168dfb20ad5de3 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/83/ec01a45fde0d3a6106b7160140deab8b27e57e b/packages/mbedtls_module.git/objects/83/ec01a45fde0d3a6106b7160140deab8b27e57e deleted file mode 100644 index 732ddf98..00000000 Binary files a/packages/mbedtls_module.git/objects/83/ec01a45fde0d3a6106b7160140deab8b27e57e and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/84/a04ae53f311bfcd8da8810d1150135f6ed5928 b/packages/mbedtls_module.git/objects/84/a04ae53f311bfcd8da8810d1150135f6ed5928 deleted file mode 100644 index 2cb8b93b..00000000 Binary files a/packages/mbedtls_module.git/objects/84/a04ae53f311bfcd8da8810d1150135f6ed5928 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/89/76701312b5b6b4251a1b2f5a1077a6208bca9b b/packages/mbedtls_module.git/objects/89/76701312b5b6b4251a1b2f5a1077a6208bca9b deleted file mode 100644 index 0ede956f..00000000 Binary files a/packages/mbedtls_module.git/objects/89/76701312b5b6b4251a1b2f5a1077a6208bca9b and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/8f/d856b2a28097b6de2be3078eef4b3655a4eed7 b/packages/mbedtls_module.git/objects/8f/d856b2a28097b6de2be3078eef4b3655a4eed7 deleted file mode 100644 index e99ba3c5..00000000 Binary files a/packages/mbedtls_module.git/objects/8f/d856b2a28097b6de2be3078eef4b3655a4eed7 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/90/03f0dfeb28f921dc02b11a7ea6339653ce091e b/packages/mbedtls_module.git/objects/90/03f0dfeb28f921dc02b11a7ea6339653ce091e deleted file mode 100644 index bdaca3ad..00000000 Binary files a/packages/mbedtls_module.git/objects/90/03f0dfeb28f921dc02b11a7ea6339653ce091e and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/93/e2b683bf489a4a1db0848e4d14da0f92cf11d5 b/packages/mbedtls_module.git/objects/93/e2b683bf489a4a1db0848e4d14da0f92cf11d5 deleted file mode 100644 index 924bd0bf..00000000 Binary files a/packages/mbedtls_module.git/objects/93/e2b683bf489a4a1db0848e4d14da0f92cf11d5 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/95/f17d456bf2624d10dd68061a518330314d8c9a b/packages/mbedtls_module.git/objects/95/f17d456bf2624d10dd68061a518330314d8c9a deleted file mode 100644 index 67674f76..00000000 Binary files a/packages/mbedtls_module.git/objects/95/f17d456bf2624d10dd68061a518330314d8c9a and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/98/5a3530b9799529e05c046068d1fe3d892a01ee b/packages/mbedtls_module.git/objects/98/5a3530b9799529e05c046068d1fe3d892a01ee deleted file mode 100644 index 12a5cc99..00000000 --- a/packages/mbedtls_module.git/objects/98/5a3530b9799529e05c046068d1fe3d892a01ee +++ /dev/null @@ -1,2 +0,0 @@ -x}O= 0uWš: .D $)b*N7jtӛw^mŨ;s1aRe -#EeBBD\?T© uKDt<6/?Xo(_}=ۧykB-_O",S30`Nϗ"'Rz^0,JkX0l ^]NW \ No newline at end of file diff --git a/packages/mbedtls_module.git/objects/99/0fe08c6c920d1908be7baf6911c6775884adc5 b/packages/mbedtls_module.git/objects/99/0fe08c6c920d1908be7baf6911c6775884adc5 deleted file mode 100644 index d120ddcd..00000000 Binary files a/packages/mbedtls_module.git/objects/99/0fe08c6c920d1908be7baf6911c6775884adc5 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/9a/6e8eb18749ee5c9c887d470f24063eb4cb0ced b/packages/mbedtls_module.git/objects/9a/6e8eb18749ee5c9c887d470f24063eb4cb0ced deleted file mode 100644 index eac2fd30..00000000 Binary files a/packages/mbedtls_module.git/objects/9a/6e8eb18749ee5c9c887d470f24063eb4cb0ced and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/9b/2d904591122a06a314df881cbe676e56429fc3 b/packages/mbedtls_module.git/objects/9b/2d904591122a06a314df881cbe676e56429fc3 deleted file mode 100644 index b88187ba..00000000 Binary files a/packages/mbedtls_module.git/objects/9b/2d904591122a06a314df881cbe676e56429fc3 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/9b/62de2dccf732a35b507723f0ab45f3676d9890 b/packages/mbedtls_module.git/objects/9b/62de2dccf732a35b507723f0ab45f3676d9890 deleted file mode 100644 index 7bcd50eb..00000000 Binary files a/packages/mbedtls_module.git/objects/9b/62de2dccf732a35b507723f0ab45f3676d9890 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/9b/996a951bb4c7aa377fe83128fe017cc56dc243 b/packages/mbedtls_module.git/objects/9b/996a951bb4c7aa377fe83128fe017cc56dc243 deleted file mode 100644 index 93134b05..00000000 Binary files a/packages/mbedtls_module.git/objects/9b/996a951bb4c7aa377fe83128fe017cc56dc243 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/9f/a7209e9fd27995b5d7a51af62b787e0196966f b/packages/mbedtls_module.git/objects/9f/a7209e9fd27995b5d7a51af62b787e0196966f deleted file mode 100644 index 35fe3e02..00000000 Binary files a/packages/mbedtls_module.git/objects/9f/a7209e9fd27995b5d7a51af62b787e0196966f and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/9f/b32de7a64b5de3dc3b7d5cbecd723f059c652c b/packages/mbedtls_module.git/objects/9f/b32de7a64b5de3dc3b7d5cbecd723f059c652c deleted file mode 100644 index f72d1e51..00000000 Binary files a/packages/mbedtls_module.git/objects/9f/b32de7a64b5de3dc3b7d5cbecd723f059c652c and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/a1/16e605d2f6be1f4879f7a023277d218f366e3f b/packages/mbedtls_module.git/objects/a1/16e605d2f6be1f4879f7a023277d218f366e3f deleted file mode 100644 index 3e16e8bc..00000000 Binary files a/packages/mbedtls_module.git/objects/a1/16e605d2f6be1f4879f7a023277d218f366e3f and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/a1/86dee981cb85f682f3021da8505cc14438462f b/packages/mbedtls_module.git/objects/a1/86dee981cb85f682f3021da8505cc14438462f deleted file mode 100644 index 92356df6..00000000 Binary files a/packages/mbedtls_module.git/objects/a1/86dee981cb85f682f3021da8505cc14438462f and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/a3/6e825a2e68a7b26aa9448e1890ccfad73a4270 b/packages/mbedtls_module.git/objects/a3/6e825a2e68a7b26aa9448e1890ccfad73a4270 deleted file mode 100644 index 6a4a7eca..00000000 Binary files a/packages/mbedtls_module.git/objects/a3/6e825a2e68a7b26aa9448e1890ccfad73a4270 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/a4/715d170305b391eb2e9d0939b0d9a6c64acc3b b/packages/mbedtls_module.git/objects/a4/715d170305b391eb2e9d0939b0d9a6c64acc3b deleted file mode 100644 index 07eef17f..00000000 Binary files a/packages/mbedtls_module.git/objects/a4/715d170305b391eb2e9d0939b0d9a6c64acc3b and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/a7/62bf7c4f88e68dd553286ec1efd68021c9fef8 b/packages/mbedtls_module.git/objects/a7/62bf7c4f88e68dd553286ec1efd68021c9fef8 deleted file mode 100644 index 4bd7f83f..00000000 Binary files a/packages/mbedtls_module.git/objects/a7/62bf7c4f88e68dd553286ec1efd68021c9fef8 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/a7/c7ff0279dfcc8c4a315906a0a3b2f6a61100e4 b/packages/mbedtls_module.git/objects/a7/c7ff0279dfcc8c4a315906a0a3b2f6a61100e4 deleted file mode 100644 index d9d0f507..00000000 Binary files a/packages/mbedtls_module.git/objects/a7/c7ff0279dfcc8c4a315906a0a3b2f6a61100e4 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/a8/8343869c3345f9a545a2b1fd5ae06c369226d2 b/packages/mbedtls_module.git/objects/a8/8343869c3345f9a545a2b1fd5ae06c369226d2 deleted file mode 100644 index a3e62696..00000000 Binary files a/packages/mbedtls_module.git/objects/a8/8343869c3345f9a545a2b1fd5ae06c369226d2 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/a9/cd814be48cd275bcf4ad1f246e3efcce5e18ca b/packages/mbedtls_module.git/objects/a9/cd814be48cd275bcf4ad1f246e3efcce5e18ca deleted file mode 100644 index c405198b..00000000 Binary files a/packages/mbedtls_module.git/objects/a9/cd814be48cd275bcf4ad1f246e3efcce5e18ca and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/aa/51556a5744bb7a9891b42b6722a5d8e0c0e3cc b/packages/mbedtls_module.git/objects/aa/51556a5744bb7a9891b42b6722a5d8e0c0e3cc deleted file mode 100644 index 8e902da6..00000000 Binary files a/packages/mbedtls_module.git/objects/aa/51556a5744bb7a9891b42b6722a5d8e0c0e3cc and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/aa/d2c14fa822faf207580e14b55e0ae818fe8409 b/packages/mbedtls_module.git/objects/aa/d2c14fa822faf207580e14b55e0ae818fe8409 deleted file mode 100644 index 5c3c9770..00000000 Binary files a/packages/mbedtls_module.git/objects/aa/d2c14fa822faf207580e14b55e0ae818fe8409 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ab/b3431420fecc312f0d7d5af42ac99e6a4e6dbc b/packages/mbedtls_module.git/objects/ab/b3431420fecc312f0d7d5af42ac99e6a4e6dbc deleted file mode 100644 index e6c248a8..00000000 Binary files a/packages/mbedtls_module.git/objects/ab/b3431420fecc312f0d7d5af42ac99e6a4e6dbc and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ac/6f96a83a30660e13331a7a0607b3b9556851ec b/packages/mbedtls_module.git/objects/ac/6f96a83a30660e13331a7a0607b3b9556851ec deleted file mode 100644 index 5019199d..00000000 Binary files a/packages/mbedtls_module.git/objects/ac/6f96a83a30660e13331a7a0607b3b9556851ec and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ac/abc86c832ec8b5a16b487a8b051fb6bce62627 b/packages/mbedtls_module.git/objects/ac/abc86c832ec8b5a16b487a8b051fb6bce62627 deleted file mode 100644 index 3de6eba7..00000000 Binary files a/packages/mbedtls_module.git/objects/ac/abc86c832ec8b5a16b487a8b051fb6bce62627 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ad/25d38333f91219f1396862cafe15acd4dd3286 b/packages/mbedtls_module.git/objects/ad/25d38333f91219f1396862cafe15acd4dd3286 deleted file mode 100644 index 6a7793e6..00000000 Binary files a/packages/mbedtls_module.git/objects/ad/25d38333f91219f1396862cafe15acd4dd3286 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ae/7a713e7a726c48f6b5e6443e4ba6d0bfef7c3a b/packages/mbedtls_module.git/objects/ae/7a713e7a726c48f6b5e6443e4ba6d0bfef7c3a deleted file mode 100644 index b0ba94f7..00000000 Binary files a/packages/mbedtls_module.git/objects/ae/7a713e7a726c48f6b5e6443e4ba6d0bfef7c3a and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ae/e10b86fe90b07eadd89d270d7cfc3735ca5e04 b/packages/mbedtls_module.git/objects/ae/e10b86fe90b07eadd89d270d7cfc3735ca5e04 deleted file mode 100644 index 5f5d0649..00000000 Binary files a/packages/mbedtls_module.git/objects/ae/e10b86fe90b07eadd89d270d7cfc3735ca5e04 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/b0/73f84efa0230189493fd3ec872b8a90ab2abc0 b/packages/mbedtls_module.git/objects/b0/73f84efa0230189493fd3ec872b8a90ab2abc0 deleted file mode 100644 index 68cc3896..00000000 Binary files a/packages/mbedtls_module.git/objects/b0/73f84efa0230189493fd3ec872b8a90ab2abc0 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/b0/c34ecc7416a5ddbe4717d50f5c0664fb434612 b/packages/mbedtls_module.git/objects/b0/c34ecc7416a5ddbe4717d50f5c0664fb434612 deleted file mode 100644 index c4c55363..00000000 Binary files a/packages/mbedtls_module.git/objects/b0/c34ecc7416a5ddbe4717d50f5c0664fb434612 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/b1/2e38843a0f8aa2ec52e6621f7c9b5aaae82b21 b/packages/mbedtls_module.git/objects/b1/2e38843a0f8aa2ec52e6621f7c9b5aaae82b21 deleted file mode 100644 index 8e43c9e4..00000000 Binary files a/packages/mbedtls_module.git/objects/b1/2e38843a0f8aa2ec52e6621f7c9b5aaae82b21 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/b1/b019e55eb925aec10fe4797521dfbb95ee42b6 b/packages/mbedtls_module.git/objects/b1/b019e55eb925aec10fe4797521dfbb95ee42b6 deleted file mode 100644 index 0ab95317..00000000 Binary files a/packages/mbedtls_module.git/objects/b1/b019e55eb925aec10fe4797521dfbb95ee42b6 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/b1/b7f1cdec6f859bde9d5a8f51fb94d53d223ff7 b/packages/mbedtls_module.git/objects/b1/b7f1cdec6f859bde9d5a8f51fb94d53d223ff7 deleted file mode 100644 index aaa8db59..00000000 Binary files a/packages/mbedtls_module.git/objects/b1/b7f1cdec6f859bde9d5a8f51fb94d53d223ff7 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/b7/b61604d073699bcb92c6e52e2814820d26ef25 b/packages/mbedtls_module.git/objects/b7/b61604d073699bcb92c6e52e2814820d26ef25 deleted file mode 100644 index 90131b1a..00000000 Binary files a/packages/mbedtls_module.git/objects/b7/b61604d073699bcb92c6e52e2814820d26ef25 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/b8/5ff9cd2c9a2695bff406f77c12baf723c98af6 b/packages/mbedtls_module.git/objects/b8/5ff9cd2c9a2695bff406f77c12baf723c98af6 deleted file mode 100644 index e771495a..00000000 Binary files a/packages/mbedtls_module.git/objects/b8/5ff9cd2c9a2695bff406f77c12baf723c98af6 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ba/499d2bde611c7d9b44bc5f6d739c057dd7318e b/packages/mbedtls_module.git/objects/ba/499d2bde611c7d9b44bc5f6d739c057dd7318e deleted file mode 100644 index fbf13338..00000000 Binary files a/packages/mbedtls_module.git/objects/ba/499d2bde611c7d9b44bc5f6d739c057dd7318e and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/bf/5f9b5bd3d43f24ef0820c654dd15315b691ef9 b/packages/mbedtls_module.git/objects/bf/5f9b5bd3d43f24ef0820c654dd15315b691ef9 deleted file mode 100644 index ae292662..00000000 Binary files a/packages/mbedtls_module.git/objects/bf/5f9b5bd3d43f24ef0820c654dd15315b691ef9 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/bf/67d02ed8af25c794e7271366d8a0401bc2fb6d b/packages/mbedtls_module.git/objects/bf/67d02ed8af25c794e7271366d8a0401bc2fb6d deleted file mode 100644 index 9774c914..00000000 Binary files a/packages/mbedtls_module.git/objects/bf/67d02ed8af25c794e7271366d8a0401bc2fb6d and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/c0/a81473124a964e2466e2e709612e47620fe8e3 b/packages/mbedtls_module.git/objects/c0/a81473124a964e2466e2e709612e47620fe8e3 deleted file mode 100644 index eed6bb48..00000000 Binary files a/packages/mbedtls_module.git/objects/c0/a81473124a964e2466e2e709612e47620fe8e3 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/c4/66bf116dd7ed4d68efd7b38d5778f6a9d7299c b/packages/mbedtls_module.git/objects/c4/66bf116dd7ed4d68efd7b38d5778f6a9d7299c deleted file mode 100644 index db4e22c6..00000000 Binary files a/packages/mbedtls_module.git/objects/c4/66bf116dd7ed4d68efd7b38d5778f6a9d7299c and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/c6/03a1357719651f001f05aabbc614411fe03424 b/packages/mbedtls_module.git/objects/c6/03a1357719651f001f05aabbc614411fe03424 deleted file mode 100644 index f121996b..00000000 Binary files a/packages/mbedtls_module.git/objects/c6/03a1357719651f001f05aabbc614411fe03424 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ca/49086e4f1db6624d1d56da4d0b330519471951 b/packages/mbedtls_module.git/objects/ca/49086e4f1db6624d1d56da4d0b330519471951 deleted file mode 100644 index 6e91a80f..00000000 --- a/packages/mbedtls_module.git/objects/ca/49086e4f1db6624d1d56da4d0b330519471951 +++ /dev/null @@ -1,4 +0,0 @@ -xWnD9_1J_(MJ""$$iZ)+@ƞ$ Ŀ3@hϞ9sfl_|φ^zZ1jk[:pg+-q ;h@ -vhQXg蕕jS߇Ql-\ۛ!X IF\s d91 EǦe:)aQ+* -r;iΓ.%;{Ijyl/K6ܥ݊XBjM̀O1Wtqعk2OF2:t(E o;$Qia4G$ v.P%rpP'Mc,I4 {4fR A5 -4'@Xԝ /h/d\CEձcBAG#oa ӥ \ No newline at end of file diff --git a/packages/mbedtls_module.git/objects/ca/c3f1457701233e0d88ca1f9f9c6bf957b3b32e b/packages/mbedtls_module.git/objects/ca/c3f1457701233e0d88ca1f9f9c6bf957b3b32e deleted file mode 100644 index 9855e86d..00000000 Binary files a/packages/mbedtls_module.git/objects/ca/c3f1457701233e0d88ca1f9f9c6bf957b3b32e and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/cc/06cbfad391b1cdf17f5da15a17c1363b994238 b/packages/mbedtls_module.git/objects/cc/06cbfad391b1cdf17f5da15a17c1363b994238 deleted file mode 100644 index 9ea809f0..00000000 Binary files a/packages/mbedtls_module.git/objects/cc/06cbfad391b1cdf17f5da15a17c1363b994238 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/cd/b0a63c0fd4958b6cc42b33e165d0a4024d3adb b/packages/mbedtls_module.git/objects/cd/b0a63c0fd4958b6cc42b33e165d0a4024d3adb deleted file mode 100644 index d58d7910..00000000 Binary files a/packages/mbedtls_module.git/objects/cd/b0a63c0fd4958b6cc42b33e165d0a4024d3adb and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/d1/d9a22a7ee231efa7fe9d554407bcd38fc2518b b/packages/mbedtls_module.git/objects/d1/d9a22a7ee231efa7fe9d554407bcd38fc2518b deleted file mode 100644 index c01839f3..00000000 Binary files a/packages/mbedtls_module.git/objects/d1/d9a22a7ee231efa7fe9d554407bcd38fc2518b and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/d4/d1b27b7f4dee0f448a61e309b56dfd8ec0656a b/packages/mbedtls_module.git/objects/d4/d1b27b7f4dee0f448a61e309b56dfd8ec0656a deleted file mode 100644 index 69ffac07..00000000 Binary files a/packages/mbedtls_module.git/objects/d4/d1b27b7f4dee0f448a61e309b56dfd8ec0656a and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/d5/df316fdd7445aef49e7c96b5ed3ec53782bfa4 b/packages/mbedtls_module.git/objects/d5/df316fdd7445aef49e7c96b5ed3ec53782bfa4 deleted file mode 100644 index 55108626..00000000 Binary files a/packages/mbedtls_module.git/objects/d5/df316fdd7445aef49e7c96b5ed3ec53782bfa4 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/d7/ab1522ec1cb1ade15b074f7d98589988686f39 b/packages/mbedtls_module.git/objects/d7/ab1522ec1cb1ade15b074f7d98589988686f39 deleted file mode 100644 index dba9f07d..00000000 Binary files a/packages/mbedtls_module.git/objects/d7/ab1522ec1cb1ade15b074f7d98589988686f39 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/da/c5d311381000eb4bf00019f1f790070a75e9c9 b/packages/mbedtls_module.git/objects/da/c5d311381000eb4bf00019f1f790070a75e9c9 deleted file mode 100644 index dd71c277..00000000 Binary files a/packages/mbedtls_module.git/objects/da/c5d311381000eb4bf00019f1f790070a75e9c9 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/dc/76af8ff4c19145dd833b97eef2c3668b4065a1 b/packages/mbedtls_module.git/objects/dc/76af8ff4c19145dd833b97eef2c3668b4065a1 deleted file mode 100644 index 8f0afcec..00000000 Binary files a/packages/mbedtls_module.git/objects/dc/76af8ff4c19145dd833b97eef2c3668b4065a1 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/dd/2db0c45c019f01f4b54a162980fbf66ecc8f61 b/packages/mbedtls_module.git/objects/dd/2db0c45c019f01f4b54a162980fbf66ecc8f61 deleted file mode 100644 index 3a2f9511..00000000 Binary files a/packages/mbedtls_module.git/objects/dd/2db0c45c019f01f4b54a162980fbf66ecc8f61 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/de/335526fe9b38c8196807bee0cac50bf5d655fb b/packages/mbedtls_module.git/objects/de/335526fe9b38c8196807bee0cac50bf5d655fb deleted file mode 100644 index 0f046f60..00000000 Binary files a/packages/mbedtls_module.git/objects/de/335526fe9b38c8196807bee0cac50bf5d655fb and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/de/aaa37515211b0b014fcb5d782e1ea97110babf b/packages/mbedtls_module.git/objects/de/aaa37515211b0b014fcb5d782e1ea97110babf deleted file mode 100644 index 73a49a35..00000000 Binary files a/packages/mbedtls_module.git/objects/de/aaa37515211b0b014fcb5d782e1ea97110babf and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/df/20ec8ebd7f69f26a4b5f8b5ebdfb9574394a76 b/packages/mbedtls_module.git/objects/df/20ec8ebd7f69f26a4b5f8b5ebdfb9574394a76 deleted file mode 100644 index 7debe24b..00000000 Binary files a/packages/mbedtls_module.git/objects/df/20ec8ebd7f69f26a4b5f8b5ebdfb9574394a76 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/e0/10558028709a9e9c83818b459275c28a12ca85 b/packages/mbedtls_module.git/objects/e0/10558028709a9e9c83818b459275c28a12ca85 deleted file mode 100644 index bdbd41a6..00000000 Binary files a/packages/mbedtls_module.git/objects/e0/10558028709a9e9c83818b459275c28a12ca85 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/e2/2363d1a34785fa690c3ff8289b781607f0b270 b/packages/mbedtls_module.git/objects/e2/2363d1a34785fa690c3ff8289b781607f0b270 deleted file mode 100644 index cb645648..00000000 Binary files a/packages/mbedtls_module.git/objects/e2/2363d1a34785fa690c3ff8289b781607f0b270 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/e2/441bbc49dccdfefd8452b44dc8297738a82428 b/packages/mbedtls_module.git/objects/e2/441bbc49dccdfefd8452b44dc8297738a82428 deleted file mode 100644 index 6d2bd66c..00000000 Binary files a/packages/mbedtls_module.git/objects/e2/441bbc49dccdfefd8452b44dc8297738a82428 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/e2/8d5a8473598a3e79c5ad2f268d06e0979ae554 b/packages/mbedtls_module.git/objects/e2/8d5a8473598a3e79c5ad2f268d06e0979ae554 deleted file mode 100644 index 2d833bcb..00000000 Binary files a/packages/mbedtls_module.git/objects/e2/8d5a8473598a3e79c5ad2f268d06e0979ae554 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/e8/66e67a2307a560f41d4544fdf8fc89be19acc9 b/packages/mbedtls_module.git/objects/e8/66e67a2307a560f41d4544fdf8fc89be19acc9 deleted file mode 100644 index 935a77bb..00000000 Binary files a/packages/mbedtls_module.git/objects/e8/66e67a2307a560f41d4544fdf8fc89be19acc9 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/e9/867bc150767cfcf4e346a9222230df1868e43b b/packages/mbedtls_module.git/objects/e9/867bc150767cfcf4e346a9222230df1868e43b deleted file mode 100644 index d9410c33..00000000 Binary files a/packages/mbedtls_module.git/objects/e9/867bc150767cfcf4e346a9222230df1868e43b and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ec/5cb9e74437ea60b95f6c412bbe253d0c3d141c b/packages/mbedtls_module.git/objects/ec/5cb9e74437ea60b95f6c412bbe253d0c3d141c deleted file mode 100644 index 73215044..00000000 Binary files a/packages/mbedtls_module.git/objects/ec/5cb9e74437ea60b95f6c412bbe253d0c3d141c and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ed/a98f6361aa376703b6a10dead24e3e50774bd9 b/packages/mbedtls_module.git/objects/ed/a98f6361aa376703b6a10dead24e3e50774bd9 deleted file mode 100644 index aa3a26e4..00000000 Binary files a/packages/mbedtls_module.git/objects/ed/a98f6361aa376703b6a10dead24e3e50774bd9 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ee/2fe056ce6c4bf9cd4e7c483c9c5f681b96852c b/packages/mbedtls_module.git/objects/ee/2fe056ce6c4bf9cd4e7c483c9c5f681b96852c deleted file mode 100644 index d05fa1b9..00000000 Binary files a/packages/mbedtls_module.git/objects/ee/2fe056ce6c4bf9cd4e7c483c9c5f681b96852c and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ef/75839baa84d8317e34b2175d64bdc467191b37 b/packages/mbedtls_module.git/objects/ef/75839baa84d8317e34b2175d64bdc467191b37 deleted file mode 100644 index 9f4592f7..00000000 Binary files a/packages/mbedtls_module.git/objects/ef/75839baa84d8317e34b2175d64bdc467191b37 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/f1/210c52c39a28607a13c6d9f8b1f6bd3a7f5a61 b/packages/mbedtls_module.git/objects/f1/210c52c39a28607a13c6d9f8b1f6bd3a7f5a61 deleted file mode 100644 index 2a1182c5..00000000 Binary files a/packages/mbedtls_module.git/objects/f1/210c52c39a28607a13c6d9f8b1f6bd3a7f5a61 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/f1/3826ed746fe468d22cff85473cac8d7e5e5735 b/packages/mbedtls_module.git/objects/f1/3826ed746fe468d22cff85473cac8d7e5e5735 deleted file mode 100644 index d453e9e8..00000000 Binary files a/packages/mbedtls_module.git/objects/f1/3826ed746fe468d22cff85473cac8d7e5e5735 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/f5/1f2251edf8ce3a30802aff93f05c7629ad9e9d b/packages/mbedtls_module.git/objects/f5/1f2251edf8ce3a30802aff93f05c7629ad9e9d deleted file mode 100644 index f4c6e46b..00000000 Binary files a/packages/mbedtls_module.git/objects/f5/1f2251edf8ce3a30802aff93f05c7629ad9e9d and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/f8/041adf08232a9f3432b31e51896eefe37772cc b/packages/mbedtls_module.git/objects/f8/041adf08232a9f3432b31e51896eefe37772cc deleted file mode 100644 index 95401149..00000000 Binary files a/packages/mbedtls_module.git/objects/f8/041adf08232a9f3432b31e51896eefe37772cc and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/f9/f9b9bb096cbeea28e67ec7eb7653791cb040c0 b/packages/mbedtls_module.git/objects/f9/f9b9bb096cbeea28e67ec7eb7653791cb040c0 deleted file mode 100644 index cafd7eac..00000000 Binary files a/packages/mbedtls_module.git/objects/f9/f9b9bb096cbeea28e67ec7eb7653791cb040c0 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/fa/d390d857720b1374e1ff10faec99ab52686e31 b/packages/mbedtls_module.git/objects/fa/d390d857720b1374e1ff10faec99ab52686e31 deleted file mode 100644 index 2cac8194..00000000 Binary files a/packages/mbedtls_module.git/objects/fa/d390d857720b1374e1ff10faec99ab52686e31 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/fc/0d2d7b4272a550df11eaefe13935a7a510675c b/packages/mbedtls_module.git/objects/fc/0d2d7b4272a550df11eaefe13935a7a510675c deleted file mode 100644 index 5e43257c..00000000 Binary files a/packages/mbedtls_module.git/objects/fc/0d2d7b4272a550df11eaefe13935a7a510675c and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/fc/ecdafdcac1170b58f03f10685e6b0269bb730e b/packages/mbedtls_module.git/objects/fc/ecdafdcac1170b58f03f10685e6b0269bb730e deleted file mode 100644 index 1b04fb40..00000000 Binary files a/packages/mbedtls_module.git/objects/fc/ecdafdcac1170b58f03f10685e6b0269bb730e and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/fe/0a3509f6f77072bbe46a332dd5cc4dfb49f72d b/packages/mbedtls_module.git/objects/fe/0a3509f6f77072bbe46a332dd5cc4dfb49f72d deleted file mode 100644 index 8868aa04..00000000 Binary files a/packages/mbedtls_module.git/objects/fe/0a3509f6f77072bbe46a332dd5cc4dfb49f72d and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/fe/86c1e8d1178e722e67388b1ebb68e7688d51a5 b/packages/mbedtls_module.git/objects/fe/86c1e8d1178e722e67388b1ebb68e7688d51a5 deleted file mode 100644 index a10eb6a8..00000000 Binary files a/packages/mbedtls_module.git/objects/fe/86c1e8d1178e722e67388b1ebb68e7688d51a5 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/fe/9843cb545e7aae949f853deff288b6babcb041 b/packages/mbedtls_module.git/objects/fe/9843cb545e7aae949f853deff288b6babcb041 deleted file mode 100644 index 7c2de421..00000000 Binary files a/packages/mbedtls_module.git/objects/fe/9843cb545e7aae949f853deff288b6babcb041 and /dev/null differ diff --git a/packages/mbedtls_module.git/objects/ff/e6bc981c1998fe72ac08c90462092029eb24d8 b/packages/mbedtls_module.git/objects/ff/e6bc981c1998fe72ac08c90462092029eb24d8 deleted file mode 100644 index ea280433..00000000 Binary files a/packages/mbedtls_module.git/objects/ff/e6bc981c1998fe72ac08c90462092029eb24d8 and /dev/null differ diff --git a/packages/mbedtls_module.git/refs/heads/master b/packages/mbedtls_module.git/refs/heads/master deleted file mode 100644 index 1697eded..00000000 --- a/packages/mbedtls_module.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -aad2c14fa822faf207580e14b55e0ae818fe8409 diff --git a/packages/mbedtls_module.git/refs/remotes/origin/master b/packages/mbedtls_module.git/refs/remotes/origin/master deleted file mode 100644 index 1697eded..00000000 --- a/packages/mbedtls_module.git/refs/remotes/origin/master +++ /dev/null @@ -1 +0,0 @@ -aad2c14fa822faf207580e14b55e0ae818fe8409 diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt new file mode 100644 index 00000000..2ff7b514 --- /dev/null +++ b/platform/CMakeLists.txt @@ -0,0 +1,37 @@ +# src platform +file(GLOB src_os ./os/${PLATFORM}/*.c ) +set(src_platform ${src_os}) + +if(${FEATURE_AUTH_WITH_NOTLS} STREQUAL "OFF") + file(GLOB src_platform_tls ./tls/mbedtls/*.c) + list(APPEND src_platform ${src_platform_tls}) +endif() + +if(AT_TCP_ENABLED STREQUAL "OFF") + file(GLOB src_os ./os/${PLATFORM}/HAL_AT*.c) + list(REMOVE_ITEM src_platform ${src_os}) +endif() + +if(${EXTRACT_SRC} STREQUAL "ON") + file(COPY ${src_platform} DESTINATION ${PROJECT_SOURCE_DIR}/output/qcloud_iot_c_sdk/platform/) +endif() + +# src at_device +if(AT_TCP_ENABLED STREQUAL "ON") + file(GLOB src_at_device ./at_device/${AT_DEVICE_NAME}/*.c) +endif() + +if(AT_TCP_ENABLED STREQUAL "ON" AND ${EXTRACT_SRC} STREQUAL "ON") + file(COPY ${src_at_device} DESTINATION ${PROJECT_SOURCE_DIR}/output/qcloud_iot_c_sdk/platform/) +endif() + +# target +set(platform_target "iot_platform") + +# add library +SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/lib/) +if(AT_TCP_ENABLED STREQUAL "ON") + add_library(${platform_target} STATIC ${src_platform} ${src_at_device}) +else() + add_library(${platform_target} STATIC ${src_platform}) +endif() diff --git a/platform/at_device/esp8266/at_device_esp8266.c b/platform/at_device/esp8266/at_device_esp8266.c new file mode 100755 index 00000000..9f30bc96 --- /dev/null +++ b/platform/at_device/esp8266/at_device_esp8266.c @@ -0,0 +1,558 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "at_device_esp8266.h" + +#include +#include + +#include "at_client.h" +#include "at_socket_inf.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +#define WIFI_CONN_FLAG (1 << 0) +#define SEND_OK_FLAG (1 << 1) +#define SEND_FAIL_FLAG (1 << 2) + +static uint8_t sg_SocketBitMap = 0; + +static at_evt_cb_t at_evt_cb_table[] = { + [AT_SOCKET_EVT_RECV] = NULL, + [AT_SOCKET_EVT_CLOSED] = NULL, +}; + +static int alloc_fd(void) +{ + uint8_t i; + int fd; + + for (i = 0; i < ESP8266_MAX_SOCKET_NUM; i++) { + if (0 == ((sg_SocketBitMap >> i) & 0x01)) { + sg_SocketBitMap |= (1 << i) & 0xff; + break; + } + } + + return (i < ESP8266_MAX_SOCKET_NUM) ? (fd = i) : (fd = UNUSED_SOCKET); +} + +static void free_fd(int fd) +{ + uint8_t i = fd; + + if ((fd != UNUSED_SOCKET) && fd < ESP8266_MAX_SOCKET_NUM) { + sg_SocketBitMap &= ~((1 << i) & 0xff); + } +} + +static void urc_send_func(const char *data, size_t size) +{ + POINTER_SANITY_CHECK_RTN(data); + + if (strstr(data, "SEND OK")) { + at_setFlag(SEND_OK_FLAG); + } else if (strstr(data, "SEND FAIL")) { + at_setFlag(SEND_FAIL_FLAG); + } +} + +static void urc_send_bfsz_func(const char *data, size_t size) +{ + POINTER_SANITY_CHECK_RTN(data); + int send_bfsz = 0; + + sscanf(data, "Recv %d bytes", &send_bfsz); +} + +static void urc_close_func(const char *data, size_t size) +{ + int fd = 0; + POINTER_SANITY_CHECK_RTN(data); + + sscanf(data, "%d,CLOSED", &fd); + + /* notice the socket is disconnect by remote */ + if (at_evt_cb_table[AT_SOCKET_EVT_CLOSED]) { + at_evt_cb_table[AT_SOCKET_EVT_CLOSED](fd, AT_SOCKET_EVT_CLOSED, NULL, 0); + } + + free_fd(fd); +} + +static void urc_recv_func(const char *data, size_t size) +{ + int fd; + size_t bfsz = 0, temp_size = 0; + uint32_t timeout; + char * recv_buf, temp[8]; + + POINTER_SANITY_CHECK_RTN(data); + + /* get the current socket and receive buffer size by receive data */ + sscanf(data, "+IPD,%d,%d:", &fd, (int *)&bfsz); + + /* get receive timeout by receive buffer length */ + timeout = bfsz; + + if (fd < 0 || bfsz == 0) + return; + + recv_buf = HAL_Malloc(bfsz); + if (NULL == recv_buf) { + Log_e("no memory for URC receive buffer (%d)!", bfsz); + /* read and clean the coming data */ + while (temp_size < bfsz) { + if (bfsz - temp_size > sizeof(temp)) { + at_client_recv(temp, sizeof(temp), timeout); + } else { + at_client_recv(temp, bfsz - temp_size, timeout); + } + temp_size += sizeof(temp); + } + return; + } + + /* sync receive data */ + if (at_client_recv(recv_buf, bfsz, timeout) != bfsz) { + Log_e("receive size(%d) data failed!", bfsz); + HAL_Free(recv_buf); + return; + } + + /* notice the receive buffer and buffer size */ + if (at_evt_cb_table[AT_SOCKET_EVT_RECV]) { + at_evt_cb_table[AT_SOCKET_EVT_RECV](fd, AT_SOCKET_EVT_RECV, recv_buf, bfsz); + } +} + +static void urc_busy_p_func(const char *data, size_t size) +{ + POINTER_SANITY_CHECK_RTN(data); + + Log_d("system is processing a commands and it cannot respond to the current commands."); +} + +static void urc_busy_s_func(const char *data, size_t size) +{ + POINTER_SANITY_CHECK_RTN(data); + + Log_d("system is sending data and it cannot respond to the current commands."); +} + +static void urc_func(const char *data, size_t size) +{ + POINTER_SANITY_CHECK_RTN(data); + int i; + + if (strstr(data, "WIFI CONNECTED")) { + at_setFlag(WIFI_CONN_FLAG); + } else if (strstr(data, "WIFI DISCONNECT")) { + /* notice the socket is disconnect by remote */ + if (at_evt_cb_table[AT_SOCKET_EVT_CLOSED]) { + for (i = 0; i < ESP8266_MAX_SOCKET_NUM; i++) { + at_evt_cb_table[AT_SOCKET_EVT_CLOSED](i, AT_SOCKET_EVT_CLOSED, NULL, 0); + free_fd(i); + } + } + } +} + +static at_urc urc_table[] = { + {"SEND OK", "\r\n", urc_send_func}, + {"SEND FAIL", "\r\n", urc_send_func}, + {"Recv", "bytes\r\n", urc_send_bfsz_func}, + {"", ",CLOSED\r\n", urc_close_func}, + {"+IPD", ":", urc_recv_func}, + {"busy p", "\r\n", urc_busy_p_func}, + {"busy s", "\r\n", urc_busy_s_func}, + {"WIFI CONNECTED", "\r\n", urc_func}, + {"WIFI DISCONNECT", "\r\n", urc_func}, +}; + +static void esp8266_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb) +{ + if (event < sizeof(at_evt_cb_table) / sizeof(at_evt_cb_table[0])) { + at_evt_cb_table[event] = cb; + } +} + +static int esp8266_init(void) +{ + at_response_t resp = NULL; + int ret; + int i; + + resp = at_create_resp(512, 0, AT_RESP_TIMEOUT_MS); + if (NULL == resp) { + Log_e("No memory for response structure!"); + ret = QCLOUD_ERR_FAILURE; + goto __exit; + } + + /* reset module */ + at_exec_cmd(resp, "AT+RST"); + + /* reset waiting delay */ + at_delayms(2000); + + /* disable echo */ + + ret = at_exec_cmd(resp, "ATE0"); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("cmd ATE0 exec err"); + // goto exit; + } + + at_delayms(100); + /* set current mode to Wi-Fi station */ + ret = at_exec_cmd(resp, "AT+CWMODE=1"); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("cmd AT+CWMODE=1 exec err"); + // goto exit; + } + + at_delayms(100); + /* get module version */ + ret = at_exec_cmd(resp, "AT+GMR"); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("cmd AT+CWMODE=1 exec err"); + // goto exit; + } + + /* show module version */ + for (i = 0; i < resp->line_counts - 1; i++) { + Log_d("%s", at_resp_get_line(resp, i + 1)); + } + + at_delayms(100); + at_clearFlag(WIFI_CONN_FLAG); + /* connect to WiFi AP */ + ret = at_exec_cmd(resp, "AT+CWJAP=\"%s\",\"%s\"", WIFI_SSID, WIFI_PASSWORD); + + if (!at_waitFlag(WIFI_CONN_FLAG, AT_RESP_TIMEOUT_MS)) { + Log_e("wifi connect timeout"); + ret = QCLOUD_ERR_FAILURE; + goto __exit; + } + + ret = at_exec_cmd(resp, "AT+CIPMUX=1"); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("cmd AT+CIPMUX=1 exec err"); + } + +__exit: + + if (resp) { + at_delete_resp(resp); + } + + return ret; +} + +static int esp8266_close(int fd) +{ + at_response_t resp; + int ret; + + resp = at_create_resp(128, 0, AT_RESP_TIMEOUT_MS); + if (NULL == resp) { + Log_e("No memory for response structure!"); + return QCLOUD_ERR_FAILURE; + } + + ret = at_exec_cmd(resp, "AT+CIPCLOSE=%d", fd); + + if (QCLOUD_RET_SUCCESS != ret) { // fancyxu + Log_e("close socket(%d) fail", fd); + } + + if (resp) { + at_delete_resp(resp); + } + + return ret; +} + +static int esp8266_connect(const char *ip, uint16_t port, eNetProto proto) +{ + at_response_t resp; + bool retryed = false; + int fd, ret; + + POINTER_SANITY_CHECK(ip, QCLOUD_ERR_INVAL); + resp = at_create_resp(128, 0, AT_RESP_TIMEOUT_MS); + if (NULL == resp) { + Log_e("No memory for response structure!"); + return QCLOUD_ERR_FAILURE; + } + + fd = alloc_fd(); + if (fd < 0) { + Log_e("esp8226 support max %d chain", ESP8266_MAX_SOCKET_NUM); + return QCLOUD_ERR_FAILURE; + } + +__retry: + + switch (proto) { + case eNET_TCP: + /* send AT commands to connect TCP server */ + ret = at_exec_cmd(resp, "AT+CIPSTART=%d,\"TCP\",\"%s\",%d,60", fd, ip, port); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("start tcp connect failed, fd=%d,ip(%s),port(%d)", fd, ip, port); + } + break; + + case eNET_UDP: + ret = at_exec_cmd(resp, "AT+CIPSTART=%d,\"UDP\",\"%s\",%d", fd, ip, port); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("start udp connect failed, fd=%d,ip(%s),port(%d)", fd, ip, port); + } + break; + + default: + Log_e("Not supported connect type : %d", proto); + ret = QCLOUD_ERR_FAILURE; + goto __exit; + } + + if ((QCLOUD_RET_SUCCESS != ret) && !retryed) { + Log_e("socket(%d) connect failed, maybe the socket was not be closed at the last time and now will retry.", fd); + if (QCLOUD_RET_SUCCESS != esp8266_close(fd)) { + goto __exit; + } + retryed = true; + at_delayms(100); + goto __retry; + } + +__exit: + + if (resp) { + at_delete_resp(resp); + } + + if (QCLOUD_RET_SUCCESS != ret) { + free_fd(fd); + fd = UNUSED_SOCKET; + } + + at_delayms(200); + return fd; +} + +static int esp8266_send(int fd, const void *buff, size_t len) +{ + int ret; + at_response_t resp; + size_t cur_pkt_size = 0; + size_t sent_size = 0; + size_t temp_size = 0; + + POINTER_SANITY_CHECK(buff, QCLOUD_ERR_INVAL); + resp = at_create_resp(512, 2, AT_RESP_TIMEOUT_MS); + if (NULL == resp) { + Log_e("No memory for response structure!"); + return QCLOUD_ERR_FAILURE; + } + + /* set AT client end sign to deal with '>' sign.*/ + at_set_end_sign('>'); + + while (sent_size < len) { + if (len - sent_size < ESP8266_SEND_MAX_LEN_ONCE) { + cur_pkt_size = len - sent_size; + } else { + cur_pkt_size = ESP8266_SEND_MAX_LEN_ONCE; + } + + at_clearFlag(SEND_OK_FLAG); + at_clearFlag(SEND_FAIL_FLAG); + /* send the "AT+CIPSEND" commands to AT server than receive the '>' response on the first line. */ + ret = at_exec_cmd(resp, "AT+CIPSEND=%d,%d", fd, cur_pkt_size); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("cmd AT+CIPSEND exec err"); + goto __exit; + } + at_set_end_sign(0); + /* send the real data to server or client */ + temp_size = at_client_send(at_client_get(), (char *)buff + sent_size, cur_pkt_size, AT_RESP_TIMEOUT_MS); + + if (cur_pkt_size != temp_size) { + Log_e("at send real data failed"); + goto __exit; + } + +#ifndef AT_OS_USED + at_urc urc_send = {.cmd_prefix = "SEND OK", .cmd_suffix = "\r\n", NULL}; + at_client_yeild(&urc_send, resp->timeout); + if (at_client_get()->resp_status != AT_RESP_OK) { + Log_e("send fail"); + ret = QCLOUD_ERR_FAILURE; + goto __exit; + } +#else + if (at_waitFlag(SEND_OK_FLAG | SEND_FAIL_FLAG, AT_RESP_TIMEOUT_MS)) { + if (at_waitFlag(SEND_FAIL_FLAG, AT_RESP_TIMEOUT_MS)) { + Log_e("send fail"); + ret = QCLOUD_ERR_FAILURE; + goto __exit; + } + } +#endif + sent_size += cur_pkt_size; + } + + ret = QCLOUD_RET_SUCCESS; + +__exit: + /* reset the end sign for data */ + if (resp) { + at_delete_resp(resp); + } + + return sent_size; // fancyxu +} + +static int esp8266_recv_timeout(int fd, void *buf, size_t len, uint32_t timeout) +{ +#ifndef AT_OS_USED + at_client_yeild(NULL, timeout); +#endif + return QCLOUD_RET_SUCCESS; +} + +static int esp8266_parse_domain(const char *host_name, char *host_ip, size_t host_ip_len) +{ +#define RESOLVE_RETRY 5 + + char recv_ip[16] = {0}; + at_response_t resp; + int ret, i; + + POINTER_SANITY_CHECK(host_name, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(host_ip, QCLOUD_ERR_INVAL); + + if (host_ip_len < 16) { + Log_e("host ip buff too short"); + return QCLOUD_ERR_FAILURE; + } + + resp = at_create_resp(128, 0, 4 * AT_RESP_TIMEOUT_MS); + if (NULL == resp) { + Log_e("No memory for response structure!"); + return QCLOUD_ERR_FAILURE; + } + + for (i = 0; i < RESOLVE_RETRY; i++) { + ret = at_exec_cmd(resp, "AT+CIPDOMAIN=\"%s\"", host_name); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("exec AT+CIPDOMAIN=\"%s\" fail", host_name); + goto __exit; + } + + /* parse the third line of response data, get the IP address */ + if (at_resp_parse_line_args_by_kw(resp, "+CIPDOMAIN:", "+CIPDOMAIN:%s", recv_ip) < 0) { + at_delayms(100); + /* resolve failed, maybe receive an URC CRLF */ + continue; + } + + if (strlen(recv_ip) < 8) { + at_delayms(100); + /* resolve failed, maybe receive an URC CRLF */ + continue; + } else { + strncpy(host_ip, recv_ip, 15); + host_ip[15] = '\0'; + break; + } + } + +__exit: + + if (resp) { + at_delete_resp(resp); + } + +#undef RESOLVE_RETRY + + return ret; +} + +at_device_op_t at_ops_esp8266 = { + .init = esp8266_init, + .connect = esp8266_connect, + .send = esp8266_send, + .recv_timeout = esp8266_recv_timeout, + .close = esp8266_close, + .parse_domain = esp8266_parse_domain, + .set_event_cb = esp8266_set_event_cb, + .deviceName = "esp8266", +}; + +int at_device_esp8266_init(void) +{ + int i; + int ret; + at_client_t p_client; + + ret = HAL_AT_Uart_Init(); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("at uart init fail!"); + } else { + Log_d("at uart init success!"); + } + + /* initialize AT client */ + ret = at_client_init(&p_client); + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("at client init fail,ret:%d", ret); + goto exit; + } else { + Log_d("at client init success"); + } + + /* register URC data execution function */ + at_set_urc_table(p_client, urc_table, sizeof(urc_table) / sizeof(urc_table[0])); + + Log_d("urc table addr:%p, size:%d", p_client->urc_table, p_client->urc_table_size); + for (i = 0; i < p_client->urc_table_size; i++) { + Log_d("%s", p_client->urc_table[i].cmd_prefix); + } + + ret = at_device_op_register(&at_ops_esp8266); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("at device driver register fail"); + goto exit; + } + +exit: + if (QCLOUD_RET_SUCCESS != ret) { + if (NULL != p_client) { + at_client_deinit(p_client); + } + } + + return ret; +} + +/*at device driver must realize this api which called by HAL_AT_TCP_Init*/ +int at_device_init(void) +{ + return at_device_esp8266_init(); +} diff --git a/platform/at_device/esp8266/at_device_esp8266.h b/platform/at_device/esp8266/at_device_esp8266.h new file mode 100755 index 00000000..ed33c041 --- /dev/null +++ b/platform/at_device/esp8266/at_device_esp8266.h @@ -0,0 +1,28 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __AT_DEVICE_ESP8266_H__ +#define __AT_DEVICE_ESP8266_H__ + +#define AT_RESP_TIMEOUT_MS (5000) +#define ESP8266_SEND_MAX_LEN_ONCE (2048) +#define ESP8266_MAX_SOCKET_NUM (5) + +#define WIFI_SSID "youga_wifi" //"Honor 8"// +#define WIFI_PASSWORD "Iot@2018" //"xy123123"// + +int at_device_esp8266_init(void); + +#endif /* __AT_DEVICE_ESP8266_H__ */ diff --git a/platform/os/freertos/HAL_AT_UART_freertos.c b/platform/os/freertos/HAL_AT_UART_freertos.c new file mode 100755 index 00000000..2bdf45ee --- /dev/null +++ b/platform/os/freertos/HAL_AT_UART_freertos.c @@ -0,0 +1,77 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifdef AT_TCP_ENABLED + +#include +#include +#include +#include + +#include "at_client.h" +#include "stm32l4xx_hal.h" +#include "utils_ringbuff.h" + +#define HAL_AT_UART_IRQHandler USART1_IRQHandler +extern UART_HandleTypeDef huart1; +static UART_HandleTypeDef *pAtUart = &huart1; + +extern void AT_Uart_Init(void); +extern void at_client_uart_rx_isr_cb(uint8_t *pdata, uint8_t len); + +#include "board.h" +/** + * @brief This function handles AT UART global interrupt,push recv char to ringbuff. + */ +void HAL_AT_UART_IRQHandler(void) +{ + uint8_t ch; + if (__HAL_UART_GET_FLAG(pAtUart, UART_FLAG_RXNE) == SET) { + ch = (uint8_t)READ_REG(pAtUart->Instance->RDR) & 0xFF; + /*this callback for at_client*/ + at_client_uart_rx_isr_cb(&ch, 1); + HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); + } + __HAL_UART_CLEAR_PEFLAG(pAtUart); +} + +/** + *pdata: pointer of data for send + *len: len of data to be sent + *return: the len of data send success + * @brief hal api for at data send + */ +int HAL_AT_Uart_Send(void *data, uint32_t size) +{ + if (HAL_OK == HAL_UART_Transmit(pAtUart, data, size, 0xFFFF)) { + return size; + } else { + return 0; + } +} + +int HAL_AT_Uart_Init(void) +{ + AT_Uart_Init(); + return QCLOUD_RET_SUCCESS; +} + +int HAL_AT_Uart_Deinit(void) +{ + return QCLOUD_RET_SUCCESS; +} +#endif diff --git a/platform/os/freertos/HAL_Device_freertos.c b/platform/os/freertos/HAL_Device_freertos.c new file mode 100755 index 00000000..e51ac07b --- /dev/null +++ b/platform/os/freertos/HAL_Device_freertos.c @@ -0,0 +1,165 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/* Enable this macro (also control by cmake) to use static string buffer to store device info */ +/* To use specific storing methods like files/flash, disable this macro and implement dedicated methods */ +#define DEBUG_DEV_INFO_USED + +#ifdef DEBUG_DEV_INFO_USED +/* product Id */ +static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; + +/* device name */ +static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_DEV_NAME"; + +#ifdef DEV_DYN_REG_ENABLED +/* product secret for device dynamic Registration */ +static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "YOUR_PRODUCT_SECRET"; +#endif + +#ifdef AUTH_MODE_CERT +/* public cert file name of certificate device */ +static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "YOUR_DEVICE_NAME_cert.crt"; +/* private key file name of certificate device */ +static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key"; +#else +/* device secret of PSK device */ +static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "YOUR_IOT_PSK"; +#endif + +#ifdef GATEWAY_ENABLED +/* sub-device product id */ +static char sg_sub_device_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; +/* sub-device device name */ +static char sg_sub_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_SUB_DEV_NAME"; +#endif + +static int device_info_copy(void *pdst, void *psrc, uint8_t max_len) +{ + if (strlen(psrc) > max_len) { + return QCLOUD_ERR_FAILURE; + } + memset(pdst, '\0', max_len); + strncpy(pdst, psrc, max_len); + return QCLOUD_RET_SUCCESS; +} + +#endif + +int HAL_SetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(sg_product_id, devInfo->product_id, MAX_SIZE_OF_PRODUCT_ID); // set product ID + ret |= device_info_copy(sg_device_name, devInfo->device_name, MAX_SIZE_OF_DEVICE_NAME); // set dev name + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(sg_device_cert_file_name, devInfo->dev_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // set dev cert file name + ret |= device_info_copy(sg_device_privatekey_file_name, devInfo->dev_key_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // set dev key file name +#else + ret |= device_info_copy(sg_device_secret, devInfo->device_secret, MAX_SIZE_OF_DEVICE_SECRET); // set dev secret +#endif + +#else + Log_e("HAL_SetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Set device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +int HAL_GetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + memset((char *)devInfo, '\0', sizeof(DeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(devInfo->product_id, sg_product_id, MAX_SIZE_OF_PRODUCT_ID); // get product ID + ret |= device_info_copy(devInfo->device_name, sg_device_name, MAX_SIZE_OF_DEVICE_NAME); // get dev name + +#ifdef DEV_DYN_REG_ENABLED + ret |= device_info_copy(devInfo->product_secret, sg_product_secret, MAX_SIZE_OF_PRODUCT_SECRET); // get product ID +#endif + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(devInfo->dev_cert_file_name, sg_device_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // get dev cert file name + ret |= device_info_copy(devInfo->dev_key_file_name, sg_device_privatekey_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // get dev key file name +#else + ret |= device_info_copy(devInfo->device_secret, sg_device_secret, MAX_SIZE_OF_DEVICE_SECRET); // get dev secret +#endif + +#else + Log_e("HAL_GetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +#ifdef GATEWAY_ENABLED +int HAL_GetGwDevInfo(void *pgwDeviceInfo) +{ + POINTER_SANITY_CHECK(pgwDeviceInfo, QCLOUD_ERR_DEV_INFO); + int ret; + GatewayDeviceInfo *gwDevInfo = (GatewayDeviceInfo *)pgwDeviceInfo; + memset((char *)gwDevInfo, 0, sizeof(GatewayDeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = HAL_GetDevInfo(&(gwDevInfo->gw_info)); // get gw dev info + // only one sub-device is supported now + gwDevInfo->sub_dev_num = 1; + gwDevInfo->sub_dev_info = (DeviceInfo *)HAL_Malloc(sizeof(DeviceInfo) * (gwDevInfo->sub_dev_num)); + memset((char *)gwDevInfo->sub_dev_info, '\0', sizeof(DeviceInfo)); + // copy sub dev info + ret = device_info_copy(gwDevInfo->sub_dev_info->product_id, sg_sub_device_product_id, MAX_SIZE_OF_PRODUCT_ID); + ret |= device_info_copy(gwDevInfo->sub_dev_info->device_name, sg_sub_device_name, MAX_SIZE_OF_DEVICE_NAME); + +#else + Log_e("HAL_GetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get gateway device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} +#endif diff --git a/platform/os/freertos/HAL_OS_freertos.c b/platform/os/freertos/HAL_OS_freertos.c new file mode 100755 index 00000000..ab69962d --- /dev/null +++ b/platform/os/freertos/HAL_OS_freertos.c @@ -0,0 +1,229 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_import.h" + +//#define PLATFORM_HAS_CMSIS + +#ifdef PLATFORM_HAS_CMSIS +#include "cmsis_os.h" +#include "stm32l4xx_hal.h" +#endif + +// TODO platform dependant +void HAL_SleepMs(_IN_ uint32_t ms) +{ + TickType_t ticks = ms / portTICK_PERIOD_MS; + + vTaskDelay(ticks ? ticks : 1); /* Minimum delay = 1 tick */ + + return; +} + +void HAL_Printf(_IN_ const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + fflush(stdout); +} + +int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...) +{ + va_list args; + int rc; + + va_start(args, fmt); + rc = vsnprintf(str, len, fmt, args); + va_end(args); + + return rc; +} + +int HAL_Vsnprintf(_IN_ char *str, _IN_ const int len, _IN_ const char *format, va_list ap) +{ + return vsnprintf(str, len, format, ap); +} + +void *HAL_Malloc(_IN_ uint32_t size) +{ + return pvPortMalloc(size); +} + +void HAL_Free(_IN_ void *ptr) +{ + if (ptr) + vPortFree(ptr); +} + +void *HAL_MutexCreate(void) +{ +#ifdef MULTITHREAD_ENABLED + SemaphoreHandle_t mutex = xSemaphoreCreateMutex(); + if (NULL == mutex) { + HAL_Printf("%s: xSemaphoreCreateMutex failed\n", __FUNCTION__); + return NULL; + } + + return mutex; +#else + return (void *)0xFFFFFFFF; +#endif +} + +void HAL_MutexDestroy(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + if (xSemaphoreTake(mutex, 0) != pdTRUE) { + HAL_Printf("%s: xSemaphoreTake failed\n", __FUNCTION__); + } + + vSemaphoreDelete(mutex); +#else + return; +#endif +} + +void HAL_MutexLock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + if (!mutex) { + HAL_Printf("%s: invalid mutex\n", __FUNCTION__); + return; + } + + if (xSemaphoreTake(mutex, portMAX_DELAY) != pdTRUE) { + HAL_Printf("%s: xSemaphoreTake failed\n", __FUNCTION__); + return; + } +#else + return; +#endif +} + +int HAL_MutexTryLock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + if (!mutex) { + HAL_Printf("%s: invalid mutex\n", __FUNCTION__); + return -1; + } + + if (xSemaphoreTake(mutex, 0) != pdTRUE) { + HAL_Printf("%s: xSemaphoreTake failed\n", __FUNCTION__); + return -1; + } + + return 0; +#else + return 0; +#endif +} + +void HAL_MutexUnlock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + if (!mutex) { + HAL_Printf("%s: invalid mutex\n", __FUNCTION__); + return; + } + + if (xSemaphoreGive(mutex) != pdTRUE) { + HAL_Printf("%s: xSemaphoreGive failed\n", __FUNCTION__); + return; + } +#else + return; +#endif +} + +#ifdef MULTITHREAD_ENABLED + +// platform-dependant thread routine/entry function +static void _HAL_thread_func_wrapper_(void *ptr) +{ + ThreadParams *params = (ThreadParams *)ptr; + + params->thread_func(params->user_arg); + + vTaskDelete(NULL); +} + +// platform-dependant thread create function +int HAL_ThreadCreate(ThreadParams *params) +{ + if (params == NULL) + return QCLOUD_ERR_INVAL; + + if (params->thread_name == NULL) { + HAL_Printf("thread name is required for FreeRTOS platform!\n"); + return QCLOUD_ERR_INVAL; + } + + int ret = xTaskCreate(_HAL_thread_func_wrapper_, params->thread_name, params->stack_size, (void *)params, + params->priority, (void *)¶ms->thread_id); + if (ret != pdPASS) { + HAL_Printf("%s: xTaskCreate failed: %d\n", __FUNCTION__, ret); + return QCLOUD_ERR_FAILURE; + } + + return QCLOUD_RET_SUCCESS; +} + +#endif + +#if defined(PLATFORM_HAS_CMSIS) && defined(AT_TCP_ENABLED) + +void *HAL_SemaphoreCreate(void) +{ + return (void *)osSemaphoreCreate(NULL, 1); +} + +void HAL_SemaphoreDestroy(void *sem) +{ + osStatus ret; + + ret = osSemaphoreDelete((osSemaphoreId)sem); + if (osOK != ret) { + HAL_Printf("HAL_SemaphoreDestroy err, err:%d\n\r", ret); + } +} + +void HAL_SemaphorePost(void *sem) +{ + osStatus ret; + + ret = osSemaphoreRelease((osSemaphoreId)sem); + + if (osOK != ret) { + HAL_Printf("HAL_SemaphorePost err, err:%d\n\r", ret); + } +} + +int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms) +{ + return osSemaphoreWait((osSemaphoreId)sem, timeout_ms); +} +#endif diff --git a/platform/os/freertos/HAL_TCP_lwip.c b/platform/os/freertos/HAL_TCP_lwip.c new file mode 100755 index 00000000..04b7cb85 --- /dev/null +++ b/platform/os/freertos/HAL_TCP_lwip.c @@ -0,0 +1,263 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "lwip/inet.h" +#include "lwip/netdb.h" +#include "lwip/sockets.h" +#include "qcloud_iot_common.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +/* lwIP socket handle start from 0 */ +#define LWIP_SOCKET_FD_SHIFT 3 + +static uint32_t _time_left(uint32_t t_end, uint32_t t_now) +{ + uint32_t t_left; + + if (t_end > t_now) { + t_left = t_end - t_now; + } else { + t_left = 0; + } + + return t_left; +} + +uintptr_t HAL_TCP_Connect(const char *host, uint16_t port) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + int fd = 0; + + char port_str[6]; + HAL_Snprintf(port_str, 6, "%d", port); + + memset(&hints, 0x00, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + ret = getaddrinfo(host, port_str, &hints, &addr_list); + if (ret) { + Log_e("getaddrinfo(%s:%s) error", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); + return 0; + } + + for (cur = addr_list; cur != NULL; cur = cur->ai_next) { + fd = (int)socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) { + ret = 0; + continue; + } + + if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) { + ret = fd + LWIP_SOCKET_FD_SHIFT; + break; + } + + close(fd); + ret = 0; + } + + if (ret == 0) { + Log_e("failed to connect with TCP server: %s:%s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); + } else { + /* reduce log print due to frequent log server connect/disconnect */ + if (0 == strncmp(host, LOG_UPLOAD_SERVER_DOMAIN, HOST_STR_LENGTH)) + UPLOAD_DBG("connected with TCP server: %s:%s", host, port_str); + else + Log_i("connected with TCP server: %s:%s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); + } + + freeaddrinfo(addr_list); + + return (uintptr_t)ret; +} + +int HAL_TCP_Disconnect(uintptr_t fd) +{ + int rc; + + fd -= LWIP_SOCKET_FD_SHIFT; + + /* Shutdown both send and receive operations. */ + rc = shutdown((int)fd, 2); + if (0 != rc) { + Log_e("shutdown error: %s", strerror(errno)); + return -1; + } + + rc = close((int)fd); + if (0 != rc) { + Log_e("closesocket error: %s", strerror(errno)); + return -1; + } + + return 0; +} + +int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *written_len) +{ + int ret; + uint32_t len_sent; + uint32_t t_end, t_left; + fd_set sets; + + fd -= LWIP_SOCKET_FD_SHIFT; + + t_end = HAL_GetTimeMs() + timeout_ms; + len_sent = 0; + ret = 1; /* send one time if timeout_ms is value 0 */ + + do { + t_left = _time_left(t_end, HAL_GetTimeMs()); + + if (0 != t_left) { + struct timeval timeout; + + FD_ZERO(&sets); + FD_SET(fd, &sets); + + timeout.tv_sec = t_left / 1000; + timeout.tv_usec = (t_left % 1000) * 1000; + + ret = select(fd + 1, NULL, &sets, NULL, &timeout); + if (ret > 0) { + if (0 == FD_ISSET(fd, &sets)) { + Log_e("Should NOT arrive"); + /* If timeout in next loop, it will not sent any data */ + ret = 0; + continue; + } + } else if (0 == ret) { + ret = QCLOUD_ERR_TCP_WRITE_TIMEOUT; + Log_e("select-write timeout %d", (int)fd); + break; + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + + ret = QCLOUD_ERR_TCP_WRITE_FAIL; + Log_e("select-write fail: %s", strerror(errno)); + break; + } + } else { + ret = QCLOUD_ERR_TCP_WRITE_TIMEOUT; + } + + if (ret > 0) { + ret = send(fd, buf + len_sent, len - len_sent, 0); + if (ret > 0) { + len_sent += ret; + } else if (0 == ret) { + Log_e("No data be sent. Should NOT arrive"); + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + + ret = QCLOUD_ERR_TCP_WRITE_FAIL; + Log_e("send fail: %s", strerror(errno)); + break; + } + } + } while ((len_sent < len) && (_time_left(t_end, HAL_GetTimeMs()) > 0)); + + *written_len = (size_t)len_sent; + + return len_sent > 0 ? QCLOUD_RET_SUCCESS : ret; +} + +int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *read_len) +{ + int ret, err_code; + uint32_t len_recv; + uint32_t t_end, t_left; + fd_set sets; + struct timeval timeout; + + fd -= LWIP_SOCKET_FD_SHIFT; + t_end = HAL_GetTimeMs() + timeout_ms; + len_recv = 0; + err_code = 0; + + do { + t_left = _time_left(t_end, HAL_GetTimeMs()); + if (0 == t_left) { + err_code = QCLOUD_ERR_TCP_READ_TIMEOUT; + break; + } + + FD_ZERO(&sets); + FD_SET(fd, &sets); + + timeout.tv_sec = t_left / 1000; + timeout.tv_usec = (t_left % 1000) * 1000; + + ret = select(fd + 1, &sets, NULL, NULL, &timeout); + if (ret > 0) { + ret = recv(fd, buf + len_recv, len - len_recv, 0); + if (ret > 0) { + len_recv += ret; + } else if (0 == ret) { + struct sockaddr_in peer; + socklen_t sLen = sizeof(peer); + int peer_port = 0; + getpeername(fd, (struct sockaddr *)&peer, &sLen); + peer_port = ntohs(peer.sin_port); + + /* reduce log print due to frequent log server connect/disconnect */ + if (peer_port == LOG_UPLOAD_SERVER_PORT) + UPLOAD_DBG("connection is closed by server: %s:%d", inet_ntoa(peer.sin_addr), peer_port); + else + Log_e("connection is closed by server: %s:%d", inet_ntoa(peer.sin_addr), peer_port); + + err_code = QCLOUD_ERR_TCP_PEER_SHUTDOWN; + break; + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + Log_e("recv error: %s", strerror(errno)); + err_code = QCLOUD_ERR_TCP_READ_FAIL; + break; + } + } else if (0 == ret) { + err_code = QCLOUD_ERR_TCP_READ_TIMEOUT; + break; + } else { + Log_e("select-recv error: %s", strerror(errno)); + err_code = QCLOUD_ERR_TCP_READ_FAIL; + break; + } + } while ((len_recv < len)); + + *read_len = (size_t)len_recv; + + if (err_code == QCLOUD_ERR_TCP_READ_TIMEOUT && len_recv == 0) + err_code = QCLOUD_ERR_TCP_NOTHING_TO_READ; + + return (len == len_recv) ? QCLOUD_RET_SUCCESS : err_code; +} diff --git a/platform/os/freertos/HAL_Timer_freertos.c b/platform/os/freertos/HAL_Timer_freertos.c new file mode 100755 index 00000000..64adc9a7 --- /dev/null +++ b/platform/os/freertos/HAL_Timer_freertos.c @@ -0,0 +1,149 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include "qcloud_iot_import.h" +#include "utils_timer.h" + +#define PLATFORM_HAS_TIME_FUNCS +//#define PLATFORM_HAS_CMSIS + +#ifdef PLATFORM_HAS_TIME_FUNCS +#include +#include +#endif + +#ifdef PLATFORM_HAS_CMSIS +#include "cmsis_os.h" +#include "stm32l4xx_hal.h" +#endif + +int HAL_Timer_set_systime_sec(size_t timestamp_sec) +{ +#if defined PLATFORM_HAS_TIME_FUNCS + struct timeval stime; + stime.tv_sec = timestamp_sec; + stime.tv_usec = 0; + if (0 != settimeofday(&stime, NULL)) { + return -1; + } + return 0; +#else + RTC_DATE_TIME date_time; + date_time.ms = 0; + timestamp_to_date(timestamp_sec, &date_time, 8); + // set RTC Time note hw rtc year base + return -1; +#endif +} + +int HAL_Timer_set_systime_ms(size_t timestamp_ms) +{ +#if defined PLATFORM_HAS_TIME_FUNCS + struct timeval stime; + stime.tv_sec = (timestamp_ms / 1000); + stime.tv_usec = ((timestamp_ms % 1000) * 1000); + + if (0 != settimeofday(&stime, NULL)) { + return -1; + } + return 0; +#else + RTC_DATE_TIME date_time; + date_time.ms = timestamp_ms % 1000; + timestamp_to_date(timestamp_ms / 1000, &date_time, 8); + // set RTC Time note hw rtc year base + return -1; +#endif +} + +uint32_t HAL_GetTimeMs(void) +{ +#if defined PLATFORM_HAS_TIME_FUNCS + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; + +#elif defined PLATFORM_HAS_CMSIS + return HAL_GetTick(); +#endif +} + +/*Get timestamp*/ +long HAL_Timer_current_sec(void) +{ + return HAL_GetTimeMs() / 1000; +} + +char *HAL_Timer_current(char *time_str) +{ +#if defined PLATFORM_HAS_TIME_FUNCS + struct timeval tv; + gettimeofday(&tv, NULL); + time_t now_time = tv.tv_sec; + struct tm tm_tmp = *localtime(&now_time); + strftime(time_str, TIME_FORMAT_STR_LEN, "%F %T", &tm_tmp); + return time_str; +#else + long time_sec; + time_sec = HAL_Timer_current_sec(); + memset(time_str, 0, TIME_FORMAT_STR_LEN); + snprintf(time_str, TIME_FORMAT_STR_LEN, "%ld", time_sec); + return time_str; +#endif +} + +bool HAL_Timer_expired(Timer *timer) +{ + uint32_t now_ts; + + now_ts = HAL_GetTimeMs(); + + return (now_ts > timer->end_time) ? true : false; +} + +void HAL_Timer_countdown_ms(Timer *timer, unsigned int timeout_ms) +{ + timer->end_time = HAL_GetTimeMs(); + timer->end_time += timeout_ms; +} + +void HAL_Timer_countdown(Timer *timer, unsigned int timeout) +{ + timer->end_time = HAL_GetTimeMs(); + timer->end_time += timeout * 1000; +} + +int HAL_Timer_remain(Timer *timer) +{ + return (int)(timer->end_time - HAL_GetTimeMs()); +} + +void HAL_Timer_init(Timer *timer) +{ + timer->end_time = 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/platform/os/freertos/HAL_UDP_lwip.c b/platform/os/freertos/HAL_UDP_lwip.c new file mode 100755 index 00000000..5ac91052 --- /dev/null +++ b/platform/os/freertos/HAL_UDP_lwip.c @@ -0,0 +1,160 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "lwip/inet.h" +#include "lwip/netdb.h" +#include "lwip/sockets.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +#ifdef COAP_COMM_ENABLED + +/* lwIP socket handle start from 0 */ +#define LWIP_SOCKET_FD_SHIFT 3 + +uintptr_t HAL_UDP_Connect(const char *host, unsigned short port) +{ +#define NETWORK_ADDR_LEN (16) + + int ret; + struct addrinfo hints, *addr_list, *cur; + int fd = 0; + + char port_str[6] = {0}; + HAL_Snprintf(port_str, 6, "%d", port); + + memset((char *)&hints, 0x00, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_INET; + hints.ai_protocol = IPPROTO_UDP; + + Log_d("establish tcp connection with server(host=%s port=%s)", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); + + if (getaddrinfo(host, port_str, &hints, &addr_list) != 0) { + Log_e("getaddrinfo error,errno:%s", strerror(errno)); + return 0; + } + + for (cur = addr_list; cur != NULL; cur = cur->ai_next) { + fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) { + ret = 0; + continue; + } + + if (0 == connect(fd, cur->ai_addr, cur->ai_addrlen)) { + ret = fd + LWIP_SOCKET_FD_SHIFT; + break; + } + + close(fd); + ret = 0; + } + + if (0 == ret) { + Log_e("fail to establish udp"); + } else { + Log_d("success to establish udp, fd=%d", ret); + } + + freeaddrinfo(addr_list); + + return (uintptr_t)ret; + +#undef NETWORK_ADDR_LEN +} + +void HAL_UDP_Disconnect(uintptr_t fd) +{ + long socket_id = -1; + fd -= LWIP_SOCKET_FD_SHIFT; + + socket_id = (int)fd; + close(socket_id); +} + +int HAL_UDP_Write(uintptr_t fd, const unsigned char *p_data, unsigned int datalen) +{ + int rc = -1; + long socket_id = -1; + fd -= LWIP_SOCKET_FD_SHIFT; + + socket_id = (int)fd; + rc = send(socket_id, (char *)p_data, (int)datalen, 0); + if (-1 == rc) { + return -1; + } + + return rc; +} + +int HAL_UDP_Read(uintptr_t fd, unsigned char *p_data, unsigned int datalen) +{ + long socket_id = -1; + int count = -1; + fd -= LWIP_SOCKET_FD_SHIFT; + + socket_id = (int)fd; + count = (int)read(socket_id, p_data, datalen); + + return count; +} + +int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datalen, unsigned int timeout_ms) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int socket_id = -1; + fd -= LWIP_SOCKET_FD_SHIFT; + + socket_id = (int)fd; + + if (socket_id < 0) { + return -1; + } + + FD_ZERO(&read_fds); + FD_SET(socket_id, &read_fds); + + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms % 1000) * 1000; + + ret = select(socket_id + 1, &read_fds, NULL, NULL, timeout_ms == 0 ? NULL : &tv); + + /* Zero fds ready means we timed out */ + if (ret == 0) { + return QCLOUD_ERR_SSL_READ_TIMEOUT; /* receive timeout */ + } + + if (ret < 0) { + if (errno == EINTR) { + return -3; /* want read */ + } + + return QCLOUD_ERR_SSL_READ; /* receive failed */ + } + + /* This call will not block */ + return HAL_UDP_Read(fd, p_data, datalen); +} + +#endif diff --git a/platform/os/linux/HAL_AT_UART_linux.c b/platform/os/linux/HAL_AT_UART_linux.c new file mode 100755 index 00000000..73a2d68f --- /dev/null +++ b/platform/os/linux/HAL_AT_UART_linux.c @@ -0,0 +1,237 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifdef AT_TCP_ENABLED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "at_uart_hal.h" + +#ifdef AT_UART_RECV_IRQ +#include "at_client.h" +#include "utils_ringbuff.h" +static void at_uart_irq_recv(void *userContex); +#endif + +#define AT_UART_LINUX_DEV "/dev/ttyUSB0" + +static uart_dev_t sg_at_uart = { + .fd = -1, + .state = eUNUSED, + .config = {BAUDRATE_115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED, MODE_TX_RX}}; + +int HAL_AT_Uart_Init(void) +{ + struct termios t_opt; + speed_t baud; + + if (sg_at_uart.state == eOPENED) { + Log_w("%s already opened", AT_UART_LINUX_DEV); + return QCLOUD_ERR_FAILURE; + } + + if ((sg_at_uart.fd = open(AT_UART_LINUX_DEV, O_RDWR | O_NOCTTY | O_NDELAY)) == -1) { + Log_e("open at uart failed\r\n"); + return QCLOUD_ERR_FAILURE; + } + + switch (sg_at_uart.config.baud_rate) { + case BAUDRATE_9600: + baud = B9600; + break; + case BAUDRATE_115200: + baud = B115200; + break; + case BAUDRATE_921600: + baud = B921600; + break; + default: + baud = B115200; + break; + } + + /* set the serial port parameters */ + fcntl(sg_at_uart.fd, F_SETFL, 0); + + if (0 != tcgetattr(sg_at_uart.fd, &t_opt)) { + return QCLOUD_ERR_FAILURE; + } + + /* set the input and output baudrate*/ + if (0 != cfsetispeed(&t_opt, baud)) { + return QCLOUD_ERR_FAILURE; + } + + if (0 != cfsetospeed(&t_opt, baud)) { + return QCLOUD_ERR_FAILURE; + } + + /* 8N1, flow control, etc. */ + t_opt.c_cflag |= (CLOCAL | CREAD); + if (sg_at_uart.config.parity == NO_PARITY) { + t_opt.c_cflag &= ~PARENB; + } + if (sg_at_uart.config.stop_bits == STOP_BITS_1) { + t_opt.c_cflag &= ~CSTOPB; + } else { + t_opt.c_cflag |= CSTOPB; + } + t_opt.c_cflag &= ~CSIZE; + switch (sg_at_uart.config.data_width) { + case DATA_WIDTH_5BIT: + t_opt.c_cflag |= CS5; + break; + case DATA_WIDTH_6BIT: + t_opt.c_cflag |= CS6; + break; + case DATA_WIDTH_7BIT: + t_opt.c_cflag |= CS7; + break; + case DATA_WIDTH_8BIT: + t_opt.c_cflag |= CS8; + break; + default: + t_opt.c_cflag |= CS8; + break; + } + t_opt.c_lflag &= ~(ECHO | ECHOE | ISIG | ICANON); + + /** + * AT is going to use a binary protocol, so make sure to + * turn off any CR/LF translation and the like. + */ + t_opt.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL); + + t_opt.c_oflag &= ~OPOST; + t_opt.c_cc[VMIN] = 0; + t_opt.c_cc[VTIME] = 5; + if (0 != tcsetattr(sg_at_uart.fd, TCSANOW, &t_opt)) { + return QCLOUD_ERR_FAILURE; + } + + sg_at_uart.state = eOPENED; + + /* clear uart buffer */ + // Log_e("open at uart 1\r\n"); + // read_and_discard_all_data(sg_at_uart.fd); + // Log_e("open at uart 2\r\n"); + +#if defined(AT_UART_RECV_IRQ) && defined(MULTITHREAD_ENABLED) + // START THERAD + int result; + ThreadParams thread_params = {0}; + thread_params.thread_func = at_uart_irq_recv; + thread_params.thread_name = "at_uart_isr_thread"; + thread_params.user_arg = NULL; + thread_params.stack_size = 6144; + thread_params.priority = 0; + + result = HAL_ThreadCreate(&thread_params); + if (QCLOUD_RET_SUCCESS == result) { + Log_d("create uart_irq_recv thread success!"); + } else { + Log_e("create uart_irq_recv thread fail!"); + } +#endif + + return QCLOUD_RET_SUCCESS; +} + +int HAL_AT_Uart_Deinit(void) +{ + if (sg_at_uart.state == eOPENED) { + close(sg_at_uart.fd); + sg_at_uart.state = eCLOSED; + } + + return QCLOUD_RET_SUCCESS; +} + +int HAL_AT_Uart_Send(void *data, uint32_t size) +{ + uint32_t leftlen = size; + int ret = QCLOUD_RET_SUCCESS; + + if (sg_at_uart.state == eOPENED) { + while (leftlen > 0) { + ret = write(sg_at_uart.fd, (char *)data + size - leftlen, leftlen); + if (ret == -1) { + Log_e("write uart fd failed on error: %d.\r\n", errno); + ret = QCLOUD_ERR_FAILURE; + break; + } + leftlen -= ret; + } + } else { + Log_e("AT Uart uninitialized"); + ret = QCLOUD_ERR_FAILURE; + } + + return (ret == QCLOUD_ERR_FAILURE) ? QCLOUD_ERR_FAILURE : size; +} + +int HAL_AT_Uart_Recv(void *data, uint32_t expect_size, uint32_t *recv_size, uint32_t timeout) +{ + int readlen; + int ret; + + if (sg_at_uart.state == eOPENED) { + if ((readlen = read(sg_at_uart.fd, data, expect_size)) == -1) { + ret = QCLOUD_ERR_FAILURE; + } + + if (recv_size) { + *recv_size = readlen; + } + + } else { + Log_e("AT Uart uninitialized"); + ret = QCLOUD_ERR_FAILURE; + } + + return ret; +} + +// simulate IRQ +#ifdef AT_UART_RECV_IRQ +extern void at_client_uart_rx_isr_cb(uint8_t *pdata, uint8_t len); +static void at_uart_irq_recv(void *userContex) +{ + uint8_t data[64]; + int readlen; + while (1) { + if ((readlen = read(sg_at_uart.fd, data, sizeof(data))) == -1) { + continue; + } + at_client_uart_rx_isr_cb(data, readlen); // push + } +} +#endif + +#endif \ No newline at end of file diff --git a/platform/os/linux/HAL_Device_linux.c b/platform/os/linux/HAL_Device_linux.c new file mode 100644 index 00000000..2df005cd --- /dev/null +++ b/platform/os/linux/HAL_Device_linux.c @@ -0,0 +1,482 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/* Enable this macro (also control by cmake) to use static string buffer to store device info */ +/* To use specific storing methods like files/flash, disable this macro and implement dedicated methods */ +//#define DEBUG_DEV_INFO_USED + +#ifdef DEBUG_DEV_INFO_USED +/* product Id */ +static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; + +/* device name */ +static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_DEV_NAME"; + +#ifdef DEV_DYN_REG_ENABLED +/* product secret for device dynamic Registration */ +static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "YOUR_PRODUCT_SECRET"; +#endif + +#ifdef AUTH_MODE_CERT +/* public cert file name of certificate device */ +static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "YOUR_DEVICE_NAME_cert.crt"; +/* private key file name of certificate device */ +static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key"; +#else +/* device secret of PSK device */ +static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "YOUR_IOT_PSK"; +#endif + +#ifdef GATEWAY_ENABLED +/* sub-device product id */ +static char sg_sub_device_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; +/* sub-device device name */ +static char sg_sub_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_SUB_DEV_NAME"; +#endif + +static int device_info_copy(void *pdst, void *psrc, uint8_t max_len) +{ + if (strlen(psrc) > max_len) { + return QCLOUD_ERR_FAILURE; + } + memset(pdst, '\0', max_len); + strncpy(pdst, psrc, max_len); + return QCLOUD_RET_SUCCESS; +} + +int HAL_SetDevInfoFile(const char *file_name) +{ + Log_w("device info is not stored in file!!"); + + return QCLOUD_RET_SUCCESS; +} + +#else +/*device info manage example method*/ + +#include "lite-utils.h" + +#define MAX_DEV_INFO_FILE_LEN 1024 +#define MAX_CONFIG_FILE_NAME 256 + +#define KEY_AUTH_MODE "auth_mode" +#define KEY_PRODUCT_ID "productId" +#define KEY_PRODUCT_SECRET "productSecret" +#define KEY_DEV_NAME "deviceName" +#define KEY_DEV_SECRET "key_deviceinfo.deviceSecret" +#define KEY_DEV_CERT "cert_deviceinfo.devCertFile" +#define KEY_DEV_PRIVATE_KEY "cert_deviceinfo.devPrivateKeyFile" +#define KEY_SUBDEV_PRODUCT_ID "subDev.sub_productId" +#define KEY_SUBDEV_NAME "subDev.sub_devName" + +#define STR_DEV_INFO "key_deviceinfo" +#define STR_DEV_SECRET "deviceSecret" +#define STR_DEV_CERT "cert_deviceinfo" +#define STR_DEV_CERT_FILE "devCertFile" +#define STR_DEV_KEY_FILE "devPrivateKeyFile" + +#define MAX_SIZE_OF_DEVICE_INFO_FILE 128 +static char sg_device_info_file[MAX_SIZE_OF_DEVICE_INFO_FILE + 1] = {"./device_info.json"}; + +int HAL_SetDevInfoFile(const char *file_name) +{ + if (file_name == NULL || strlen(file_name) > MAX_SIZE_OF_DEVICE_INFO_FILE) { + Log_e("illegal device info file name!"); + return QCLOUD_ERR_INVAL; + } + + /* check if file exists */ + if (access(file_name, 0)) { + Log_e("device info file \"%s\" not existed", STRING_PTR_PRINT_SANITY_CHECK(file_name)); + return QCLOUD_ERR_FAILURE; + } + + memset(sg_device_info_file, 0, sizeof(sg_device_info_file)); + strncpy(sg_device_info_file, file_name, MAX_SIZE_OF_DEVICE_INFO_FILE); + return QCLOUD_RET_SUCCESS; +} + +int HAL_GetDevInfoFromFile(const char *file_name, void *dev_info) +{ + FILE * fp; + uint32_t len; + uint32_t rlen; + int ret = QCLOUD_RET_SUCCESS; + char * authMode = NULL; + char * productId = NULL; + char * devName = NULL; +#ifdef DEV_DYN_REG_ENABLED + char * productSecret = NULL; +#endif +#ifdef AUTH_MODE_CERT + char * devCrtFileName = NULL; + char * devKeyFileName = NULL; +#else + char *devSecret = NULL; +#endif + char * JsonDoc = NULL; + + DeviceInfo *pDevInfo = (DeviceInfo *)dev_info; + + fp = fopen(file_name, "r"); + if (NULL == fp) { + Log_e("open device info file \"%s\" failed", STRING_PTR_PRINT_SANITY_CHECK(file_name)); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + if (len > MAX_DEV_INFO_FILE_LEN) { + Log_e("device info file \"%s\" is too big!", file_name); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + JsonDoc = (char *)HAL_Malloc(len + 10); + if (NULL == JsonDoc) { + Log_e("malloc buffer for json file read fail"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + memset(JsonDoc, 0, len + 10); + + rewind(fp); + rlen = fread(JsonDoc, 1, len, fp); + + if (len != rlen) { + Log_e("read data len (%d) less than needed (%d), %s", rlen, len, JsonDoc); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + /*Get device info*/ + authMode = LITE_json_value_of(KEY_AUTH_MODE, JsonDoc); + productId = LITE_json_value_of(KEY_PRODUCT_ID, JsonDoc); + devName = LITE_json_value_of(KEY_DEV_NAME, JsonDoc); + + if (NULL == authMode || NULL == productId || NULL == devName) { + Log_e("read device data from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + strncpy(pDevInfo->product_id, productId, MAX_SIZE_OF_PRODUCT_ID); + strncpy(pDevInfo->device_name, devName, MAX_SIZE_OF_DEVICE_NAME); + +#ifdef DEV_DYN_REG_ENABLED + productSecret = LITE_json_value_of(KEY_PRODUCT_SECRET, JsonDoc); + if (NULL == productSecret) { + Log_e("read product secret from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + strncpy(pDevInfo->product_secret, productSecret, MAX_SIZE_OF_PRODUCT_SECRET); +#endif + +#ifdef AUTH_MODE_CERT + devCrtFileName = LITE_json_value_of(KEY_DEV_CERT, JsonDoc); + devKeyFileName = LITE_json_value_of(KEY_DEV_PRIVATE_KEY, JsonDoc); + if (NULL == devCrtFileName || NULL == devKeyFileName) { + Log_e("read cert file name from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + strncpy(pDevInfo->dev_cert_file_name, devCrtFileName, MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); + strncpy(pDevInfo->dev_key_file_name, devKeyFileName, MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); + // Log_d("mode:%s, pid:%s, devName:%s, devCrtFileName:%s, devKeyFileName:%s", authMode, productId, devName, + // devCrtFileName, devKeyFileName); +#else + devSecret = LITE_json_value_of(KEY_DEV_SECRET, JsonDoc); + if (NULL == devSecret) { + Log_e("read device secret from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + strncpy(pDevInfo->device_secret, devSecret, MAX_SIZE_OF_DEVICE_SECRET); + // Log_d("mode:%s, pid:%s, devName:%s, devSerect:%s", authMode, productId, devName, devSecret); +#endif + +exit: + HAL_Free(authMode); + HAL_Free(productId); + HAL_Free(devName); +#ifdef DEV_DYN_REG_ENABLED + HAL_Free(productSecret); +#endif +#ifdef AUTH_MODE_CERT + HAL_Free(devCrtFileName); + HAL_Free(devKeyFileName); +#else + HAL_Free(devSecret); +#endif + HAL_Free(JsonDoc); + + if (NULL != fp) { + fclose(fp); + } + + return ret; +} + +#ifdef GATEWAY_ENABLED +static int iot_parse_subdevinfo_from_json_file(DeviceInfo *pDevInfo) +{ + FILE * fp; + uint32_t len; + uint32_t rlen; + int ret = QCLOUD_RET_SUCCESS; + char * productId = NULL; + char * devName = NULL; + char * JsonDoc = NULL; + + fp = fopen(sg_device_info_file, "r"); + if (NULL == fp) { + Log_e("open device info file \"%s\" failed", sg_device_info_file); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + if (len > MAX_DEV_INFO_FILE_LEN) { + Log_e("device info file \"%s\" is too big!", sg_device_info_file); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + JsonDoc = (char *)HAL_Malloc(len + 10); + if (NULL == JsonDoc) { + Log_e("malloc buffer for json file read fail"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + rewind(fp); + rlen = fread(JsonDoc, 1, len, fp); + + if (len != rlen) { + Log_e("read data len (%d) less than needed (%d), %s", rlen, len, JsonDoc); + } + + /*Get sub device info*/ + productId = LITE_json_value_of(KEY_SUBDEV_PRODUCT_ID, JsonDoc); + devName = LITE_json_value_of(KEY_SUBDEV_NAME, JsonDoc); + + if (NULL == productId || NULL == devName) { + Log_e("read sub device data from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + strncpy(pDevInfo->product_id, productId, MAX_SIZE_OF_PRODUCT_ID); + strncpy(pDevInfo->device_name, devName, MAX_SIZE_OF_DEVICE_NAME); + // Log_d("pid:%s, devName:%s", productId, devName); + +exit: + HAL_Free(productId); + HAL_Free(devName); + HAL_Free(JsonDoc); + + if (NULL != fp) { + fclose(fp); + } + + return ret; +} +#endif + +static int iot_save_devinfo_to_json_file(DeviceInfo *pDevInfo) +{ + char JsonDoc[MAX_DEV_INFO_FILE_LEN] = {0}; + int32_t remain_size = MAX_DEV_INFO_FILE_LEN; + int32_t rc_of_snprintf = 0; + int32_t wlen; + FILE * fp; + + rc_of_snprintf = HAL_Snprintf(JsonDoc, remain_size, "{\n"); + remain_size -= rc_of_snprintf; + + // auth_mode +#ifdef AUTH_MODE_CERT + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n", KEY_AUTH_MODE, "CERT"); + remain_size -= rc_of_snprintf; +#else + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n", KEY_AUTH_MODE, "KEY"); + remain_size -= rc_of_snprintf; +#endif + + // product id, device name + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n\"%s\":\"%s\",\n", + KEY_PRODUCT_ID, STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->product_id), KEY_DEV_NAME, + STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->device_name)); + remain_size -= rc_of_snprintf; + + // product secret +#ifdef DEV_DYN_REG_ENABLED + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n", KEY_PRODUCT_SECRET, + STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->product_secret)); + remain_size -= rc_of_snprintf; +#endif + + // key device info or cert device info +#ifdef AUTH_MODE_CERT + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":{\n", STR_DEV_CERT); + remain_size -= rc_of_snprintf; + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n\"%s\":\"%s\"\n}", + STR_DEV_CERT_FILE, STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->dev_cert_file_name), + STR_DEV_KEY_FILE, STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->dev_key_file_name)); + remain_size -= rc_of_snprintf; +#else + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":{\n", STR_DEV_INFO); + remain_size -= rc_of_snprintf; + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\"\n}", STR_DEV_SECRET, + STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->device_secret)); + remain_size -= rc_of_snprintf; +#endif + + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\n}"); + remain_size -= rc_of_snprintf; + + Log_d("JsonDoc(%d):%s", MAX_DEV_INFO_FILE_LEN - remain_size, JsonDoc); + + fp = fopen(sg_device_info_file, "w"); + if (NULL == fp) { + Log_e("open file %s failed", sg_device_info_file); + return QCLOUD_ERR_FAILURE; + } + + wlen = fwrite(JsonDoc, 1, strlen(JsonDoc), fp); + if (wlen < (MAX_DEV_INFO_FILE_LEN - remain_size)) { + Log_e("write len less than needed"); + } + fclose(fp); + return QCLOUD_RET_SUCCESS; +} +#endif + +int HAL_SetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(sg_product_id, devInfo->product_id, MAX_SIZE_OF_PRODUCT_ID); // set product ID + ret |= device_info_copy(sg_device_name, devInfo->device_name, MAX_SIZE_OF_DEVICE_NAME); // set dev name + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(sg_device_cert_file_name, devInfo->dev_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // set dev cert file name + ret |= device_info_copy(sg_device_privatekey_file_name, devInfo->dev_key_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // set dev key file name +#else + ret |= device_info_copy(sg_device_secret, devInfo->device_secret, MAX_SIZE_OF_DEVICE_SECRET); // set dev secret +#endif + +#else + ret = iot_save_devinfo_to_json_file(devInfo); +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Set device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +int HAL_GetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + memset((char *)devInfo, '\0', sizeof(DeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(devInfo->product_id, sg_product_id, MAX_SIZE_OF_PRODUCT_ID); // get product ID + ret |= device_info_copy(devInfo->device_name, sg_device_name, MAX_SIZE_OF_DEVICE_NAME); // get dev name + +#ifdef DEV_DYN_REG_ENABLED + ret |= device_info_copy(devInfo->product_secret, sg_product_secret, MAX_SIZE_OF_PRODUCT_SECRET); // get product ID +#endif + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(devInfo->dev_cert_file_name, sg_device_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // get dev cert file name + ret |= device_info_copy(devInfo->dev_key_file_name, sg_device_privatekey_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // get dev key file name +#else + ret |= device_info_copy(devInfo->device_secret, sg_device_secret, MAX_SIZE_OF_DEVICE_SECRET); // get dev secret +#endif + +#else + // get devinfo from file + ret = HAL_GetDevInfoFromFile(sg_device_info_file, devInfo); +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +#ifdef GATEWAY_ENABLED +int HAL_GetGwDevInfo(void *pgwDeviceInfo) +{ + POINTER_SANITY_CHECK(pgwDeviceInfo, QCLOUD_ERR_DEV_INFO); + int ret; + GatewayDeviceInfo *gwDevInfo = (GatewayDeviceInfo *)pgwDeviceInfo; + memset((char *)gwDevInfo, 0, sizeof(GatewayDeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = HAL_GetDevInfo(&(gwDevInfo->gw_info)); // get gw dev info + // only one sub-device is supported now + gwDevInfo->sub_dev_num = 1; + gwDevInfo->sub_dev_info = (DeviceInfo *)HAL_Malloc(sizeof(DeviceInfo) * (gwDevInfo->sub_dev_num)); + memset((char *)gwDevInfo->sub_dev_info, '\0', sizeof(DeviceInfo)); + // copy sub dev info + ret = device_info_copy(gwDevInfo->sub_dev_info->product_id, sg_sub_device_product_id, MAX_SIZE_OF_PRODUCT_ID); + ret |= device_info_copy(gwDevInfo->sub_dev_info->device_name, sg_sub_device_name, MAX_SIZE_OF_DEVICE_NAME); + +#else + ret = HAL_GetDevInfoFromFile(sg_device_info_file, &(gwDevInfo->gw_info)); + if (ret != QCLOUD_RET_SUCCESS) { + return QCLOUD_ERR_FAILURE; + } + // only one sub-device is supported now + gwDevInfo->sub_dev_num = 1; + gwDevInfo->sub_dev_info = (DeviceInfo *)HAL_Malloc(sizeof(DeviceInfo) * (gwDevInfo->sub_dev_num)); + memset((char *)gwDevInfo->sub_dev_info, '\0', sizeof(DeviceInfo)); + // copy sub dev info + ret = iot_parse_subdevinfo_from_json_file(gwDevInfo->sub_dev_info); +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get gateway device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} +#endif diff --git a/platform/os/linux/HAL_Log_linux.c b/platform/os/linux/HAL_Log_linux.c new file mode 100755 index 00000000..cd3624fb --- /dev/null +++ b/platform/os/linux/HAL_Log_linux.c @@ -0,0 +1,91 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +#ifdef LOG_UPLOAD + +#define LOG_SAVE_FILE_PATH "upload-fail-save.log" + +size_t HAL_Log_Save(const char *log, size_t wLen) +{ + FILE * fp; + size_t len; + + if ((fp = fopen(LOG_SAVE_FILE_PATH, "a+")) == NULL) { + Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); + return 0; + } + + len = fwrite((void *)log, 1, wLen, fp); + Log_d("write %d of %d to log file", len, wLen); + + fclose(fp); + + return len; +} + +size_t HAL_Log_Read(char *buff, size_t rLen) +{ + FILE * fp; + size_t len; + + if ((fp = fopen(LOG_SAVE_FILE_PATH, "r")) == NULL) { + Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); + return 0; + } + + len = fread((void *)buff, 1, rLen, fp); + Log_d("read %d of %d from log file", len, rLen); + + fclose(fp); + + return len; +} + +int HAL_Log_Del(void) +{ + return remove(LOG_SAVE_FILE_PATH); +} + +size_t HAL_Log_Get_Size(void) +{ + long length; + FILE *fp; + + /* check if file exists */ + if (access(LOG_SAVE_FILE_PATH, 0)) + return 0; + + if ((fp = fopen(LOG_SAVE_FILE_PATH, "r")) == NULL) { + Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); + return 0; + } + + fseek(fp, 0L, SEEK_END); + length = ftell(fp); + fclose(fp); + if (length > 0) + return (size_t)length; + else + return 0; +} + +#endif diff --git a/platform/os/linux/HAL_OS_linux.c b/platform/os/linux/HAL_OS_linux.c new file mode 100755 index 00000000..e74f654c --- /dev/null +++ b/platform/os/linux/HAL_OS_linux.c @@ -0,0 +1,251 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_import.h" + +void *HAL_MutexCreate(void) +{ +#ifdef MULTITHREAD_ENABLED + int err_num; + pthread_mutex_t *mutex = (pthread_mutex_t *)HAL_Malloc(sizeof(pthread_mutex_t)); + if (NULL == mutex) { + return NULL; + } + + if (0 != (err_num = pthread_mutex_init(mutex, NULL))) { + HAL_Printf("%s: create mutex failed\n", __FUNCTION__); + HAL_Free(mutex); + return NULL; + } + + return mutex; +#else + return (void *)0xFFFFFFFF; +#endif +} + +void HAL_MutexDestroy(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + int err_num; + if (0 != (err_num = pthread_mutex_destroy((pthread_mutex_t *)mutex))) { + HAL_Printf("%s: destroy mutex failed\n", __FUNCTION__); + } + + HAL_Free(mutex); +#else + return; +#endif +} + +void HAL_MutexLock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + int err_num; + if (0 != (err_num = pthread_mutex_lock((pthread_mutex_t *)mutex))) { + HAL_Printf("%s: lock mutex failed\n", __FUNCTION__); + } +#else + return; +#endif +} + +int HAL_MutexTryLock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + return pthread_mutex_trylock((pthread_mutex_t *)mutex); +#else + return 0; +#endif +} + +void HAL_MutexUnlock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + int err_num; + if (0 != (err_num = pthread_mutex_unlock((pthread_mutex_t *)mutex))) { + HAL_Printf("%s: unlock mutex failed\n", __FUNCTION__); + } +#else + return; +#endif +} + +void *HAL_Malloc(_IN_ uint32_t size) +{ + return malloc(size); +} + +void HAL_Free(_IN_ void *ptr) +{ + if (ptr) + free(ptr); +} + +void HAL_Printf(_IN_ const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + fflush(stdout); +} + +int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...) +{ + va_list args; + int rc; + + va_start(args, fmt); + rc = vsnprintf(str, len, fmt, args); + va_end(args); + + return rc; +} + +int HAL_Vsnprintf(_IN_ char *str, _IN_ const int len, _IN_ const char *format, va_list ap) +{ + return vsnprintf(str, len, format, ap); +} + +uint32_t HAL_GetTimeMs(void) +{ + struct timeval time_val = {0}; + uint32_t time_ms; + + gettimeofday(&time_val, NULL); + time_ms = time_val.tv_sec * 1000 + time_val.tv_usec / 1000; + + return time_ms; +} + +void HAL_SleepMs(_IN_ uint32_t ms) +{ + usleep(1000 * ms); +} + +#ifdef MULTITHREAD_ENABLED + +// platform-dependant thread routine/entry function +static void *_HAL_thread_func_wrapper_(void *ptr) +{ + ThreadParams *params = (ThreadParams *)ptr; + + params->thread_func(params->user_arg); + + pthread_detach(pthread_self()); + pthread_exit(0); + return NULL; +} + +// platform-dependant thread create function +int HAL_ThreadCreate(ThreadParams *params) +{ + if (params == NULL) + return QCLOUD_ERR_INVAL; + + int ret = pthread_create((pthread_t *)¶ms->thread_id, NULL, _HAL_thread_func_wrapper_, (void *)params); + if (ret) { + HAL_Printf("%s: pthread_create failed: %d\n", __FUNCTION__, ret); + return QCLOUD_ERR_FAILURE; + } + + return QCLOUD_RET_SUCCESS; +} + +void HAL_ThreadExit(void) {} + +#endif + +#ifdef AT_TCP_ENABLED + +void HAL_DelayMs(_IN_ uint32_t ms) +{ + usleep(1000 * ms); +} + +void *HAL_SemaphoreCreate(void) +{ + sem_t *sem = (sem_t *)malloc(sizeof(sem_t)); + if (NULL == sem) { + return NULL; + } + + if (0 != sem_init(sem, 0, 0)) { + free(sem); + return NULL; + } + + return sem; +} + +void HAL_SemaphoreDestroy(void *sem) +{ + sem_destroy((sem_t *)sem); + free(sem); +} + +void HAL_SemaphorePost(void *sem) +{ + sem_post((sem_t *)sem); +} + +int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms) +{ +#define PLATFORM_WAIT_INFINITE (~0) + + if (PLATFORM_WAIT_INFINITE == timeout_ms) { + sem_wait(sem); + return QCLOUD_RET_SUCCESS; + } else { + struct timespec ts; + int s; + /* Restart if interrupted by handler */ + do { + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + return QCLOUD_ERR_FAILURE; + } + + s = 0; + ts.tv_nsec += (timeout_ms % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000) { + ts.tv_nsec -= 1000000000; + s = 1; + } + + ts.tv_sec += timeout_ms / 1000 + s; + + } while (((s = sem_timedwait(sem, &ts)) != 0) && errno == EINTR); + + return s ? QCLOUD_ERR_FAILURE : QCLOUD_RET_SUCCESS; + } +#undef PLATFORM_WAIT_INFINITE +} + +#endif diff --git a/src/platform/os/linux/HAL_TCP_linux.c b/platform/os/linux/HAL_TCP_linux.c old mode 100644 new mode 100755 similarity index 68% rename from src/platform/os/linux/HAL_TCP_linux.c rename to platform/os/linux/HAL_TCP_linux.c index 4caccf64..2a4cb767 --- a/src/platform/os/linux/HAL_TCP_linux.c +++ b/platform/os/linux/HAL_TCP_linux.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,28 +13,28 @@ * */ +#include +#include +#include +#include +#include +#include #include #include -#include -#include #include #include +#include #include -#include -#include -#include -#include -#include -#include "qcloud_iot_import.h" -#include "qcloud_iot_export_log.h" +#include "qcloud_iot_common.h" #include "qcloud_iot_export_error.h" - +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" static uint64_t _linux_get_time_ms(void) { - struct timeval tv = { 0 }; - uint64_t time_ms; + struct timeval tv = {0}; + uint64_t time_ms; gettimeofday(&tv, NULL); @@ -58,53 +58,51 @@ static uint64_t _linux_time_left(uint64_t t_end, uint64_t t_now) uintptr_t HAL_TCP_Connect(const char *host, uint16_t port) { - int ret; - struct addrinfo hints, *addr_list, *cur; - int fd = 0; + int ret; + struct addrinfo hints, *addr_list, *cur; + int fd = 0; char port_str[6]; HAL_Snprintf(port_str, 6, "%d", port); memset(&hints, 0x00, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; + hints.ai_protocol = IPPROTO_TCP; ret = getaddrinfo(host, port_str, &hints, &addr_list); - if (ret) { + if (ret) { if (ret == EAI_SYSTEM) - Log_e("getaddrinfo(%s:%s) error: %s", host, port_str, strerror(errno)); + Log_e("getaddrinfo(%s:%s) error: %s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str, strerror(errno)); else - Log_e("getaddrinfo(%s:%s) error: %s", host, port_str, gai_strerror(ret)); + Log_e("getaddrinfo(%s:%s) error: %s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str, gai_strerror(ret)); return 0; } for (cur = addr_list; cur != NULL; cur = cur->ai_next) { - fd = (int) socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); - if( fd < 0 ) - { - ret = 0; - continue; - } - - if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) - { - ret = fd; - break; - } - - close( fd ); - ret = 0; + fd = (int)socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) { + ret = 0; + continue; + } + + if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) { + ret = fd; + break; + } + + close(fd); + ret = 0; } if (0 == ret) { - Log_e("fail to connect with TCP server: %s:%s", host, port_str); + Log_e("fail to connect with TCP server: %s:%s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); } else { /* reduce log print due to frequent log server connect/disconnect */ - if (port == LOG_UPLOAD_SERVER_PORT) + if (0 == strncmp(host, LOG_UPLOAD_SERVER_DOMAIN, HOST_STR_LENGTH)) UPLOAD_DBG("connected with TCP server: %s:%s", host, port_str); else - Log_i("connected with TCP server: %s:%s", host, port_str); + Log_i("connected with TCP server: %s:%s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); } freeaddrinfo(addr_list); @@ -112,39 +110,37 @@ uintptr_t HAL_TCP_Connect(const char *host, uint16_t port) return (uintptr_t)ret; } - int HAL_TCP_Disconnect(uintptr_t fd) { int rc; /* Shutdown both send and receive operations. */ - rc = shutdown((int) fd, 2); - if (0 != rc) { - Log_e("shutdown error: %s", strerror(errno)); + rc = shutdown((int)fd, 2); + if (0 != rc) { + Log_e("shutdown error: %s", strerror(errno)); return -1; } - rc = close((int) fd); + rc = close((int)fd); if (0 != rc) { - Log_e("closesocket error: %s", strerror(errno)); + Log_e("closesocket error: %s", strerror(errno)); return -1; } return 0; } - int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *written_len) { - int ret; + int ret; uint32_t len_sent; uint64_t t_end, t_left; - fd_set sets; + fd_set sets; - t_end = _linux_get_time_ms() + timeout_ms; + t_end = _linux_get_time_ms() + timeout_ms; len_sent = 0; - ret = 1; /* send one time if timeout_ms is value 0 */ + /* send one time if timeout_ms is value 0 */ do { t_left = _linux_time_left(t_end, _linux_get_time_ms()); @@ -154,7 +150,7 @@ int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t FD_ZERO(&sets); FD_SET(fd, &sets); - timeout.tv_sec = t_left / 1000; + timeout.tv_sec = t_left / 1000; timeout.tv_usec = (t_left % 1000) * 1000; ret = select(fd + 1, NULL, &sets, NULL, &timeout); @@ -175,13 +171,12 @@ int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t continue; } - ret = QCLOUD_ERR_TCP_WRITE_FAIL; - Log_e("select-write fail: %s", strerror(errno)); + ret = QCLOUD_ERR_TCP_WRITE_FAIL; + Log_e("select-write fail: %s", strerror(errno)); break; } - } - else { - ret = QCLOUD_ERR_TCP_WRITE_TIMEOUT; + } else { + ret = QCLOUD_ERR_TCP_WRITE_TIMEOUT; } if (ret > 0) { @@ -196,8 +191,8 @@ int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t continue; } - ret = QCLOUD_ERR_TCP_WRITE_FAIL; - Log_e("send fail: %s", strerror(errno)); + ret = QCLOUD_ERR_TCP_WRITE_FAIL; + Log_e("send fail: %s", strerror(errno)); break; } } @@ -205,33 +200,32 @@ int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t *written_len = (size_t)len_sent; - return len_sent > 0 ? QCLOUD_ERR_SUCCESS : ret; + return len_sent > 0 ? QCLOUD_RET_SUCCESS : ret; } - int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *read_len) { - int ret, err_code; - uint32_t len_recv; - uint64_t t_end, t_left; - fd_set sets; + int ret, err_code; + uint32_t len_recv; + uint64_t t_end, t_left; + fd_set sets; struct timeval timeout; - t_end = _linux_get_time_ms() + timeout_ms; + t_end = _linux_get_time_ms() + timeout_ms; len_recv = 0; err_code = 0; do { t_left = _linux_time_left(t_end, _linux_get_time_ms()); if (0 == t_left) { - err_code = QCLOUD_ERR_TCP_READ_TIMEOUT; + err_code = QCLOUD_ERR_TCP_READ_TIMEOUT; break; } FD_ZERO(&sets); FD_SET(fd, &sets); - timeout.tv_sec = t_left / 1000; + timeout.tv_sec = t_left / 1000; timeout.tv_usec = (t_left % 1000) * 1000; ret = select(fd + 1, &sets, NULL, NULL, &timeout); @@ -241,25 +235,25 @@ int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeou len_recv += ret; } else if (0 == ret) { struct sockaddr_in peer; - socklen_t sLen = sizeof(peer); - int peer_port = 0; - getpeername(fd, (struct sockaddr*)&peer, &sLen); + socklen_t sLen = sizeof(peer); + int peer_port = 0; + getpeername(fd, (struct sockaddr *)&peer, &sLen); peer_port = ntohs(peer.sin_port); /* reduce log print due to frequent log server connect/disconnect */ if (peer_port == LOG_UPLOAD_SERVER_PORT) - UPLOAD_DBG("connection is closed by server: %s:%d", inet_ntoa(peer.sin_addr), peer_port); + UPLOAD_DBG("connection is closed by server: %s:%d", inet_ntoa(peer.sin_addr), peer_port); else Log_e("connection is closed by server: %s:%d", inet_ntoa(peer.sin_addr), peer_port); - + err_code = QCLOUD_ERR_TCP_PEER_SHUTDOWN; break; } else { if (EINTR == errno) { Log_e("EINTR be caught"); continue; - } - Log_e("recv error: %s", strerror(errno)); + } + Log_e("recv error: %s", strerror(errno)); err_code = QCLOUD_ERR_TCP_READ_FAIL; break; } @@ -267,7 +261,7 @@ int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeou err_code = QCLOUD_ERR_TCP_READ_TIMEOUT; break; } else { - Log_e("select-recv error: %s", strerror(errno)); + Log_e("select-recv error: %s", strerror(errno)); err_code = QCLOUD_ERR_TCP_READ_FAIL; break; } @@ -278,5 +272,5 @@ int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeou if (err_code == QCLOUD_ERR_TCP_READ_TIMEOUT && len_recv == 0) err_code = QCLOUD_ERR_TCP_NOTHING_TO_READ; - return (len == len_recv) ? QCLOUD_ERR_SUCCESS : err_code; + return (len == len_recv) ? QCLOUD_RET_SUCCESS : err_code; } diff --git a/src/platform/os/linux/HAL_Timer_linux.c b/platform/os/linux/HAL_Timer_linux.c old mode 100644 new mode 100755 similarity index 55% rename from src/platform/os/linux/HAL_Timer_linux.c rename to platform/os/linux/HAL_Timer_linux.c index 12373bb0..5390fd4c --- a/src/platform/os/linux/HAL_Timer_linux.c +++ b/platform/os/linux/HAL_Timer_linux.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -16,64 +16,96 @@ #ifdef __cplusplus extern "C" { #endif - -#include + #include - +#include + #include "qcloud_iot_import.h" -static char now_time_str[20] = {0}; - -bool HAL_Timer_expired(Timer *timer) { +bool HAL_Timer_expired(Timer *timer) +{ struct timeval now, res; gettimeofday(&now, NULL); timersub(&timer->end_time, &now, &res); return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0); } -void HAL_Timer_countdown_ms(Timer *timer, unsigned int timeout_ms) { +void HAL_Timer_countdown_ms(Timer *timer, unsigned int timeout_ms) +{ struct timeval now; gettimeofday(&now, NULL); struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000}; timeradd(&now, &interval, &timer->end_time); } -void HAL_Timer_countdown(Timer *timer, unsigned int timeout) { +void HAL_Timer_countdown(Timer *timer, unsigned int timeout) +{ struct timeval now; gettimeofday(&now, NULL); struct timeval interval = {timeout, 0}; timeradd(&now, &interval, &timer->end_time); } -int HAL_Timer_remain(Timer *timer) { +int HAL_Timer_remain(Timer *timer) +{ struct timeval now, res; gettimeofday(&now, NULL); timersub(&timer->end_time, &now, &res); return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000; } -void HAL_Timer_init(Timer *timer) { - timer->end_time = (struct timeval) {0, 0}; +void HAL_Timer_init(Timer *timer) +{ + timer->end_time = (struct timeval){0, 0}; +} + +char *HAL_Timer_current(char *time_str) +{ + if (time_str == NULL) + return " "; + + struct timeval tv; + gettimeofday(&tv, NULL); + time_t now_time = tv.tv_sec; + + struct tm tm_tmp = *localtime(&now_time); + strftime(time_str, TIME_FORMAT_STR_LEN, "%F %T", &tm_tmp); + + return time_str; } -char* HAL_Timer_current(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - time_t now_time = tv.tv_sec; +long HAL_Timer_current_sec(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); - struct tm tm_tmp = *localtime(&now_time); - strftime(now_time_str, 20, "%F %T", &tm_tmp); + return tv.tv_sec; +} + +int HAL_Timer_set_systime_sec(size_t timestamp_sec) +{ + struct timeval stime; + stime.tv_sec = timestamp_sec; + stime.tv_usec = 0; - return now_time_str; + if (0 != settimeofday(&stime, NULL)) { + return -1; + } + return 0; } -long HAL_Timer_current_sec(void) { - struct timeval tv; - gettimeofday(&tv, NULL); +int HAL_Timer_set_systime_ms(size_t timestamp_ms) +{ + struct timeval stime; + stime.tv_sec = (timestamp_ms / 1000); + stime.tv_usec = ((timestamp_ms % 1000) * 1000); - return tv.tv_sec; + if (0 != settimeofday(&stime, NULL)) { + return -1; + } + return 0; } - + #ifdef __cplusplus } #endif diff --git a/src/platform/os/linux/HAL_UDP_linux.c b/platform/os/linux/HAL_UDP_linux.c old mode 100644 new mode 100755 similarity index 68% rename from src/platform/os/linux/HAL_UDP_linux.c rename to platform/os/linux/HAL_UDP_linux.c index d2463a00..58ae6d91 --- a/src/platform/os/linux/HAL_UDP_linux.c +++ b/platform/os/linux/HAL_UDP_linux.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,59 +13,61 @@ * */ +#include +#include +#include +#include +#include #include #include #include -#include #include #include -#include -#include -#include #include -#include -#include "qcloud_iot_import.h" -#include "qcloud_iot_export_log.h" #include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +#ifdef COAP_COMM_ENABLED uintptr_t HAL_UDP_Connect(const char *host, unsigned short port) { -#define NETWORK_ADDR_LEN (16) +#define NETWORK_ADDR_LEN (16) - int ret; - struct addrinfo hints, *addr_list, *cur; - int fd = 0; + int ret; + struct addrinfo hints, *addr_list, *cur; + int fd = 0; - char port_str[6] = {0}; + char port_str[6] = {0}; HAL_Snprintf(port_str, 6, "%d", port); memset((char *)&hints, 0x00, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; - hints.ai_family = AF_INET; + hints.ai_family = AF_INET; hints.ai_protocol = IPPROTO_UDP; - Log_d("establish tcp connection with server(host=%s port=%s)", host, port_str); + Log_d("establish tcp connection with server(host=%s port=%s)", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); - if (getaddrinfo(host, port_str, &hints, &addr_list) != 0) { - Log_e("getaddrinfo error,errno:%s",strerror(errno)); + if (getaddrinfo(host, port_str, &hints, &addr_list) != 0) { + Log_e("getaddrinfo error,errno:%s", strerror(errno)); return 0; } for (cur = addr_list; cur != NULL; cur = cur->ai_next) { - fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); - if (fd < 0) { - ret = 0; - continue; - } - - if (0 == connect(fd, cur->ai_addr, cur->ai_addrlen)) { - ret = fd; - break; - } - - close(fd); - ret = 0; + fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) { + ret = 0; + continue; + } + + if (0 == connect(fd, cur->ai_addr, cur->ai_addrlen)) { + ret = fd; + break; + } + + close(fd); + ret = 0; } if (0 == ret) { @@ -83,7 +85,7 @@ uintptr_t HAL_UDP_Connect(const char *host, unsigned short port) void HAL_UDP_Disconnect(uintptr_t fd) { - long socket_id = -1; + long socket_id = -1; socket_id = (int)fd; close(socket_id); @@ -91,11 +93,11 @@ void HAL_UDP_Disconnect(uintptr_t fd) int HAL_UDP_Write(uintptr_t fd, const unsigned char *p_data, unsigned int datalen) { - int rc = -1; - long socket_id = -1; + int rc = -1; + long socket_id = -1; socket_id = (int)fd; - rc = send(socket_id, (char *)p_data, (int)datalen, 0); + rc = send(socket_id, (char *)p_data, (int)datalen, 0); if (-1 == rc) { return -1; } @@ -105,21 +107,21 @@ int HAL_UDP_Write(uintptr_t fd, const unsigned char *p_data, unsigned int datale int HAL_UDP_Read(uintptr_t fd, unsigned char *p_data, unsigned int datalen) { - long socket_id = -1; - int count = -1; + long socket_id = -1; + int count = -1; socket_id = (int)fd; - count = (int)read(socket_id, p_data, datalen); + count = (int)read(socket_id, p_data, datalen); return count; } int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datalen, unsigned int timeout_ms) { - int ret; - struct timeval tv; - fd_set read_fds; - int socket_id = -1; + int ret; + struct timeval tv; + fd_set read_fds; + int socket_id = -1; socket_id = (int)fd; @@ -137,12 +139,12 @@ int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datale /* Zero fds ready means we timed out */ if (ret == 0) { - return QCLOUD_ERR_SSL_READ_TIMEOUT; /* receive timeout */ + return QCLOUD_ERR_SSL_READ_TIMEOUT; /* receive timeout */ } if (ret < 0) { if (errno == EINTR) { - return -3; /* want read */ + return -3; /* want read */ } return QCLOUD_ERR_SSL_READ; /* receive failed */ @@ -151,3 +153,5 @@ int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datale /* This call will not block */ return HAL_UDP_Read(fd, p_data, datalen); } + +#endif diff --git a/platform/os/nonos/HAL_AT_UART_nonos.c b/platform/os/nonos/HAL_AT_UART_nonos.c new file mode 100755 index 00000000..d100b55c --- /dev/null +++ b/platform/os/nonos/HAL_AT_UART_nonos.c @@ -0,0 +1,73 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include + +#include "at_client.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "stm32l4xx_hal.h" +#include "utils_ringbuff.h" + +#define HAL_AT_UART_IRQHandler USART1_IRQHandler +extern UART_HandleTypeDef huart1; +static UART_HandleTypeDef *pAtUart = &huart1; + +extern void AT_Uart_Init(void); +extern void at_client_uart_rx_isr_cb(uint8_t *pdata, uint8_t len); + +#include "board.h" +/** + * @brief This function handles AT UART global interrupt,push recv char to ringbuff. + */ +void HAL_AT_UART_IRQHandler(void) +{ + uint8_t ch; + if (__HAL_UART_GET_FLAG(pAtUart, UART_FLAG_RXNE) == SET) { + ch = (uint8_t)READ_REG(pAtUart->Instance->RDR) & 0xFF; + /*this callback for at_client*/ + at_client_uart_rx_isr_cb(&ch, 1); + HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); + } + __HAL_UART_CLEAR_PEFLAG(pAtUart); +} + +/** + *pdata: pointer of data for send + *len: len of data to be sent + *return: the len of data send success + * @brief hal api for at data send + */ +int HAL_AT_Uart_Send(void *data, uint32_t size) +{ + if (HAL_OK == HAL_UART_Transmit(pAtUart, data, size, 0xFFFF)) { + return size; + } else { + return 0; + } +} + +int HAL_AT_Uart_Init(void) +{ + AT_Uart_Init(); + return QCLOUD_RET_SUCCESS; +} + +int HAL_AT_Uart_Deinit(void) +{ + return QCLOUD_RET_SUCCESS; +} diff --git a/platform/os/nonos/HAL_Device_nonos.c b/platform/os/nonos/HAL_Device_nonos.c new file mode 100755 index 00000000..11c132dc --- /dev/null +++ b/platform/os/nonos/HAL_Device_nonos.c @@ -0,0 +1,166 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/* Enable this macro (also control by cmake) to use static string buffer to store device info */ +/* To use specific storing methods like files/flash, disable this macro and implement dedicated methods */ +#define DEBUG_DEV_INFO_USED + +#ifdef DEBUG_DEV_INFO_USED +/* product Id */ +static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; + +/* device name */ +static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_DEV_NAME"; + +#ifdef DEV_DYN_REG_ENABLED +/* product secret for device dynamic Registration */ +static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "YOUR_PRODUCT_SECRET"; +#endif + +#ifdef AUTH_MODE_CERT +/* public cert file name of certificate device */ +static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "YOUR_DEVICE_NAME_cert.crt"; +/* private key file name of certificate device */ +static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key"; +#else +/* device secret of PSK device */ +static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "YOUR_IOT_PSK"; +#endif + +#ifdef GATEWAY_ENABLED +/* sub-device product id */ +static char sg_sub_device_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; +/* sub-device device name */ +static char sg_sub_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_SUB_DEV_NAME"; +#endif + +static int device_info_copy(void *pdst, void *psrc, uint8_t max_len) +{ + if (strlen(psrc) > max_len) { + return QCLOUD_ERR_FAILURE; + } + memset(pdst, '\0', max_len); + strncpy(pdst, psrc, max_len); + return QCLOUD_RET_SUCCESS; +} + +#endif + +int HAL_SetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(sg_product_id, devInfo->product_id, MAX_SIZE_OF_PRODUCT_ID); // set product ID + ret |= device_info_copy(sg_device_name, devInfo->device_name, MAX_SIZE_OF_DEVICE_NAME); // set dev name + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(sg_device_cert_file_name, devInfo->dev_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // set dev cert file name + ret |= device_info_copy(sg_device_privatekey_file_name, devInfo->dev_key_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // set dev key file name +#else + ret |= device_info_copy(sg_device_secret, devInfo->device_secret, MAX_SIZE_OF_DEVICE_SECRET); // set dev secret +#endif + +#else + Log_e("HAL_SetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Set device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +int HAL_GetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + memset((char *)devInfo, '\0', sizeof(DeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(devInfo->product_id, sg_product_id, MAX_SIZE_OF_PRODUCT_ID); // get product ID + ret |= device_info_copy(devInfo->device_name, sg_device_name, MAX_SIZE_OF_DEVICE_NAME); // get dev name + +#ifdef DEV_DYN_REG_ENABLED + ret |= device_info_copy(devInfo->product_secret, sg_product_secret, MAX_SIZE_OF_PRODUCT_SECRET); // get product ID +#endif + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(devInfo->dev_cert_file_name, sg_device_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // get dev cert file name + ret |= device_info_copy(devInfo->dev_key_file_name, sg_device_privatekey_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // get dev key file name +#else + ret |= device_info_copy(devInfo->device_secret, sg_device_secret, MAX_SIZE_OF_DEVICE_SECRET); // get dev secret +#endif + +#else + Log_e("HAL_GetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +#ifdef GATEWAY_ENABLED +int HAL_GetGwDevInfo(void *pgwDeviceInfo) +{ + POINTER_SANITY_CHECK(pgwDeviceInfo, QCLOUD_ERR_DEV_INFO); + int ret; + GatewayDeviceInfo *gwDevInfo = (GatewayDeviceInfo *)pgwDeviceInfo; + memset((char *)gwDevInfo, 0, sizeof(GatewayDeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = HAL_GetDevInfo(&(gwDevInfo->gw_info)); // get gw dev info + // only one sub-device is supported now + gwDevInfo->sub_dev_num = 1; + gwDevInfo->sub_dev_info = (DeviceInfo *)HAL_Malloc(sizeof(DeviceInfo) * (gwDevInfo->sub_dev_num)); + memset((char *)gwDevInfo->sub_dev_info, '\0', sizeof(DeviceInfo)); + // copy sub dev info + ret = device_info_copy(gwDevInfo->sub_dev_info->product_id, sg_sub_device_product_id, MAX_SIZE_OF_PRODUCT_ID); + ret |= device_info_copy(gwDevInfo->sub_dev_info->device_name, sg_sub_device_name, MAX_SIZE_OF_DEVICE_NAME); + +#else + Log_e("HAL_GetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get gateway device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} +#endif diff --git a/platform/os/nonos/HAL_OS_nonos.c b/platform/os/nonos/HAL_OS_nonos.c new file mode 100755 index 00000000..a5c20f5c --- /dev/null +++ b/platform/os/nonos/HAL_OS_nonos.c @@ -0,0 +1,90 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "qcloud_iot_import.h" +#include "stm32l4xx_hal.h" + +void HAL_Printf(_IN_ const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + fflush(stdout); +} + +int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...) +{ + va_list args; + int rc; + + va_start(args, fmt); + rc = vsnprintf(str, len, fmt, args); + va_end(args); + + return rc; +} + +int HAL_Vsnprintf(_IN_ char *str, _IN_ const int len, _IN_ const char *format, va_list ap) +{ + return vsnprintf(str, len, format, ap); +} + +void HAL_SleepMs(_IN_ uint32_t ms) +{ + (void)HAL_Delay(ms); +} + +void HAL_DelayMs(_IN_ uint32_t ms) +{ + (void)HAL_Delay(ms); +} + +void HAL_Free(void *ptr) +{ + if (ptr) + free(ptr); +} + +void *HAL_Malloc(uint32_t size) +{ + return malloc(size); +} + +void *HAL_MutexCreate(void) +{ + return (void *)1; +} + +void HAL_MutexDestroy(void *mutex) +{ + return; +} + +void HAL_MutexLock(void *mutex) +{ + return; +} + +void HAL_MutexUnlock(void *mutex) +{ + return; +} diff --git a/platform/os/nonos/HAL_Timer_nonos.c b/platform/os/nonos/HAL_Timer_nonos.c new file mode 100755 index 00000000..5f125ede --- /dev/null +++ b/platform/os/nonos/HAL_Timer_nonos.c @@ -0,0 +1,111 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include "qcloud_iot_import.h" +#include "utils_timer.h" + +#include "stm32l4xx_hal.h" + +static char now_time_str[20] = {0}; + +int HAL_Timer_set_systime_sec(size_t timestamp_sec) +{ +#ifndef PLATFORM_HAS_TIME_FUNCS + RTC_DATE_TIME date_time; + date_time.ms = 0; + timestamp_to_date(timestamp_sec, &date_time, 8); + // set RTC Time note hw rtc year base +#endif + return -1; +} + +int HAL_Timer_set_systime_ms(size_t timestamp_ms) +{ +#ifndef PLATFORM_HAS_TIME_FUNCS + RTC_DATE_TIME date_time; + date_time.ms = timestamp_ms % 1000; + timestamp_to_date(timestamp_ms / 1000, &date_time, 8); + // set RTC Time note hw rtc year base +#endif + return -1; +} + +uint32_t HAL_GetTimeMs(void) +{ + return HAL_GetTick(); +} + +/*Get timestamp*/ +long HAL_Timer_current_sec(void) +{ + // return GetTimeStampByAt(NULL); + + return HAL_GetTimeMs() / 1000; +} + +char *HAL_Timer_current(void) +{ + long time_sec; + + time_sec = HAL_Timer_current_sec(); + memset(now_time_str, 0, 20); + snprintf(now_time_str, 20, "%ld", time_sec); + + return now_time_str; +} + +bool HAL_Timer_expired(Timer *timer) +{ + uint32_t now_ts; + + now_ts = HAL_GetTimeMs(); + + return (now_ts > timer->end_time) ? true : false; +} + +void HAL_Timer_countdown_ms(Timer *timer, unsigned int timeout_ms) +{ + timer->end_time = HAL_GetTimeMs(); + timer->end_time += timeout_ms; +} + +void HAL_Timer_countdown(Timer *timer, unsigned int timeout) +{ + timer->end_time = HAL_GetTimeMs(); + timer->end_time += timeout * 1000; +} + +int HAL_Timer_remain(Timer *timer) +{ + return (int)(timer->end_time - HAL_GetTimeMs()); +} + +void HAL_Timer_init(Timer *timer) +{ + timer->end_time = 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/platform/os/rtthread/HAL_Device_rtthread.c b/platform/os/rtthread/HAL_Device_rtthread.c new file mode 100755 index 00000000..e51ac07b --- /dev/null +++ b/platform/os/rtthread/HAL_Device_rtthread.c @@ -0,0 +1,165 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/* Enable this macro (also control by cmake) to use static string buffer to store device info */ +/* To use specific storing methods like files/flash, disable this macro and implement dedicated methods */ +#define DEBUG_DEV_INFO_USED + +#ifdef DEBUG_DEV_INFO_USED +/* product Id */ +static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; + +/* device name */ +static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_DEV_NAME"; + +#ifdef DEV_DYN_REG_ENABLED +/* product secret for device dynamic Registration */ +static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "YOUR_PRODUCT_SECRET"; +#endif + +#ifdef AUTH_MODE_CERT +/* public cert file name of certificate device */ +static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "YOUR_DEVICE_NAME_cert.crt"; +/* private key file name of certificate device */ +static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key"; +#else +/* device secret of PSK device */ +static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "YOUR_IOT_PSK"; +#endif + +#ifdef GATEWAY_ENABLED +/* sub-device product id */ +static char sg_sub_device_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; +/* sub-device device name */ +static char sg_sub_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_SUB_DEV_NAME"; +#endif + +static int device_info_copy(void *pdst, void *psrc, uint8_t max_len) +{ + if (strlen(psrc) > max_len) { + return QCLOUD_ERR_FAILURE; + } + memset(pdst, '\0', max_len); + strncpy(pdst, psrc, max_len); + return QCLOUD_RET_SUCCESS; +} + +#endif + +int HAL_SetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(sg_product_id, devInfo->product_id, MAX_SIZE_OF_PRODUCT_ID); // set product ID + ret |= device_info_copy(sg_device_name, devInfo->device_name, MAX_SIZE_OF_DEVICE_NAME); // set dev name + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(sg_device_cert_file_name, devInfo->dev_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // set dev cert file name + ret |= device_info_copy(sg_device_privatekey_file_name, devInfo->dev_key_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // set dev key file name +#else + ret |= device_info_copy(sg_device_secret, devInfo->device_secret, MAX_SIZE_OF_DEVICE_SECRET); // set dev secret +#endif + +#else + Log_e("HAL_SetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Set device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +int HAL_GetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + memset((char *)devInfo, '\0', sizeof(DeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(devInfo->product_id, sg_product_id, MAX_SIZE_OF_PRODUCT_ID); // get product ID + ret |= device_info_copy(devInfo->device_name, sg_device_name, MAX_SIZE_OF_DEVICE_NAME); // get dev name + +#ifdef DEV_DYN_REG_ENABLED + ret |= device_info_copy(devInfo->product_secret, sg_product_secret, MAX_SIZE_OF_PRODUCT_SECRET); // get product ID +#endif + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(devInfo->dev_cert_file_name, sg_device_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // get dev cert file name + ret |= device_info_copy(devInfo->dev_key_file_name, sg_device_privatekey_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // get dev key file name +#else + ret |= device_info_copy(devInfo->device_secret, sg_device_secret, MAX_SIZE_OF_DEVICE_SECRET); // get dev secret +#endif + +#else + Log_e("HAL_GetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +#ifdef GATEWAY_ENABLED +int HAL_GetGwDevInfo(void *pgwDeviceInfo) +{ + POINTER_SANITY_CHECK(pgwDeviceInfo, QCLOUD_ERR_DEV_INFO); + int ret; + GatewayDeviceInfo *gwDevInfo = (GatewayDeviceInfo *)pgwDeviceInfo; + memset((char *)gwDevInfo, 0, sizeof(GatewayDeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = HAL_GetDevInfo(&(gwDevInfo->gw_info)); // get gw dev info + // only one sub-device is supported now + gwDevInfo->sub_dev_num = 1; + gwDevInfo->sub_dev_info = (DeviceInfo *)HAL_Malloc(sizeof(DeviceInfo) * (gwDevInfo->sub_dev_num)); + memset((char *)gwDevInfo->sub_dev_info, '\0', sizeof(DeviceInfo)); + // copy sub dev info + ret = device_info_copy(gwDevInfo->sub_dev_info->product_id, sg_sub_device_product_id, MAX_SIZE_OF_PRODUCT_ID); + ret |= device_info_copy(gwDevInfo->sub_dev_info->device_name, sg_sub_device_name, MAX_SIZE_OF_DEVICE_NAME); + +#else + Log_e("HAL_GetDevInfo not implement yet"); + ret = QCLOUD_ERR_DEV_INFO; +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get gateway device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} +#endif diff --git a/src/platform/os/linux/HAL_OS_linux.c b/platform/os/rtthread/HAL_OS_rtthread.c old mode 100644 new mode 100755 similarity index 54% rename from src/platform/os/linux/HAL_OS_linux.c rename to platform/os/rtthread/HAL_OS_rtthread.c index 2c5cf6a3..fac836df --- a/src/platform/os/linux/HAL_OS_linux.c +++ b/platform/os/rtthread/HAL_OS_rtthread.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -12,120 +12,117 @@ * limitations under the License. * */ - -#include -#include +#include #include -#include - -#include - -#include -#include -#include +#include +#include "qcloud_iot_export.h" #include "qcloud_iot_import.h" +#include "rtconfig.h" -void *HAL_MutexCreate(void) -{ - int err_num; - pthread_mutex_t *mutex = (pthread_mutex_t *)HAL_Malloc(sizeof(pthread_mutex_t)); - if (NULL == mutex) { - return NULL; - } +#define HAL_OS_LOG_MAXLEN 1024 +static uint16_t g_mutex_count = 0; - if (0 != (err_num = pthread_mutex_init(mutex, NULL))) { - HAL_Printf("%s: create mutex failed\n", __FUNCTION__); - HAL_Free(mutex); - return NULL; - } +void HAL_Printf(_IN_ const char *fmt, ...) +{ + va_list args; + char log_buf[HAL_OS_LOG_MAXLEN]; - return mutex; + va_start(args, fmt); + rt_vsnprintf(log_buf, HAL_OS_LOG_MAXLEN, fmt, args); + va_end(args); + printf("%s", log_buf); } -void HAL_MutexDestroy(_IN_ void *mutex) +int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...) { - int err_num; - if (0 != (err_num = pthread_mutex_destroy((pthread_mutex_t *)mutex))) { - HAL_Printf("%s: destroy mutex failed\n", __FUNCTION__); - } + va_list args; + int rc; - HAL_Free(mutex); + va_start(args, fmt); + rc = vsnprintf(str, len, fmt, args); + va_end(args); + + return rc; } -void HAL_MutexLock(_IN_ void *mutex) +int HAL_Vsnprintf(_IN_ char *str, _IN_ const int len, _IN_ const char *format, va_list ap) { - int err_num; - if (0 != (err_num = pthread_mutex_lock((pthread_mutex_t *)mutex))) { - HAL_Printf("%s: lock mutex failed\n", __FUNCTION__); - } + return vsnprintf(str, len, format, ap); } -int HAL_MutexTryLock(_IN_ void *mutex) +void *HAL_MutexCreate(void) { - return pthread_mutex_trylock((pthread_mutex_t *)mutex); - //return 0; -} + rt_mutex_t mutex; + char mutexName[RT_NAME_MAX]; + memset(mutexName, 0, RT_NAME_MAX); + HAL_Snprintf(mutexName, RT_NAME_MAX, "tmutex_%d", g_mutex_count++); + mutex = rt_mutex_create(mutexName, RT_IPC_FLAG_FIFO); + if (NULL == mutex) { + HAL_Printf("create mutex failed"); + } -void HAL_MutexUnlock(_IN_ void *mutex) + return mutex; +} + +void HAL_MutexDestroy(_IN_ void *mutex) { int err_num; - if (0 != (err_num = pthread_mutex_unlock((pthread_mutex_t *)mutex))) { - HAL_Printf("%s: unlock mutex failed\n", __FUNCTION__); + + err_num = rt_mutex_delete((rt_mutex_t)mutex); + + if (0 != err_num) { + HAL_Printf("destroy mutex failed"); } } -void *HAL_Malloc(_IN_ uint32_t size) +void HAL_MutexLock(_IN_ void *mutex) { - return malloc(size); -} + int err_num; -void HAL_Free(_IN_ void *ptr) -{ - free(ptr); + err_num = rt_mutex_take((rt_mutex_t)mutex, RT_WAITING_FOREVER); + + if (0 != err_num) { + HAL_Printf("lock mutex failed"); + } } -void HAL_Printf(_IN_ const char *fmt, ...) +void HAL_MutexUnlock(_IN_ void *mutex) { - va_list args; + int err_num; - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); + err_num = rt_mutex_release((rt_mutex_t)mutex); - fflush(stdout); + if (0 != err_num) { + HAL_Printf("unlock mutex failed"); + } } -int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...) +int HAL_MutexTryLock(_IN_ void *mutex) { - va_list args; - int rc; + int err_num; - va_start(args, fmt); - rc = vsnprintf(str, len, fmt, args); - va_end(args); + err_num = rt_mutex_take((rt_mutex_t)mutex, RT_WAITING_NO); - return rc; + if (0 != err_num) { + HAL_Printf("trylock mutex failed"); + } + return err_num; } -int HAL_Vsnprintf(_IN_ char *str, _IN_ const int len, _IN_ const char *format, va_list ap) +void *HAL_Malloc(_IN_ uint32_t size) { - return vsnprintf(str, len, format, ap); + return rt_malloc(size); } -uint32_t HAL_UptimeMs(void) +void HAL_Free(_IN_ void *ptr) { - struct timeval time_val = {0}; - uint32_t time_ms; - - gettimeofday(&time_val, NULL); - time_ms = time_val.tv_sec * 1000 + time_val.tv_usec / 1000; - - return time_ms; + if (ptr) + rt_free(ptr); } void HAL_SleepMs(_IN_ uint32_t ms) { - usleep(1000 * ms); + (void)rt_thread_delay(rt_tick_from_millisecond(ms)); } diff --git a/platform/os/rtthread/HAL_TCP_rtthread.c b/platform/os/rtthread/HAL_TCP_rtthread.c new file mode 100755 index 00000000..fef96938 --- /dev/null +++ b/platform/os/rtthread/HAL_TCP_rtthread.c @@ -0,0 +1,245 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +//#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include + +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +static uint64_t rtthread_get_time_ms(void) +{ + return HAL_GetTimeMs(); +} + +static uint64_t rtthread_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 HAL_TCP_Connect(const char *host, uint16_t port) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + int fd = 0; + + char port_str[6]; + HAL_Snprintf(port_str, 6, "%d", port); + + memset(&hints, 0x00, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + Log_d("establish tcp connection with server(host=%s port=%s)", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); + + if (getaddrinfo(host, port_str, &hints, &addr_list) != 0) { + perror("getaddrinfo error"); + return 0; + } + + for (cur = addr_list; cur != NULL; cur = cur->ai_next) { + if (cur->ai_family != AF_INET) { + perror("socket type error"); + ret = -1; + continue; + } + fd = (int)socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) { + ret = 0; + continue; + } + + if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) { + ret = fd; + break; + } + + close(fd); + ret = 0; + } + + if (0 == ret) { + Log_e("fail to establish tcp"); + } else { + Log_d("success to establish tcp, fd=%d", ret); + } + + freeaddrinfo(addr_list); + + return (uintptr_t)ret; +} + +int HAL_TCP_Disconnect(uintptr_t fd) +{ + int rc; + + rc = close((int)fd); + if (0 != rc) { + perror("closesocket error"); + return -1; + } + + return 0; +} + +int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *written_len) +{ + int ret; + uint32_t len_sent; + uint64_t t_end, t_left; + fd_set sets; + + t_end = rtthread_get_time_ms() + timeout_ms; + len_sent = 0; + ret = 1; /* send one time if timeout_ms is value 0 */ + + do { + t_left = rtthread_time_left(t_end, rtthread_get_time_ms()); + if (0 != t_left) { + struct timeval timeout; + + FD_ZERO(&sets); + FD_SET(fd, &sets); + + timeout.tv_sec = t_left / 1000; + timeout.tv_usec = (t_left % 1000) * 1000; + + ret = select(fd + 1, NULL, &sets, NULL, &timeout); + if (ret > 0) { + if (0 == FD_ISSET(fd, &sets)) { + Log_e("Should NOT arrive"); + /* If timeout in next loop, it will not sent any data */ + ret = 0; + continue; + } + } else if (0 == ret) { + Log_e("select-write timeout %d", (int)fd); + break; + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + + perror("select-write fail"); + break; + } + } else { + ret = QCLOUD_ERR_SSL_WRITE_TIMEOUT; + } + + if (ret > 0) { + ret = send(fd, buf + len_sent, len - len_sent, 0); + if (ret > 0) { + len_sent += ret; + } else if (0 == ret) { + Log_e("No data be sent"); + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + + ret = QCLOUD_ERR_TCP_WRITE_FAIL; + perror("send fail"); + break; + } + } + } while ((len_sent < len) && (rtthread_time_left(t_end, rtthread_get_time_ms()) > 0)); + + *written_len = (size_t)len_sent; + + return len_sent > 0 ? QCLOUD_RET_SUCCESS : ret; +} + +int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *read_len) +{ + int ret, err_code; + uint32_t len_recv; + uint64_t t_end, t_left; + fd_set sets; + struct timeval timeout; + + // Log_d("readTimeout %dms,readlen %d", timeout_ms, *read_len); + HAL_SleepMs(1); // wihout delay,read seems to be blocked + + t_end = rtthread_get_time_ms() + timeout_ms; + len_recv = 0; + err_code = 0; + + do { + t_left = rtthread_time_left(t_end, rtthread_get_time_ms()); + if (0 == t_left) { + err_code = QCLOUD_ERR_MQTT_NOTHING_TO_READ; + break; + } + FD_ZERO(&sets); + FD_SET(fd, &sets); + + timeout.tv_sec = t_left / 1000; + timeout.tv_usec = (t_left % 1000) * 1000; + + ret = select(fd + 1, &sets, NULL, NULL, &timeout); + if (ret > 0) { + ret = recv(fd, buf + len_recv, len - len_recv, 0); + if (ret > 0) { + len_recv += ret; + } else if (0 == ret) { + perror("connection is closed"); + err_code = -1; + break; + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + perror("recv fail"); + err_code = -2; + break; + } + } else if (0 == ret) { + err_code = QCLOUD_ERR_MQTT_NOTHING_TO_READ; + break; + } else { + perror("select-recv fail"); + err_code = -2; + break; + } + } while ((len_recv < len)); + + *read_len = (size_t)len_recv; + + return (0 != len_recv) ? 0 : err_code; +} diff --git a/platform/os/rtthread/HAL_TLS_mbedtls_rtthread.c b/platform/os/rtthread/HAL_TLS_mbedtls_rtthread.c new file mode 100755 index 00000000..43a36e24 --- /dev/null +++ b/platform/os/rtthread/HAL_TLS_mbedtls_rtthread.c @@ -0,0 +1,407 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_import.h" + +#ifndef AUTH_WITH_NOTLS + +#include +#include +#include + +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/entropy.h" +#include "mbedtls/error.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "utils_param_check.h" +#include "utils_timer.h" + +#ifndef AUTH_MODE_CERT +static const int ciphersuites[] = {MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0}; +#endif + +/** + * @brief data structure for mbedtls SSL connection + */ +typedef struct { + mbedtls_net_context socket_fd; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config ssl_conf; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt ca_cert; + mbedtls_x509_crt client_cert; +#endif + mbedtls_pk_context private_key; +} TLSDataParams; + +/** + * @brief free memory/resources allocated by mbedtls + */ +static void _free_mebedtls(TLSDataParams *pParams) +{ + mbedtls_net_free(&(pParams->socket_fd)); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free(&(pParams->client_cert)); + mbedtls_x509_crt_free(&(pParams->ca_cert)); + mbedtls_pk_free(&(pParams->private_key)); +#endif + mbedtls_ssl_free(&(pParams->ssl)); + mbedtls_ssl_config_free(&(pParams->ssl_conf)); + mbedtls_ctr_drbg_free(&(pParams->ctr_drbg)); + mbedtls_entropy_free(&(pParams->entropy)); + + HAL_Free(pParams); +} + +/** + * @brief mbedtls SSL client init + * + * 1. call a series of mbedtls init functions + * 2. init and set seed for random functions + * 3. load CA file, cert files or PSK + * + * @param pDataParams mbedtls TLS parmaters + * @param pConnectParams device info for TLS connection + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +static int _mbedtls_client_init(TLSDataParams *pDataParams, TLSConnectParams *pConnectParams) +{ + int ret = QCLOUD_RET_SUCCESS; + mbedtls_net_init(&(pDataParams->socket_fd)); + mbedtls_ssl_init(&(pDataParams->ssl)); + mbedtls_ssl_config_init(&(pDataParams->ssl_conf)); + mbedtls_ctr_drbg_init(&(pDataParams->ctr_drbg)); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init(&(pDataParams->ca_cert)); + mbedtls_x509_crt_init(&(pDataParams->client_cert)); + mbedtls_pk_init(&(pDataParams->private_key)); +#endif + + mbedtls_entropy_init(&(pDataParams->entropy)); + // custom parameter is NULL for now + if ((ret = mbedtls_ctr_drbg_seed(&(pDataParams->ctr_drbg), mbedtls_entropy_func, &(pDataParams->entropy), NULL, + 0)) != 0) { + Log_e("mbedtls_ctr_drbg_seed failed returned 0x%04x", ret < 0 ? -ret : ret); + return QCLOUD_ERR_SSL_INIT; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if (pConnectParams->ca_crt != NULL) { + if ((ret = mbedtls_x509_crt_parse(&(pDataParams->ca_cert), (const unsigned char *)pConnectParams->ca_crt, + (pConnectParams->ca_crt_len + 1)))) { + Log_e("parse ca crt failed returned 0x%04x", ret < 0 ? -ret : ret); + return QCLOUD_ERR_SSL_CERT; + } + } +#endif + +#ifdef AUTH_MODE_CERT + if (pConnectParams->cert_file != NULL && pConnectParams->key_file != NULL) { + if ((ret = mbedtls_x509_crt_parse_file(&(pDataParams->client_cert), pConnectParams->cert_file)) != 0) { + Log_e("load client cert file failed returned 0x%x", ret < 0 ? -ret : ret); + return QCLOUD_ERR_SSL_CERT; + } + + if ((ret = mbedtls_pk_parse_keyfile(&(pDataParams->private_key), pConnectParams->key_file, "")) != 0) { + Log_e("load client key file failed returned 0x%x", ret < 0 ? -ret : ret); + return QCLOUD_ERR_SSL_CERT; + } + } else { + Log_d("cert_file/key_file is empty!|cert_file=%s|key_file=%s", + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->cert_file), + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->key_file)); + } +#else + if (pConnectParams->psk != NULL && pConnectParams->psk_id != NULL) { + const char *psk_id = pConnectParams->psk_id; + ret = mbedtls_ssl_conf_psk(&(pDataParams->ssl_conf), (unsigned char *)pConnectParams->psk, + pConnectParams->psk_length, (const unsigned char *)psk_id, strlen(psk_id)); + } else { + Log_d("psk/pskid is empty!|psk=%s|psd_id=%s", STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->psk), + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->psk_id)); + } + + if (0 != ret) { + Log_e("mbedtls_ssl_conf_psk fail: 0x%x", ret < 0 ? -ret : ret); + return ret; + } +#endif + + return QCLOUD_RET_SUCCESS; +} + +/** + * @brief Setup TCP connection + * + * @param socket_fd socket handle + * @param host server address + * @param port server port + * @return QCLOUD_RET_SUCCESS when success, or err code for failure + */ +int _mbedtls_tcp_connect(mbedtls_net_context *socket_fd, const char *host, int port) +{ + int ret = 0; + char port_str[6]; + HAL_Snprintf(port_str, 6, "%d", port); + if ((ret = mbedtls_net_connect(socket_fd, host, port_str, MBEDTLS_NET_PROTO_TCP)) != 0) { + Log_e("tcp connect failed returned 0x%04x errno: %d", ret < 0 ? -ret : ret, errno); + + switch (ret) { + case MBEDTLS_ERR_NET_SOCKET_FAILED: + return QCLOUD_ERR_TCP_SOCKET_FAILED; + case MBEDTLS_ERR_NET_UNKNOWN_HOST: + return QCLOUD_ERR_TCP_UNKNOWN_HOST; + default: + return QCLOUD_ERR_TCP_CONNECT; + } + } +#if 0 + if ((ret = mbedtls_net_set_block(socket_fd)) != 0) { + Log_e("set block faliled returned 0x%04x", ret < 0 ? -ret : ret); + return QCLOUD_ERR_TCP_CONNECT; + } +#endif + return QCLOUD_RET_SUCCESS; +} + +/** + * @brief verify server certificate + * + * mbedtls has provided similar function mbedtls_x509_crt_verify_with_profile + * + * @return + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +int _qcloud_server_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags) +{ + return *flags; +} +#endif + +uintptr_t HAL_TLS_Connect(TLSConnectParams *pConnectParams, const char *host, int port) +{ + int ret = 0; + + TLSDataParams *pDataParams = (TLSDataParams *)HAL_Malloc(sizeof(TLSDataParams)); + + if ((ret = _mbedtls_client_init(pDataParams, pConnectParams)) != QCLOUD_RET_SUCCESS) { + goto error; + } + + Log_d("Setting up the SSL/TLS structure..."); + if ((ret = mbedtls_ssl_config_defaults(&(pDataParams->ssl_conf), MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + Log_e("mbedtls_ssl_config_defaults failed returned 0x%04x", ret < 0 ? -ret : ret); + goto error; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + + mbedtls_ssl_conf_verify(&(pDataParams->ssl_conf), _qcloud_server_certificate_verify, (void *)host); + + mbedtls_ssl_conf_authmode(&(pDataParams->ssl_conf), MBEDTLS_SSL_VERIFY_REQUIRED); +#endif + mbedtls_ssl_conf_rng(&(pDataParams->ssl_conf), mbedtls_ctr_drbg_random, &(pDataParams->ctr_drbg)); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_conf_ca_chain(&(pDataParams->ssl_conf), &(pDataParams->ca_cert), NULL); + if ((ret = mbedtls_ssl_conf_own_cert(&(pDataParams->ssl_conf), &(pDataParams->client_cert), + &(pDataParams->private_key))) != 0) { + Log_e("mbedtls_ssl_conf_own_cert failed returned 0x%04x", ret < 0 ? -ret : ret); + goto error; + } +#endif + + mbedtls_ssl_conf_read_timeout(&(pDataParams->ssl_conf), pConnectParams->timeout_ms); + if ((ret = mbedtls_ssl_setup(&(pDataParams->ssl), &(pDataParams->ssl_conf))) != 0) { + Log_e("mbedtls_ssl_setup failed returned 0x%04x", ret < 0 ? -ret : ret); + goto error; + } + +#ifndef AUTH_MODE_CERT + // ciphersuites selection for PSK device + if (pConnectParams->psk != NULL) { + mbedtls_ssl_conf_ciphersuites(&(pDataParams->ssl_conf), ciphersuites); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + + // Set the hostname to check against the received server certificate and sni + if ((ret = mbedtls_ssl_set_hostname(&(pDataParams->ssl), host)) != 0) { + Log_e("mbedtls_ssl_set_hostname failed returned 0x%04x", ret < 0 ? -ret : ret); + goto error; + } + +#endif + + mbedtls_ssl_set_bio(&(pDataParams->ssl), &(pDataParams->socket_fd), mbedtls_net_send, mbedtls_net_recv, + mbedtls_net_recv_timeout); + + Log_d("Performing the SSL/TLS handshake..."); + Log_d("Connecting to /%s/%d...", STRING_PTR_PRINT_SANITY_CHECK(host), port); + if ((ret = _mbedtls_tcp_connect(&(pDataParams->socket_fd), host, port)) != QCLOUD_RET_SUCCESS) { + goto error; + } + + while ((ret = mbedtls_ssl_handshake(&(pDataParams->ssl))) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + Log_e("mbedtls_ssl_handshake failed returned 0x%04x", -ret); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { + Log_e("Unable to verify the server's certificate"); + } +#endif + goto error; + } + } + + if ((ret = mbedtls_ssl_get_verify_result(&(pDataParams->ssl))) != 0) { + Log_e("mbedtls_ssl_get_verify_result failed returned 0x%04x", ret < 0 ? -ret : ret); + goto error; + } + + mbedtls_ssl_conf_read_timeout(&(pDataParams->ssl_conf), 100); + + Log_i("connected with /%s/%d...", STRING_PTR_PRINT_SANITY_CHECK(host), port); + + return (uintptr_t)pDataParams; + +error: + _free_mebedtls(pDataParams); + return 0; +} + +void HAL_TLS_Disconnect(uintptr_t handle) +{ + if ((uintptr_t)NULL == handle) { + Log_d("handle is NULL"); + return; + } + TLSDataParams *pParams = (TLSDataParams *)handle; + int ret = 0; + do { + ret = mbedtls_ssl_close_notify(&(pParams->ssl)); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + mbedtls_net_free(&(pParams->socket_fd)); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free(&(pParams->client_cert)); + mbedtls_x509_crt_free(&(pParams->ca_cert)); +#endif + mbedtls_pk_free(&(pParams->private_key)); + mbedtls_ssl_free(&(pParams->ssl)); + mbedtls_ssl_config_free(&(pParams->ssl_conf)); + mbedtls_ctr_drbg_free(&(pParams->ctr_drbg)); + mbedtls_entropy_free(&(pParams->entropy)); + + HAL_Free((void *)handle); +} + +int HAL_TLS_Write(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_t timeout_ms, size_t *written_len) +{ + Timer timer; + InitTimer(&timer); + countdown_ms(&timer, (unsigned int)timeout_ms); + size_t written_so_far; + bool errorFlag = false; + int write_rc = 0; + + TLSDataParams *pParams = (TLSDataParams *)handle; + + for (written_so_far = 0; written_so_far < totalLen && !expired(&timer); written_so_far += write_rc) { + while (!expired(&timer) && + (write_rc = mbedtls_ssl_write(&(pParams->ssl), msg + written_so_far, totalLen - written_so_far)) <= 0) { + if (write_rc != MBEDTLS_ERR_SSL_WANT_READ && write_rc != MBEDTLS_ERR_SSL_WANT_WRITE) { + Log_e("HAL_TLS_write failed 0x%04x", write_rc < 0 ? -write_rc : write_rc); + errorFlag = true; + break; + } + } + + if (errorFlag) { + break; + } + } + + *written_len = written_so_far; + + if (errorFlag) { + return QCLOUD_ERR_SSL_WRITE; + } else if (expired(&timer) && written_so_far != totalLen) { + return QCLOUD_ERR_SSL_WRITE_TIMEOUT; + } + + return QCLOUD_RET_SUCCESS; +} + +int HAL_TLS_Read(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_t timeout_ms, size_t *read_len) +{ + // mbedtls_ssl_conf_read_timeout(&(pParams->ssl_conf), timeout_ms); TODO:this cause read blocking and no return even + // timeout + // use non-blocking read + Timer timer; + InitTimer(&timer); + countdown_ms(&timer, (unsigned int)timeout_ms); + *read_len = 0; + + TLSDataParams *pParams = (TLSDataParams *)handle; + + do { + int read_rc = 0; + read_rc = mbedtls_ssl_read(&(pParams->ssl), msg + *read_len, totalLen - *read_len); + + if (read_rc > 0) { + *read_len += read_rc; + } else if (read_rc == 0 || (read_rc != MBEDTLS_ERR_SSL_WANT_WRITE && read_rc != MBEDTLS_ERR_SSL_WANT_READ && + read_rc != MBEDTLS_ERR_SSL_TIMEOUT)) { + Log_e("cloud_iot_network_tls_read failed: 0x%04x", read_rc < 0 ? -read_rc : read_rc); + return QCLOUD_ERR_SSL_READ; + } + + if (expired(&timer)) { + break; + } + + } while (*read_len < totalLen); + + if (totalLen == *read_len) { + return QCLOUD_RET_SUCCESS; + } + + if (*read_len == 0) { + return QCLOUD_ERR_SSL_NOTHING_TO_READ; + } else { + return QCLOUD_ERR_SSL_READ_TIMEOUT; + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/os/rtthread/HAL_Timer_rtthread.c b/platform/os/rtthread/HAL_Timer_rtthread.c new file mode 100755 index 00000000..2aa527f3 --- /dev/null +++ b/platform/os/rtthread/HAL_Timer_rtthread.c @@ -0,0 +1,114 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "qcloud_iot_import.h" +#include "utils_timer.h" + +static char now_time_str[20] = {0}; + +int HAL_Timer_set_systime_sec(size_t timestamp_sec) +{ +#ifndef PLATFORM_HAS_TIME_FUNCS + RTC_DATE_TIME date_time; + date_time.ms = 0; + timestamp_to_date(timestamp_sec, &date_time, 8); + // set RTC Time note hw rtc year base + return -1; +#endif +} + +int HAL_Timer_set_systime_ms(size_t timestamp_ms) +{ +#ifndef PLATFORM_HAS_TIME_FUNCS + RTC_DATE_TIME date_time; + date_time.ms = timestamp_ms % 1000; + timestamp_to_date(timestamp_ms / 1000, &date_time, 8); + // set RTC Time note hw rtc year base + return -1; +#endif +} + +uint32_t HAL_GetTimeMs(void) +{ +#if (RT_TICK_PER_SECOND == 1000) + /* #define RT_TICK_PER_SECOND 1000 */ + return (unsigned long)rt_tick_get(); +#else + unsigned long tick = 0; + + tick = rt_tick_get(); + tick = tick * 1000; + return (unsigned long)((tick + RT_TICK_PER_SECOND - 1) / RT_TICK_PER_SECOND); +#endif +} + +/*Get timestamp*/ +long HAL_Timer_current_sec(void) +{ + return HAL_GetTimeMs() / 1000; +} + +char *HAL_Timer_current(void) +{ + long time_sec; + + time_sec = HAL_Timer_current_sec(); + memset(now_time_str, 0, 20); + snprintf(now_time_str, 20, "%ld", time_sec); + + return now_time_str; +} + +bool HAL_Timer_expired(Timer *timer) +{ + uint32_t now_ts; + + now_ts = HAL_GetTimeMs(); + + return (now_ts > timer->end_time) ? true : false; +} + +void HAL_Timer_countdown_ms(Timer *timer, unsigned int timeout_ms) +{ + timer->end_time = HAL_GetTimeMs(); + timer->end_time += timeout_ms; +} + +void HAL_Timer_countdown(Timer *timer, unsigned int timeout) +{ + timer->end_time = HAL_GetTimeMs(); + timer->end_time += timeout * 1000; +} + +int HAL_Timer_remain(Timer *timer) +{ + return (int)(timer->end_time - HAL_GetTimeMs()); +} + +void HAL_Timer_init(Timer *timer) +{ + timer->end_time = 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/platform/os/rtthread/tc_tls_config.h b/platform/os/rtthread/tc_tls_config.h new file mode 100755 index 00000000..74ada841 --- /dev/null +++ b/platform/os/rtthread/tc_tls_config.h @@ -0,0 +1,2749 @@ +/** + * \file tls_config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* the memory allocation method configurations */ +#include + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/mbedtls/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h and time(), gmtime() and the clock is correct. + * The time needs to be correct (not necesarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + */ +// #define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_XTEA_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_deinit( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_deinit are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + */ +//#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#if 0 +#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 +#endif + +/** + * \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 + +#ifdef AUTH_MODE_CERT +/** + * \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_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 + +#endif + +/** + * \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_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. + */ + +#ifdef PKG_USING_MBEDTLS_DEBUG +#define MBEDTLS_DEBUG_C +#endif + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +//#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +//#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +//#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +//#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +//#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +//#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +//#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +//#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +#ifdef AUTH_MODE_CERT + +/** + * \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 + +#endif + +/** + * \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 + +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the +//null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generte SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * for compatibility with existing peers. + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations */ +//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h" + +#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE) +#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE +#endif + +/* + * Allow user to override any previous default. + * + * Use two macro names for that, as: + * - with yotta the prefix YOTTA_CFG_ is forced + * - without yotta is looks weird to have a YOTTA prefix. + */ +#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) +#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE +#elif defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "mbedtls/check_config.h" + +#define tls_malloc rt_malloc +#define tls_free rt_free +#define tls_realloc rt_realloc +#define tls_calloc rt_calloc +#define tls_strdup rt_strdup + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/platform/os/windows/HAL_AT_UART_win.c b/platform/os/windows/HAL_AT_UART_win.c new file mode 100755 index 00000000..391308c4 --- /dev/null +++ b/platform/os/windows/HAL_AT_UART_win.c @@ -0,0 +1,55 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifdef AT_TCP_ENABLED + +#include +#include +#include +#include + +#include "at_client.h" +#include "utils_ringbuff.h" + +/** + * @brief This function handles AT UART global interrupt,push recv char to ringbuff. + */ +void HAL_AT_UART_IRQHandler(void) {} + +/** + *pdata: pointer of data for send + *len: len of data to be sent + *return: the len of data send success + * @brief hal api for at data send + */ +int HAL_AT_Uart_Send(void *data, uint32_t size) +{ + return 0; +} + +int HAL_AT_Uart_Init(void) +{ + return QCLOUD_RET_SUCCESS; +} + +int HAL_AT_Uart_Deinit(void) +{ + return QCLOUD_RET_SUCCESS; +} + +#endif diff --git a/platform/os/windows/HAL_Device_win.c b/platform/os/windows/HAL_Device_win.c new file mode 100644 index 00000000..e75f4eec --- /dev/null +++ b/platform/os/windows/HAL_Device_win.c @@ -0,0 +1,482 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/* Enable this macro (also control by cmake) to use static string buffer to store device info */ +/* To use specific storing methods like files/flash, disable this macro and implement dedicated methods */ +//#define DEBUG_DEV_INFO_USED + +#ifdef DEBUG_DEV_INFO_USED +/* product Id */ +static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; + +/* device name */ +static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_DEV_NAME"; + +#ifdef DEV_DYN_REG_ENABLED +/* product secret for device dynamic Registration */ +static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "YOUR_PRODUCT_SECRET"; +#endif + +#ifdef AUTH_MODE_CERT +/* public cert file name of certificate device */ +static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "YOUR_DEVICE_NAME_cert.crt"; +/* private key file name of certificate device */ +static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key"; +#else +/* device secret of PSK device */ +static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "YOUR_IOT_PSK"; +#endif + +#ifdef GATEWAY_ENABLED +/* sub-device product id */ +static char sg_sub_device_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID"; +/* sub-device device name */ +static char sg_sub_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_SUB_DEV_NAME"; +#endif + +static int device_info_copy(void *pdst, void *psrc, uint8_t max_len) +{ + if (strlen(psrc) > max_len) { + return QCLOUD_ERR_FAILURE; + } + memset(pdst, '\0', max_len); + strncpy(pdst, psrc, max_len); + return QCLOUD_RET_SUCCESS; +} + +int HAL_SetDevInfoFile(const char *file_name) +{ + Log_w("device info is not stored in file!!"); + + return QCLOUD_RET_SUCCESS; +} + +#else +/*device info manage example method*/ + +#include "lite-utils.h" + +#define MAX_DEV_INFO_FILE_LEN 1024 +#define MAX_CONFIG_FILE_NAME 256 + +#define KEY_AUTH_MODE "auth_mode" +#define KEY_PRODUCT_ID "productId" +#define KEY_PRODUCT_SECRET "productSecret" +#define KEY_DEV_NAME "deviceName" +#define KEY_DEV_SECRET "key_deviceinfo.deviceSecret" +#define KEY_DEV_CERT "cert_deviceinfo.devCertFile" +#define KEY_DEV_PRIVATE_KEY "cert_deviceinfo.devPrivateKeyFile" +#define KEY_SUBDEV_PRODUCT_ID "subDev.sub_productId" +#define KEY_SUBDEV_NAME "subDev.sub_devName" + +#define STR_DEV_INFO "key_deviceinfo" +#define STR_DEV_SECRET "deviceSecret" +#define STR_DEV_CERT "cert_deviceinfo" +#define STR_DEV_CERT_FILE "devCertFile" +#define STR_DEV_KEY_FILE "devPrivateKeyFile" + +#define MAX_SIZE_OF_DEVICE_INFO_FILE 128 +static char sg_device_info_file[MAX_SIZE_OF_DEVICE_INFO_FILE + 1] = {".\\device_info.json"}; + +int HAL_SetDevInfoFile(const char *file_name) +{ + if (file_name == NULL || strlen(file_name) > MAX_SIZE_OF_DEVICE_INFO_FILE) { + Log_e("illegal device info file name!"); + return QCLOUD_ERR_INVAL; + } + + /* check if file exists */ + if (access(file_name, 0)) { + Log_e("device info file \"%s\" not existed", file_name); + return QCLOUD_ERR_FAILURE; + } + + memset(sg_device_info_file, 0, sizeof(sg_device_info_file)); + strncpy(sg_device_info_file, file_name, MAX_SIZE_OF_DEVICE_INFO_FILE); + return QCLOUD_RET_SUCCESS; +} + +int HAL_GetDevInfoFromFile(const char *file_name, void *dev_info) +{ + FILE * fp; + uint32_t len; + uint32_t rlen; + int ret = QCLOUD_RET_SUCCESS; + char * authMode = NULL; + char * productId = NULL; + char * devName = NULL; +#ifdef DEV_DYN_REG_ENABLED + char * productSecret = NULL; +#endif +#ifdef AUTH_MODE_CERT + char * devCrtFileName = NULL; + char * devKeyFileName = NULL; +#else + char *devSecret = NULL; +#endif + char * JsonDoc = NULL; + + DeviceInfo *pDevInfo = (DeviceInfo *)dev_info; + + fp = fopen(file_name, "rb"); + if (NULL == fp) { + Log_e("open device info file \"%s\" failed", STRING_PTR_PRINT_SANITY_CHECK(file_name)); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + if (len > MAX_DEV_INFO_FILE_LEN) { + Log_e("device info file \"%s\" is too big!", file_name); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + JsonDoc = (char *)HAL_Malloc(len + 10); + if (NULL == JsonDoc) { + Log_e("malloc buffer for json file read fail"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + memset(JsonDoc, 0, len + 10); + + rewind(fp); + rlen = fread(JsonDoc, 1, len, fp); + + if (len != rlen) { + Log_e("read data len (%d) less than needed (%d), %s", rlen, len, JsonDoc); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + /*Get device info*/ + authMode = LITE_json_value_of(KEY_AUTH_MODE, JsonDoc); + productId = LITE_json_value_of(KEY_PRODUCT_ID, JsonDoc); + devName = LITE_json_value_of(KEY_DEV_NAME, JsonDoc); + + if (NULL == authMode || NULL == productId || NULL == devName) { + Log_e("read device data from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + strncpy(pDevInfo->product_id, productId, MAX_SIZE_OF_PRODUCT_ID); + strncpy(pDevInfo->device_name, devName, MAX_SIZE_OF_DEVICE_NAME); + +#ifdef DEV_DYN_REG_ENABLED + productSecret = LITE_json_value_of(KEY_PRODUCT_SECRET, JsonDoc); + if (NULL == productSecret) { + Log_e("read product secret from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + strncpy(pDevInfo->product_secret, productSecret, MAX_SIZE_OF_PRODUCT_SECRET); +#endif + +#ifdef AUTH_MODE_CERT + devCrtFileName = LITE_json_value_of(KEY_DEV_CERT, JsonDoc); + devKeyFileName = LITE_json_value_of(KEY_DEV_PRIVATE_KEY, JsonDoc); + if (NULL == devCrtFileName || NULL == devKeyFileName) { + Log_e("read cert file name from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + strncpy(pDevInfo->dev_cert_file_name, devCrtFileName, MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); + strncpy(pDevInfo->dev_key_file_name, devKeyFileName, MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); + // Log_d("mode:%s, pid:%s, devName:%s, devCrtFileName:%s, devKeyFileName:%s", authMode, productId, devName, + // devCrtFileName, devKeyFileName); +#else + devSecret = LITE_json_value_of(KEY_DEV_SECRET, JsonDoc); + if (NULL == devSecret) { + Log_e("read device secret from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + strncpy(pDevInfo->device_secret, devSecret, MAX_SIZE_OF_DEVICE_SECRET); + // Log_d("mode:%s, pid:%s, devName:%s, devSerect:%s", authMode, productId, devName, devSecret); +#endif + +exit: + HAL_Free(authMode); + HAL_Free(productId); + HAL_Free(devName); +#ifdef DEV_DYN_REG_ENABLED + HAL_Free(productSecret); +#endif +#ifdef AUTH_MODE_CERT + HAL_Free(devCrtFileName); + HAL_Free(devKeyFileName); +#else + HAL_Free(devSecret); +#endif + HAL_Free(JsonDoc); + + if (NULL != fp) { + fclose(fp); + } + + return ret; +} + +#ifdef GATEWAY_ENABLED +static int iot_parse_subdevinfo_from_json_file(DeviceInfo *pDevInfo) +{ + FILE * fp; + uint32_t len; + uint32_t rlen; + int ret = QCLOUD_RET_SUCCESS; + char * productId = NULL; + char * devName = NULL; + char * JsonDoc = NULL; + + fp = fopen(sg_device_info_file, "r"); + if (NULL == fp) { + Log_e("open device info file \"%s\" failed", sg_device_info_file); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + if (len > MAX_DEV_INFO_FILE_LEN) { + Log_e("device info file \"%s\" is too big!", sg_device_info_file); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + JsonDoc = (char *)HAL_Malloc(len + 10); + if (NULL == JsonDoc) { + Log_e("malloc buffer for json file read fail"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + rewind(fp); + rlen = fread(JsonDoc, 1, len, fp); + + if (len != rlen) { + Log_e("read data len (%d) less than needed (%d), %s", rlen, len, JsonDoc); + } + + /*Get sub device info*/ + productId = LITE_json_value_of(KEY_SUBDEV_PRODUCT_ID, JsonDoc); + devName = LITE_json_value_of(KEY_SUBDEV_NAME, JsonDoc); + + if (NULL == productId || NULL == devName) { + Log_e("read sub device data from json file failed!"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + strncpy(pDevInfo->product_id, productId, MAX_SIZE_OF_PRODUCT_ID); + strncpy(pDevInfo->device_name, devName, MAX_SIZE_OF_DEVICE_NAME); + // Log_d("pid:%s, devName:%s", productId, devName); + +exit: + HAL_Free(productId); + HAL_Free(devName); + HAL_Free(JsonDoc); + + if (NULL != fp) { + fclose(fp); + } + + return ret; +} +#endif + +static int iot_save_devinfo_to_json_file(DeviceInfo *pDevInfo) +{ + char JsonDoc[MAX_DEV_INFO_FILE_LEN] = {0}; + int32_t remain_size = MAX_DEV_INFO_FILE_LEN; + int32_t rc_of_snprintf = 0; + int32_t wlen; + FILE * fp; + + rc_of_snprintf = HAL_Snprintf(JsonDoc, remain_size, "{\n"); + remain_size -= rc_of_snprintf; + + // auth_mode +#ifdef AUTH_MODE_CERT + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n", KEY_AUTH_MODE, "CERT"); + remain_size -= rc_of_snprintf; +#else + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n", KEY_AUTH_MODE, "KEY"); + remain_size -= rc_of_snprintf; +#endif + + // product id, device name + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n\"%s\":\"%s\",\n", + KEY_PRODUCT_ID, STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->product_id), KEY_DEV_NAME, + STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->device_name)); + remain_size -= rc_of_snprintf; + + // product secret +#ifdef DEV_DYN_REG_ENABLED + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n", KEY_PRODUCT_SECRET, + STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->product_secret)); + remain_size -= rc_of_snprintf; +#endif + + // key device info or cert device info +#ifdef AUTH_MODE_CERT + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":{\n", STR_DEV_CERT); + remain_size -= rc_of_snprintf; + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\",\n\"%s\":\"%s\"\n}", + STR_DEV_CERT_FILE, STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->dev_cert_file_name), + STR_DEV_KEY_FILE, STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->dev_key_file_name)); + remain_size -= rc_of_snprintf; +#else + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":{\n", STR_DEV_INFO); + remain_size -= rc_of_snprintf; + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\"%s\":\"%s\"\n}", STR_DEV_SECRET, + STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->device_secret)); + remain_size -= rc_of_snprintf; +#endif + + rc_of_snprintf = HAL_Snprintf(JsonDoc + strlen(JsonDoc), remain_size, "\n}"); + remain_size -= rc_of_snprintf; + + Log_d("JsonDoc(%d):%s", MAX_DEV_INFO_FILE_LEN - remain_size, JsonDoc); + + fp = fopen(sg_device_info_file, "w"); + if (NULL == fp) { + Log_e("open file %s failed", sg_device_info_file); + return QCLOUD_ERR_FAILURE; + } + + wlen = fwrite(JsonDoc, 1, strlen(JsonDoc), fp); + if (wlen < (MAX_DEV_INFO_FILE_LEN - remain_size)) { + Log_e("write len less than needed"); + } + fclose(fp); + return QCLOUD_RET_SUCCESS; +} +#endif + +int HAL_SetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(sg_product_id, devInfo->product_id, MAX_SIZE_OF_PRODUCT_ID); // set product ID + ret |= device_info_copy(sg_device_name, devInfo->device_name, MAX_SIZE_OF_DEVICE_NAME); // set dev name + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(sg_device_cert_file_name, devInfo->dev_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // set dev cert file name + ret |= device_info_copy(sg_device_privatekey_file_name, devInfo->dev_key_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // set dev key file name +#else + ret |= device_info_copy(sg_device_secret, devInfo->device_secret, MAX_SIZE_OF_DEVICE_SECRET); // set dev secret +#endif + +#else + ret = iot_save_devinfo_to_json_file(devInfo); +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Set device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +int HAL_GetDevInfo(void *pdevInfo) +{ + POINTER_SANITY_CHECK(pdevInfo, QCLOUD_ERR_DEV_INFO); + int ret; + DeviceInfo *devInfo = (DeviceInfo *)pdevInfo; + memset((char *)devInfo, '\0', sizeof(DeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = device_info_copy(devInfo->product_id, sg_product_id, MAX_SIZE_OF_PRODUCT_ID); // get product ID + ret |= device_info_copy(devInfo->device_name, sg_device_name, MAX_SIZE_OF_DEVICE_NAME); // get dev name + +#ifdef DEV_DYN_REG_ENABLED + ret |= device_info_copy(devInfo->product_secret, sg_product_secret, MAX_SIZE_OF_PRODUCT_SECRET); // get product ID +#endif + +#ifdef AUTH_MODE_CERT + ret |= device_info_copy(devInfo->dev_cert_file_name, sg_device_cert_file_name, + MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // get dev cert file name + ret |= device_info_copy(devInfo->dev_key_file_name, sg_device_privatekey_file_name, + MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // get dev key file name +#else + ret |= device_info_copy(devInfo->device_secret, sg_device_secret, MAX_SIZE_OF_DEVICE_SECRET); // get dev secret +#endif + +#else + // get devinfo from file + ret = HAL_GetDevInfoFromFile(sg_device_info_file, devInfo); +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} + +#ifdef GATEWAY_ENABLED +int HAL_GetGwDevInfo(void *pgwDeviceInfo) +{ + POINTER_SANITY_CHECK(pgwDeviceInfo, QCLOUD_ERR_DEV_INFO); + int ret; + GatewayDeviceInfo *gwDevInfo = (GatewayDeviceInfo *)pgwDeviceInfo; + memset((char *)gwDevInfo, 0, sizeof(GatewayDeviceInfo)); + +#ifdef DEBUG_DEV_INFO_USED + ret = HAL_GetDevInfo(&(gwDevInfo->gw_info)); // get gw dev info + // only one sub-device is supported now + gwDevInfo->sub_dev_num = 1; + gwDevInfo->sub_dev_info = (DeviceInfo *)HAL_Malloc(sizeof(DeviceInfo) * (gwDevInfo->sub_dev_num)); + memset((char *)gwDevInfo->sub_dev_info, '\0', sizeof(DeviceInfo)); + // copy sub dev info + ret = device_info_copy(gwDevInfo->sub_dev_info->product_id, sg_sub_device_product_id, MAX_SIZE_OF_PRODUCT_ID); + ret |= device_info_copy(gwDevInfo->sub_dev_info->device_name, sg_sub_device_name, MAX_SIZE_OF_DEVICE_NAME); + +#else + ret = HAL_GetDevInfoFromFile(sg_device_info_file, &(gwDevInfo->gw_info)); + if (ret != QCLOUD_RET_SUCCESS) { + return QCLOUD_ERR_FAILURE; + } + // only one sub-device is supported now + gwDevInfo->sub_dev_num = 1; + gwDevInfo->sub_dev_info = (DeviceInfo *)HAL_Malloc(sizeof(DeviceInfo) * (gwDevInfo->sub_dev_num)); + memset((char *)gwDevInfo->sub_dev_info, '\0', sizeof(DeviceInfo)); + // copy sub dev info + ret = iot_parse_subdevinfo_from_json_file(gwDevInfo->sub_dev_info); +#endif + + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Get gateway device info err"); + ret = QCLOUD_ERR_DEV_INFO; + } + return ret; +} +#endif diff --git a/platform/os/windows/HAL_Log_win.c b/platform/os/windows/HAL_Log_win.c new file mode 100755 index 00000000..cd3624fb --- /dev/null +++ b/platform/os/windows/HAL_Log_win.c @@ -0,0 +1,91 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +#ifdef LOG_UPLOAD + +#define LOG_SAVE_FILE_PATH "upload-fail-save.log" + +size_t HAL_Log_Save(const char *log, size_t wLen) +{ + FILE * fp; + size_t len; + + if ((fp = fopen(LOG_SAVE_FILE_PATH, "a+")) == NULL) { + Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); + return 0; + } + + len = fwrite((void *)log, 1, wLen, fp); + Log_d("write %d of %d to log file", len, wLen); + + fclose(fp); + + return len; +} + +size_t HAL_Log_Read(char *buff, size_t rLen) +{ + FILE * fp; + size_t len; + + if ((fp = fopen(LOG_SAVE_FILE_PATH, "r")) == NULL) { + Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); + return 0; + } + + len = fread((void *)buff, 1, rLen, fp); + Log_d("read %d of %d from log file", len, rLen); + + fclose(fp); + + return len; +} + +int HAL_Log_Del(void) +{ + return remove(LOG_SAVE_FILE_PATH); +} + +size_t HAL_Log_Get_Size(void) +{ + long length; + FILE *fp; + + /* check if file exists */ + if (access(LOG_SAVE_FILE_PATH, 0)) + return 0; + + if ((fp = fopen(LOG_SAVE_FILE_PATH, "r")) == NULL) { + Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); + return 0; + } + + fseek(fp, 0L, SEEK_END); + length = ftell(fp); + fclose(fp); + if (length > 0) + return (size_t)length; + else + return 0; +} + +#endif diff --git a/platform/os/windows/HAL_OS_win.c b/platform/os/windows/HAL_OS_win.c new file mode 100755 index 00000000..8385229d --- /dev/null +++ b/platform/os/windows/HAL_OS_win.c @@ -0,0 +1,175 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_import.h" + +void *HAL_MutexCreate(void) +{ +#ifdef MULTITHREAD_ENABLED + HANDLE mutex = CreateMutex(NULL, FALSE, NULL); + + if (mutex == NULL) { + HAL_Printf("%s: create mutex failed\n", __FUNCTION__); + } + + return (void *)mutex; +#else + return (void *)0xFFFFFFFF; +#endif +} + +void HAL_MutexDestroy(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + CloseHandle((HANDLE)mutex); +#else + return; +#endif +} + +void HAL_MutexLock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + WaitForSingleObject((HANDLE)mutex, INFINITE); +#else + return; +#endif +} + +int HAL_MutexTryLock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + return WaitForSingleObject((HANDLE)mutex, 0) == WAIT_OBJECT_0 ? 0 : -1; +#else + return 0; +#endif +} + +void HAL_MutexUnlock(_IN_ void *mutex) +{ +#ifdef MULTITHREAD_ENABLED + ReleaseMutex((HANDLE)mutex); +#else + return; +#endif +} + +void *HAL_Malloc(_IN_ uint32_t size) +{ + return malloc(size); +} + +void HAL_Free(_IN_ void *ptr) +{ + if (ptr) + free(ptr); +} + +void HAL_Printf(_IN_ const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + fflush(stdout); +} + +int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...) +{ + va_list args; + int rc; + + va_start(args, fmt); + rc = vsnprintf(str, len, fmt, args); + va_end(args); + + return rc; +} + +int HAL_Vsnprintf(_IN_ char *str, _IN_ const int len, _IN_ const char *format, va_list ap) +{ + return vsnprintf(str, len, format, ap); +} + +uint32_t HAL_GetTimeMs(void) +{ + return (uint32_t)GetTickCount64(); +} + +void HAL_SleepMs(_IN_ uint32_t ms) +{ + Sleep(ms); +} + +#ifdef MULTITHREAD_ENABLED + +// platform-dependant thread routine/entry function +static void _HAL_thread_func_wrapper_(void *ptr) +{ + ThreadParams *params = (ThreadParams *)ptr; + + params->thread_func(params->user_arg); + + _endthread(); +} + +// platform-dependant thread create function +int HAL_ThreadCreate(ThreadParams *params) +{ + if (params == NULL) + return QCLOUD_ERR_INVAL; + + uintptr_t ret = _beginthread(_HAL_thread_func_wrapper_, params->stack_size, (void *)params); + if (ret == -1L) { + HAL_Printf("%s: _beginthread failed: %d\n", __FUNCTION__, errno); + return QCLOUD_ERR_FAILURE; + } + + return QCLOUD_RET_SUCCESS; +} + +#endif + +#ifdef AT_TCP_ENABLED + +void *HAL_SemaphoreCreate(void) +{ + return NULL; +} + +void HAL_SemaphoreDestroy(void *sem) +{ + return; +} + +void HAL_SemaphorePost(void *sem) +{ + return; +} + +int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms) +{ + return QCLOUD_RET_SUCCESS; +} + +#endif diff --git a/platform/os/windows/HAL_TCP_win.c b/platform/os/windows/HAL_TCP_win.c new file mode 100755 index 00000000..a5fd431d --- /dev/null +++ b/platform/os/windows/HAL_TCP_win.c @@ -0,0 +1,257 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include + +// DO NOT change the include order +#include +#include +#pragma comment(lib, "ws2_32.lib") +#include + +#include "qcloud_iot_common.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +static uint64_t _win_get_time_ms(void) +{ + return GetTickCount64(); +} + +static uint64_t _win_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 HAL_TCP_Connect(const char *host, uint16_t port) +{ + WORD sockVersion = MAKEWORD(2, 2); + WSADATA data; + + if (WSAStartup(sockVersion, &data) != 0) { + return 0; + } + int ret; + struct addrinfo hints, *addr_list, *cur; + SOCKET fd; + + char port_str[6]; + HAL_Snprintf(port_str, 6, "%d", port); + + memset(&hints, 0x00, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + ret = getaddrinfo(host, port_str, &hints, &addr_list); + if (ret) { + Log_e("getaddrinfo(%s:%s) error: %s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str, strerror(errno)); + + return 0; + } + + for (cur = addr_list; cur != NULL; cur = cur->ai_next) { + fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd == INVALID_SOCKET) { + ret = 0; + continue; + } + + if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) { + ret = fd; + break; + } + + closesocket(fd); + ret = 0; + } + + if (0 == ret) { + Log_e("fail to connect with TCP server: %s:%s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); + } else { + /* reduce log print due to frequent log server connect/disconnect */ + if (0 == strncmp(host, LOG_UPLOAD_SERVER_DOMAIN, HOST_STR_LENGTH)) + UPLOAD_DBG("connected with TCP server: %s:%s", host, port_str); + else + Log_i("connected with TCP server: %s:%s", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); + } + + freeaddrinfo(addr_list); + + return (uintptr_t)ret; +} + +int HAL_TCP_Disconnect(uintptr_t fd) +{ + closesocket(fd); + WSACleanup(); + + return 0; +} + +int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *written_len) +{ + int ret; + uint32_t len_sent; + uint64_t t_end, t_left; + fd_set sets; + + t_end = _win_get_time_ms() + timeout_ms; + len_sent = 0; + ret = 1; /* send one time if timeout_ms is value 0 */ + + do { + t_left = _win_time_left(t_end, _win_get_time_ms()); + + if (0 != t_left) { + struct timeval timeout; + + FD_ZERO(&sets); + FD_SET(fd, &sets); + + timeout.tv_sec = (long)t_left / 1000; + timeout.tv_usec = ((long)t_left % 1000) * 1000; + + ret = select(fd + 1, NULL, &sets, NULL, &timeout); + if (ret > 0) { + if (0 == FD_ISSET(fd, &sets)) { + Log_e("Should NOT arrive"); + /* If timeout in next loop, it will not sent any data */ + ret = 0; + continue; + } + } else if (0 == ret) { + ret = QCLOUD_ERR_TCP_WRITE_TIMEOUT; + Log_e("select-write timeout %d", (int)fd); + break; + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + + ret = QCLOUD_ERR_TCP_WRITE_FAIL; + Log_e("select-write fail: %s", strerror(errno)); + break; + } + } else { + ret = QCLOUD_ERR_TCP_WRITE_TIMEOUT; + } + + if (ret > 0) { + ret = send(fd, buf + len_sent, len - len_sent, 0); + if (ret > 0) { + len_sent += ret; + } else if (0 == ret) { + Log_e("No data be sent. Should NOT arrive"); + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + + ret = QCLOUD_ERR_TCP_WRITE_FAIL; + Log_e("send fail: %s", strerror(errno)); + break; + } + } + } while ((len_sent < len) && (_win_time_left(t_end, _win_get_time_ms()) > 0)); + + *written_len = (size_t)len_sent; + + return len_sent > 0 ? QCLOUD_RET_SUCCESS : ret; +} + +int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeout_ms, size_t *read_len) +{ + int ret, err_code; + uint32_t len_recv; + uint64_t t_end, t_left; + fd_set sets; + struct timeval timeout; + + t_end = _win_get_time_ms() + timeout_ms; + len_recv = 0; + err_code = 0; + + do { + t_left = _win_time_left(t_end, _win_get_time_ms()); + if (0 == t_left) { + err_code = QCLOUD_ERR_TCP_READ_TIMEOUT; + break; + } + + FD_ZERO(&sets); + FD_SET(fd, &sets); + + timeout.tv_sec = (long)(t_left / 1000); + timeout.tv_usec = (long)((t_left % 1000) * 1000); + + ret = select(fd + 1, &sets, NULL, NULL, &timeout); + if (ret > 0) { + ret = recv(fd, buf + len_recv, len - len_recv, 0); + if (ret > 0) { + len_recv += ret; + } else if (0 == ret) { + struct sockaddr_in peer; + int sLen = sizeof(peer); + int peer_port = 0; + getpeername(fd, (struct sockaddr *)&peer, &sLen); + peer_port = ntohs(peer.sin_port); + + /* reduce log print due to frequent log server connect/disconnect */ + if (peer_port == LOG_UPLOAD_SERVER_PORT) + UPLOAD_DBG("connection is closed by server: %s:%d", inet_ntoa(peer.sin_addr), peer_port); + else + Log_e("connection is closed by server: %s:%d", inet_ntoa(peer.sin_addr), peer_port); + + err_code = QCLOUD_ERR_TCP_PEER_SHUTDOWN; + break; + } else { + if (EINTR == errno) { + Log_e("EINTR be caught"); + continue; + } + Log_e("recv error: %s", strerror(errno)); + err_code = QCLOUD_ERR_TCP_READ_FAIL; + break; + } + } else if (0 == ret) { + err_code = QCLOUD_ERR_TCP_READ_TIMEOUT; + break; + } else { + Log_e("select-recv error: %s", strerror(errno)); + err_code = QCLOUD_ERR_TCP_READ_FAIL; + break; + } + } while ((len_recv < len)); + + *read_len = (size_t)len_recv; + + if (err_code == QCLOUD_ERR_TCP_READ_TIMEOUT && len_recv == 0) + err_code = QCLOUD_ERR_TCP_NOTHING_TO_READ; + + return (len == len_recv) ? QCLOUD_RET_SUCCESS : err_code; +} diff --git a/platform/os/windows/HAL_Timer_win.c b/platform/os/windows/HAL_Timer_win.c new file mode 100755 index 00000000..471e8558 --- /dev/null +++ b/platform/os/windows/HAL_Timer_win.c @@ -0,0 +1,132 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "qcloud_iot_import.h" + +int HAL_Timer_set_systime_sec(size_t timestamp_sec) +{ + int val = 0; + time_t now = (time_t)timestamp_sec; + struct tm tm_val; + SYSTEMTIME system_time = {0}; + localtime_s(&tm_val, &now); + system_time.wYear = tm_val.tm_year + 1900; + system_time.wMonth = tm_val.tm_mon + 1; + system_time.wDay = tm_val.tm_mday; + system_time.wHour = tm_val.tm_hour; + system_time.wMinute = tm_val.tm_min; + system_time.wSecond = tm_val.tm_sec; + system_time.wMilliseconds = 0; + + if (0 != SetLocalTime(&system_time)) { + val = 0; + } else { + val = -1; + } + + return val; +} + +int HAL_Timer_set_systime_ms(size_t timestamp_ms) +{ + int val = 0; + struct tm tm_val; + size_t milliseconds = timestamp_ms % 1000; + size_t timestamp_sec = timestamp_ms / 1000; + time_t now = (time_t)timestamp_sec; + localtime_s(&tm_val, &now); + SYSTEMTIME system_time = {0}; + + system_time.wYear = tm_val.tm_year + 1900; + system_time.wMonth = tm_val.tm_mon + 1; + system_time.wDay = tm_val.tm_mday; + system_time.wHour = tm_val.tm_hour; + system_time.wMinute = tm_val.tm_min; + system_time.wSecond = tm_val.tm_sec; + system_time.wMilliseconds = milliseconds; + + if (0 != SetLocalTime(&system_time)) { + val = 0; + } else { + val = -1; + } + + return val; +} + +bool HAL_Timer_expired(Timer *timer) +{ + if (GetTickCount64() >= timer->end_time) { + return true; + } + + return false; +} + +void HAL_Timer_countdown_ms(Timer *timer, unsigned int timeout_ms) +{ + timer->end_time = GetTickCount64() + timeout_ms; +} + +void HAL_Timer_countdown(Timer *timer, unsigned int timeout) +{ + timer->end_time = GetTickCount64() + (UINT64)timeout * 1000; +} + +int HAL_Timer_remain(Timer *timer) +{ + UINT64 now = GetTickCount64(); + + if (now >= timer->end_time) { + return 0; + } + + return (int)(timer->end_time - now); +} + +void HAL_Timer_init(Timer *timer) +{ + timer->end_time = 0; +} + +char *HAL_Timer_current(char *time_str) +{ + time_t now; + struct tm tm_val; + + time(&now); + localtime_s(&tm_val, &now); + + snprintf(time_str, TIME_FORMAT_STR_LEN, "%04d/%02d/%02d %02d:%02d:%02d", tm_val.tm_year + 1900, tm_val.tm_mon + 1, + tm_val.tm_mday, tm_val.tm_hour, tm_val.tm_min, tm_val.tm_sec); + + return time_str; +} + +long HAL_Timer_current_sec(void) +{ + return (long)(GetTickCount64() / 1000); +} + +#ifdef __cplusplus +} +#endif diff --git a/platform/os/windows/HAL_UDP_win.c b/platform/os/windows/HAL_UDP_win.c new file mode 100755 index 00000000..3ed4524f --- /dev/null +++ b/platform/os/windows/HAL_UDP_win.c @@ -0,0 +1,156 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +// DO NOT change the include order +#include +#include +#pragma comment(lib, "ws2_32.lib") +#include + +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +#ifdef COAP_COMM_ENABLED + +uintptr_t HAL_UDP_Connect(const char *host, unsigned short port) +{ +#define NETWORK_ADDR_LEN (16) + + int ret; + struct addrinfo hints, *addr_list, *cur; + int fd = 0; + + char port_str[6] = {0}; + HAL_Snprintf(port_str, 6, "%d", port); + + memset((char *)&hints, 0x00, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_INET; + hints.ai_protocol = IPPROTO_UDP; + + Log_d("establish tcp connection with server(host=%s port=%s)", STRING_PTR_PRINT_SANITY_CHECK(host), port_str); + + if (getaddrinfo(host, port_str, &hints, &addr_list) != 0) { + Log_e("getaddrinfo error,errno:%s", strerror(errno)); + return 0; + } + + for (cur = addr_list; cur != NULL; cur = cur->ai_next) { + fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) { + ret = 0; + continue; + } + + if (0 == connect(fd, cur->ai_addr, cur->ai_addrlen)) { + ret = fd; + break; + } + + closesocket(fd); + ret = 0; + } + + if (0 == ret) { + Log_e("fail to establish udp"); + } else { + Log_d("success to establish udp, fd=%d", ret); + } + + freeaddrinfo(addr_list); + + return ret; + +#undef NETWORK_ADDR_LEN +} + +void HAL_UDP_Disconnect(uintptr_t fd) +{ + long socket_id = -1; + + socket_id = (int)fd; + closesocket(socket_id); +} + +int HAL_UDP_Write(uintptr_t fd, const unsigned char *p_data, unsigned int datalen) +{ + int rc = -1; + long socket_id = -1; + + socket_id = (int)fd; + rc = send(socket_id, (char *)p_data, (int)datalen, 0); + if (-1 == rc) { + return -1; + } + + return rc; +} + +int HAL_UDP_Read(uintptr_t fd, unsigned char *p_data, unsigned int datalen) +{ + long socket_id = -1; + int count = -1; + + socket_id = (int)fd; + count = (int)recv(socket_id, p_data, datalen, 0); + + return count; +} + +int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datalen, unsigned int timeout_ms) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int socket_id = -1; + + socket_id = (int)fd; + + if (socket_id < 0) { + return -1; + } + + FD_ZERO(&read_fds); + FD_SET(socket_id, &read_fds); + + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms % 1000) * 1000; + + ret = select(socket_id + 1, &read_fds, NULL, NULL, timeout_ms == 0 ? NULL : &tv); + + /* Zero fds ready means we timed out */ + if (ret == 0) { + return QCLOUD_ERR_SSL_READ_TIMEOUT; /* receive timeout */ + } + + if (ret < 0) { + if (errno == EINTR) { + return -3; /* want read */ + } + + return QCLOUD_ERR_SSL_READ; /* receive failed */ + } + + /* This call will not block */ + return HAL_UDP_Read(fd, p_data, datalen); +} + +#endif diff --git a/src/platform/ssl/mbedtls/HAL_DTLS_mbedtls.c b/platform/tls/mbedtls/HAL_DTLS_mbedtls.c old mode 100644 new mode 100755 similarity index 53% rename from src/platform/ssl/mbedtls/HAL_DTLS_mbedtls.c rename to platform/tls/mbedtls/HAL_DTLS_mbedtls.c index 3d9f7f26..1a8fde39 --- a/src/platform/ssl/mbedtls/HAL_DTLS_mbedtls.c +++ b/platform/tls/mbedtls/HAL_DTLS_mbedtls.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -17,51 +17,54 @@ extern "C" { #endif +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifndef AUTH_WITH_NOTLS + #ifdef COAP_COMM_ENABLED + +#include #include #include -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" - -#include "mbedtls/net_sockets.h" + +#include "mbedtls/certs.h" +#include "mbedtls/ctr_drbg.h" #include "mbedtls/debug.h" -#include "mbedtls/ssl.h" #include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" -#include "mbedtls/certs.h" -#include "mbedtls/timing.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" #include "mbedtls/ssl_cookie.h" - +#include "mbedtls/timing.h" +#include "utils_param_check.h" #include "utils_timer.h" - + #define DEBUG_LEVEL 0 - + #ifndef AUTH_MODE_CERT -static const int ciphersuites[] = { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0 }; +static const int ciphersuites[] = {MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0}; #endif - -typedef struct -{ - mbedtls_net_context socket_fd; // socket文件描述符 - mbedtls_entropy_context entropy; // 保存熵配置 - mbedtls_ctr_drbg_context ctr_drbg; // 随机数生成器 - mbedtls_ssl_context ssl; // 保存SSL基本数据 - mbedtls_ssl_config ssl_conf; // TSL/TLS配置信息 - mbedtls_x509_crt ca_cert; // ca证书信息 - mbedtls_x509_crt client_cert; // 客户端证书信息 - mbedtls_pk_context private_key; // 客户端私钥信息 - - mbedtls_timing_delay_context timer; - mbedtls_ssl_cookie_ctx cookie_ctx; +/** + * @brief data structure for mbedtls SSL connection + */ +typedef struct { + mbedtls_net_context socket_fd; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config ssl_conf; + mbedtls_x509_crt ca_cert; + mbedtls_x509_crt client_cert; + mbedtls_pk_context private_key; + + mbedtls_timing_delay_context timer; + mbedtls_ssl_cookie_ctx cookie_ctx; } DTLSDataParams; /** - * @brief 释放mbedtls开辟的内存 + * @brief free memory/resources allocated by mbedtls */ static void _free_mebeddtls(DTLSDataParams *pParams) { @@ -77,44 +80,40 @@ static void _free_mebeddtls(DTLSDataParams *pParams) HAL_Free(pParams); } - -static void _dtls_debug( void *ctx, int level, - const char *file, int line, - const char *str ) + +static void _dtls_debug(void *ctx, int level, const char *file, int line, const char *str) { - Log_i("[mbedTLS]:[%s]:[%d]: %s\r\n", file, line, str); + Log_i("[mbedTLS]:[%s]:[%d]: %s\r\n", STRING_PTR_PRINT_SANITY_CHECK(file), line, STRING_PTR_PRINT_SANITY_CHECK(str)); } - + static int _mbedtls_client_init(DTLSDataParams *pDataParams, DTLSConnectParams *pConnectParams) { - int ret = QCLOUD_ERR_SUCCESS; + int ret = QCLOUD_RET_SUCCESS; #if defined(MBEDTLS_DEBUG_C) - mbedtls_debug_set_threshold( DEBUG_LEVEL ); + mbedtls_debug_set_threshold(DEBUG_LEVEL); #endif - - mbedtls_net_init( &(pDataParams->socket_fd) ); - mbedtls_ssl_init( &(pDataParams->ssl) ); - mbedtls_ssl_config_init( &(pDataParams->ssl_conf) ); - mbedtls_x509_crt_init( &(pDataParams->ca_cert) ); + + mbedtls_net_init(&(pDataParams->socket_fd)); + mbedtls_ssl_init(&(pDataParams->ssl)); + mbedtls_ssl_config_init(&(pDataParams->ssl_conf)); + mbedtls_x509_crt_init(&(pDataParams->ca_cert)); mbedtls_x509_crt_init(&(pDataParams->client_cert)); mbedtls_pk_init(&(pDataParams->private_key)); - mbedtls_ctr_drbg_init( &(pDataParams->ctr_drbg) ); - mbedtls_entropy_init( &(pDataParams->entropy) ); + mbedtls_ctr_drbg_init(&(pDataParams->ctr_drbg)); + mbedtls_entropy_init(&(pDataParams->entropy)); - if((ret = mbedtls_ctr_drbg_seed(&pDataParams->ctr_drbg, mbedtls_entropy_func, - &pDataParams->entropy, NULL,0)) != 0) - { + if ((ret = mbedtls_ctr_drbg_seed(&pDataParams->ctr_drbg, mbedtls_entropy_func, &pDataParams->entropy, NULL, 0)) != + 0) { Log_e("mbedtls_ctr_drbg_seed failed returned -0x%x", -ret); return QCLOUD_ERR_SSL_INIT; } - mbedtls_ssl_conf_authmode(&pDataParams->ssl_conf, MBEDTLS_SSL_VERIFY_NONE ); + mbedtls_ssl_conf_authmode(&pDataParams->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); - if (pConnectParams->ca_crt != NULL) - { + if (pConnectParams->ca_crt != NULL) { if ((ret = mbedtls_x509_crt_parse(&(pDataParams->ca_cert), (const unsigned char *)pConnectParams->ca_crt, - (pConnectParams->ca_crt_len + 1)))) { + (pConnectParams->ca_crt_len + 1)))) { Log_e("parse ca crt failed returned -0x%04x", -ret); return QCLOUD_ERR_SSL_CERT; } @@ -122,7 +121,7 @@ static int _mbedtls_client_init(DTLSDataParams *pDataParams, DTLSConnectParams * #ifdef AUTH_MODE_CERT if (pConnectParams->cert_file != NULL && pConnectParams->key_file != NULL) { - if ((ret = mbedtls_x509_crt_parse_file(&(pDataParams->client_cert), pConnectParams->cert_file)) != 0) { + if ((ret = mbedtls_x509_crt_parse_file(&(pDataParams->client_cert), pConnectParams->cert_file)) != 0) { Log_e("load client cert file failed returned -0x%x", ret); return QCLOUD_ERR_SSL_CERT; } @@ -134,47 +133,53 @@ static int _mbedtls_client_init(DTLSDataParams *pDataParams, DTLSConnectParams * if (0 == ret) { mbedtls_ssl_conf_ca_chain(&(pDataParams->ssl_conf), &(pDataParams->ca_cert), NULL); - if ((ret = mbedtls_ssl_conf_own_cert(&(pDataParams->ssl_conf), &(pDataParams->client_cert), &(pDataParams->private_key))) != 0) { + if ((ret = mbedtls_ssl_conf_own_cert(&(pDataParams->ssl_conf), &(pDataParams->client_cert), + &(pDataParams->private_key))) != 0) { Log_e("mbedtls_ssl_conf_own_cert failed returned -0x%x", -ret); return QCLOUD_ERR_SSL_CERT; } } } else { - Log_d("cert_file/key_file is empty!|cert_file=%s|key_file=%s", pConnectParams->cert_file, pConnectParams->key_file); + Log_d("cert_file/key_file is empty!|cert_file=%s|key_file=%s", + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->cert_file), + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->key_file)); } - + #else - if (pConnectParams->psk != NULL && pConnectParams->psk_id !=NULL) { + if (pConnectParams->psk != NULL && pConnectParams->psk_id != NULL) { const char *psk_id = pConnectParams->psk_id; - ret = mbedtls_ssl_conf_psk(&(pDataParams->ssl_conf), (unsigned char *)pConnectParams->psk, pConnectParams->psk_length, - (const unsigned char *) psk_id, strlen( psk_id )); + ret = mbedtls_ssl_conf_psk(&(pDataParams->ssl_conf), (unsigned char *)pConnectParams->psk, + pConnectParams->psk_length, (const unsigned char *)psk_id, strlen(psk_id)); } else { - Log_d("psk/pskid is empty!|psk=%s|psd_id=%s", pConnectParams->psk, pConnectParams->psk_id); + Log_d("psk/pskid is empty!|psk=%s|psd_id=%s", STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->psk), + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->psk_id)); + } + + if (0 != ret) { + Log_e("mbedtls_ssl_conf_psk fail: -0x%x", -ret); + return ret; } - - if (0 != ret) { - Log_e("mbedtls_ssl_conf_psk fail: -0x%x", -ret); - return ret; - } #endif return ret; } /** - * @brief 建立UDP连接 + * @brief Setup UDP connection * - * @param socket_fd Socket描述符 - * @param host 服务器主机名 - * @param port 服务器端口地址 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 + * @param socket_fd socket handle + * @param host server address + * @param port server port + * @return QCLOUD_RET_SUCCESS when success, or err code for failure */ -int _mbedtls_udp_connect(mbedtls_net_context *socket_fd, const char *host, int port) { - int ret = 0; +int _mbedtls_udp_connect(mbedtls_net_context *socket_fd, const char *host, int port) +{ + int ret = 0; char port_str[6]; HAL_Snprintf(port_str, 6, "%d", port); if ((ret = mbedtls_net_connect(socket_fd, host, port_str, MBEDTLS_NET_PROTO_UDP)) != 0) { - Log_e("mbedtls_net_connect host:%s port:%s returned -0x%04x errno: %d", host, port_str, -ret, errno); + Log_e("mbedtls_net_connect host:%s port:%s returned -0x%04x errno: %d", STRING_PTR_PRINT_SANITY_CHECK(host), + port_str, -ret, errno); switch (ret) { case MBEDTLS_ERR_NET_SOCKET_FAILED: return QCLOUD_ERR_TCP_SOCKET_FAILED; @@ -190,27 +195,27 @@ int _mbedtls_udp_connect(mbedtls_net_context *socket_fd, const char *host, int p return QCLOUD_ERR_TCP_CONNECT; } - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } uintptr_t HAL_DTLS_Connect(DTLSConnectParams *pConnectParams, const char *host, int port) { - IOT_FUNC_ENTRY; + IOT_FUNC_ENTRY; + + int ret = QCLOUD_RET_SUCCESS; - int ret = QCLOUD_ERR_SUCCESS; - - DTLSDataParams * pDataParams = (DTLSDataParams *)HAL_Malloc(sizeof(DTLSDataParams)); + DTLSDataParams *pDataParams = (DTLSDataParams *)HAL_Malloc(sizeof(DTLSDataParams)); - if ((ret = _mbedtls_client_init(pDataParams, pConnectParams)) != QCLOUD_ERR_SUCCESS) { - goto error; - } + if ((ret = _mbedtls_client_init(pDataParams, pConnectParams)) != QCLOUD_RET_SUCCESS) { + goto error; + } - if ((ret = _mbedtls_udp_connect(&(pDataParams->socket_fd), host, port)) != QCLOUD_ERR_SUCCESS) { - goto error; - } + if ((ret = _mbedtls_udp_connect(&(pDataParams->socket_fd), host, port)) != QCLOUD_RET_SUCCESS) { + goto error; + } - if ((ret = mbedtls_ssl_config_defaults(&pDataParams->ssl_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + if ((ret = mbedtls_ssl_config_defaults(&pDataParams->ssl_conf, MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { Log_e("mbedtls_ssl_config_defaults result 0x%04x", ret); goto error; } @@ -220,66 +225,67 @@ uintptr_t HAL_DTLS_Connect(DTLSConnectParams *pConnectParams, const char *host, mbedtls_ssl_conf_rng(&pDataParams->ssl_conf, mbedtls_ctr_drbg_random, &pDataParams->ctr_drbg); mbedtls_ssl_conf_dbg(&pDataParams->ssl_conf, _dtls_debug, NULL); - if ((ret = mbedtls_ssl_cookie_setup(&pDataParams->cookie_ctx, mbedtls_ctr_drbg_random, &pDataParams->ctr_drbg)) != 0) { + if ((ret = mbedtls_ssl_cookie_setup(&pDataParams->cookie_ctx, mbedtls_ctr_drbg_random, &pDataParams->ctr_drbg)) != + 0) { Log_e("mbedtls_ssl_cookie_setup result 0x%04x", ret); goto error; } - mbedtls_ssl_conf_dtls_cookies(&pDataParams->ssl_conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &pDataParams->cookie_ctx); + mbedtls_ssl_conf_dtls_cookies(&pDataParams->ssl_conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, + &pDataParams->cookie_ctx); #ifndef AUTH_MODE_CERT - mbedtls_ssl_conf_ciphersuites(&(pDataParams->ssl_conf), ciphersuites); -#endif - + mbedtls_ssl_conf_ciphersuites(&(pDataParams->ssl_conf), ciphersuites); +#endif + #ifdef MBEDTLS_SSL_PROTO_DTLS - if (pDataParams->ssl_conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) - { + if (pDataParams->ssl_conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_conf_min_version(&pDataParams->ssl_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); - + mbedtls_ssl_conf_max_version(&pDataParams->ssl_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); - + mbedtls_ssl_conf_handshake_timeout(&pDataParams->ssl_conf, (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2), - (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2 * 4)); + (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2 * 4)); } #endif if ((ret = mbedtls_ssl_setup(&(pDataParams->ssl), &(pDataParams->ssl_conf))) != 0) { - Log_e("mbedtls_ssl_setup failed returned -0x%x", -ret); - goto error; - } + Log_e("mbedtls_ssl_setup failed returned -0x%x", -ret); + goto error; + } if (pDataParams->ssl_conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - mbedtls_ssl_set_timer_cb(&(pDataParams->ssl), (void *)&pDataParams->timer, mbedtls_timing_set_delay, - mbedtls_timing_get_delay); - } + mbedtls_ssl_set_timer_cb(&(pDataParams->ssl), (void *)&pDataParams->timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay); + } if ((ret = mbedtls_ssl_set_hostname(&(pDataParams->ssl), host)) != 0) { - Log_e("mbedtls_ssl_set_hostname failed returned -0x%x", -ret); - goto error; - } - - mbedtls_ssl_set_bio(&(pDataParams->ssl), (void *)&pDataParams->socket_fd, mbedtls_net_send, mbedtls_net_recv, - mbedtls_net_recv_timeout); - - while ((ret = mbedtls_ssl_handshake(&(pDataParams->ssl))) != 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - Log_e("mbedtls_ssl_handshake failed returned -0x%x", -ret); - if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - Log_e("Unable to verify the server's certificate"); - } - goto error; - } - } - + Log_e("mbedtls_ssl_set_hostname failed returned -0x%x", -ret); + goto error; + } + + mbedtls_ssl_set_bio(&(pDataParams->ssl), (void *)&pDataParams->socket_fd, mbedtls_net_send, mbedtls_net_recv, + mbedtls_net_recv_timeout); + + while ((ret = mbedtls_ssl_handshake(&(pDataParams->ssl))) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + Log_e("mbedtls_ssl_handshake failed returned -0x%x", -ret); + if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { + Log_e("Unable to verify the server's certificate"); + } + goto error; + } + } + if ((ret = mbedtls_ssl_get_verify_result(&(pDataParams->ssl))) != 0) { Log_e("mbedtls_ssl_get_verify_result failed returned -0x%x", -ret); goto error; } return (uintptr_t)pDataParams; - + error: - _free_mebeddtls(pDataParams); + _free_mebeddtls(pDataParams); return 0; } @@ -291,7 +297,7 @@ void HAL_DTLS_Disconnect(uintptr_t handle) } DTLSDataParams *pParams = (DTLSDataParams *)handle; - int ret = 0; + int ret = 0; do { ret = mbedtls_ssl_close_notify(&(pParams->ssl)); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); @@ -308,69 +314,68 @@ void HAL_DTLS_Disconnect(uintptr_t handle) HAL_Free((void *)handle); } - + int HAL_DTLS_Write(uintptr_t handle, const unsigned char *data, size_t datalen, size_t *written_len) { - DTLSDataParams *data_params = (DTLSDataParams *)handle; - POINTER_SANITY_CHECK(data_params, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(data, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(written_len, QCLOUD_ERR_INVAL); + DTLSDataParams *data_params = (DTLSDataParams *)handle; + POINTER_SANITY_CHECK(data_params, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(data, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(written_len, QCLOUD_ERR_INVAL); int rc = mbedtls_ssl_write(&data_params->ssl, data, datalen); - if( rc < 0 ) { - Log_e("failed! mbedtls_ssl_write returned %d", rc); - rc = QCLOUD_ERR_SSL_WRITE; - } + if (rc < 0) { + Log_e("failed! mbedtls_ssl_write returned %d", rc); + rc = QCLOUD_ERR_SSL_WRITE; + } + + *written_len = rc; + rc = QCLOUD_RET_SUCCESS; - *written_len = rc; - rc = QCLOUD_ERR_SUCCESS; - IOT_FUNC_EXIT_RC(rc); } -int HAL_DTLS_Read(uintptr_t handle, unsigned char *data, size_t datalen, unsigned int timeout_ms, - size_t *read_len) +int HAL_DTLS_Read(uintptr_t handle, unsigned char *data, size_t datalen, unsigned int timeout_ms, size_t *read_len) { DTLSDataParams *data_params = (DTLSDataParams *)handle; POINTER_SANITY_CHECK(data_params, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(data, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(read_len, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(data, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(read_len, QCLOUD_ERR_INVAL); int rc = QCLOUD_ERR_SSL_READ; - - mbedtls_ssl_conf_read_timeout(&(data_params->ssl_conf), timeout_ms); - - do { - rc = mbedtls_ssl_read(&(data_params->ssl), data, datalen); - } while (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE); - - if( rc <= 0 ) { - *read_len = 0; - switch( rc ) - { - case MBEDTLS_ERR_SSL_TIMEOUT: - rc = QCLOUD_ERR_SSL_READ_TIMEOUT; - break; - - case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: - Log_e("connection was closed gracefully"); - rc = QCLOUD_ERR_DTLS_PEER_CLOSE_NOTIFY; - break; - - default: - Log_e( " mbedtls_ssl_read returned -0x%x", -rc ); - break; - } - } else { - *read_len = rc; - rc = QCLOUD_ERR_SUCCESS; - } - + + mbedtls_ssl_conf_read_timeout(&(data_params->ssl_conf), timeout_ms); + + do { + rc = mbedtls_ssl_read(&(data_params->ssl), data, datalen); + } while (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (rc <= 0) { + *read_len = 0; + switch (rc) { + case MBEDTLS_ERR_SSL_TIMEOUT: + rc = QCLOUD_ERR_SSL_READ_TIMEOUT; + break; + + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + Log_e("connection was closed gracefully"); + rc = QCLOUD_ERR_DTLS_PEER_CLOSE_NOTIFY; + break; + + default: + Log_e(" mbedtls_ssl_read returned -0x%x", -rc); + break; + } + } else { + *read_len = rc; + rc = QCLOUD_RET_SUCCESS; + } + return rc; } #endif - + #ifdef __cplusplus } #endif +#endif \ No newline at end of file diff --git a/src/platform/ssl/mbedtls/HAL_TLS_mbedtls.c b/platform/tls/mbedtls/HAL_TLS_mbedtls.c old mode 100644 new mode 100755 similarity index 63% rename from src/platform/ssl/mbedtls/HAL_TLS_mbedtls.c rename to platform/tls/mbedtls/HAL_TLS_mbedtls.c index c7393696..af46c38e --- a/src/platform/ssl/mbedtls/HAL_TLS_mbedtls.c +++ b/platform/tls/mbedtls/HAL_TLS_mbedtls.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,47 +13,48 @@ * */ -#include -#include -#include - #ifdef __cplusplus extern "C" { #endif #include "qcloud_iot_import.h" -#include "qcloud_iot_export_error.h" -#include "qcloud_iot_export_log.h" -#include "qcloud_iot_sdk_impl_internal.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/net_sockets.h" +#ifndef AUTH_WITH_NOTLS + +#include +#include +#include + #include "mbedtls/ctr_drbg.h" +#include "mbedtls/entropy.h" #include "mbedtls/error.h" - +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" +#include "utils_param_check.h" #include "utils_timer.h" #ifndef AUTH_MODE_CERT -static const int ciphersuites[] = { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0 }; +static const int ciphersuites[] = {MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0}; #endif - + /** - * @brief 用于保存SSL连接相关数据结构 + * @brief data structure for mbedtls SSL connection */ typedef struct { - mbedtls_net_context socket_fd; // socket文件描述符 - mbedtls_entropy_context entropy; // 保存熵配置 - mbedtls_ctr_drbg_context ctr_drbg; // 随机数生成器 - mbedtls_ssl_context ssl; // 保存SSL基本数据 - mbedtls_ssl_config ssl_conf; // TSL/TLS配置信息 - mbedtls_x509_crt ca_cert; // ca证书信息 - mbedtls_x509_crt client_cert; // 客户端证书信息 - mbedtls_pk_context private_key; // 客户端私钥信息 + mbedtls_net_context socket_fd; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config ssl_conf; + mbedtls_x509_crt ca_cert; + mbedtls_x509_crt client_cert; + mbedtls_pk_context private_key; } TLSDataParams; - + /** - * @brief 释放mbedtls开辟的内存 + * @brief free memory/resources allocated by mbedtls */ static void _free_mebedtls(TLSDataParams *pParams) { @@ -65,24 +66,24 @@ static void _free_mebedtls(TLSDataParams *pParams) mbedtls_ssl_config_free(&(pParams->ssl_conf)); mbedtls_ctr_drbg_free(&(pParams->ctr_drbg)); mbedtls_entropy_free(&(pParams->entropy)); - + HAL_Free(pParams); } /** - * @brief mbedtls库初始化 + * @brief mbedtls SSL client init * - * 1. 执行mbedtls库相关初始化函数 - * 2. 随机数生成器 - * 3. 加载CA证书, 客户端证书及私钥文件/设置psk + * 1. call a series of mbedtls init functions + * 2. init and set seed for random functions + * 3. load CA file, cert files or PSK * - * @param pDataParams TLS连接相关数据结构 - * @param pConnectParams TLS证书密钥相关 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 + * @param pDataParams mbedtls TLS parmaters + * @param pConnectParams device info for TLS connection + * @return QCLOUD_RET_SUCCESS when success, or err code for failure */ -static int _mbedtls_client_init(TLSDataParams *pDataParams, TLSConnectParams *pConnectParams) { - - int ret = QCLOUD_ERR_SUCCESS; +static int _mbedtls_client_init(TLSDataParams *pDataParams, TLSConnectParams *pConnectParams) +{ + int ret = QCLOUD_RET_SUCCESS; mbedtls_net_init(&(pDataParams->socket_fd)); mbedtls_ssl_init(&(pDataParams->ssl)); mbedtls_ssl_config_init(&(pDataParams->ssl_conf)); @@ -92,69 +93,71 @@ static int _mbedtls_client_init(TLSDataParams *pDataParams, TLSConnectParams *pC mbedtls_pk_init(&(pDataParams->private_key)); mbedtls_entropy_init(&(pDataParams->entropy)); - // 随机数, 增加custom参数, 目前为NULL - if ((ret = mbedtls_ctr_drbg_seed(&(pDataParams->ctr_drbg), mbedtls_entropy_func, - &(pDataParams->entropy), NULL, 0)) != 0) { - Log_e("mbedtls_ctr_drbg_seed failed returned 0x%04x", ret<0?-ret:ret); + // custom parameter is NULL for now + if ((ret = mbedtls_ctr_drbg_seed(&(pDataParams->ctr_drbg), mbedtls_entropy_func, &(pDataParams->entropy), NULL, + 0)) != 0) { + Log_e("mbedtls_ctr_drbg_seed failed returned 0x%04x", ret < 0 ? -ret : ret); return QCLOUD_ERR_SSL_INIT; } - - if (pConnectParams->ca_crt != NULL) - { + + if (pConnectParams->ca_crt != NULL) { if ((ret = mbedtls_x509_crt_parse(&(pDataParams->ca_cert), (const unsigned char *)pConnectParams->ca_crt, - (pConnectParams->ca_crt_len + 1)))) { - Log_e("parse ca crt failed returned 0x%04x", ret<0?-ret:ret); + (pConnectParams->ca_crt_len + 1)))) { + Log_e("parse ca crt failed returned 0x%04x", ret < 0 ? -ret : ret); return QCLOUD_ERR_SSL_CERT; } } #ifdef AUTH_MODE_CERT if (pConnectParams->cert_file != NULL && pConnectParams->key_file != NULL) { - if ((ret = mbedtls_x509_crt_parse_file(&(pDataParams->client_cert), pConnectParams->cert_file)) != 0) { - Log_e("load client cert file failed returned 0x%x", ret<0?-ret:ret); + if ((ret = mbedtls_x509_crt_parse_file(&(pDataParams->client_cert), pConnectParams->cert_file)) != 0) { + Log_e("load client cert file failed returned 0x%x", ret < 0 ? -ret : ret); return QCLOUD_ERR_SSL_CERT; } if ((ret = mbedtls_pk_parse_keyfile(&(pDataParams->private_key), pConnectParams->key_file, "")) != 0) { - Log_e("load client key file failed returned 0x%x", ret<0?-ret:ret); + Log_e("load client key file failed returned 0x%x", ret < 0 ? -ret : ret); return QCLOUD_ERR_SSL_CERT; } } else { - Log_d("cert_file/key_file is empty!|cert_file=%s|key_file=%s", pConnectParams->cert_file, pConnectParams->key_file); + Log_d("cert_file/key_file is empty!|cert_file=%s|key_file=%s", + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->cert_file), + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->key_file)); } #else - if (pConnectParams->psk != NULL && pConnectParams->psk_id !=NULL) { + if (pConnectParams->psk != NULL && pConnectParams->psk_id != NULL) { const char *psk_id = pConnectParams->psk_id; - ret = mbedtls_ssl_conf_psk(&(pDataParams->ssl_conf), (unsigned char *)pConnectParams->psk, pConnectParams->psk_length, - (const unsigned char *) psk_id, strlen( psk_id )); + ret = mbedtls_ssl_conf_psk(&(pDataParams->ssl_conf), (unsigned char *)pConnectParams->psk, + pConnectParams->psk_length, (const unsigned char *)psk_id, strlen(psk_id)); } else { - Log_d("psk/pskid is empty!|psk=%s|psd_id=%s", pConnectParams->psk, pConnectParams->psk_id); + Log_d("psk/pskid is empty!|psk=%s|psd_id=%s", STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->psk), + STRING_PTR_PRINT_SANITY_CHECK(pConnectParams->psk_id)); + } + + if (0 != ret) { + Log_e("mbedtls_ssl_conf_psk fail: 0x%x", ret < 0 ? -ret : ret); + return ret; } - - if (0 != ret) { - Log_e("mbedtls_ssl_conf_psk fail: 0x%x", ret<0?-ret:ret); - return ret; - } #endif - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } /** - * @brief 建立TCP连接 + * @brief Setup TCP connection * - * @param socket_fd Socket描述符 - * @param host 服务器主机名 - * @param port 服务器端口地址 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 + * @param socket_fd socket handle + * @param host server address + * @param port server port + * @return QCLOUD_RET_SUCCESS when success, or err code for failure */ -int _mbedtls_tcp_connect(mbedtls_net_context *socket_fd, const char *host, int port) { - int ret = 0; +int _mbedtls_tcp_connect(mbedtls_net_context *socket_fd, const char *host, int port) +{ + int ret = 0; char port_str[6]; HAL_Snprintf(port_str, 6, "%d", port); if ((ret = mbedtls_net_connect(socket_fd, host, port_str, MBEDTLS_NET_PROTO_TCP)) != 0) { - - Log_e("tcp connect failed returned 0x%04x errno: %d", ret<0?-ret:ret, errno); + Log_e("tcp connect failed returned 0x%04x errno: %d", ret < 0 ? -ret : ret, errno); switch (ret) { case MBEDTLS_ERR_NET_SOCKET_FAILED: @@ -164,30 +167,25 @@ int _mbedtls_tcp_connect(mbedtls_net_context *socket_fd, const char *host, int p default: return QCLOUD_ERR_TCP_CONNECT; } - } if ((ret = mbedtls_net_set_block(socket_fd)) != 0) { - Log_e("set block faliled returned 0x%04x", ret<0?-ret:ret); + Log_e("set block faliled returned 0x%04x", ret < 0 ? -ret : ret); return QCLOUD_ERR_TCP_CONNECT; } - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } /** - * @brief 在该函数中可对服务端证书进行自定义的校验 + * @brief verify server certificate * - * 这种行为发生在握手过程中, 一般是校验连接服务器的主机名与服务器证书中的CN或SAN的域名信息是否一致 - * 不过, mbedtls库已经实现该功能, 可以参考函数 `mbedtls_x509_crt_verify_with_profile` + * mbedtls has provided similar function mbedtls_x509_crt_verify_with_profile * - * @param hostname 连接服务器的主机名 - * @param crt x509格式的证书 - * @param depth - * @param flags * @return */ -int _qcloud_server_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { +int _qcloud_server_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags) +{ return *flags; } @@ -195,21 +193,16 @@ uintptr_t HAL_TLS_Connect(TLSConnectParams *pConnectParams, const char *host, in { int ret = 0; - TLSDataParams * pDataParams = (TLSDataParams *)HAL_Malloc(sizeof(TLSDataParams)); - - if ((ret = _mbedtls_client_init(pDataParams, pConnectParams)) != QCLOUD_ERR_SUCCESS) { - goto error; - } + TLSDataParams *pDataParams = (TLSDataParams *)HAL_Malloc(sizeof(TLSDataParams)); - Log_d("Connecting to /%s/%d...", host, port); - if ((ret = _mbedtls_tcp_connect(&(pDataParams->socket_fd), host, port)) != QCLOUD_ERR_SUCCESS) { + if ((ret = _mbedtls_client_init(pDataParams, pConnectParams)) != QCLOUD_RET_SUCCESS) { goto error; } Log_d("Setting up the SSL/TLS structure..."); if ((ret = mbedtls_ssl_config_defaults(&(pDataParams->ssl_conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - Log_e("mbedtls_ssl_config_defaults failed returned 0x%04x", ret<0?-ret:ret); + Log_e("mbedtls_ssl_config_defaults failed returned 0x%04x", ret < 0 ? -ret : ret); goto error; } @@ -220,28 +213,28 @@ uintptr_t HAL_TLS_Connect(TLSConnectParams *pConnectParams, const char *host, in mbedtls_ssl_conf_rng(&(pDataParams->ssl_conf), mbedtls_ctr_drbg_random, &(pDataParams->ctr_drbg)); mbedtls_ssl_conf_ca_chain(&(pDataParams->ssl_conf), &(pDataParams->ca_cert), NULL); - if ((ret = mbedtls_ssl_conf_own_cert(&(pDataParams->ssl_conf), - &(pDataParams->client_cert), &(pDataParams->private_key))) != 0) { - Log_e("mbedtls_ssl_conf_own_cert failed returned 0x%04x", ret<0?-ret:ret); + if ((ret = mbedtls_ssl_conf_own_cert(&(pDataParams->ssl_conf), &(pDataParams->client_cert), + &(pDataParams->private_key))) != 0) { + Log_e("mbedtls_ssl_conf_own_cert failed returned 0x%04x", ret < 0 ? -ret : ret); goto error; } mbedtls_ssl_conf_read_timeout(&(pDataParams->ssl_conf), pConnectParams->timeout_ms); if ((ret = mbedtls_ssl_setup(&(pDataParams->ssl), &(pDataParams->ssl_conf))) != 0) { - Log_e("mbedtls_ssl_setup failed returned 0x%04x", ret<0?-ret:ret); + Log_e("mbedtls_ssl_setup failed returned 0x%04x", ret < 0 ? -ret : ret); goto error; } #ifndef AUTH_MODE_CERT - // 选择加密套件代码,以后不通加密方式合并端口的时候可以用到 - if(pConnectParams->psk != NULL) { + // ciphersuites selection for PSK device + if (pConnectParams->psk != NULL) { mbedtls_ssl_conf_ciphersuites(&(pDataParams->ssl_conf), ciphersuites); } #endif // Set the hostname to check against the received server certificate and sni if ((ret = mbedtls_ssl_set_hostname(&(pDataParams->ssl), host)) != 0) { - Log_e("mbedtls_ssl_set_hostname failed returned 0x%04x", ret<0?-ret:ret); + Log_e("mbedtls_ssl_set_hostname failed returned 0x%04x", ret < 0 ? -ret : ret); goto error; } @@ -249,9 +242,14 @@ uintptr_t HAL_TLS_Connect(TLSConnectParams *pConnectParams, const char *host, in mbedtls_net_recv_timeout); Log_d("Performing the SSL/TLS handshake..."); + Log_d("Connecting to /%s/%d...", STRING_PTR_PRINT_SANITY_CHECK(host), port); + if ((ret = _mbedtls_tcp_connect(&(pDataParams->socket_fd), host, port)) != QCLOUD_RET_SUCCESS) { + goto error; + } + while ((ret = mbedtls_ssl_handshake(&(pDataParams->ssl))) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - Log_e("mbedtls_ssl_handshake failed returned 0x%04x", ret<0?-ret:ret); + Log_e("mbedtls_ssl_handshake failed returned 0x%04x", ret < 0 ? -ret : ret); if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { Log_e("Unable to verify the server's certificate"); } @@ -260,14 +258,14 @@ uintptr_t HAL_TLS_Connect(TLSConnectParams *pConnectParams, const char *host, in } if ((ret = mbedtls_ssl_get_verify_result(&(pDataParams->ssl))) != 0) { - Log_e("mbedtls_ssl_get_verify_result failed returned 0x%04x", ret<0?-ret:ret); + Log_e("mbedtls_ssl_get_verify_result failed returned 0x%04x", ret < 0 ? -ret : ret); goto error; } mbedtls_ssl_conf_read_timeout(&(pDataParams->ssl_conf), 100); - Log_i("connected with /%s/%d...", host, port); - + Log_i("connected with /%s/%d...", STRING_PTR_PRINT_SANITY_CHECK(host), port); + return (uintptr_t)pDataParams; error: @@ -275,13 +273,14 @@ uintptr_t HAL_TLS_Connect(TLSConnectParams *pConnectParams, const char *host, in return 0; } -void HAL_TLS_Disconnect(uintptr_t handle) { +void HAL_TLS_Disconnect(uintptr_t handle) +{ if ((uintptr_t)NULL == handle) { Log_d("handle is NULL"); return; } TLSDataParams *pParams = (TLSDataParams *)handle; - int ret = 0; + int ret = 0; do { ret = mbedtls_ssl_close_notify(&(pParams->ssl)); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); @@ -294,29 +293,26 @@ void HAL_TLS_Disconnect(uintptr_t handle) { mbedtls_ssl_config_free(&(pParams->ssl_conf)); mbedtls_ctr_drbg_free(&(pParams->ctr_drbg)); mbedtls_entropy_free(&(pParams->entropy)); - + HAL_Free((void *)handle); } -int HAL_TLS_Write(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_t timeout_ms, - size_t *written_len) +int HAL_TLS_Write(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_t timeout_ms, size_t *written_len) { - Timer timer; InitTimer(&timer); - countdown_ms(&timer, (unsigned int) timeout_ms); + countdown_ms(&timer, (unsigned int)timeout_ms); size_t written_so_far; - bool errorFlag = false; - int write_rc = 0; - + bool errorFlag = false; + int write_rc = 0; + TLSDataParams *pParams = (TLSDataParams *)handle; for (written_so_far = 0; written_so_far < totalLen && !expired(&timer); written_so_far += write_rc) { - - while (!expired(&timer) && (write_rc = mbedtls_ssl_write(&(pParams->ssl), msg + written_so_far, totalLen - written_so_far)) <= 0) - { + while (!expired(&timer) && + (write_rc = mbedtls_ssl_write(&(pParams->ssl), msg + written_so_far, totalLen - written_so_far)) <= 0) { if (write_rc != MBEDTLS_ERR_SSL_WANT_READ && write_rc != MBEDTLS_ERR_SSL_WANT_WRITE) { - Log_e("HAL_TLS_write failed 0x%04x", write_rc<0?-write_rc:write_rc); + Log_e("HAL_TLS_write failed 0x%04x", write_rc < 0 ? -write_rc : write_rc); errorFlag = true; break; } @@ -335,30 +331,30 @@ int HAL_TLS_Write(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_ return QCLOUD_ERR_SSL_WRITE_TIMEOUT; } - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } -int HAL_TLS_Read(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_t timeout_ms, size_t *read_len) +int HAL_TLS_Read(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_t timeout_ms, size_t *read_len) { - - //mbedtls_ssl_conf_read_timeout(&(pParams->ssl_conf), timeout_ms); TODO:每次调用这个方法会导致read阻塞, 超时也不返回 - // 这里使用非阻塞的方式, 具体的超时操作由上层做 + // mbedtls_ssl_conf_read_timeout(&(pParams->ssl_conf), timeout_ms); TODO:this cause read blocking and no return even + // timeout + // use non-blocking read Timer timer; InitTimer(&timer); - countdown_ms(&timer, (unsigned int) timeout_ms); + countdown_ms(&timer, (unsigned int)timeout_ms); *read_len = 0; - + TLSDataParams *pParams = (TLSDataParams *)handle; do { int read_rc = 0; - read_rc = mbedtls_ssl_read(&(pParams->ssl), msg + *read_len, totalLen - *read_len); + read_rc = mbedtls_ssl_read(&(pParams->ssl), msg + *read_len, totalLen - *read_len); if (read_rc > 0) { *read_len += read_rc; - } else if (read_rc == 0 || (read_rc != MBEDTLS_ERR_SSL_WANT_WRITE - && read_rc != MBEDTLS_ERR_SSL_WANT_READ && read_rc != MBEDTLS_ERR_SSL_TIMEOUT)) { - Log_e("cloud_iot_network_tls_read failed: 0x%04x", read_rc<0?-read_rc:read_rc); + } else if (read_rc == 0 || (read_rc != MBEDTLS_ERR_SSL_WANT_WRITE && read_rc != MBEDTLS_ERR_SSL_WANT_READ && + read_rc != MBEDTLS_ERR_SSL_TIMEOUT)) { + Log_e("cloud_iot_network_tls_read failed: 0x%04x", read_rc < 0 ? -read_rc : read_rc); return QCLOUD_ERR_SSL_READ; } @@ -369,7 +365,7 @@ int HAL_TLS_Read(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_t } while (*read_len < totalLen); if (totalLen == *read_len) { - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } if (*read_len == 0) { @@ -382,3 +378,5 @@ int HAL_TLS_Read(uintptr_t handle, unsigned char *msg, size_t totalLen, uint32_t #ifdef __cplusplus } #endif + +#endif diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt new file mode 100755 index 00000000..6f5e8daf --- /dev/null +++ b/samples/CMakeLists.txt @@ -0,0 +1,137 @@ + +set(INC_DIR ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/include) +set(LINK_DIR ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/lib/) +include_directories(${INC_DIR}) +link_directories(${LINK_DIR}) + +if(FEATURE_AUTH_WITH_NOTLS) +set(link_lib + iot_sdk + iot_platform +) +else() +set(link_lib + iot_sdk + iot_platform + mbedtls + mbedx509 + mbedcrypto +) +endif() + +if (PLATFORM STREQUAL "linux" AND COMPILE_TOOLS STREQUAL "gcc") + set(lib -Wl,--start-group ${link_lib} -Wl,--end-group) +elseif (PLATFORM STREQUAL "windows" AND COMPILE_TOOLS STREQUAL "MSVC") + set(lib ${link_lib}) +endif() + + +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/bin) + +# MQTT +if(${FEATURE_MQTT_COMM_ENABLED} STREQUAL "ON") +file(GLOB src_mqtt_sample ${PROJECT_SOURCE_DIR}/samples/mqtt/mqtt_sample.c) +add_executable(mqtt_sample ${src_mqtt_sample}) +target_link_libraries(mqtt_sample ${lib}) + +file(GLOB src_door_mqtt_sample ${PROJECT_SOURCE_DIR}/samples/scenarized/door_mqtt_sample.c) +add_executable(door_mqtt_sample ${src_door_mqtt_sample}) +target_link_libraries(door_mqtt_sample ${lib}) +endif() + +# Multi-Thread Multi-Client sample +if (${FEATURE_MULTITHREAD_ENABLED} STREQUAL "ON") + file(GLOB src_multi_thread_mqtt_sample ${PROJECT_SOURCE_DIR}/samples/mqtt/multi_thread_mqtt_sample.c) + add_executable(multi_thread_mqtt_sample ${src_multi_thread_mqtt_sample}) + target_link_libraries(multi_thread_mqtt_sample ${lib}) + +if (${FEATURE_DEBUG_DEV_INFO_USED} STREQUAL "OFF") + file(GLOB src_multi_client_mqtt_sample ${PROJECT_SOURCE_DIR}/samples/multi_client/multi_client_mqtt_sample.c) + add_executable(multi_client_mqtt_sample ${src_multi_client_mqtt_sample}) + target_link_libraries(multi_client_mqtt_sample ${lib}) + + file(GLOB src_multi_client_shadow_sample ${PROJECT_SOURCE_DIR}/samples/multi_client/multi_client_shadow_sample.c) + add_executable(multi_client_shadow_sample ${src_multi_client_shadow_sample}) + target_link_libraries(multi_client_shadow_sample ${lib}) +endif() +endif() + +# DYN_REG +if(${FEATURE_DEV_DYN_REG_ENABLED} STREQUAL "ON") + file(GLOB src_dynreg_dev_sample ${PROJECT_SOURCE_DIR}/samples/dynreg_dev/dynreg_dev_sample.c) + add_executable(dynreg_dev_sample ${src_dynreg_dev_sample}) + target_link_libraries(dynreg_dev_sample ${lib}) +endif() + +# OTA MQTT +if(${FEATURE_OTA_COMM_ENABLED} STREQUAL "ON" AND ${FEATURE_OTA_SIGNAL_CHANNEL} STREQUAL "MQTT") + file(GLOB src_ota_mqtt_sample ${PROJECT_SOURCE_DIR}/samples/ota/ota_mqtt_sample.c) + add_executable(ota_mqtt_sample ${src_ota_mqtt_sample}) + target_link_libraries(ota_mqtt_sample ${lib}) +endif() + +# SHADOW +if(${FEATURE_MQTT_DEVICE_SHADOW} STREQUAL "ON") + file(GLOB src_shadow_sample ${PROJECT_SOURCE_DIR}/samples/shadow/shadow_sample.c) + add_executable(shadow_sample ${src_shadow_sample}) + target_link_libraries(shadow_sample ${lib}) + + file(GLOB src_aircond_shadow_sample ${PROJECT_SOURCE_DIR}/samples/scenarized/aircond_shadow_sample.c) + file(GLOB src_aircond_shadow_sample_v2 ${PROJECT_SOURCE_DIR}/samples/scenarized/aircond_shadow_sample_v2.c) + add_executable(aircond_shadow_sample ${src_aircond_shadow_sample}) + add_executable(aircond_shadow_sample_v2 ${src_aircond_shadow_sample_v2}) + target_link_libraries(aircond_shadow_sample ${lib}) + target_link_libraries(aircond_shadow_sample_v2 ${lib}) +endif() + + +# GATEWAY +if(${FEATURE_GATEWAY_ENABLED} STREQUAL "ON") + file(GLOB src_gateway_sample ${PROJECT_SOURCE_DIR}/samples/gateway/gateway_sample.c) + add_executable(gateway_sample ${src_gateway_sample}) + target_link_libraries(gateway_sample ${lib}) +endif() + +# GATEWAY SubDev ota +if(${FEATURE_OTA_COMM_ENABLED} STREQUAL "ON" AND ${FEATURE_OTA_SIGNAL_CHANNEL} STREQUAL "MQTT" AND ${FEATURE_GATEWAY_ENABLED} STREQUAL "ON") + file(GLOB src_ota_mqtt_subdev_sample ${PROJECT_SOURCE_DIR}/samples/ota/ota_mqtt_subdev_sample.c) + add_executable(ota_mqtt_subdev_sample ${src_ota_mqtt_subdev_sample}) + target_link_libraries(ota_mqtt_subdev_sample ${lib}) +endif() + +# COAP +if(${FEATURE_COAP_COMM_ENABLED} STREQUAL "ON") + file(GLOB src_coap_sample ${PROJECT_SOURCE_DIR}/samples/coap/coap_sample.c) + add_executable(coap_sample ${src_coap_sample}) + target_link_libraries(coap_sample ${lib}) + + file(GLOB src_door_coap_sample ${PROJECT_SOURCE_DIR}/samples/scenarized/door_coap_sample.c) + add_executable(door_coap_sample ${src_door_coap_sample}) + target_link_libraries(door_coap_sample ${lib}) +endif() + + +if(${FEATURE_OTA_COMM_ENABLED} STREQUAL "ON" AND ${FEATURE_OTA_SIGNAL_CHANNEL} STREQUAL "COAP") + file(GLOB src_ota_coap_sample ${PROJECT_SOURCE_DIR}/samples/ota/ota_coap_sample.c) + add_executable(ota_coap_sample ${src_ota_coap_sample}) + target_link_libraries(ota_coap_sample ${lib}) +endif() + +if(${FEATURE_BROADCAST_ENABLED} STREQUAL "ON") + file(GLOB src_broadcast_sample ${PROJECT_SOURCE_DIR}/samples/broadcast/broadcast_sample.c) + add_executable(broadcast_sample ${src_broadcast_sample}) + target_link_libraries(broadcast_sample ${lib}) +endif() + +if(${FEATURE_RRPC_ENABLED} STREQUAL "ON") + file(GLOB src_rrpc_sample ${PROJECT_SOURCE_DIR}/samples/rrpc/rrpc_sample.c) + add_executable(rrpc_sample ${src_rrpc_sample}) + target_link_libraries(rrpc_sample ${lib}) +endif() + +if(${FEATURE_REMOTE_CONFIG_MQTT_ENABLED} STREQUAL "ON") + file(GLOB src_remote_config_mqtt_sample ${PROJECT_SOURCE_DIR}/samples/config/remote_config_mqtt_sample.c) + add_executable(remote_config_mqtt_sample ${src_remote_config_mqtt_sample}) + target_link_libraries(remote_config_mqtt_sample ${lib}) +endif() + diff --git a/samples/Makefile b/samples/Makefile new file mode 100755 index 00000000..03117d5a --- /dev/null +++ b/samples/Makefile @@ -0,0 +1,200 @@ +# Basic Settings +SHELL := /bin/bash +TOP_DIR ?= $(CURDIR)/../ +SUBDIRS := directory-not-exist-actually + +# Settings of input directory +SCRIPT_DIR := $(TOP_DIR)/tools/build_scripts + +include $(TOP_DIR)/make.settings +include $(SCRIPT_DIR)/parse_make_settings.mk + +# Makefile echo +ifeq ($(DEBUG_MAKEFILE),n) + Q := @ + TOP_Q := @ +else + Q := + TOP_Q := +endif + +# Settings of output directory +SAMPLE_DIR := $(CURDIR) +FINAL_DIR := $(CURDIR)/../output/$(BUILD_TYPE) + +IOT_LIB_DIR = $(FINAL_DIR)/lib +IOT_INC_CFLAGS = -I$(FINAL_DIR)/include -I$(FINAL_DIR)/include/exports + +LDFLAGS := -Wl,--start-group $(IOT_LIB_DIR)/libiot_sdk.a +ifeq ($(FEATURE_AUTH_WITH_NOTLS),n) +LDFLAGS += $(IOT_LIB_DIR)/libmbedtls.a $(IOT_LIB_DIR)/libmbedx509.a $(IOT_LIB_DIR)/libmbedcrypto.a +endif +LDFLAGS += $(IOT_LIB_DIR)/libiot_platform.a -Wl,--end-group + + +CFLAGS += -Wall -Wno-error=sign-compare -Wno-error=format -Os -pthread -DFORCE_SSL_VERIFY +CFLAGS += ${IOT_INC_CFLAGS} + +ifeq ($(FEATURE_AUTH_MODE),CERT) +CFLAGS += -DAUTH_MODE_CERT +endif + +.PHONY: mqtt_sample ota_mqtt_sample ota_coap_sample shadow_sample coap_sample gateway_sample multi_thread_mqtt_sample \ + dynreg_dev_sample multi_client broadcast_sample rrpc_sample remote_config_mqtt_sample ota_mqtt_subdev_sample + +all: mqtt_sample ota_mqtt_sample ota_coap_sample shadow_sample coap_sample gateway_sample multi_thread_mqtt_sample \ + dynreg_dev_sample multi_client broadcast_sample rrpc_sample remote_config_mqtt_sample ota_mqtt_subdev_sample + +ifneq (,$(filter -DMQTT_COMM_ENABLED,$(CFLAGS))) +mqtt_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/mqtt/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/scenarized/door_$@.c $(LDFLAGS) -o door_$@ + + $(TOP_Q) \ + mv door_$@ $(FINAL_DIR)/bin && \ + mv $@ $(FINAL_DIR)/bin + +# Multi-Thread Multi-Client sample +ifneq (,$(filter -DMULTITHREAD_ENABLED,$(CFLAGS))) +multi_thread_mqtt_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/mqtt/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin + +ifeq (,$(filter -DDEBUG_DEV_INFO_USED,$(CFLAGS))) +multi_client: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/multi_client/$@_mqtt_sample.c $(LDFLAGS) -o $@_mqtt_sample + + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/multi_client/$@_shadow_sample.c $(LDFLAGS) -o $@_shadow_sample + + $(TOP_Q) \ + mv $@_mqtt_sample $(FINAL_DIR)/bin && \ + mv $@_shadow_sample $(FINAL_DIR)/bin +endif +endif + +ifneq (,$(filter -DDEV_DYN_REG_ENABLED,$(CFLAGS))) +dynreg_dev_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/dynreg_dev/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin +endif + +ifneq (,$(filter -DOTA_COMM_ENABLED,$(CFLAGS))) +ifneq (,$(filter -DOTA_MQTT_CHANNEL,$(CFLAGS))) +ota_mqtt_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/ota/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin +endif +endif + +ifneq (,$(filter -DOTA_COMM_ENABLED,$(CFLAGS))) +ifneq (,$(filter -DOTA_MQTT_CHANNEL,$(CFLAGS))) +ifneq (,$(filter -DGATEWAY_ENABLED,$(CFLAGS))) +ota_mqtt_subdev_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/ota/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin +endif +endif +endif + +ifneq (,$(filter -DMQTT_DEVICE_SHADOW,$(CFLAGS))) +shadow_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/shadow/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/scenarized/aircond_$@.c $(LDFLAGS) -o aircond_$@ + + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/scenarized/aircond_$@_v2.c $(LDFLAGS) -o aircond_$@_v2 + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin && \ + mv aircond_$@ $(FINAL_DIR)/bin && \ + mv aircond_$@_v2 $(FINAL_DIR)/bin +endif + + +ifneq (,$(filter -DGATEWAY_ENABLED,$(CFLAGS))) +gateway_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/gateway/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin +endif +endif + +ifneq (,$(filter -DCOAP_COMM_ENABLED,$(CFLAGS))) +coap_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/coap/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/scenarized/door_$@.c $(LDFLAGS) -o door_$@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin + + $(TOP_Q) \ + mv door_$@ $(FINAL_DIR)/bin + +ifneq (,$(filter -DOTA_COMM_ENABLED,$(CFLAGS))) +ifneq (,$(filter -DOTA_COAP_CHANNEL,$(CFLAGS))) +ota_coap_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/ota/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin +endif +endif + +endif + +ifneq (,$(filter -DBROADCAST_ENABLED,$(CFLAGS))) +broadcast_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/broadcast/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin +endif + +ifneq (,$(filter -DRRPC_ENABLED,$(CFLAGS))) +rrpc_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/rrpc/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin +endif + +ifneq (,$(filter -DREMOTE_CONFIG_MQTT_ENABLED,$(CFLAGS))) +remote_config_mqtt_sample: + $(TOP_Q) \ + $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/config/$@.c $(LDFLAGS) -o $@ + + $(TOP_Q) \ + mv $@ $(FINAL_DIR)/bin +endif + +clean: + rm -rf $(FINAL_DIR)/bin/* + diff --git a/samples/broadcast/broadcast_sample.c b/samples/broadcast/broadcast_sample.c new file mode 100755 index 00000000..24f029af --- /dev/null +++ b/samples/broadcast/broadcast_sample.c @@ -0,0 +1,228 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" + +// MQTT event callback +static void _mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + MQTTMessage *mqtt_messge = (MQTTMessage *)msg->msg; + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + mqtt_messge->topic_len, STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->ptopic), mqtt_messge->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->payload)); + break; + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} + +// Setup MQTT construct parameters +static int _setup_connect_init_params(MQTTInitParams *initParams, DeviceInfo *device_info) +{ + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#endif + +#else + initParams->device_secret = device_info->device_secret; +#endif + + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = _mqtt_event_handler; + initParams->event_handle.context = NULL; + + return QCLOUD_RET_SUCCESS; +} + +// User callback +static void _broadcast_message_handler(void *pClient, const char *msg, uint32_t msgLen) +{ + Log_i("broadcast message=%.*s", msgLen, STRING_PTR_PRINT_SANITY_CHECK(msg)); +} + +static int sg_loop_count = 5; +static int parse_arguments(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "c:l:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + case 'l': + sg_loop_count = atoi(utils_optarg); + if (sg_loop_count > 10000) + sg_loop_count = 10000; + else if (sg_loop_count < 0) + sg_loop_count = 1; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n" + " [-l ] \n", + argv[0]); + return -1; + } + return 0; +} + +int main(int argc, char **argv) +{ + int rc; + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + // parse arguments for device info file and loop test; + rc = parse_arguments(argc, argv); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("parse arguments error, rc = %d", rc); + return rc; + } + + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + return rc; + } + + // init connection + MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; + rc = _setup_connect_init_params(&init_params, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params error, rc = %d", rc); + return rc; + } + + // create MQTT client and connect with server + void *client = IOT_MQTT_Construct(&init_params); + if (client != NULL) { + Log_i("Cloud Device Construct Success"); + } else { + Log_e("MQTT Construct failed!"); + IOT_Log_Upload(true); + return QCLOUD_ERR_FAILURE; + } + + // subscribe broadcast topics + rc = IOT_Broadcast_Subscribe(client, _broadcast_message_handler); + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + do { + rc = IOT_MQTT_Yield(client, 500); + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + HAL_SleepMs(1000); + + } while (--sg_loop_count > 0); + + rc = IOT_MQTT_Destroy(&client); + + return rc; +} diff --git a/samples/coap/coap_sample.c b/samples/coap/coap_sample.c old mode 100644 new mode 100755 index a628d81b..eb69030d --- a/samples/coap/coap_sample.c +++ b/samples/coap/coap_sample.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,180 +13,183 @@ * */ +#include #include #include -#include #include -#include -#include #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" - -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" - - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 - -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" -#endif - -void response_message_callback(void* coap_message, void* userContext) +void response_message_callback(void *coap_message, void *userContext) { - int ret_code = IOT_COAP_GetMessageCode(coap_message); - switch (ret_code) { - case COAP_EVENT_RECEIVE_ACK: - Log_i("message received ACK, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_RECEIVE_RESPCONTENT: - { - char* payload = NULL; - int payload_len = 0; - int ret = -1; - ret = IOT_COAP_GetMessagePayload(coap_message, &payload, &payload_len); - if (ret == QCLOUD_ERR_SUCCESS) { - Log_i("message received response, content: %s", payload); - } - else { - Log_e("message received response, content error."); - } - } - - break; - case COAP_EVENT_UNAUTHORIZED: - Log_i("coap client auth token expired or invalid, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_FORBIDDEN: - Log_i("coap URI is invalid for this device, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_INTERNAL_SERVER_ERROR: - Log_i("coap server internal error, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_ACK_TIMEOUT: - Log_i("message receive ACK timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_SEPRESP_TIMEOUT: - Log_i("message received ACK but receive response timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - default: - break; - } + int ret_code = IOT_COAP_GetMessageCode(coap_message); + switch (ret_code) { + case COAP_EVENT_RECEIVE_ACK: + Log_i("message received ACK, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_RECEIVE_RESPCONTENT: { + char *payload = NULL; + int payload_len = 0; + int ret = -1; + ret = IOT_COAP_GetMessagePayload(coap_message, &payload, &payload_len); + if (ret == QCLOUD_RET_SUCCESS) { + Log_i("message received response, content: %s", payload); + } else { + Log_e("message received response, content error."); + } + } + + break; + case COAP_EVENT_UNAUTHORIZED: + Log_i("coap client auth token expired or invalid, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_FORBIDDEN: + Log_i("coap URI is invalid for this device, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_INTERNAL_SERVER_ERROR: + Log_i("coap server internal error, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_ACK_TIMEOUT: + Log_i("message receive ACK timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_SEPRESP_TIMEOUT: + Log_i("message received ACK but receive response timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + default: + break; + } } void event_handler(void *pcontext, CoAPEventMessage *message) { - switch (message->event_type) { - case COAP_EVENT_RECEIVE_ACK: - Log_i("message received ACK, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_RECEIVE_RESPCONTENT: - Log_i("message received response, content: %s", IOT_COAP_GetMessageId(message->message)); - break; - case COAP_EVENT_UNAUTHORIZED: - Log_i("coap client auth token expired or invalid, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_FORBIDDEN: - Log_i("coap URI is invalid for this device, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_INTERNAL_SERVER_ERROR: - Log_i("coap server internal error, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_ACK_TIMEOUT: - Log_i("message receive ACK timeout, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_SEPRESP_TIMEOUT: - Log_i("message received ACK but receive response timeout, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - default: - Log_e("unrecogonized event type: %d", message->event_type); - break; - } + switch (message->event_type) { + case COAP_EVENT_RECEIVE_ACK: + Log_i("message received ACK, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_RECEIVE_RESPCONTENT: + Log_i("message received response, content: %s", IOT_COAP_GetMessageId(message->message)); + break; + case COAP_EVENT_UNAUTHORIZED: + Log_i("coap client auth token expired or invalid, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_FORBIDDEN: + Log_i("coap URI is invalid for this device, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_INTERNAL_SERVER_ERROR: + Log_i("coap server internal error, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_ACK_TIMEOUT: + Log_i("message receive ACK timeout, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_SEPRESP_TIMEOUT: + Log_i("message received ACK but receive response timeout, msgid: %d", + (unsigned)(uintptr_t)message->message); + break; + default: + Log_e("unrecogonized event type: %d", message->event_type); + break; + } } -int main(int argc, char **argv) +static int _setup_connect_init_params(CoAPInitParams *initParams, DeviceInfo *device_info) { - IOT_Log_Set_Level(DEBUG); - - CoAPInitParams init_params = DEFAULT_COAPINIT_PARAMS; - init_params.product_id = QCLOUD_IOT_MY_PRODUCT_ID; - init_params.device_name = QCLOUD_IOT_MY_DEVICE_NAME; + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; #ifdef AUTH_MODE_CERT - // 获取CA证书、客户端证书以及私钥文件的路径 - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - init_params.cert_file = sg_cert_file; - init_params.key_file = sg_key_file; + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#endif + #else - init_params.device_secret = QCLOUD_IOT_DEVICE_SECRET; + initParams->device_secret = device_info->device_secret; #endif - init_params.command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - init_params.event_handle.h_fp = event_handler; - init_params.max_retry_count = 3; + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->event_handle.h_fp = event_handler; + initParams->max_retry_count = 3; - void *coap_client = IOT_COAP_Construct(&init_params); - if (coap_client == NULL) { - Log_e("COAP Client construct failed."); - return QCLOUD_ERR_FAILURE; - } + return QCLOUD_RET_SUCCESS; +} - int rc = QCLOUD_ERR_SUCCESS; +int main(int argc, char **argv) +{ + int rc = QCLOUD_RET_SUCCESS; + + IOT_Log_Set_Level(eLOG_DEBUG); + + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + return rc; + } + + CoAPInitParams init_params = DEFAULT_COAPINIT_PARAMS; + rc = _setup_connect_init_params(&init_params, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + return rc; + } + + void *coap_client = IOT_COAP_Construct(&init_params); + if (coap_client == NULL) { + Log_e("COAP Client construct failed."); + return QCLOUD_ERR_FAILURE; + } do { - SendMsgParams send_params = DEFAULT_SENDMSG_PARAMS; - send_params.pay_load = "{\"name\":\"hello world\"}"; - send_params.pay_load_len = strlen("{\"name\":\"hello world\"}"); - send_params.resp_callback = response_message_callback; + SendMsgParams send_params = DEFAULT_SENDMSG_PARAMS; + send_params.pay_load = "{\"action\":\"hello world\"}"; + send_params.pay_load_len = strlen("{\"action\":\"hello world\"}"); + send_params.resp_callback = response_message_callback; char topicName[128] = ""; - sprintf(topicName, "%s/%s/data", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME); + sprintf(topicName, "%s/%s/data", device_info.product_id, device_info.device_name); Log_i("topic name is %s", topicName); rc = IOT_COAP_SendMessage(coap_client, topicName, &send_params); - if (rc < 0) { - Log_e("client publish topic failed :%d.", rc); - } - else { - Log_d("client topic has been sent, msg_id: %d", rc); - } + if (rc < 0) { + Log_e("client publish topic failed :%d.", rc); + } else { + Log_d("client topic has been sent, msg_id: %d", rc); + } - if (!(argc >= 2 && !strcmp("loop", argv[1]))) { - sleep(1); - } + if (!(argc >= 2 && !strcmp("loop", argv[1]))) { + HAL_SleepMs(1000); + } - rc = IOT_COAP_Yield(coap_client, 200); + rc = IOT_COAP_Yield(coap_client, 200); - if (rc != QCLOUD_ERR_SUCCESS){ - Log_e("exit with error: %d", rc); - break; - } + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("exit with error: %d", rc); + break; + } - if (argc >= 2) - sleep(1); + if (argc >= 2) + HAL_SleepMs(1000); } while (argc >= 2 && !strcmp("loop", argv[1])); IOT_COAP_Destroy(&coap_client); - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } diff --git a/samples/config/remote_config_mqtt_sample.c b/samples/config/remote_config_mqtt_sample.c new file mode 100644 index 00000000..f456aabe --- /dev/null +++ b/samples/config/remote_config_mqtt_sample.c @@ -0,0 +1,317 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" +#include "lite-utils.h" + +typedef struct { + int baud_rate; + int data_bits; + int parity; + int stop_bit; + int thread_sleep_time; +} ConfigData; + +static ConfigData sg_config_data = {9600, 8, 0, 1, 1000}; +static bool sg_config_arrived = false; + +static void _on_config_proc_handler(void *client, int config_reply_errcode, char *config_json, int config_json_len) +{ + int rc; + Log_i("config message arrived , config data: %s", STRING_PTR_PRINT_SANITY_CHECK(config_json)); + + if (REMOTE_CONFIG_ERRCODE_SUCCESS != config_reply_errcode) { + Log_i("remote config data arrived!!! error code is %d not 0", config_reply_errcode); + return; + } else if (0 == config_json_len) { + Log_i("remote config data arrived!!! config data is null but error code is 0"); + return; + } + + char *data_rate = LITE_json_value_of("baud rate", config_json); + char *data_bits = LITE_json_value_of("data bits", config_json); + char *parity = LITE_json_value_of("parity", config_json); + char *stop_bit = LITE_json_value_of("stop bit", config_json); + char *thread_sleep_time = LITE_json_value_of("thread sleep", config_json); + + if (NULL != data_rate) { + rc = LITE_get_int32(&sg_config_data.baud_rate, data_rate); + HAL_Free(data_rate); + } + + if (NULL != data_bits) { + rc = LITE_get_int32(&sg_config_data.data_bits, data_bits); + HAL_Free(data_bits); + } + + if (NULL != parity) { + rc = LITE_get_int32(&sg_config_data.parity, parity); + HAL_Free(parity); + } + + if (NULL != stop_bit) { + rc = LITE_get_int32(&sg_config_data.stop_bit, stop_bit); + HAL_Free(stop_bit); + } + + if (NULL != thread_sleep_time) { + rc = LITE_get_int32(&sg_config_data.thread_sleep_time, thread_sleep_time); + + sg_config_data.thread_sleep_time = + (sg_config_data.thread_sleep_time > 1000) ? sg_config_data.thread_sleep_time : 1000; + + HAL_Free(thread_sleep_time); + } + + sg_config_arrived = true; + + Log_i("config message arrived , proc end: %d, %d, %d, %d, %d", sg_config_data.baud_rate, sg_config_data.data_bits, + sg_config_data.parity, sg_config_data.stop_bit, sg_config_data.thread_sleep_time); + + (void)rc; + + return; +} + +// MQTT event callback +static void _mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + MQTTMessage *mqtt_messge = (MQTTMessage *)msg->msg; + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + mqtt_messge->topic_len, STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->ptopic), mqtt_messge->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->payload)); + break; + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} + +// Setup MQTT construct parameters +static int _setup_connect_init_params(MQTTInitParams *initParams, DeviceInfo *device_info) +{ + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#endif + +#else + initParams->device_secret = device_info->device_secret; +#endif + + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = _mqtt_event_handler; + initParams->event_handle.context = NULL; + + return QCLOUD_RET_SUCCESS; +} + +static bool sg_loop_test = false; +static int parse_arguments(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "c:l")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + case 'l': + sg_loop_test = true; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n" + " [-l ] loop test or not\n", + argv[0]); + return -1; + } + return 0; +} + +int main(int argc, char **argv) +{ + int rc; + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + // parse arguments for device info file and loop test; + rc = parse_arguments(argc, argv); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("parse arguments error, rc = %d", rc); + return rc; + } + + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + return rc; + } + + // init connection + MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; + rc = _setup_connect_init_params(&init_params, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params error, rc = %d", rc); + return rc; + } + + // create MQTT client and connect with server + void *client = IOT_MQTT_Construct(&init_params); + if (client != NULL) { + Log_i("Cloud Device Construct Success"); + } else { + Log_e("MQTT Construct failed!"); + return QCLOUD_ERR_FAILURE; + } + + // subscribe config topic + // example: config json data : {"baud rate":115200,"data bits":8,"stop bit":1,"parity":"NONE","thread sleep":1000} + static ConfigSubscirbeUserData config_sub_userdata; + config_sub_userdata.on_config_proc = _on_config_proc_handler; + config_sub_userdata.json_buffer_len = REMOTE_CONFIG_JSON_BUFFER_MIN_LEN + 88; + config_sub_userdata.json_buffer = HAL_Malloc(config_sub_userdata.json_buffer_len); + if (NULL == config_sub_userdata.json_buffer) { + Log_e("Malloc Error size:%d", config_sub_userdata.json_buffer_len); + return QCLOUD_ERR_MALLOC; + } + + for (int count = 0; count < 3; count++) { + rc = IOT_Subscribe_Config(client, &config_sub_userdata, 5000); + if (QCLOUD_RET_SUCCESS <= rc) { + Log_i("config topic subscribe success, packetid:%d", rc); + break; + } else { + Log_i("config topic subscribe failed, ret:%d, retry :%d", rc, count + 1); + } + } + + char json_buffer[32]; + int time_count = 0; + rc = IOT_Get_Config(client, json_buffer, sizeof(json_buffer), 5000); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("get config failed ret: %d", rc); + } + + do { + rc = IOT_MQTT_Yield(client, 500); + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + time_count++; + if ((time_count % 120) == 0) { + rc = IOT_Get_Config(client, json_buffer, sizeof(json_buffer), 5000); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("get config failed ret: %d", rc); + } + } + + if (sg_loop_test) + HAL_SleepMs(sg_config_data.thread_sleep_time); + + } while (sg_loop_test); + + rc = IOT_MQTT_Destroy(&client); + + return rc; +} diff --git a/samples/dynreg_dev/dynreg_dev_sample.c b/samples/dynreg_dev/dynreg_dev_sample.c new file mode 100755 index 00000000..dba3d841 --- /dev/null +++ b/samples/dynreg_dev/dynreg_dev_sample.c @@ -0,0 +1,109 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" + +#ifdef AUTH_MODE_CERT +/* NULL cert file */ +#define QCLOUD_IOT_NULL_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" +/* NULL key file */ +#define QCLOUD_IOT_NULL_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" +#else +/* NULL device secret */ +#define QCLOUD_IOT_NULL_DEVICE_SECRET "YOUR_IOT_PSK" +#endif + +int main(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "c:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n", + argv[0]); + + return -1; + } + + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + int ret; + DeviceInfo sDevInfo; + bool infoNullFlag = false; + + memset((char *)&sDevInfo, 0, sizeof(DeviceInfo)); + + ret = HAL_GetDevInfo(&sDevInfo); + +#ifdef AUTH_MODE_CERT + /* just demo the cert/key files are empty */ + if (!strcmp(sDevInfo.dev_cert_file_name, QCLOUD_IOT_NULL_CERT_FILENAME) || + !strcmp(sDevInfo.dev_key_file_name, QCLOUD_IOT_NULL_KEY_FILENAME)) { + Log_d("dev Cert not exist!"); + infoNullFlag = true; + } else { + Log_d("dev Cert exist"); + } +#else + /* just demo the PSK is empty */ + if (!strcmp(sDevInfo.device_secret, QCLOUD_IOT_NULL_DEVICE_SECRET)) { + Log_d("dev psk not exist!"); + infoNullFlag = true; + } else { + Log_d("dev psk exist"); + } +#endif + + /* device cert/key files or PSK is empty, do dynamic register to fetch */ + if (infoNullFlag) { + if (QCLOUD_RET_SUCCESS == IOT_DynReg_Device(&sDevInfo)) { + ret = HAL_SetDevInfo(&sDevInfo); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("devices info save fail"); + } else { +#ifdef AUTH_MODE_CERT + Log_d("dynamic register success, productID: %s, devName: %s, CertFile: %s, KeyFile: %s", + STRING_PTR_PRINT_SANITY_CHECK(sDevInfo.product_id), + STRING_PTR_PRINT_SANITY_CHECK(sDevInfo.device_name), + STRING_PTR_PRINT_SANITY_CHECK(sDevInfo.dev_cert_file_name), + STRING_PTR_PRINT_SANITY_CHECK(sDevInfo.dev_key_file_name)); +#else + Log_d("dynamic register success,productID: %s, devName: %s, device_secret: %s", + STRING_PTR_PRINT_SANITY_CHECK(sDevInfo.product_id), + STRING_PTR_PRINT_SANITY_CHECK(sDevInfo.device_name), + STRING_PTR_PRINT_SANITY_CHECK(sDevInfo.device_secret)); +#endif + } + } else { + Log_e("devName: %s dynamic register fail", STRING_PTR_PRINT_SANITY_CHECK(sDevInfo.device_name)); + } + } + + return ret; +} diff --git a/samples/gateway/gateway_sample.c b/samples/gateway/gateway_sample.c index ce0cc3ed..139b7955 100755 --- a/samples/gateway/gateway_sample.c +++ b/samples/gateway/gateway_sample.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,255 +13,407 @@ * */ +#include +#include #include #include -#include #include -#include -#include #include "qcloud_iot_export.h" +#include "utils_getopt.h" +void _event_handler(void *client, void *context, MQTTEventMsg *msg) +{ + MQTTMessage *mqtt_messge = (MQTTMessage *)msg->msg; + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + mqtt_messge->topic_len, STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->ptopic), mqtt_messge->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->payload)); + break; + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} -/* 网关产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_GW_PRODUCT_ID" -/* 网关设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_GW_DEVICE_NAME" +static void _message_handler(void *client, MQTTMessage *message, void *user_data) +{ + if (message == NULL) { + return; + } -#ifdef AUTH_MODE_CERT - /* 网关客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_GW_DEVICE_NAME_cert.crt" - /* 网关客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_GW_DEVICE_NAME_private.key" + Log_i("Receive Message With topicName:%.*s, payload:%.*s", (int)message->topic_len, + STRING_PTR_PRINT_SANITY_CHECK(message->ptopic), (int)message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); +} - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 +static int _setup_gw_init_params(GatewayInitParam *gw_init_params, GatewayDeviceInfo *gw_dev_info) +{ + MQTTInitParams *init_params = &gw_init_params->init_param; + DeviceInfo * dev_info = &gw_dev_info->gw_info; + init_params->product_id = dev_info->product_id; + init_params->device_name = dev_info->device_name; +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(init_params->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_cert_file_name)); + HAL_Snprintf(init_params->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_key_file_name)); #else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_GW_IOT_PSK" + HAL_Snprintf(init_params->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_cert_file_name)); + HAL_Snprintf(init_params->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_key_file_name)); #endif -/* 子产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_SUBDEV_PRODUCT_ID "YOUR_SUBDEV_PRODUCT_ID" -/* 子设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_SUBDEV_DEVICE_NAME "YOUR_SUBDEV_DEVICE_NAME" - - -#define MAX_SIZE_OF_TOPIC (128) -#define MAX_SIZE_OF_DATA (128) - +#else + init_params->device_secret = dev_info->device_secret; +#endif -#if 1 + init_params->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + init_params->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; -//static int sg_count = 0; -static int sg_sub_packet_id = -1; + init_params->auto_connect_enable = 1; + init_params->event_handle.h_fp = _event_handler; + init_params->event_handle.context = NULL; + return QCLOUD_RET_SUCCESS; +} -void _event_handler(void *client, void *context, MQTTEventMsg *msg) +// subscribe subdev MQTT topic and wait for sub result +static int _subscribe_subdev_topic_wait_result(void *client, char *topic_keyword, QoS qos, GatewayParam *gw_info) { - MQTTMessage* mqtt_messge = (MQTTMessage*)msg->msg; - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_PUBLISH_RECVEIVED: - Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - mqtt_messge->topic_len, - mqtt_messge->ptopic, - mqtt_messge->payload_len, - mqtt_messge->payload); - break; - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - sg_sub_packet_id = packet_id; - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - sg_sub_packet_id = packet_id; - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - sg_sub_packet_id = packet_id; - break; - - case MQTT_EVENT_UNSUBCRIBE_SUCCESS: - Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_NACK: - Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } + char topic_name[128] = {0}; + int size = HAL_Snprintf( + topic_name, sizeof(topic_name), "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(gw_info->subdev_product_id), + STRING_PTR_PRINT_SANITY_CHECK(gw_info->subdev_device_name), STRING_PTR_PRINT_SANITY_CHECK(topic_keyword)); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.qos = qos; + sub_params.on_message_handler = _message_handler; + + int rc = IOT_Gateway_Subscribe(client, topic_name, &sub_params); + if (rc < 0) { + Log_e("IOT_Gateway_Subscribe fail."); + return rc; + } + + int wait_cnt = 10; + while (!IOT_Gateway_IsSubReady(client, topic_name) && (wait_cnt > 0)) { + // wait for subscription result + rc = IOT_Gateway_Yield(client, 1000); + if (rc) { + Log_e("MQTT error: %d", rc); + return rc; + } + wait_cnt--; + } + + if (wait_cnt > 0) { + return QCLOUD_RET_SUCCESS; + } else { + Log_e("wait for subscribe result timeout!"); + return QCLOUD_ERR_FAILURE; + } } - -static void _message_handler(void *client, MQTTMessage *message, void *user_data) +// publish MQTT msg +static int _publish_subdev_msg(void *client, char *topic_keyword, QoS qos, GatewayParam *gw_info) { - if (message == NULL) { - return; - } - - Log_i("Receive Message With topicName:%.*s, payload:%.*s", - (int) message->topic_len, message->ptopic, (int) message->payload_len, (char *) message->payload); + char topic_name[128] = {0}; + int size = HAL_Snprintf( + topic_name, sizeof(topic_name), "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(gw_info->subdev_product_id), + STRING_PTR_PRINT_SANITY_CHECK(gw_info->subdev_device_name), STRING_PTR_PRINT_SANITY_CHECK(topic_keyword)); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + + static int test_count = 0; + PublishParams pub_params = DEFAULT_PUB_PARAMS; + pub_params.qos = qos; + + char topic_content[128] = {0}; + size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"gateway_test\", \"count\": \"%d\"}", + test_count++); + if (size < 0 || size > sizeof(topic_content) - 1) { + Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); + return -3; + } + + pub_params.payload = topic_content; + pub_params.payload_len = strlen(topic_content); + + return IOT_Gateway_Publish(client, topic_name, &pub_params); } -#endif -int demo_gateway() +static void _get_gw_subdev_bindlist(void *client, GatewayParam *gw_param) { - int rc = QCLOUD_ERR_FAILURE; - int count = 0; - void* client = NULL; - - GatewayInitParam init_params = DEFAULT_GATEWAY_INIT_PARAMS; - init_params.init_param.product_id = QCLOUD_IOT_MY_PRODUCT_ID; - init_params.init_param.device_name = QCLOUD_IOT_MY_DEVICE_NAME; - + SubdevBindList bindlist; + SubdevBindInfo *cur_bindinfo = NULL; + int rc; + + bindlist.bindlist_head = NULL; + bindlist.bind_num = 0; + + rc = IOT_Gateway_Subdev_GetBindList(client, gw_param, &bindlist); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get sub device bind list failed: %d", rc); + } else { + cur_bindinfo = bindlist.bindlist_head; + HAL_Printf("bind list sub device nums: %d\r\n", bindlist.bind_num); + if (NULL == cur_bindinfo) { + Log_e("gateway no bind sub device on cloud platform"); + } else { + HAL_Printf("bind list sub device info:\r\n"); + int count = 1; + while (cur_bindinfo) { + HAL_Printf("sub device: %05d product_id: % -11s device_name: % -49s\r\n", count, + STRING_PTR_PRINT_SANITY_CHECK(cur_bindinfo->product_id), + STRING_PTR_PRINT_SANITY_CHECK(cur_bindinfo->device_name)); + cur_bindinfo = cur_bindinfo->next; + count += 1; + } + // destory bind list + IOT_Gateway_Subdev_DestoryBindList(&bindlist); + } + } + + return; +} -#ifdef AUTH_MODE_CERT - // 获取CA证书、客户端证书以及私钥文件的路径 - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - init_params.init_param.cert_file = sg_cert_file; - init_params.init_param.key_file = sg_key_file; -#else - init_params.init_param.device_secret = QCLOUD_IOT_DEVICE_SECRET; -#endif +// for reply code, pls check https://cloud.tencent.com/document/product/634/45960 +#define GATEWAY_RC_REPEAT_BIND 809 +static char *new_subdev_file = NULL; +static int sg_loop_count = 5; - init_params.init_param.command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - init_params.init_param.auto_connect_enable = 1; - init_params.init_param.event_handle.h_fp = _event_handler; - client = IOT_Gateway_Construct(&init_params); - if (client == NULL) { - Log_e("client constructed failed."); - return QCLOUD_ERR_FAILURE; - } - - //上线子设备 - GatewayParam param = DEFAULT_GATEWAY_PARAMS;; - param.product_id = QCLOUD_IOT_MY_PRODUCT_ID; - param.device_name = QCLOUD_IOT_MY_DEVICE_NAME; - - param.subdev_product_id = QCLOUD_IOT_SUBDEV_PRODUCT_ID; - param.subdev_device_name = QCLOUD_IOT_SUBDEV_DEVICE_NAME; - - rc = IOT_Gateway_Subdev_Online(client, ¶m); - if(rc != QCLOUD_ERR_SUCCESS) { - Log_e("IOT_Gateway_Subdev_Online fail."); - return rc; - } -#if 1 - //订阅消息 - char topic_filter[MAX_SIZE_OF_TOPIC+1] = {0}; - SubscribeParams sub_param = DEFAULT_SUB_PARAMS; - int size = HAL_Snprintf(topic_filter, MAX_SIZE_OF_TOPIC+1, "%s/%s/data", QCLOUD_IOT_SUBDEV_PRODUCT_ID, QCLOUD_IOT_SUBDEV_DEVICE_NAME); - if (size < 0 || size > MAX_SIZE_OF_TOPIC) - { - Log_e("buf size < topic length!"); - return QCLOUD_ERR_FAILURE; - } - sub_param.on_message_handler = _message_handler; - rc = IOT_Gateway_Subscribe(client, topic_filter, &sub_param); - if(rc < 0) { - Log_e("IOT_Gateway_Subscribe fail."); - return rc; - } - - rc = IOT_Gateway_Yield(client, 200); - - //发布消息 - char topic_name[MAX_SIZE_OF_TOPIC+1] = {0}; - PublishParams pub_param = DEFAULT_PUB_PARAMS; - size = HAL_Snprintf(topic_name, MAX_SIZE_OF_TOPIC+1, "%s/%s/data", QCLOUD_IOT_SUBDEV_PRODUCT_ID, QCLOUD_IOT_SUBDEV_DEVICE_NAME); - if (size < 0 || size > MAX_SIZE_OF_TOPIC) - { - Log_e("buf size < topic length!"); - return QCLOUD_ERR_FAILURE; - } - - pub_param.qos = QOS1; - pub_param.payload = "{\"data\":\"test gateway\"}"; - pub_param.payload_len = sizeof("{\"data\":\"test gateway\"}"); - - do { - if(sg_sub_packet_id > 0) { - rc = IOT_Gateway_Publish(client, topic_name, &pub_param); - if(rc < 0) { - Log_e("IOT_Gateway_Publish fail."); - } - } - rc = IOT_Gateway_Yield(client, 200); - - if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { - sleep(1); - continue; - } - else if (rc != QCLOUD_ERR_SUCCESS && rc != QCLOUD_ERR_MQTT_RECONNECTED){ - Log_e("exit with error: %d", rc); - break; - } - - sleep(1); - - } while (count++ < 1); -#endif - //下线子设备 - rc = IOT_Gateway_Subdev_Offline(client, ¶m); - if(rc != QCLOUD_ERR_SUCCESS) { - Log_e("IOT_Gateway_Subdev_Offline fail."); - return rc; - } - - rc = IOT_Gateway_Destroy(client); - - return rc; +static int parse_arguments(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "c:b:l:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + case 'b': + new_subdev_file = utils_optarg; + break; + + case 'l': + sg_loop_count = atoi(utils_optarg); + if (sg_loop_count > 10000) + sg_loop_count = 10000; + else if (sg_loop_count < 0) + sg_loop_count = 1; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n" + " [-b ] \n" + " [-l ] \n", + argv[0]); + return -1; + } + return 0; } -int main() +int main(int argc, char **argv) { - IOT_Log_Set_Level(DEBUG); - - demo_gateway(); + int rc = QCLOUD_ERR_FAILURE; + void *client = NULL; + + IOT_Log_Set_Level(eLOG_DEBUG); + + // parse arguments for device info file and loop test; + rc = parse_arguments(argc, argv); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("parse arguments error, rc = %d", rc); + return rc; + } + + GatewayDeviceInfo gw_dev_info; + rc = HAL_GetGwDevInfo((void *)&gw_dev_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("Get gateway dev info err,rc:%d", rc); + return rc; + } + + GatewayInitParam init_params = DEFAULT_GATEWAY_INIT_PARAMS; + _setup_gw_init_params(&init_params, &gw_dev_info); + + client = IOT_Gateway_Construct(&init_params); + if (client == NULL) { + Log_e("client constructed failed."); + return QCLOUD_ERR_FAILURE; + } + + // make sub-device online + GatewayParam gw_param = DEFAULT_GATEWAY_PARAMS; + gw_param.product_id = gw_dev_info.gw_info.product_id; + gw_param.device_name = gw_dev_info.gw_info.device_name; + + DeviceInfo *sub_dev_info = gw_dev_info.sub_dev_info; + + // to bind a new sub device + DeviceInfo new_sub_dev = {0}; + if (new_subdev_file) { + do { + rc = HAL_GetDevInfoFromFile(new_subdev_file, &new_sub_dev); + if (rc) { + Log_e("get devinfo from file failed: %d", rc); + break; + } + + rc = IOT_Gateway_Subdev_Bind(client, &gw_param, &new_sub_dev); + if (rc == QCLOUD_RET_SUCCESS || rc == GATEWAY_RC_REPEAT_BIND) { + Log_i("bind sub-device %s-%s success", new_sub_dev.product_id, new_sub_dev.device_name); + sub_dev_info = &new_sub_dev; + break; + } else { + Log_e("bind subdev failed: %d", rc); + } + } while (0); + } + + gw_param.subdev_product_id = sub_dev_info->product_id; + gw_param.subdev_device_name = sub_dev_info->device_name; + +#if 0 + // one GatewayParam only support one sub-device + // use more GatewayParam to add more sub-device + GatewayParam gw_param1 = DEFAULT_GATEWAY_PARAMS;; + gw_param1.product_id = gw_dev_info.gw_info.product_id; + gw_param1.device_name = gw_dev_info.gw_info.device_name; + + gw_param1.subdev_product_id = "SUB-PRODUCT"; + gw_param1.subdev_device_name = "SUB-DEVICE"; +#endif - return 0; + // get bind list from cloud platform + _get_gw_subdev_bindlist(client, &gw_param); + + rc = IOT_Gateway_Subdev_Online(client, &gw_param); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("IOT_Gateway_Subdev_Online fail."); + return rc; + } + + // gateway proxy loop for sub-device + // subscribe sub-device topic + rc = _subscribe_subdev_topic_wait_result(client, "data", QOS0, &gw_param); + if (rc) { + Log_e("Subdev Subscribe Topic Failed: %d", rc); + return rc; + } + + do { + // get bind list from cloud platform + if (sg_loop_count % 60 == 0) { + _get_gw_subdev_bindlist(client, &gw_param); + } + + // publish msg to sub-device topic + rc = _publish_subdev_msg(client, "data", QOS1, &gw_param); + if (rc < 0) { + Log_e("IOT_Gateway_Publish fail."); + } + + rc = IOT_Gateway_Yield(client, 200); + + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + HAL_SleepMs(1000); + + } while (--sg_loop_count > 0); + + // make sub-device offline + rc = IOT_Gateway_Subdev_Offline(client, &gw_param); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("IOT_Gateway_Subdev_Offline fail."); + return rc; + } + + if (new_subdev_file) { + rc = IOT_Gateway_Subdev_Unbind(client, &gw_param, &new_sub_dev); + if (rc) { + Log_e("unbind failed: %d", rc); + } + } + + rc = IOT_Gateway_Destroy(client); + + return rc; } diff --git a/samples/mqtt/mqtt_sample.c b/samples/mqtt/mqtt_sample.c old mode 100644 new mode 100755 index e1b178db..b0c836e1 --- a/samples/mqtt/mqtt_sample.c +++ b/samples/mqtt/mqtt_sample.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,388 +13,356 @@ * */ +#include #include #include -#include -#include -#include #include -#include #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" +#include "utils_getopt.h" +// MQTT event callback +static void _mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + MQTTMessage *mqtt_messge = (MQTTMessage *)msg->msg; + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + mqtt_messge->topic_len, STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->ptopic), mqtt_messge->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->payload)); + break; + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" +// Setup MQTT construct parameters +static int _setup_connect_init_params(MQTTInitParams *initParams, DeviceInfo *device_info) +{ + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; #ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); #else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); #endif -#define MAX_SIZE_OF_TOPIC_CONTENT 100 - -static int sg_count = 0; -static int sg_sub_packet_id = -1; - -bool log_handler(const char* message) { - //实现日志回调的写方法 - //实现内容后请返回true - return false; -} - -void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) { - MQTTMessage* mqtt_messge = (MQTTMessage*)msg->msg; - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_PUBLISH_RECVEIVED: - Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - mqtt_messge->topic_len, - mqtt_messge->ptopic, - mqtt_messge->payload_len, - mqtt_messge->payload); - break; - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - sg_sub_packet_id = packet_id; - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - sg_sub_packet_id = packet_id; - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - sg_sub_packet_id = packet_id; - break; - - case MQTT_EVENT_UNSUBCRIBE_SUCCESS: - Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_NACK: - Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } -} - -/** - * MQTT消息接收处理函数 - * - * @param topicName topic主题 - * @param topicNameLen topic长度 - * @param message 已订阅消息的结构 - * @param userData 消息负载 - */ -static void on_message_callback(void *pClient, MQTTMessage *message, void *userData) { - if (message == NULL) { - return; - } - - Log_i("Receive Message With topicName:%.*s, payload:%.*s", - (int) message->topic_len, message->ptopic, (int) message->payload_len, (char *) message->payload); -} - -/** - * 设置MQTT connet初始化参数 - * - * @param initParams MQTT connet初始化参数 - * - * @return 0: 参数初始化成功 非0: 失败 - */ -static int _setup_connect_init_params(MQTTInitParams* initParams) -{ - initParams->device_name = QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = QCLOUD_IOT_MY_PRODUCT_ID; - -#ifdef AUTH_MODE_CERT - /* 使用非对称加密*/ - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - initParams->cert_file = sg_cert_file; - initParams->key_file = sg_key_file; #else - initParams->device_secret = QCLOUD_IOT_DEVICE_SECRET; + initParams->device_secret = device_info->device_secret; #endif - initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; - initParams->auto_connect_enable = 1; - initParams->event_handle.h_fp = event_handler; - initParams->event_handle.context = NULL; + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = _mqtt_event_handler; + initParams->event_handle.context = NULL; - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } -/** - * 发送topic消息 - * - */ -static int _publish_msg(void *client) +// publish MQTT msg +static int _publish_test_msg(void *client, char *topic_keyword, QoS qos) { - char topicName[128] = {0}; - sprintf(topicName,"%s/%s/%s", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME, "data"); + char topic_name[128] = {0}; + DeviceInfo *dev_info = IOT_MQTT_GetDeviceInfo(client); + + int size = HAL_Snprintf( + topic_name, sizeof(topic_name), "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name), STRING_PTR_PRINT_SANITY_CHECK(topic_keyword)); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + static int test_count = 0; PublishParams pub_params = DEFAULT_PUB_PARAMS; - pub_params.qos = QOS1; + pub_params.qos = qos; + + char topic_content[128] = {0}; + size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"publish_test\", \"count\": \"%d\"}", + test_count++); + if (size < 0 || size > sizeof(topic_content) - 1) { + Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); + return -3; + } - char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; + pub_params.payload = topic_content; + pub_params.payload_len = strlen(topic_content); - int size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"publish_test\", \"count\": \"%d\"}", sg_count++); - if (size < 0 || size > sizeof(topic_content) - 1) - { - Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); - return -3; - } + return IOT_MQTT_Publish(client, topic_name, &pub_params); +} - pub_params.payload = topic_content; - pub_params.payload_len = strlen(topic_content); +// callback when MQTT msg arrives +static void _on_message_callback(void *pClient, MQTTMessage *message, void *userData) +{ + if (message == NULL) { + return; + } - return IOT_MQTT_Publish(client, topicName, &pub_params); + Log_i("Receive Message With topicName:%.*s, payload:%.*s", (int)message->topic_len, + STRING_PTR_PRINT_SANITY_CHECK(message->ptopic), (int)message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); } -/** - * 订阅关注topic和注册相应回调处理 - * - */ -static int _register_subscribe_topics(void *client) +// subscribe MQTT topic and wait for sub result +static int _subscribe_topic_wait_result(void *client, char *topic_keyword, QoS qos) { - char topic_name[128] = {0}; - int size = HAL_Snprintf(topic_name, sizeof(topic_name), "%s/%s/%s", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME, "data"); - if (size < 0 || size > sizeof(topic_name) - 1) - { + char topic_name[128] = {0}; + DeviceInfo *dev_info = IOT_MQTT_GetDeviceInfo(client); + + int size = HAL_Snprintf( + topic_name, sizeof(topic_name), "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name), STRING_PTR_PRINT_SANITY_CHECK(topic_keyword)); + if (size < 0 || size > sizeof(topic_name) - 1) { Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); return QCLOUD_ERR_FAILURE; } - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.on_message_handler = on_message_callback; - return IOT_MQTT_Subscribe(client, topic_name, &sub_params); -} -#ifdef LOG_UPLOAD + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.qos = qos; + sub_params.on_message_handler = _on_message_callback; + + int rc = IOT_MQTT_Subscribe(client, topic_name, &sub_params); + if (rc < 0) { + Log_e("MQTT subscribe FAILED: %d", rc); + return rc; + } -#define LOG_SAVE_FILE_PATH "./upload-fail-save.log" + int wait_cnt = 10; + while (!IOT_MQTT_IsSubReady(client, topic_name) && (wait_cnt > 0)) { + // wait for subscription result + rc = IOT_MQTT_Yield(client, 1000); + if (rc) { + Log_e("MQTT error: %d", rc); + return rc; + } + wait_cnt--; + } -/** - * 日志上报功能用户自定义回调函数,用于上报失败时的缓存和通讯恢复后的重传 - * sample示例采用读写文件的方式来处理,需要有文件系统支持 - */ -//缓存指定长度日志到非易失性存储(比如文件),返回值为成功写入的长度 -static size_t _log_save_callback(const char *msg, size_t wLen) -{ - FILE *fp; - size_t len; - - if( ( fp = fopen(LOG_SAVE_FILE_PATH, "a+" ) ) == NULL ) { - Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); - return 0; - } - - len = fwrite((void *)msg, 1, wLen, fp); - Log_d("write %d of %d to log file", len, wLen); - - fclose(fp); - - return len; + if (wait_cnt > 0) { + return QCLOUD_RET_SUCCESS; + } else { + Log_e("wait for subscribe result timeout!"); + return QCLOUD_ERR_FAILURE; + } } -//从非易失性存储(比如文件)读取指定长度日志,返回值为成功读取的长度 -static size_t _log_read_callback(char *buff, size_t rLen) +#ifdef LOG_UPLOAD +// init log upload module +static int _init_log_upload(MQTTInitParams *init_params) { - FILE *fp; - size_t len; + LogUploadInitParams log_init_params; + memset(&log_init_params, 0, sizeof(LogUploadInitParams)); - if( ( fp = fopen(LOG_SAVE_FILE_PATH, "r" ) ) == NULL ) { - Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); - return 0; - } + log_init_params.product_id = init_params->product_id; + log_init_params.device_name = init_params->device_name; +#ifdef AUTH_MODE_CERT + log_init_params.sign_key = init_params->cert_file; +#else + log_init_params.sign_key = init_params->device_secret; +#endif - len = fread((void *)buff, 1, rLen, fp); - Log_d("read %d of %d from log file", len, rLen); - - fclose(fp); +#if defined(__linux__) || defined(WIN32) + log_init_params.read_func = HAL_Log_Read; + log_init_params.save_func = HAL_Log_Save; + log_init_params.del_func = HAL_Log_Del; + log_init_params.get_size_func = HAL_Log_Get_Size; +#endif - return len; + return IOT_Log_Init_Uploader(&log_init_params); } -//从非易失性存储(比如文件)删除缓存的日志,返回值为0删除成功,非0删除失败 -static int _log_del_callback(void) -{ - return remove(LOG_SAVE_FILE_PATH); -} +#endif -//获取存储在非易失性存储(比如文件)中的log长度,返回0为没有缓存 -static size_t _log_get_size_callback() +static bool sg_loop_test = false; +static int parse_arguments(int argc, char **argv) { - long length; - FILE *fp; - - /* check if file exists */ - if (access(LOG_SAVE_FILE_PATH, 0)) - return 0; - - if( ( fp = fopen(LOG_SAVE_FILE_PATH, "r" ) ) == NULL ) { - Log_e("fail to open file %s", LOG_SAVE_FILE_PATH); - return 0; - } - - fseek(fp, 0L, SEEK_END); - length = ftell(fp); - fclose(fp); - if (length > 0) - return (size_t)length; - else - return 0; + int c; + while ((c = utils_getopt(argc, argv, "c:l")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + case 'l': + sg_loop_test = true; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n" + " [-l ] loop test or not\n", + argv[0]); + return -1; + } + return 0; } -#endif +int main(int argc, char **argv) +{ + int rc; + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); -int main(int argc, char **argv) { + // parse arguments for device info file and loop test; + rc = parse_arguments(argc, argv); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("parse arguments error, rc = %d", rc); + return rc; + } - //init log level - IOT_Log_Set_Level(DEBUG); - IOT_Log_Set_MessageHandler(log_handler); - - int rc; + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + return rc; + } - // to avoid process crash when writing to a broken socket - signal(SIGPIPE, SIG_IGN); - - //init connection + // init connection MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; - rc = _setup_connect_init_params(&init_params); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } + rc = _setup_connect_init_params(&init_params, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params error, rc = %d", rc); + return rc; + } #ifdef LOG_UPLOAD - // IOT_Log_Init_Uploader should be done after _setup_connect_init_params - LogUploadInitParams log_init_params = {.product_id = QCLOUD_IOT_MY_PRODUCT_ID, - .device_name = QCLOUD_IOT_MY_DEVICE_NAME, .sign_key = NULL, - .read_func = _log_read_callback, .save_func = _log_save_callback, - .del_func = _log_del_callback, .get_size_func = _log_get_size_callback}; -#ifdef AUTH_MODE_CERT - log_init_params.sign_key = sg_cert_file; -#else - log_init_params.sign_key = QCLOUD_IOT_DEVICE_SECRET; -#endif - IOT_Log_Init_Uploader(&log_init_params); + // _init_log_upload should be done after _setup_connect_init_params and before IOT_MQTT_Construct + rc = _init_log_upload(&init_params); + if (rc != QCLOUD_RET_SUCCESS) + Log_e("init log upload error, rc = %d", rc); #endif + // create MQTT client and connect with server void *client = IOT_MQTT_Construct(&init_params); if (client != NULL) { Log_i("Cloud Device Construct Success"); } else { - Log_e("Cloud Device Construct Failed"); + Log_e("MQTT Construct failed!"); IOT_Log_Upload(true); return QCLOUD_ERR_FAILURE; } #ifdef SYSTEM_COMM long time = 0; + // get system timestamp from server + rc = IOT_Get_SysTime(client, &time); + if (QCLOUD_RET_SUCCESS == rc) { + Log_i("system time is %ld", time); + } else { + Log_e("get system time failed!"); + } - rc = IOT_SYSTEM_GET_TIME(client, &time); - if (QCLOUD_ERR_SUCCESS == rc){ - Log_i("system time is %ld", time); - } - else{ - Log_e("get system time failed!"); - } + // Sync time by NTP timestamp from server + rc = IOT_Sync_NTPTime(client); + if (QCLOUD_RET_SUCCESS == rc) { + Log_i("sync ntp time success!"); + } else { + Log_e("sync ntp time failed!"); + } #endif - //register subscribe topics here - rc = _register_subscribe_topics(client); - if (rc < 0) { + // subscribe normal topics and wait result + rc = _subscribe_topic_wait_result(client, "data", QOS0); + if (rc) { Log_e("Client Subscribe Topic Failed: %d", rc); IOT_Log_Upload(true); return rc; } - rc = IOT_MQTT_Yield(client, 200); - do { - // 等待订阅结果 - if (sg_sub_packet_id > 0) { - rc = _publish_msg(client); - if (rc < 0) { - Log_e("client publish topic failed :%d.", rc); - } - } - - rc = IOT_MQTT_Yield(client, 200); - - if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { - sleep(1); - continue; - } - else if (rc != QCLOUD_ERR_SUCCESS && rc != QCLOUD_ERR_MQTT_RECONNECTED){ - Log_e("exit with error: %d", rc); - break; - } - - if (argc >= 2) - sleep(1); - - } while (argc >= 2 && !strcmp("loop", argv[1])); + rc = _publish_test_msg(client, "data", QOS1); + if (rc < 0) { + Log_e("client publish topic failed :%d.", rc); + } + + rc = IOT_MQTT_Yield(client, 500); + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + if (sg_loop_test) + HAL_SleepMs(1000); + + } while (sg_loop_test); rc = IOT_MQTT_Destroy(&client); - //注意进程异常退出情况 - + IOT_Log_Upload(true); - + return rc; } diff --git a/samples/mqtt/multi_thread_mqtt_sample.c b/samples/mqtt/multi_thread_mqtt_sample.c old mode 100644 new mode 100755 index af9115d6..0f159b08 --- a/samples/mqtt/multi_thread_mqtt_sample.c +++ b/samples/mqtt/multi_thread_mqtt_sample.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,494 +13,454 @@ * */ +#include #include #include -#include -#include -#include #include -#include -#include -#include -#include +#include "lite-utils.h" #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" /* - * 多线程环境使用SDK注意事项: - * 1. 不允许多线程调用IOT_MQTT_Yield,IOT_MQTT_Construct以及IOT_MQTT_Destroy - * 2. 可以多线程调用IOT_MQTT_Publish,IOT_MQTT_Subscribe及IOT_MQTT_Unsubscribe - * 3. IOT_MQTT_Yield 作为从socket读取并处理MQTT报文的函数,应保证一定的执行时间,避免被长时间挂起或抢占 + * Notes for using SDK in multi-thread programing + * 1. IOT_MQTT_Yield, IOT_MQTT_Construct and IOT_MQTT_Destroy are NOT thread-safe, only calling them in the same thread + * 2. IOT_MQTT_Publish, IOT_MQTT_Subscribe and IOT_MQTT_Unsubscribe are thread-safe, and be executed in multi-threads + * simultaneously + * 3. IOT_MQTT_Yield is the only entry to read from socket and should not be hand up for long + * 4. Using IOT_MQTT_StartLoop to start a default thread for IOT_MQTT_Yield is recommended */ /* - * 本示例程序基于Linux pthread环境对MQTT接口函数进行多线程测试,注意该测试设备数据格式应为自定义,非JSON格式 + * This sample test MQTT multi-thread performance for one device. */ -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" +#define MAX_PUB_THREAD_COUNT 5 +#define PUBLISH_COUNT 10 +#define THREAD_SLEEP_INTERVAL_MS 1000 +#define RX_RECEIVE_PERCENTAGE 99.0f +#define MAX_SIZE_OF_TOPIC_CONTENT 100 -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" +// device info +static DeviceInfo sg_device_info; - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 +static bool sg_sub_unsub_thread_quit; +static unsigned int sg_rx_count_array[MAX_PUB_THREAD_COUNT] + [PUBLISH_COUNT]; // record the times when msg from subscribed topic is received +static unsigned int sg_rx_msg_buf_too_big_count; // record the times when msg is oversize +static unsigned int sg_rx_unexpected_count; // record the times when unexpected msg is received +static unsigned int sg_republish_count; // record the times of re-publish +static char sg_pub_sub_test_topic[MAX_SIZE_OF_TOPIC_CONTENT]; // topic for sub/pub -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" -#endif +typedef struct AppThreadData { + void *client; + int thread_id; + int thread_status; +} AppThreadData; -#define MAX_SIZE_OF_TOPIC_CONTENT 100 -#define MAX_PUB_THREAD_COUNT 5 -#define PUBLISH_COUNT 10 -#define THREAD_SLEEP_INTERVAL_USEC 500000 -#define CONNECT_MAX_ATTEMPT_COUNT 3 -#define RX_RECEIVE_PERCENTAGE 99.0f -#define INTEGRATION_TEST_TOPIC ""QCLOUD_IOT_MY_PRODUCT_ID"/"QCLOUD_IOT_MY_DEVICE_NAME"/data" // 需要创建设备的时候配置权限 - -static bool sg_terminate_yield_thread; -static bool sg_terminate_subUnsub_thread; - -static unsigned int sg_countArray[MAX_PUB_THREAD_COUNT][PUBLISH_COUNT]; // 订阅回调函数中,每次成功收订阅topic返回的数据的时候,记录每个订阅的成功次数 -static unsigned int sg_rxMsgBufferTooBigCounter; // 记录收到消息长度过长的次数 -static unsigned int sg_rxUnexpectedNumberCounter; // 记录收到错误消息的次数 -static unsigned int sg_rePublishCount; // 记录重新发布的次数 -static unsigned int sg_wrongYieldCount; // 记录yield失败的次数 -static unsigned int sg_threadStatus[MAX_PUB_THREAD_COUNT]; // 记录所有线程的状态 - -typedef struct ThreadData { - int threadId; - void *client; -} ThreadData; - - -void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) { - MQTTMessage* mqtt_messge = (MQTTMessage*)msg->msg; - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_PUBLISH_RECVEIVED: - Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - mqtt_messge->topic_len, - mqtt_messge->ptopic, - mqtt_messge->payload_len, - mqtt_messge->payload); - break; - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_SUCCESS: - Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_NACK: - Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } +void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + MQTTMessage *mqtt_messge = (MQTTMessage *)msg->msg; + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + mqtt_messge->topic_len, STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->ptopic), mqtt_messge->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->payload)); + break; + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } } -static int _setup_connect_init_params(MQTTInitParams* initParams) +static int _setup_connect_init_params(MQTTInitParams *initParams) { - initParams->device_name = QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = QCLOUD_IOT_MY_PRODUCT_ID; + int ret; + + ret = HAL_GetDevInfo((void *)&sg_device_info); + if (QCLOUD_RET_SUCCESS != ret) { + return ret; + } + + initParams->device_name = sg_device_info.device_name; + initParams->product_id = sg_device_info.product_id; #ifdef AUTH_MODE_CERT - /* 使用非对称加密*/ - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - initParams->cert_file = sg_cert_file; - initParams->key_file = sg_key_file; + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_device_info.dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_device_info.dev_key_file_name)); #else - initParams->device_secret = QCLOUD_IOT_DEVICE_SECRET; + initParams->device_secret = sg_device_info.device_secret; #endif + memset(sg_pub_sub_test_topic, 0, MAX_SIZE_OF_TOPIC_CONTENT); + HAL_Snprintf(sg_pub_sub_test_topic, MAX_SIZE_OF_TOPIC_CONTENT, "%s/%s/data", + STRING_PTR_PRINT_SANITY_CHECK(sg_device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(sg_device_info.device_name)); - initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; - initParams->auto_connect_enable = 1; - initParams->event_handle.h_fp = event_handler; + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = event_handler; - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } -/** - * 订阅topic回调函数,解析payload报文- 自定义格式,非JSON格式 - */ -static void _mqtt_message_handler(void *pClient, MQTTMessage *message, void *userData) +static void _mqtt_message_handler(void *pClient, MQTTMessage *message, void *userData) { - if (message == NULL) { - return; - } - - if(MAX_SIZE_OF_TOPIC_CONTENT >= message->payload_len) { - /* 解析 payload */ - char tempBuf[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; - unsigned int tempRow = 0, tempCol = 0; - char *temp = NULL; - - HAL_Snprintf(tempBuf, message->payload_len + 1, "%s", (char *)message->payload); - Log_d("Message received : %s", tempBuf); - temp = strtok(tempBuf, " ,:"); - if(NULL == temp) { - return; - } - temp = strtok(NULL, " ,:"); - if(NULL == temp) { - return; - } - tempRow = atoi(temp); - temp = strtok(NULL, " ,:"); - if(NULL == temp) { - return; - } - temp = strtok(NULL, " ,:"); - if(NULL == temp) { - return; - } - tempCol = atoi(temp); - - if(((tempRow - 1) < MAX_PUB_THREAD_COUNT) && (tempCol < PUBLISH_COUNT)) { - sg_countArray[tempRow - 1][tempCol]++; - } else { - Log_e(" Unexpected Thread : %d, Message : %d ", tempRow, tempCol); - sg_rxUnexpectedNumberCounter++; - } - } else { - sg_rxMsgBufferTooBigCounter++; - } -} - -/** - * yield 测试线程函数 - */ -static void *_mqtt_yield_thread_runner(void *ptr) { - int rc = QCLOUD_ERR_SUCCESS; - void *pClient = ptr; - - while(false == sg_terminate_yield_thread) { + if (message == NULL) { + return; + } - rc = IOT_MQTT_Yield(pClient, 200); + if (MAX_SIZE_OF_TOPIC_CONTENT >= message->payload_len) { + /* parsing payload */ + char tempBuf[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; + unsigned int tempRow = 0, tempCol = 0; + char * temp = NULL; + + HAL_Snprintf(tempBuf, message->payload_len + 1, "%s", STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); + Log_d("Message received : %s", tempBuf); + + char *count_value = LITE_json_value_of("count", tempBuf); + if (count_value != NULL) { + tempCol = atoi(count_value); + HAL_Free(count_value); + } else { + Log_e("count value not found!"); + sg_rx_unexpected_count++; + return; + } - if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { - usleep(THREAD_SLEEP_INTERVAL_USEC); - continue; + char *action_value = LITE_json_value_of("action", tempBuf); + if (action_value != NULL) { + temp = strstr(action_value, "-"); + if (NULL != temp) { + tempRow = atoi(temp + 1); + HAL_Free(action_value); + } else { + HAL_Free(action_value); + Log_e("invalid action value: %s", action_value); + sg_rx_unexpected_count++; + return; + } + } else { + Log_e("action value not found!"); + sg_rx_unexpected_count++; + return; } - else if (rc != QCLOUD_ERR_SUCCESS && rc != QCLOUD_ERR_MQTT_RECONNECTED){ - Log_e("Yield thread exit with error: %d", rc); - break; + + if (((tempRow - 1) < MAX_PUB_THREAD_COUNT) && (tempCol < PUBLISH_COUNT)) { + sg_rx_count_array[tempRow - 1][tempCol]++; + } else { + Log_e(" Unexpected Thread : %d, Message : %d ", tempRow, tempCol); + sg_rx_unexpected_count++; } - usleep(THREAD_SLEEP_INTERVAL_USEC); - } - return NULL; + } else { + sg_rx_msg_buf_too_big_count++; + } } /** - * subscribe/unsubscribe 测试线程函数 - * 函数中会在一个单独的线程中先订阅相关主题,然后再取消订阅 + * subscribe/unsubscribe test thread runner + * subscribed and unsubscribe */ -static void *_mqtt_sub_unsub_thread_runner(void *ptr) { - int rc = QCLOUD_ERR_SUCCESS; - void *pClient = ptr; - char testTopic[128]; - HAL_Snprintf(testTopic, 128, ""QCLOUD_IOT_MY_PRODUCT_ID"/"QCLOUD_IOT_MY_DEVICE_NAME"/control"); - - while(QCLOUD_ERR_SUCCESS == rc && false == sg_terminate_subUnsub_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.qos = QOS1; - sub_params.on_message_handler = _mqtt_message_handler; - rc = IOT_MQTT_Subscribe(pClient, testTopic, &sub_params); - - } while(QCLOUD_ERR_MQTT_NO_CONN == rc || QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); - - if(rc < 0) { - Log_e("Subscribe failed. Ret : %d ", rc); - } - - sleep(1); - - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = IOT_MQTT_Unsubscribe(pClient, testTopic); - } while(QCLOUD_ERR_MQTT_NO_CONN == rc|| QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); - - if(rc < 0) { - Log_e("Unsubscribe failed. Returned : %d ", rc); - } - } - return NULL; +static void _mqtt_sub_unsub_thread_runner(void *ptr) +{ + int rc = QCLOUD_RET_SUCCESS; + void *pClient = ptr; + char testTopic[128]; + HAL_Snprintf(testTopic, 128, "%s/%s/control", STRING_PTR_PRINT_SANITY_CHECK(sg_device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(sg_device_info.device_name)); + + while (QCLOUD_RET_SUCCESS == rc && false == sg_sub_unsub_thread_quit) { + do { + HAL_SleepMs(THREAD_SLEEP_INTERVAL_MS); + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.qos = QOS1; + sub_params.on_message_handler = _mqtt_message_handler; + rc = IOT_MQTT_Subscribe(pClient, testTopic, &sub_params); + + } while (QCLOUD_ERR_MQTT_NO_CONN == rc || QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); + + if (rc < 0) { + Log_e("Subscribe failed. Ret : %d ", rc); + } + + HAL_SleepMs(1000); + + do { + HAL_SleepMs(THREAD_SLEEP_INTERVAL_MS); + rc = IOT_MQTT_Unsubscribe(pClient, testTopic); + } while (QCLOUD_ERR_MQTT_NO_CONN == rc || QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); + + if (rc < 0) { + Log_e("Unsubscribe failed. Returned : %d ", rc); + } + } } /** - * 在子线程上进行subscribe操作 - * 这里会记录发布前/后的时间,并保存到pSubscribeTime中 + * do subscribe in the thread */ static int _mqtt_subscribe_to_test_topic(void *pClient) { - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; sub_params.on_message_handler = _mqtt_message_handler; - sub_params.qos = QOS1; - return IOT_MQTT_Subscribe(pClient, INTEGRATION_TEST_TOPIC, &sub_params); + sub_params.qos = QOS1; + return IOT_MQTT_Subscribe(pClient, sg_pub_sub_test_topic, &sub_params); } /** - * 在子线程上进行publish操作 - * 这里会循环PUBLISH_COUNT次,发布topic - * 如果第一次publish失败,则进行第二次发布,并且记录失败的次数 + * do publish in the thread + * loop for PUBLISH_COUNT times + * If publish failed in 1st time, do it again */ -static void *_mqtt_publish_thread_runner(void *ptr) { - int itr = 0; - char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; - - PublishParams params; - int rc = QCLOUD_ERR_SUCCESS; - ThreadData *threadData = (ThreadData *) ptr; - void *pClient = threadData->client; - int threadId = threadData->threadId; - - int sleep_us = THREAD_SLEEP_INTERVAL_USEC; - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - int size = HAL_Snprintf(topic_content, sizeof(topic_content), "Thread : %d, Msg : %d", threadId, itr); - if (size < 0 || size > sizeof(topic_content) - 1) { - Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); - return 0; - } - - params.payload = (void *) topic_content; - params.payload_len = strlen(topic_content); - params.qos = QOS1; - Log_d("Msg being published: %s", topic_content); - - do { - rc = IOT_MQTT_Publish(pClient, INTEGRATION_TEST_TOPIC, ¶ms); - usleep(sleep_us); - } while(QCLOUD_ERR_MQTT_NO_CONN == rc || QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); - - // 发布失败的时候进行一次重新发布,并且记录重新发布的次数 - if(rc < 0) { - Log_e("Failed attempt 1 Publishing Thread : %d, Msg : %d, cs : %d ", threadId, itr, rc); - do { - rc = IOT_MQTT_Publish(pClient, INTEGRATION_TEST_TOPIC, ¶ms); - usleep(sleep_us); - } while(QCLOUD_ERR_MQTT_NO_CONN == rc); - sg_rePublishCount++; - if(QCLOUD_ERR_SUCCESS != rc) { - Log_e("Failed attempt 2 Publishing Thread : %d, Msg : %d, cs : %d Second Attempt ", threadId, itr, rc); - } - } - } - sg_threadStatus[threadId - 1] = 1; - return 0; +static void _mqtt_publish_thread_runner(void *ptr) +{ + int itr = 0; + char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; + + PublishParams params; + int rc = QCLOUD_RET_SUCCESS; + AppThreadData *thread_data = (AppThreadData *)ptr; + void * pClient = thread_data->client; + int thread_id = thread_data->thread_id; + + for (itr = 0; itr < PUBLISH_COUNT; itr++) { + int size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"thread-%d\", \"count\": \"%d\"}", + thread_id, itr); + if (size < 0 || size > sizeof(topic_content) - 1) { + Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); + } + + params.payload = (void *)topic_content; + params.payload_len = strlen(topic_content); + params.qos = QOS1; + Log_d("Msg being published: %s", topic_content); + + do { + rc = IOT_MQTT_Publish(pClient, sg_pub_sub_test_topic, ¶ms); + HAL_SleepMs(THREAD_SLEEP_INTERVAL_MS); + } while (QCLOUD_ERR_MQTT_NO_CONN == rc || QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); + + // 1st publish failed, re-publish and update sg_republish_count + if (rc < 0) { + Log_e("Failed attempt 1 Publishing Thread : %d, Msg : %d, cs : %d ", thread_id, itr, rc); + do { + rc = IOT_MQTT_Publish(pClient, sg_pub_sub_test_topic, ¶ms); + HAL_SleepMs(THREAD_SLEEP_INTERVAL_MS); + } while (QCLOUD_ERR_MQTT_NO_CONN == rc); + sg_republish_count++; + if (rc < 0) { + Log_e("Failed attempt 2 Publishing Thread : %d, Msg : %d, cs : %d Second Attempt ", thread_id, itr, rc); + } + } + } + + thread_data->thread_status = 1; } /** - * 线程安全测试函数 + * thread safety performance test */ -static int _mqtt_multi_thread_test(void* client) +static int _mqtt_multi_thread_test(void *client) { - pthread_t publish_thread[MAX_PUB_THREAD_COUNT]; // 用来保存所有publish的线程 - pthread_t yield_thread; // yield的线程 - pthread_t sub_unsub_thread; // 订阅/取消订阅的线程 - int threadId[MAX_PUB_THREAD_COUNT]; // 记录线程id - int pubThreadReturn[MAX_PUB_THREAD_COUNT]; // 保存pub线程创建函数返回结果 - float percentOfRxMsg = 0.0; // 记录从pub到sub整个流程的成功率 - int finishedThreadCount = 0; // 记录publish_thread线程数组中, 已经执行完pub操作的线程数 - int rxMsgCount = 0; // 记录订阅回调函数成功的次数 - ThreadData threadData[MAX_PUB_THREAD_COUNT]; // 对client和threadId进行包装,在publish线程函数中进行传递 - - int rc = QCLOUD_ERR_SUCCESS; - int test_result = 0; - int i = 0 , j = 0; - - // init the global variables - sg_terminate_yield_thread = false; - sg_rxMsgBufferTooBigCounter = 0; - sg_rxUnexpectedNumberCounter = 0; - sg_rePublishCount = 0; - sg_wrongYieldCount = 0; + float percent_of_rx_msg = 0.0; // record the success percentage of every pub send and recv + int finished_thread_count = 0; // record the number of finished publish threads + int rx_msg_count = 0; // record the times of successfull subscribe + // thread data passed to publish thread + AppThreadData thread_data[MAX_PUB_THREAD_COUNT] = {0}; + ThreadParams pub_thread_params[MAX_PUB_THREAD_COUNT] = {0}; + + int rc = QCLOUD_RET_SUCCESS; + int test_result = 0; + int i = 0, j = 0; + + // init the global variables + sg_rx_msg_buf_too_big_count = 0; + sg_rx_unexpected_count = 0; + sg_republish_count = 0; if (client == NULL) { Log_e("MQTT client is invalid!"); return QCLOUD_ERR_FAILURE; - } - - /* Firstly create the thread for IOT_MQTT_Yield() so we can read and handle MQTT packet */ - rc = pthread_create(&yield_thread, NULL, _mqtt_yield_thread_runner, client); - if (rc < 0) { - Log_e("Create Yield thread failed. err: %d - %s", rc, strerror(rc)); - return rc; } /* create a thread to test subscribe and unsubscribe another topic */ - rc = pthread_create(&sub_unsub_thread, NULL, _mqtt_sub_unsub_thread_runner, client); + ThreadParams sub_thread_params = {0}; + sub_thread_params.thread_func = _mqtt_sub_unsub_thread_runner; + sub_thread_params.user_arg = client; + + rc = HAL_ThreadCreate(&sub_thread_params); if (rc < 0) { - Log_e("Create Sub_unsub thread failed. err: %d - %s", rc, strerror(rc)); + Log_e("Create Sub_unsub thread failed: %d", rc); return rc; } - + /* subscribe the same test topic as publish threads */ - rc = _mqtt_subscribe_to_test_topic(client); + rc = _mqtt_subscribe_to_test_topic(client); if (rc < 0) { Log_e("Client subscribe failed: %d", rc); return rc; - } - + } + /* setup the thread info for pub-threads */ - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - threadId[j] = j + 1; // self defined thread ID: 1 - MAX_PUB_THREAD_COUNT - sg_threadStatus[j] = 0; // thread status flag - for(i = 0; i < PUBLISH_COUNT; i++) { - sg_countArray[j][i] = 0; - } - } - - /* create multi threads to test IOT_MQTT_Publish() */ - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - threadData[i].client = client; - threadData[i].threadId = threadId[i]; - pubThreadReturn[i] = pthread_create(&publish_thread[i], NULL, _mqtt_publish_thread_runner, - &threadData[i]); - - if (pubThreadReturn[i] < 0) { - Log_e("Create publish thread(ID: %d) failed. err: %d - %s", - threadId[i], pubThreadReturn[i], strerror(pubThreadReturn[i])); + for (j = 0; j < MAX_PUB_THREAD_COUNT; j++) { + thread_data[j].client = client; + // self defined thread ID: 1 - MAX_PUB_THREAD_COUNT + thread_data[j].thread_id = j + 1; + thread_data[j].thread_status = 0; + for (i = 0; i < PUBLISH_COUNT; i++) { + sg_rx_count_array[j][i] = 0; } - } - - /* wait for all pub-threads to finish their jobs */ - do { - finishedThreadCount = 0; - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - finishedThreadCount += sg_threadStatus[i]; - } - Log_i(">>>>>>>>Finished thread count : %d", finishedThreadCount); - sleep(1); - } while(finishedThreadCount < MAX_PUB_THREAD_COUNT); - - Log_i("Publishing is finished"); - - sg_terminate_yield_thread = true; - sg_terminate_subUnsub_thread = true; - - /* Allow time for yield_thread and sub_sunsub thread to exit */ - - /* Not using pthread_join because all threads should have terminated gracefully at this point. If they haven't, - * which should not be possible, something below will fail. */ - sleep(1); - - /* Calculating Test Results */ - for(i = 0; i < PUBLISH_COUNT; i++) { - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - if(sg_countArray[j][i] > 0) { - rxMsgCount++; - } - } - } - percentOfRxMsg = (float) rxMsgCount * 100 / (PUBLISH_COUNT * MAX_PUB_THREAD_COUNT); - - printf("\n\nMQTT Multi-thread Test Result : \n"); - printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - if(RX_RECEIVE_PERCENTAGE <= percentOfRxMsg && // 成功率达标 - 0 == sg_rxMsgBufferTooBigCounter && // 返回数据buffer没有越界 - 0 == sg_rxUnexpectedNumberCounter && // 返回预期范围内的数据 - 0 == sg_wrongYieldCount) // yield过程中没有发生失败 - { - // 测试成功 - printf("Success! PercentOfRxMsg: %f %%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT * MAX_PUB_THREAD_COUNT, rxMsgCount); - printf("QoS 1 re publish count %u\n", sg_rePublishCount); - printf("Yield count without error during callback %u\n", sg_wrongYieldCount); - test_result = 0; - } else { - // 测试失败 - printf("\nFailure! PercentOfRxMsg: %f %%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT * MAX_PUB_THREAD_COUNT, rxMsgCount); - printf("\"Received message was too big than anything sent\" count: %u\n", sg_rxMsgBufferTooBigCounter); - printf("\"The number received is out of the range\" count: %u\n", sg_rxUnexpectedNumberCounter); - printf("Yield count without error during callback %u\n", sg_wrongYieldCount); - test_result = -1; - } - printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); - - return test_result; -} + } + + /* create multi threads to test IOT_MQTT_Publish() */ + for (i = 0; i < MAX_PUB_THREAD_COUNT; i++) { + pub_thread_params[i].thread_func = _mqtt_publish_thread_runner; + pub_thread_params[i].user_arg = (void *)&thread_data[i]; + + rc = HAL_ThreadCreate(&pub_thread_params[i]); + if (rc < 0) { + Log_e("Create publish thread(ID: %d) failed: %d", thread_data[i].thread_id, rc); + } + } + + /* wait for all pub-threads to finish their jobs */ + do { + finished_thread_count = 0; + for (i = 0; i < MAX_PUB_THREAD_COUNT; i++) { + finished_thread_count += thread_data[i].thread_status; + } + + Log_i(">>>>>>>>Finished thread count : %d", finished_thread_count); + + int exit_code; + if (!IOT_MQTT_GetLoopStatus(client, &exit_code)) + Log_e("MQTT Loop thread quit with code: %d", exit_code); + + HAL_SleepMs(1000); + } while (finished_thread_count < MAX_PUB_THREAD_COUNT); + + Log_i("Publishing is finished"); + + sg_sub_unsub_thread_quit = true; + + /* Allow time for sub_sunsub thread to exit */ + HAL_SleepMs(1000); + /* all threads should have terminated gracefully at this point. If they haven't, + * which should not be possible, something below will fail. */ -int main(int argc, char **argv) { + /* Calculating Test Results */ + for (i = 0; i < PUBLISH_COUNT; i++) { + for (j = 0; j < MAX_PUB_THREAD_COUNT; j++) { + if (sg_rx_count_array[j][i] > 0) { + rx_msg_count++; + } + } + } + percent_of_rx_msg = (float)rx_msg_count * 100 / (PUBLISH_COUNT * MAX_PUB_THREAD_COUNT); + + HAL_Printf("\n\nMQTT Multi-thread Test Result : \n"); + HAL_Printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + if (RX_RECEIVE_PERCENTAGE <= percent_of_rx_msg && 0 == sg_rx_msg_buf_too_big_count && 0 == sg_rx_unexpected_count) { + // test success + HAL_Printf("Success! PercentOfRxMsg: %f %%\n", percent_of_rx_msg); + HAL_Printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT * MAX_PUB_THREAD_COUNT, + rx_msg_count); + HAL_Printf("QoS 1 re publish count %u\n", sg_republish_count); + test_result = 0; + } else { + // test fail + HAL_Printf("\nFailure! PercentOfRxMsg: %f %%\n", percent_of_rx_msg); + HAL_Printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT * MAX_PUB_THREAD_COUNT, + rx_msg_count); + HAL_Printf("\"Received message was too big than anything sent\" count: %u\n", sg_rx_msg_buf_too_big_count); + HAL_Printf("\"The number received is out of the range\" count: %u\n", sg_rx_unexpected_count); + test_result = -1; + } + HAL_Printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); + + return test_result; +} + +int main(int argc, char **argv) +{ int rc; - - //Init log level - IOT_Log_Set_Level(DEBUG); - //Avoid broken pipe crash - signal(SIGPIPE, SIG_IGN); + // Init log level + IOT_Log_Set_Level(eLOG_DEBUG); - //Init connection + // Init connection MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; - rc = _setup_connect_init_params(&init_params); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; + rc = _setup_connect_init_params(&init_params); + if (rc != QCLOUD_RET_SUCCESS) { + return rc; } - //MQTT client connect - void * client = IOT_MQTT_Construct(&init_params); + // MQTT client create and connect + void *client = IOT_MQTT_Construct(&init_params); if (client != NULL) { Log_i("Cloud Device Construct Success"); } else { @@ -508,15 +468,24 @@ int main(int argc, char **argv) { return QCLOUD_ERR_FAILURE; } - //Start rock & roll + // Start the default loop thread to read and handle MQTT packet + rc = IOT_MQTT_StartLoop(client); + if (rc) { + Log_e("MQTT start loop failed: %d", rc); + rc = IOT_MQTT_Destroy(&client); + return rc; + } + + // Start application rc = _mqtt_multi_thread_test(client); - if(0 != rc) { + if (0 != rc) { Log_e("MQTT multi-thread test FAILED! RC: %d", rc); } else { Log_i("MQTT multi-thread test SUCCESS"); } - //Finish and destroy + // Finish and destroy + IOT_MQTT_StopLoop(client); rc = IOT_MQTT_Destroy(&client); return rc; } diff --git a/samples/multi_client/multi_client_mqtt_sample.c b/samples/multi_client/multi_client_mqtt_sample.c new file mode 100755 index 00000000..6c73e0ea --- /dev/null +++ b/samples/multi_client/multi_client_mqtt_sample.c @@ -0,0 +1,433 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" + +/* + * This sample test multi MQTT clients in multi-thread runtime. + * 3 MQTT clients run in each own thread + * psk/cert_device_info1/2/3.json for each device info are required + * data topic forward configuration is required + */ + +#define MAX_MQTT_THREAD_COUNT 3 +// record the status of all the threadss +static unsigned int sg_thread_status[MAX_MQTT_THREAD_COUNT]; + +#ifdef WIN32 +#define OS_PATH ".\\" +#else +#define OS_PATH "./" +#endif + +#ifdef AUTH_MODE_CERT +char *device_info_file[MAX_MQTT_THREAD_COUNT] = {OS_PATH "cert_device_info1.json", OS_PATH "cert_device_info2.json", + OS_PATH "cert_device_info3.json"}; +#else +char *device_info_file[MAX_MQTT_THREAD_COUNT] = {OS_PATH "psk_device_info1.json", OS_PATH "psk_device_info2.json", + OS_PATH "psk_device_info3.json"}; +#endif + +// sample data structures +typedef struct AppThreadData { + int thread_id; + char * device_info_file; + bool sub_ready; + uint32_t msg_recv_cnt; +} AppThreadData; + +static int sg_loop_cnt = 10; + +// MQTT event callback +static void _mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + MQTTMessage * mqtt_messge = (MQTTMessage *)msg->msg; + uintptr_t packet_id = (uintptr_t)msg->msg; + AppThreadData *app_data = (AppThreadData *)handle_context; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + mqtt_messge->topic_len, mqtt_messge->ptopic, mqtt_messge->payload_len, mqtt_messge->payload); + break; + + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_d("mqtt topic subscribe success"); + app_data->sub_ready = true; + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("mqtt topic subscribe timeout"); + app_data->sub_ready = false; + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("mqtt topic subscribe NACK"); + app_data->sub_ready = false; + break; + + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); + app_data->sub_ready = false; + break; + + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} + +// Setup MQTT construct parameters +static int _setup_connect_init_params(MQTTInitParams *initParams, DeviceInfo *device_info, AppThreadData *app_data) +{ + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#endif + +#else + initParams->device_secret = device_info->device_secret; +#endif + + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = _mqtt_event_handler; + initParams->event_handle.context = (void *)app_data; + + return QCLOUD_RET_SUCCESS; +} + +#define MAX_SIZE_OF_TOPIC_CONTENT 100 +// publish MQTT msg +static int _publish_test_msg(void *client, char *topic_keyword, QoS qos, int count, int thread_id) +{ + char topic_name[128] = {0}; + DeviceInfo *dev_info = IOT_MQTT_GetDeviceInfo(client); + + int size = HAL_Snprintf( + topic_name, sizeof(topic_name), "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name), STRING_PTR_PRINT_SANITY_CHECK(topic_keyword)); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + + PublishParams pub_params = DEFAULT_PUB_PARAMS; + pub_params.qos = qos; + + char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; + + size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"text\": \"thread-%u\", \"count\": \"%d\"}", thread_id, + count); + if (size < 0 || size > sizeof(topic_content) - 1) { + Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); + return -3; + } + + pub_params.payload = topic_content; + pub_params.payload_len = strlen(topic_content); + + return IOT_MQTT_Publish(client, topic_name, &pub_params); +} + +// callback when MQTT msg arrives +static void _on_message_callback(void *pClient, MQTTMessage *message, void *user_data) +{ + if (message == NULL) { + return; + } + + AppThreadData *app_data = (AppThreadData *)user_data; + app_data->msg_recv_cnt += 1; + Log_i("Thread-%d recv msg topic:%.*s, payload:%.*s", app_data->thread_id, (int)message->topic_len, + STRING_PTR_PRINT_SANITY_CHECK(message->ptopic), (int)message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); +} + +// subscrib MQTT topic +static int _subscribe_topic_wait_result(void *client, char *topic_keyword, QoS qos, AppThreadData *app_data) +{ + static char topic_name[128] = {0}; + DeviceInfo *dev_info = IOT_MQTT_GetDeviceInfo(client); + int size = HAL_Snprintf( + topic_name, sizeof(topic_name), "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name), STRING_PTR_PRINT_SANITY_CHECK(topic_keyword)); + + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.qos = qos; + sub_params.on_message_handler = _on_message_callback; + sub_params.user_data = (void *)app_data; + int rc = IOT_MQTT_Subscribe(client, topic_name, &sub_params); + if (rc < 0) { + Log_e("MQTT subscribe failed: %d", rc); + return rc; + } + + int wait_cnt = 10; + while (!app_data->sub_ready && (wait_cnt > 0)) { + // wait for subscription result + rc = IOT_MQTT_Yield(client, 1000); + if (rc) { + Log_e("MQTT error: %d", rc); + return rc; + } + wait_cnt--; + } + + if (wait_cnt > 0) { + return QCLOUD_RET_SUCCESS; + } else { + Log_e("wait for subscribe result timeout!"); + return QCLOUD_ERR_FAILURE; + } +} + +static uint32_t _get_random_delay(void) +{ + srand((unsigned)HAL_GetTimeMs()); + /* range: 1000 - 5000 ms, in 10ms unit */ + return (rand() % 400 + 100) * 10; +} + +static void _mqtt_client_thread_runner(void *ptr) +{ + int pub_cnt = 0; + void * client = NULL; + AppThreadData *app_data = (AppThreadData *)ptr; + int thread_id = app_data->thread_id; + + DeviceInfo dev_info = {0}; + if (HAL_GetDevInfoFromFile(app_data->device_info_file, (void *)&dev_info)) { + Log_e("invalid dev info file: %s", STRING_PTR_PRINT_SANITY_CHECK(app_data->device_info_file)); + goto thread_exit; + } + + Log_i("Thread running. ID: %d; device file: %s", thread_id, app_data->device_info_file); + + // init connection + MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; + int rc = _setup_connect_init_params(&init_params, &dev_info, app_data); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params error: %d", rc); + goto thread_exit; + } + + // create MQTT client and connect with server + client = IOT_MQTT_Construct(&init_params); + if (client != NULL) { + Log_i("Cloud Device Construct Success"); + } else { + Log_e("MQTT Construct failed: %d", init_params.err_code); + goto thread_exit; + } + +#ifdef SYSTEM_COMM + long time = 0; + // get system timestamp from server + rc = IOT_Get_SysTime(client, &time); + if (QCLOUD_RET_SUCCESS == rc) { + Log_i("system time is %ld", time); + } else { + Log_e("get system time failed!"); + } +#endif + + // subscribe topic first + rc = _subscribe_topic_wait_result(client, "data", QOS1, app_data); + if (rc < 0) { + Log_e("Client Subscribe Topic Failed: %d", rc); + goto thread_exit; + } + + int test_count = 0; + do { + rc = _publish_test_msg(client, "data", QOS1, test_count, thread_id); + if (rc < 0) { + Log_e("client publish topic failed :%d.", rc); + } else { + pub_cnt++; + } + + rc = IOT_MQTT_Yield(client, 1000); + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + test_count++; + + if (test_count < sg_loop_cnt) + HAL_SleepMs(_get_random_delay()); + +#ifdef SYSTEM_COMM + long time = 0; + // get system timestamp from server + rc = IOT_Get_SysTime(client, &time); + if (QCLOUD_RET_SUCCESS == rc) { + Log_i("system time is %ld", time); + } else { + Log_e("get system time failed!"); + } +#endif + } while (test_count < sg_loop_cnt); + +thread_exit: + if (client != NULL) + IOT_MQTT_Destroy(&client); + + Log_i(">>>>>>>>>>Thread-%d totally pub %d msg and recv %d msg", thread_id, pub_cnt, app_data->msg_recv_cnt); + sg_thread_status[thread_id] = 1; +} + +static int parse_arguments(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "l:")) != EOF) switch (c) { + case 'l': + sg_loop_cnt = atoi(utils_optarg); + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-l n] test loop count\n", + argv[0]); + return -1; + } + return 0; +} + +int main(int argc, char **argv) +{ + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + parse_arguments(argc, argv); + + AppThreadData app_data[MAX_MQTT_THREAD_COUNT]; + + int i; + // init thread app data + for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) { + sg_thread_status[i] = 0; // init thread status flag + + app_data[i].device_info_file = device_info_file[i]; + app_data[i].thread_id = i; + app_data[i].sub_ready = false; + app_data[i].msg_recv_cnt = 0; + } + + int created_thread_cnt = 0; + /* create multi threads for multi mqtt client test */ + for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) { + sg_thread_status[i] = 0; // init thread status flag + + ThreadParams thread_params = {0}; + thread_params.thread_func = _mqtt_client_thread_runner; + thread_params.user_arg = &app_data[i]; + + int rc = HAL_ThreadCreate(&thread_params); + if (rc) { + Log_e("create mqtt thread fail: %d", rc); + } else { + created_thread_cnt++; + } + + HAL_SleepMs(300); + } + + Log_i("created %d mqtt threads", created_thread_cnt); + + /* wait for all threads to finish their jobs */ + int finished_created_thread_cnt; + do { + finished_created_thread_cnt = 0; + for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) { + finished_created_thread_cnt += sg_thread_status[i]; + } + Log_i(">>>>>>>>Finished thread count : %d", finished_created_thread_cnt); + + HAL_SleepMs(1000); + } while (finished_created_thread_cnt < created_thread_cnt); + + return 0; +} diff --git a/samples/multi_client/multi_client_shadow_sample.c b/samples/multi_client/multi_client_shadow_sample.c new file mode 100755 index 00000000..f18fa470 --- /dev/null +++ b/samples/multi_client/multi_client_shadow_sample.c @@ -0,0 +1,304 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" + +/* + * This sample test multi shadow clients in multi-thread runtime. + * 3 shadow clients run in each own thread + * psk/cert_device_info1/2/3.json for each device info are required + */ + +#define MAX_MQTT_THREAD_COUNT 3 +// record the status of all the threadss +static unsigned int sg_thread_status[MAX_MQTT_THREAD_COUNT]; + +#ifdef WIN32 +#ifdef AUTH_MODE_CERT +char *device_info_file[MAX_MQTT_THREAD_COUNT] = {".\\cert_device_info1.json", ".\\cert_device_info2.json", + ".\\cert_device_info3.json"}; +#else +char *device_info_file[MAX_MQTT_THREAD_COUNT] = {".\\psk_device_info1.json", ".\\psk_device_info2.json", + ".\\psk_device_info3.json"}; +#endif +#else +#ifdef AUTH_MODE_CERT +char *device_info_file[MAX_MQTT_THREAD_COUNT] = {"./cert_device_info1.json", "./cert_device_info2.json", + "./cert_device_info3.json"}; +#else +char *device_info_file[MAX_MQTT_THREAD_COUNT] = {"./psk_device_info1.json", "./psk_device_info2.json", + "./psk_device_info3.json"}; +#endif +#endif + +// sample data structures +typedef struct SampleThreadData { + int thread_id; + char *device_info_file; + char *property_key; +} SampleThreadData; + +static int sg_loop_cnt = 10; + +void OnDeltaCallback(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength, DeviceProperty *pProperty) +{ + Log_i("Thread recv delta str: %s", STRING_PTR_PRINT_SANITY_CHECK(pJsonValueBuffer)); + pProperty->delta_arrived = true; +} + +void OnShadowUpdateCallback(void *pClient, Method method, RequestAck requestAck, const char *pJsonDocument, + void *pUserdata) +{ + Log_i("Thread recv shadow update response ack: %d", requestAck); +} + +static int _report_desire_null(void *handle, char *jsonBuffer, size_t sizeOfBuffer) +{ + /* device data updated, desire should be set null */ + int rc = IOT_Shadow_JSON_ConstructDesireAllNull(handle, jsonBuffer, sizeOfBuffer); + if (rc == QCLOUD_RET_SUCCESS) { + rc = IOT_Shadow_Update(handle, jsonBuffer, sizeOfBuffer, OnShadowUpdateCallback, "desire_null", + QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + if (rc == QCLOUD_RET_SUCCESS) { + Log_d("shadow update(desired) success"); + } else { + Log_e("shadow update(desired) failed, err: %d", rc); + } + + } else { + Log_e("construct desire failed, err: %d", rc); + } + + return rc; +} + +static int _setup_connect_init_params(ShadowInitParams *initParams, DeviceInfo *device_info) +{ + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#endif + +#else + initParams->device_secret = device_info->device_secret; +#endif + + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + initParams->auto_connect_enable = 1; + + return QCLOUD_RET_SUCCESS; +} + +static uint32_t _get_random_delay(void) +{ + srand((unsigned)HAL_GetTimeMs()); + /* range: 1000 - 5000 ms, in 10ms unit */ + return (rand() % 400 + 100) * 10; +} + +static void _shadow_client_thread_runner(void *ptr) +{ + int rc = QCLOUD_ERR_FAILURE; + void *shadow_client = NULL; + + SampleThreadData *thread_data = (SampleThreadData *)ptr; + int thread_id = thread_data->thread_id; + + DeviceInfo dev_info = {0}; + if (HAL_GetDevInfoFromFile(thread_data->device_info_file, (void *)&dev_info)) { + Log_e("invalid dev info file: %s", STRING_PTR_PRINT_SANITY_CHECK(thread_data->device_info_file)); + goto thread_exit; + } + + Log_i("Thread running. ID: %d; device: %s", thread_id, thread_data->device_info_file); + + char shadow_json_buffer[200]; + size_t shadow_json_buf_size = sizeof(shadow_json_buffer) / sizeof(shadow_json_buffer[0]); + DeviceProperty shadow_property; + int current_update_count = 0; + + // init connection + ShadowInitParams init_params = DEFAULT_SHAWDOW_INIT_PARAMS; + rc = _setup_connect_init_params(&init_params, &dev_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + goto thread_exit; + } + + shadow_client = IOT_Shadow_Construct(&init_params); + if (shadow_client == NULL) { + Log_e("shadow client constructed failed."); + goto thread_exit; + } + + // register delta property + shadow_property.key = thread_data->property_key; + shadow_property.data = ¤t_update_count; + shadow_property.type = JINT32; + rc = IOT_Shadow_Register_Property(shadow_client, &shadow_property, OnDeltaCallback); + if (rc != QCLOUD_RET_SUCCESS) { + rc = IOT_Shadow_Destroy(shadow_client); + Log_e("register device shadow property failed, err: %d", rc); + goto thread_exit; + } + + // do get and sync operation before update + rc = IOT_Shadow_Get_Sync(shadow_client, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("get device shadow failed, err: %d", rc); + goto thread_exit; + } + + int loop_cnt = 0; + while (IOT_Shadow_IsConnected(shadow_client) || QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT == rc || + QCLOUD_RET_MQTT_RECONNECTED == rc || QCLOUD_RET_SUCCESS == rc) { + rc = IOT_Shadow_Yield(shadow_client, 500); + + if (QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT == rc) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + if (shadow_property.delta_arrived) { + _report_desire_null(shadow_client, shadow_json_buffer, shadow_json_buf_size); + + shadow_property.delta_arrived = false; + } + + IOT_Shadow_JSON_ConstructReport(shadow_client, shadow_json_buffer, shadow_json_buf_size, 1, &shadow_property); + rc = IOT_Shadow_Update(shadow_client, shadow_json_buffer, shadow_json_buf_size, OnShadowUpdateCallback, NULL, + QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + current_update_count++; + + if (loop_cnt++ >= sg_loop_cnt) + break; + + // sleep for some time + HAL_SleepMs(_get_random_delay()); + } + +thread_exit: + + if (shadow_client != NULL) { + IOT_Shadow_Destroy(shadow_client); + shadow_client = NULL; + } + + sg_thread_status[thread_id] = 1; +} + +static int parse_arguments(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "l:")) != EOF) switch (c) { + case 'l': + sg_loop_cnt = atoi(utils_optarg); + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-l n] test loop count\n", + argv[0]); + return -1; + } + return 0; +} + +int main(int argc, char **argv) +{ + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + parse_arguments(argc, argv); + + SampleThreadData thread_data[MAX_MQTT_THREAD_COUNT]; + + char *property_key[MAX_MQTT_THREAD_COUNT] = {"update_count_1", "update_count_2", "update_count_3"}; + + int i; + for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) { + sg_thread_status[i] = 0; // init thread status flag + thread_data[i].property_key = property_key[i]; + thread_data[i].device_info_file = device_info_file[i]; + thread_data[i].thread_id = i; + } + + int created_thread_cnt = 0; + /* create multi threads for multi mqtt client test */ + for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) { + sg_thread_status[i] = 0; // init thread status flag + + ThreadParams thread_params = {0}; + thread_params.thread_func = _shadow_client_thread_runner; + thread_params.user_arg = &thread_data[i]; + + int rc = HAL_ThreadCreate(&thread_params); + if (rc) { + Log_e("create mqtt thread fail: %d", rc); + } else { + created_thread_cnt++; + } + + HAL_SleepMs(300); + } + + Log_i("created %d shadow threads", created_thread_cnt); + + /* wait for all threads to finish their jobs */ + int finished_created_thread_cnt; + do { + finished_created_thread_cnt = 0; + for (i = 0; i < MAX_MQTT_THREAD_COUNT; i++) { + finished_created_thread_cnt += sg_thread_status[i]; + } + Log_i(">>>>>>>>Finished thread count : %d", finished_created_thread_cnt); + + HAL_SleepMs(1000); + } while (finished_created_thread_cnt < created_thread_cnt); + + return 0; +} diff --git a/samples/nbiot/nbiot_sample.c b/samples/nbiot/nbiot_sample.c deleted file mode 100644 index d07dd165..00000000 --- a/samples/nbiot/nbiot_sample.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" - -#include -#include - -static void StrToHex(char *pbDest, char *pbSrc, int nLen) -{ - char h1,h2,s1,s2; - int i; - for (i=0; i < nLen; i++) - { - h1 = pbSrc[2*i]; - h2 = pbSrc[2*i + 1]; - s1 = toupper(h1) - 0x30; - if (s1 > 9) - s1 -= 7; - - s2 = toupper(h2) - 0x30; - if (s2 > 9) - s2 -= 7; - - pbDest[i] = s1*16 + s2; - } -} - -int main(int argc, char** argv) -{ - IOT_Log_Set_Level(DEBUG); - NBIoTSetMessage nbiotSetMsg = {0}; - unsigned char msgBuf[MAX_SIZE_MESSAGE] = {0}; - unsigned int length = 0; - int i = 0; - - nbiotSetMsg.address = 0; - nbiotSetMsg.version = 0; - nbiotSetMsg.sigType = 1; - nbiotSetMsg.expiry = 0xffffffff; - nbiotSetMsg.qos = 1; - nbiotSetMsg.topic = "8W0BMHHEJC/shanghuirecv/event"; - nbiotSetMsg.payload = "{\"data\":\"123\",\"test\":1}"; - nbiotSetMsg.key = "qF2SNXIyEOH50g+tNNLO1w=="; - - IOT_NB_setMessage(msgBuf, &length, &nbiotSetMsg); - - for(i = 0; i < length; i++) - { - printf("%02x", msgBuf[i]); - } - printf("\n"); - printf("length: %d\n", length); - - NBIoTGetMessage nbiotGetMsg = {0}; - char topic[MAX_SIZE_TOPIC] = {0}; - char payload[MAX_SIZE_PAYLOAD] = {0}; - - nbiotGetMsg.topic = topic; - nbiotGetMsg.payload = payload; - - char* pbSrc = "0100704151466250516A5541415542414268534F44684F4E544930554446464C3342316332686B5A5859765A585A6C626E514341425344554A416E2F6553346B534D667A2B5535533245325941493978774D414333736961325635496A6F784D6A4E39424141454141412B346755414151413D"; - unsigned char bDest[1024] = {0}; - StrToHex((char*)bDest, pbSrc, strlen(pbSrc)/2); - - IOT_NB_getMessage(&nbiotGetMsg, bDest); - - printf("address: 0x%x\n", nbiotGetMsg.address); - printf("version: 0x%x\n", nbiotGetMsg.version); - printf("signature: 0x%x\n", nbiotGetMsg.sigType); - printf("expiry: 0x%x\n", nbiotGetMsg.expiry); - printf("qos: 0x%x\n", nbiotGetMsg.qos); - printf("topic: %s\n", nbiotGetMsg.topic); - printf("payload: %s\n", nbiotGetMsg.payload); - - return QCLOUD_ERR_SUCCESS; -} \ No newline at end of file diff --git a/samples/ota/ota_coap_sample.c b/samples/ota/ota_coap_sample.c old mode 100644 new mode 100755 index ab06e8c7..48c4673d --- a/samples/ota/ota_coap_sample.c +++ b/samples/ota/ota_coap_sample.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -15,150 +15,145 @@ #include #include -#include -#include #include #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" - -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" - - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 - -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" -#endif - #define OTA_BUF_LEN (5000) -static bool sg_pub_ack = false; -static int sg_packet_id = 0; +static bool sg_pub_ack = false; +static int sg_packet_id = 0; -void response_message_callback(void* coap_message, void* userContext) +void response_message_callback(void *coap_message, void *userContext) { - int ret_code = IOT_COAP_GetMessageCode(coap_message); - switch (ret_code) { - case COAP_EVENT_RECEIVE_ACK: + int ret_code = IOT_COAP_GetMessageCode(coap_message); + switch (ret_code) { + case COAP_EVENT_RECEIVE_ACK: Log_i("message received ACK, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_RECEIVE_RESPCONTENT: - { - char* payload = NULL; - int payload_len = 0; - int ret = -1; - ret = IOT_COAP_GetMessagePayload(coap_message, &payload, &payload_len); - if (ret == QCLOUD_ERR_SUCCESS) { - Log_i("message received response, content: %s", payload); - } - else { - Log_e("message received response, content error."); - } - } - - break; - case COAP_EVENT_UNAUTHORIZED: - Log_i("coap client auth token expired or invalid, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_FORBIDDEN: - Log_i("coap URI is invalid for this device, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_INTERNAL_SERVER_ERROR: - Log_i("coap server internal error, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_ACK_TIMEOUT: - Log_i("message receive ACK timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_SEPRESP_TIMEOUT: - Log_i("message received ACK but receive response timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - default: - break; - } + break; + case COAP_EVENT_RECEIVE_RESPCONTENT: { + char *payload = NULL; + int payload_len = 0; + int ret = -1; + ret = IOT_COAP_GetMessagePayload(coap_message, &payload, &payload_len); + if (ret == QCLOUD_RET_SUCCESS) { + Log_i("message received response, content: %s", payload); + } else { + Log_e("message received response, content error."); + } + } + + break; + case COAP_EVENT_UNAUTHORIZED: + Log_i("coap client auth token expired or invalid, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_FORBIDDEN: + Log_i("coap URI is invalid for this device, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_INTERNAL_SERVER_ERROR: + Log_i("coap server internal error, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_ACK_TIMEOUT: + Log_i("message receive ACK timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_SEPRESP_TIMEOUT: + Log_i("message received ACK but receive response timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + default: + break; + } } void event_handler(void *pcontext, CoAPEventMessage *message) { - switch (message->event_type) { - case COAP_EVENT_RECEIVE_ACK: - if(sg_packet_id == (unsigned)(uintptr_t)message->message){ + switch (message->event_type) { + case COAP_EVENT_RECEIVE_ACK: + if (sg_packet_id == (unsigned)(uintptr_t)message->message) { sg_pub_ack = true; } - Log_i("message received ACK, msgid: %d", sg_packet_id); - break; - case COAP_EVENT_RECEIVE_RESPCONTENT: - Log_i("message received response, content: %s", IOT_COAP_GetMessageId(message->message)); - break; - case COAP_EVENT_UNAUTHORIZED: - Log_i("coap client auth token expired or invalid, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_FORBIDDEN: - Log_i("coap URI is invalid for this device, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_INTERNAL_SERVER_ERROR: - Log_i("coap server internal error, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_ACK_TIMEOUT: - Log_i("message receive ACK timeout, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_SEPRESP_TIMEOUT: - Log_i("message received ACK but receive response timeout, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - default: - Log_e("unrecogonized event type: %d", message->event_type); - break; - } + Log_i("message received ACK, msgid: %d", sg_packet_id); + break; + case COAP_EVENT_RECEIVE_RESPCONTENT: + Log_i("message received response, content: %s", IOT_COAP_GetMessageId(message->message)); + break; + case COAP_EVENT_UNAUTHORIZED: + Log_i("coap client auth token expired or invalid, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_FORBIDDEN: + Log_i("coap URI is invalid for this device, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_INTERNAL_SERVER_ERROR: + Log_i("coap server internal error, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_ACK_TIMEOUT: + Log_i("message receive ACK timeout, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_SEPRESP_TIMEOUT: + Log_i("message received ACK but receive response timeout, msgid: %d", + (unsigned)(uintptr_t)message->message); + break; + default: + Log_e("unrecogonized event type: %d", message->event_type); + break; + } } -static int _setup_connect_init_params(CoAPInitParams* initParams) +static int _setup_connect_init_params(CoAPInitParams *initParams, DeviceInfo *device_info) { - initParams->device_name = QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = QCLOUD_IOT_MY_PRODUCT_ID; + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; #ifdef AUTH_MODE_CERT - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; + char certs_dir[16] = "certs"; + char current_path[128]; char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { + + if (cwd == NULL) { Log_e("getcwd return NULL"); return QCLOUD_ERR_FAILURE; } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - initParams->cert_file = sg_cert_file; - initParams->key_file = sg_key_file; +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#endif + #else - initParams->device_secret = QCLOUD_IOT_DEVICE_SECRET; + initParams->device_secret = device_info->device_secret; #endif - initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; initParams->event_handle.h_fp = event_handler; + initParams->max_retry_count = 3; - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } int main(int argc, char **argv) { - IOT_Log_Set_Level(DEBUG); + IOT_Log_Set_Level(eLOG_DEBUG); int rc; + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + return rc; + } + CoAPInitParams init_params = DEFAULT_COAPINIT_PARAMS; - rc = _setup_connect_init_params(&init_params); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } + rc = _setup_connect_init_params(&init_params, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } void *client = IOT_COAP_Construct(&init_params); if (client != NULL) { @@ -168,7 +163,8 @@ int main(int argc, char **argv) return QCLOUD_ERR_FAILURE; } - void *h_ota = IOT_OTA_Init(QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME, client); + DeviceInfo *dev_info = IOT_COAP_GetDeviceInfo(client); + void * h_ota = IOT_OTA_Init(dev_info->product_id, dev_info->device_name, client); if (NULL == h_ota) { Log_e("initialize OTA failed"); return QCLOUD_ERR_FAILURE; @@ -180,10 +176,10 @@ int main(int argc, char **argv) } HAL_SleepMs(2000); - int ota_over = 0; - bool upgrade_fetch_success = true; + int ota_over = 0; + bool upgrade_fetch_success = true; FILE *fp; - char buf_ota[OTA_BUF_LEN]; + char buf_ota[OTA_BUF_LEN]; if (NULL == (fp = fopen("ota.bin", "wb+"))) { Log_e("open file failed"); return QCLOUD_ERR_FAILURE; @@ -196,7 +192,7 @@ int main(int argc, char **argv) IOT_COAP_Yield(client, 200); if (IOT_OTA_IsFetching(h_ota)) { - char version[128], md5sum[33]; + char version[128], md5sum[33]; uint32_t len, size_downloaded, size_file; do { len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1); @@ -238,11 +234,9 @@ int main(int argc, char **argv) HAL_SleepMs(2000); - } while(!ota_over); - + } while (!ota_over); - if (upgrade_fetch_success) - { + if (upgrade_fetch_success) { /* begin execute OTA files, should report upgrade begin */ // sg_packet_id = IOT_OTA_ReportUpgradeBegin(h_ota); // if (0 > sg_packet_id) { diff --git a/samples/ota/ota_mqtt_sample.c b/samples/ota/ota_mqtt_sample.c index 44e4d380..347f34f0 100755 --- a/samples/ota/ota_mqtt_sample.c +++ b/samples/ota/ota_mqtt_sample.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -15,170 +15,405 @@ #include #include -#include -#include #include +#include "lite-utils.h" #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" +#define FW_RUNNING_VERSION "1.0.0" +#define KEY_VER "version" +#define KEY_SIZE "downloaded_size" -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" +#define FW_VERSION_MAX_LEN 32 +#define FW_FILE_PATH_MAX_LEN 128 +#define OTA_BUF_LEN 5000 +#define FW_INFO_FILE_DATA_LEN 128 - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 +typedef struct OTAContextData { + void *ota_handle; + void *mqtt_client; + char fw_file_path[FW_FILE_PATH_MAX_LEN]; + char fw_info_file_path[FW_FILE_PATH_MAX_LEN]; -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" -#endif + // remote_version means version for the FW in the cloud and to be downloaded + char remote_version[FW_VERSION_MAX_LEN]; + uint32_t fw_file_size; + + // for resuming download + /* local_version means downloading but not running */ + char local_version[FW_VERSION_MAX_LEN]; + int downloaded_size; -#define OTA_BUF_LEN (5000) - -static bool sg_pub_ack = false; -static int sg_packet_id = 0; - -static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - if (sg_packet_id == packet_id) - sg_pub_ack = true; - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } + // to make sure report is acked + bool report_pub_ack; + int report_packet_id; + +} OTAContextData; + +static void _event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + uintptr_t packet_id = (uintptr_t)msg->msg; + OTAContextData *ota_ctx = (OTAContextData *)handle_context; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + if (ota_ctx->report_packet_id == packet_id) + ota_ctx->report_pub_ack = true; + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } } -static int _setup_connect_init_params(MQTTInitParams* initParams) +static int _setup_connect_init_params(MQTTInitParams *initParams, void *ota_ctx, DeviceInfo *device_info) { - initParams->device_name = QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = QCLOUD_IOT_MY_PRODUCT_ID; + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; #ifdef AUTH_MODE_CERT - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; + char certs_dir[16] = "certs"; + char current_path[128]; char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { + + if (cwd == NULL) { Log_e("getcwd return NULL"); return QCLOUD_ERR_FAILURE; } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - initParams->cert_file = sg_cert_file; - initParams->key_file = sg_key_file; +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#endif + #else - initParams->device_secret = QCLOUD_IOT_DEVICE_SECRET; + initParams->device_secret = device_info->device_secret; #endif - - initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; - initParams->auto_connect_enable = 1; - initParams->event_handle.h_fp = event_handler; - return QCLOUD_ERR_SUCCESS; + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = _event_handler; + initParams->event_handle.context = ota_ctx; + + return QCLOUD_RET_SUCCESS; } -int main(int argc, char **argv) +static void _wait_for_pub_ack(OTAContextData *ota_ctx, int packet_id) { - IOT_Log_Set_Level(DEBUG); - int rc; + int wait_cnt = 10; + ota_ctx->report_pub_ack = false; + ota_ctx->report_packet_id = packet_id; + + while (!ota_ctx->report_pub_ack) { + HAL_SleepMs(500); + IOT_MQTT_Yield(ota_ctx->mqtt_client, 500); + if (wait_cnt-- == 0) { + Log_e("wait report pub ack timeout!"); + break; + } + } + ota_ctx->report_pub_ack = false; + return; +} - MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; - rc = _setup_connect_init_params(&init_params); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } +/********************************************************************************** + * OTA file operations START + * these are platform-dependant functions + * POSIX FILE is used in this sample code + **********************************************************************************/ +// calculate left MD5 for resuming download from break point +static int _cal_exist_fw_md5(OTAContextData *ota_ctx) +{ + char buff[OTA_BUF_LEN]; + size_t rlen, total_read = 0; + int ret = QCLOUD_RET_SUCCESS; - void *client = IOT_MQTT_Construct(&init_params); - if (client != NULL) { - Log_i("Cloud Device Construct Success"); - } else { - Log_e("Cloud Device Construct Failed"); + ret = IOT_OTA_ResetClientMD5(ota_ctx->ota_handle); + if (ret) { + Log_e("reset MD5 failed: %d", ret); return QCLOUD_ERR_FAILURE; } - void *h_ota = IOT_OTA_Init(QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME, client); - if (NULL == h_ota) { - Log_e("initialize OTA failed"); + FILE *fp = fopen(ota_ctx->fw_file_path, "ab+"); + if (NULL == fp) { + Log_e("open file %s failed", STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->fw_file_path)); return QCLOUD_ERR_FAILURE; } - /* Must report version first */ - if (0 > IOT_OTA_ReportVersion(h_ota, "1.0.0")) { - Log_e("report OTA version failed"); - return QCLOUD_ERR_FAILURE; + // rewind(fp); + size_t size = ota_ctx->downloaded_size; + + while ((size > 0) && (!feof(fp))) { + rlen = (size > OTA_BUF_LEN) ? OTA_BUF_LEN : size; + if (rlen != fread(buff, 1, rlen, fp)) { + Log_e("read data len not expected"); + ret = QCLOUD_ERR_FAILURE; + break; + } + IOT_OTA_UpdateClientMd5(ota_ctx->ota_handle, buff, rlen); + size -= rlen; + total_read += rlen; + } + + fclose(fp); + Log_d("total read: %d", total_read); + return ret; +} + +/* update local firmware info for resuming download from break point */ +static int _update_local_fw_info(OTAContextData *ota_ctx) +{ + FILE *fp; + int wlen; + int ret = QCLOUD_RET_SUCCESS; + char data_buf[FW_INFO_FILE_DATA_LEN]; + + memset(data_buf, 0, sizeof(data_buf)); + HAL_Snprintf(data_buf, sizeof(data_buf), "{\"%s\":\"%s\", \"%s\":%d}", KEY_VER, + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->remote_version), KEY_SIZE, ota_ctx->downloaded_size); + + fp = fopen(ota_ctx->fw_info_file_path, "w"); + if (NULL == fp) { + Log_e("open file %s failed", STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->fw_info_file_path)); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + wlen = fwrite(data_buf, 1, strlen(data_buf), fp); + if (wlen != strlen(data_buf)) { + Log_e("save version to file err"); + ret = QCLOUD_ERR_FAILURE; + } + +exit: + + if (NULL != fp) { + fclose(fp); + } + + return ret; +} + +static int _get_local_fw_info(char *file_name, char *local_version) +{ + int len; + int rlen; + char json_doc[FW_INFO_FILE_DATA_LEN] = {0}; + + FILE *fp = fopen(file_name, "r"); + if (NULL == fp) { + Log_e("open file %s failed", STRING_PTR_PRINT_SANITY_CHECK(file_name)); + return 0; + } + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + if (len > FW_INFO_FILE_DATA_LEN) { + Log_e("%s is too big, pls check", file_name); + fclose(fp); + return 0; + } + + rewind(fp); + rlen = fread(json_doc, 1, len, fp); + if (len != rlen) { + Log_e("read data len (%d) less than needed (%d), %s", rlen, len, json_doc); + fclose(fp); + return 0; + } + + char *version = LITE_json_value_of(KEY_VER, json_doc); + char *size = LITE_json_value_of(KEY_SIZE, json_doc); + + if ((NULL == version) || (NULL == size)) { + if (version) + HAL_Free(version); + if (size) + HAL_Free(size); + fclose(fp); + return 0; + } + + int local_size = atoi(size); + HAL_Free(size); + + if (local_size <= 0) { + Log_w("local info offset invalid: %d", local_size); + HAL_Free(version); + local_size = 0; + } + + strncpy(local_version, version, FW_VERSION_MAX_LEN); + HAL_Free(version); + fclose(fp); + return local_size; +} + +/* get local firmware offset for resuming download from break point */ +static int _update_fw_downloaded_size(OTAContextData *ota_ctx) +{ + int local_size = _get_local_fw_info(ota_ctx->fw_info_file_path, ota_ctx->local_version); + if (local_size == 0) { + ota_ctx->downloaded_size = 0; + return 0; + } + + if ((0 != strcmp(ota_ctx->local_version, ota_ctx->remote_version)) || + (ota_ctx->downloaded_size > ota_ctx->fw_file_size)) { + ota_ctx->downloaded_size = 0; + return 0; + } + + ota_ctx->downloaded_size = local_size; + Log_i("calc MD5 for resuming download from offset: %d", ota_ctx->downloaded_size); + int ret = _cal_exist_fw_md5(ota_ctx); + if (ret) { + Log_e("regen OTA MD5 error: %d", ret); + remove(ota_ctx->fw_info_file_path); + ota_ctx->downloaded_size = 0; + return 0; } + Log_d("local MD5 update done!"); + return local_size; +} - HAL_SleepMs(2000); +static int _delete_fw_info_file(char *file_name) +{ + return remove(file_name); +} - int ota_over = 0; - bool upgrade_fetch_success = true; +static int _save_fw_data_to_file(char *file_name, uint32_t offset, char *buf, int len) +{ FILE *fp; - char buf_ota[OTA_BUF_LEN]; - if (NULL == (fp = fopen("ota.bin", "wb+"))) { - Log_e("open file failed"); + if (offset > 0) { + if (NULL == (fp = fopen(file_name, "ab+"))) { + Log_e("open file failed"); + return QCLOUD_ERR_FAILURE; + } + } else { + if (NULL == (fp = fopen(file_name, "wb+"))) { + Log_e("open file failed"); + return QCLOUD_ERR_FAILURE; + } + } + + fseek(fp, offset, SEEK_SET); + + if (1 != fwrite(buf, len, 1, fp)) { + Log_e("write data to file failed"); + fclose(fp); return QCLOUD_ERR_FAILURE; } + fflush(fp); + fclose(fp); + + return 0; +} + +static char *_get_local_fw_running_version() +{ + // asuming the version is inside the code and binary + // you can also get from a meta file + Log_i("FW running version: %s", FW_RUNNING_VERSION); + return FW_RUNNING_VERSION; +} +/********************************************************************************** + * OTA file operations END + **********************************************************************************/ + +// main OTA cycle +bool process_ota(OTAContextData *ota_ctx) +{ + bool download_finished = false; + bool upgrade_fetch_success = true; + char buf_ota[OTA_BUF_LEN]; + int rc; + void *h_ota = ota_ctx->ota_handle; + + /* Must report version first */ + if (0 > IOT_OTA_ReportVersion(h_ota, _get_local_fw_running_version())) { + Log_e("report OTA version failed"); + return false; + } do { - uint32_t firmware_valid; + IOT_MQTT_Yield(ota_ctx->mqtt_client, 200); + Log_i("wait for ota upgrade command..."); - IOT_MQTT_Yield(client, 200); - + // recv the upgrade cmd if (IOT_OTA_IsFetching(h_ota)) { - char version[128], md5sum[33]; - uint32_t len, size_downloaded, size_file; + IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &ota_ctx->fw_file_size, 4); + IOT_OTA_Ioctl(h_ota, IOT_OTAG_VERSION, ota_ctx->remote_version, FW_VERSION_MAX_LEN); + + DeviceInfo *device_info = IOT_MQTT_GetDeviceInfo(ota_ctx->mqtt_client); + HAL_Snprintf(ota_ctx->fw_file_path, FW_FILE_PATH_MAX_LEN, "./FW_%s_%s.bin", + STRING_PTR_PRINT_SANITY_CHECK(device_info->client_id), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->remote_version)); + HAL_Snprintf(ota_ctx->fw_info_file_path, FW_FILE_PATH_MAX_LEN, "./FW_%s.json", + STRING_PTR_PRINT_SANITY_CHECK(device_info->client_id)); + + /* check if pre-downloading finished or not */ + /* if local FW downloaded size (ota_ctx->downloaded_size) is not zero, it will do resuming download */ + _update_fw_downloaded_size(ota_ctx); + + /*set offset and start http connect*/ + rc = IOT_OTA_StartDownload(h_ota, ota_ctx->downloaded_size, ota_ctx->fw_file_size); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("OTA download start err,rc:%d", rc); + upgrade_fetch_success = false; + break; + } + + // download and save the fw do { - len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1); + int len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1); if (len > 0) { - if (1 != fwrite(buf_ota, len, 1, fp)) { + rc = _save_fw_data_to_file(ota_ctx->fw_file_path, ota_ctx->downloaded_size, buf_ota, len); + if (rc) { Log_e("write data to file failed"); upgrade_fetch_success = false; break; @@ -189,17 +424,28 @@ int main(int argc, char **argv) break; } - /* get OTA information */ - IOT_OTA_Ioctl(h_ota, IOT_OTAG_FETCHED_SIZE, &size_downloaded, 4); - IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &size_file, 4); - IOT_OTA_Ioctl(h_ota, IOT_OTAG_MD5SUM, md5sum, 33); - IOT_OTA_Ioctl(h_ota, IOT_OTAG_VERSION, version, 128); + /* get OTA information and update local info */ + IOT_OTA_Ioctl(h_ota, IOT_OTAG_FETCHED_SIZE, &ota_ctx->downloaded_size, 4); + rc = _update_local_fw_info(ota_ctx); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("update local fw info err,rc:%d", rc); + } + + // quit ota process as something wrong with mqtt + rc = IOT_MQTT_Yield(ota_ctx->mqtt_client, 100); + if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("MQTT error: %d", rc); + return false; + } - IOT_MQTT_Yield(client, 100); } while (!IOT_OTA_IsFetchFinish(h_ota)); - /* Must check MD5 match or not */ + /* Must check MD5 match or not */ if (upgrade_fetch_success) { + // download is finished, delete the fw info file + _delete_fw_info_file(ota_ctx->fw_info_file_path); + + uint32_t firmware_valid; IOT_OTA_Ioctl(h_ota, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4); if (0 == firmware_valid) { Log_e("The firmware is invalid"); @@ -210,56 +456,105 @@ int main(int argc, char **argv) } } - ota_over = 1; + download_finished = true; } - HAL_SleepMs(2000); - } while(!ota_over); + if (!download_finished) + HAL_SleepMs(1000); + + } while (!download_finished); + // do some post-download stuff for your need + // report result + int packet_id; if (upgrade_fetch_success) - { - /* begin execute OTA files, should report upgrade begin */ - // sg_packet_id = IOT_OTA_ReportUpgradeBegin(h_ota); - // if (0 > sg_packet_id) { - // Log_e("report OTA begin failed error:%d", sg_packet_id); - // return QCLOUD_ERR_FAILURE; - // } - // while (!sg_pub_ack) { - // HAL_SleepMs(1000); - // IOT_MQTT_Yield(client, 200); - // } - // sg_pub_ack = false; - - /* if upgrade success */ - /* after execute OTA files, should report upgrade result */ - // sg_packet_id = IOT_OTA_ReportUpgradeSuccess(h_ota, "1.0.1"); - // if (0 > sg_packet_id) { - // Log_e("report OTA result failed error:%d", sg_packet_id); - // return QCLOUD_ERR_FAILURE; - // } - // while (!sg_pub_ack) { - // HAL_SleepMs(1000); - // IOT_MQTT_Yield(client, 200); - // } - // sg_pub_ack = false; - - /* if upgrade fail */ - // sg_packet_id = IOT_OTA_ReportUpgradeFail(h_ota, "1.0.1"); - // if (0 > sg_packet_id) { - // Log_e("report OTA result failed error:%d", sg_packet_id); - // return QCLOUD_ERR_FAILURE; - // } - // while (!sg_pub_ack) { - // HAL_SleepMs(1000); - // IOT_MQTT_Yield(client, 200); - // } - // sg_pub_ack = false; + packet_id = IOT_OTA_ReportUpgradeSuccess(h_ota, NULL); + else + packet_id = IOT_OTA_ReportUpgradeFail(h_ota, NULL); + _wait_for_pub_ack(ota_ctx, packet_id); + + return upgrade_fetch_success; +} + +int main(int argc, char **argv) +{ + int rc; + OTAContextData *ota_ctx = NULL; + void * mqtt_client = NULL; + void * h_ota = NULL; + + IOT_Log_Set_Level(eLOG_DEBUG); + ota_ctx = (OTAContextData *)HAL_Malloc(sizeof(OTAContextData)); + if (ota_ctx == NULL) { + Log_e("malloc failed"); + goto exit; + } + memset(ota_ctx, 0, sizeof(OTAContextData)); + + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + goto exit; + } + + // setup MQTT init params + MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; + rc = _setup_connect_init_params(&init_params, ota_ctx, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + return rc; + } + + // create MQTT mqtt_client and connect to server + mqtt_client = IOT_MQTT_Construct(&init_params); + if (mqtt_client != NULL) { + Log_i("Cloud Device Construct Success"); + } else { + Log_e("Cloud Device Construct Failed"); + return QCLOUD_ERR_FAILURE; + } + + // init OTA handle + h_ota = IOT_OTA_Init(device_info.product_id, device_info.device_name, mqtt_client); + if (NULL == h_ota) { + Log_e("initialize OTA failed"); + goto exit; } - IOT_OTA_Destroy(h_ota); + ota_ctx->ota_handle = h_ota; + ota_ctx->mqtt_client = mqtt_client; + + bool ota_success; + do { + // mqtt should be ready first + rc = IOT_MQTT_Yield(mqtt_client, 500); + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + // OTA process + ota_success = process_ota(ota_ctx); + if (!ota_success) { + Log_e("OTA failed! Do it again"); + HAL_SleepMs(2000); + } + } while (!ota_success); + +exit: + + if (NULL != ota_ctx) + HAL_Free(ota_ctx); + + if (NULL != h_ota) + IOT_OTA_Destroy(h_ota); + + IOT_MQTT_Destroy(&mqtt_client); - IOT_MQTT_Destroy(&client); - return 0; } diff --git a/samples/ota/ota_mqtt_subdev_sample.c b/samples/ota/ota_mqtt_subdev_sample.c new file mode 100755 index 00000000..340cf268 --- /dev/null +++ b/samples/ota/ota_mqtt_subdev_sample.c @@ -0,0 +1,901 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub + available. + * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file + except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software + distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, + * either express or implied. See the License for the specific language + governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "utils_getopt.h" +#include "lite-utils.h" + +static DeviceInfo sg_subdev_info[] = { + {.product_id = "E69UADXUYY", .device_name = "light1"}, + {.product_id = "E69UADXUYY", .device_name = "light2"}, + {.product_id = "E69UADXUYY", .device_name = "light3"}, + {.product_id = "YI7XCD5DRH", .device_name = "airConditioner1"}, +}; + +#define MAX_SIZE_OF_TOPIC (128) +#define MAX_SIZE_OF_DATA (128) + +static int sg_sub_packet_id = -1; +static int sg_pub_packet_id = -1; + +static int sg_loop_count = 1; +static GatewayDeviceInfo sg_GWdevInfo; + +#define FW_RUNNING_VERSION "0.1" +#define KEY_VER "version" +#define KEY_SIZE "downloaded_size" + +#define FW_VERSION_MAX_LEN 32 +#define FW_FILE_PATH_MAX_LEN 128 +#define OTA_BUF_LEN 5000 +#define FW_INFO_FILE_DATA_LEN 128 + +/* The structure of subdevice ota context */ +typedef struct _SubdevOtaContext { + void * ota_handle; + char * product_id; + char * device_name; + struct _SubdevOtaContext *next; +} SubdevOtaContext; + +typedef struct OTAContextData { + void *ota_handle; + void *gateway_client; + char *product_id; + char *device_name; + char fw_file_path[FW_FILE_PATH_MAX_LEN]; + char fw_info_file_path[FW_FILE_PATH_MAX_LEN]; + // remote_version means version for the FW in the cloud and to be downloaded + char remote_version[FW_VERSION_MAX_LEN]; + uint32_t fw_file_size; + + // for resuming download + /* local_version means downloading but not running */ + char local_version[FW_VERSION_MAX_LEN]; + int downloaded_size; + + // to make sure report is acked + bool report_pub_ack; + int report_packet_id; +} OTAContextData; + +static SubdevOtaContext *sg_subdev_ota_context_list = NULL; + +/********************************************************************************** + * OTA file operations START + * these are platform-dependant functions + * POSIX FILE is used in this sample code + **********************************************************************************/ +// calculate left MD5 for resuming download from break point +static int _cal_exist_fw_md5(OTAContextData *ota_ctx) +{ + char buff[OTA_BUF_LEN]; + size_t rlen, total_read = 0; + int ret = QCLOUD_RET_SUCCESS; + + ret = IOT_OTA_ResetClientMD5(ota_ctx->ota_handle); + if (ret) { + Log_e("reset MD5 failed: %d", ret); + return QCLOUD_ERR_FAILURE; + } + + FILE *fp = fopen(ota_ctx->fw_file_path, "ab+"); + if (NULL == fp) { + Log_e("open file %s failed", STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->fw_file_path)); + return QCLOUD_ERR_FAILURE; + } + + // rewind(fp); + size_t size = ota_ctx->downloaded_size; + + while ((size > 0) && (!feof(fp))) { + rlen = (size > OTA_BUF_LEN) ? OTA_BUF_LEN : size; + if (rlen != fread(buff, 1, rlen, fp)) { + Log_e("read data len not expected"); + ret = QCLOUD_ERR_FAILURE; + break; + } + IOT_OTA_UpdateClientMd5(ota_ctx->ota_handle, buff, rlen); + size -= rlen; + total_read += rlen; + } + + fclose(fp); + Log_d("total read: %d", total_read); + return ret; +} + +/* update local firmware info for resuming download from break point */ +static int _update_local_fw_info(OTAContextData *ota_ctx) +{ + FILE *fp; + int wlen; + int ret = QCLOUD_RET_SUCCESS; + char data_buf[FW_INFO_FILE_DATA_LEN]; + + memset(data_buf, 0, sizeof(data_buf)); + HAL_Snprintf(data_buf, sizeof(data_buf), "{\"%s\":\"%s\", \"%s\":%d}", KEY_VER, + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->remote_version), KEY_SIZE, ota_ctx->downloaded_size); + + fp = fopen(ota_ctx->fw_info_file_path, "w"); + if (NULL == fp) { + Log_e("open file %s failed", STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->fw_info_file_path)); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + wlen = fwrite(data_buf, 1, strlen(data_buf), fp); + if (wlen != strlen(data_buf)) { + Log_e("save version to file err"); + ret = QCLOUD_ERR_FAILURE; + } + +exit: + + if (NULL != fp) { + fclose(fp); + } + + return ret; +} + +static int _get_local_fw_info(char *file_name, char *local_version) +{ + int len = 0; + int rlen; + char json_doc[FW_INFO_FILE_DATA_LEN] = {0}; + + FILE *fp = fopen(file_name, "r"); + if (NULL == fp) { + Log_e("open file %s failed", STRING_PTR_PRINT_SANITY_CHECK(file_name)); + return 0; + } + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + if ((len < 0) || (len > FW_INFO_FILE_DATA_LEN)) { + Log_e("%s is too big, pls check", file_name); + fclose(fp); + return 0; + } + + rewind(fp); + rlen = fread(json_doc, 1, len, fp); + if (len != rlen) { + Log_e("read data len (%d) less than needed (%d), %s", rlen, len, json_doc); + fclose(fp); + return 0; + } + + char *version = LITE_json_value_of(KEY_VER, json_doc); + char *size = LITE_json_value_of(KEY_SIZE, json_doc); + + if ((NULL == version) || (NULL == size)) { + if (version) + HAL_Free(version); + if (size) + HAL_Free(size); + fclose(fp); + return 0; + } + + int local_size = atoi(size); + HAL_Free(size); + + if (local_size <= 0) { + Log_w("local info offset invalid: %d", local_size); + HAL_Free(version); + local_size = 0; + return local_size; + } + + strncpy(local_version, version, FW_VERSION_MAX_LEN); + HAL_Free(version); + fclose(fp); + return local_size; +} + +/* get local firmware offset for resuming download from break point */ +static int _update_fw_downloaded_size(OTAContextData *ota_ctx) +{ + int local_size = _get_local_fw_info(ota_ctx->fw_info_file_path, ota_ctx->local_version); + if (local_size == 0) { + ota_ctx->downloaded_size = 0; + return 0; + } + + if ((0 != strcmp(ota_ctx->local_version, ota_ctx->remote_version)) || + (ota_ctx->downloaded_size > ota_ctx->fw_file_size)) { + ota_ctx->downloaded_size = 0; + return 0; + } + + ota_ctx->downloaded_size = local_size; + Log_i("calc MD5 for resuming download from offset: %d", ota_ctx->downloaded_size); + int ret = _cal_exist_fw_md5(ota_ctx); + if (ret) { + Log_e("regen OTA MD5 error: %d", ret); + remove(ota_ctx->fw_info_file_path); + ota_ctx->downloaded_size = 0; + return 0; + } + Log_d("local MD5 update done!"); + return local_size; +} + +static int _delete_fw_info_file(char *file_name) +{ + return remove(file_name); +} + +static int _save_fw_data_to_file(char *file_name, uint32_t offset, char *buf, int len) +{ + FILE *fp; + if (offset > 0) { + if (NULL == (fp = fopen(file_name, "ab+"))) { + Log_e("open file failed"); + return QCLOUD_ERR_FAILURE; + } + } else { + if (NULL == (fp = fopen(file_name, "wb+"))) { + Log_e("open file failed"); + return QCLOUD_ERR_FAILURE; + } + } + + fseek(fp, offset, SEEK_SET); + + if (1 != fwrite(buf, len, 1, fp)) { + Log_e("write data to file failed"); + fclose(fp); + return QCLOUD_ERR_FAILURE; + } + fflush(fp); + fclose(fp); + + return 0; +} + +/********************************************************************************** + * OTA file operations END + **********************************************************************************/ + +/*****************************************************************************************************************/ +static void _wait_for_pub_ack(OTAContextData *ota_ctx, int packet_id) +{ + int wait_cnt = 10; + ota_ctx->report_pub_ack = false; + ota_ctx->report_packet_id = packet_id; + + while (sg_pub_packet_id != packet_id) { + HAL_SleepMs(500); + IOT_Gateway_Yield(ota_ctx->gateway_client, 500); + if (wait_cnt-- == 0) { + Log_e("wait report pub ack timeout!"); + break; + } + } + ota_ctx->report_pub_ack = false; + return; +} + +static SubdevOtaContext *_subdev_ota_context_create(void *gateway_client, char *subdev_product_id, + char *subdev_device_name) +{ + SubdevOtaContext *ota_context = NULL; + char * product_id = NULL; + char * device_name = NULL; + + ota_context = sg_subdev_ota_context_list; + /* ota_handle is exist */ + while (ota_context) { + product_id = ota_context->product_id; + device_name = ota_context->device_name; + + if (0 == strcmp(product_id, subdev_product_id) && (0 == strcmp(device_name, subdev_device_name))) { + return ota_context; + } + ota_context = ota_context->next; + } + + ota_context = HAL_Malloc(sizeof(SubdevOtaContext)); + if (ota_context == NULL) { + Log_e("Not enough memory"); + return NULL; + } + + memset(ota_context, 0, sizeof(SubdevOtaContext)); + + ota_context->ota_handle = + IOT_OTA_Init(subdev_product_id, subdev_device_name, IOT_Gateway_Get_Mqtt_Client(gateway_client)); + if (NULL == ota_context->ota_handle) { + Log_e("subDev %s-%s initialize OTA failed", STRING_PTR_PRINT_SANITY_CHECK(subdev_product_id), + STRING_PTR_PRINT_SANITY_CHECK(subdev_device_name)); + HAL_Free(ota_context); + return NULL; + } + + ota_context->product_id = subdev_product_id; + ota_context->device_name = subdev_device_name; + + /* add ota handle to list */ + ota_context->next = sg_subdev_ota_context_list; + sg_subdev_ota_context_list = ota_context; + + return ota_context; +} + +static SubdevOtaContext *_subdev_ota_context_get_fetch() +{ + SubdevOtaContext *ota_context = sg_subdev_ota_context_list; + while (NULL != ota_context) { + if (IOT_OTA_IsFetching(ota_context->ota_handle)) { + break; + } else { + ota_context = ota_context->next; + } + } + + return ota_context; +} + +static int _subdev_ota_context_destory(char *subdev_product_id, char *subdev_device_name) +{ + SubdevOtaContext *cur_ota_context = NULL; + SubdevOtaContext *pre_ota_context = NULL; + char * product_id = NULL; + char * device_name = NULL; + + cur_ota_context = pre_ota_context = sg_subdev_ota_context_list; + + if (NULL == cur_ota_context) { + Log_e("ota_handle list is empty"); + return QCLOUD_RET_SUCCESS; + } + + /* ota_handle is exist */ + while (cur_ota_context) { + product_id = cur_ota_context->product_id; + device_name = cur_ota_context->device_name; + + if (0 == strcmp(product_id, subdev_product_id) && (0 == strcmp(device_name, subdev_device_name))) { + if (cur_ota_context == sg_subdev_ota_context_list) { + sg_subdev_ota_context_list = cur_ota_context->next; + } else { + pre_ota_context->next = cur_ota_context->next; + } + + IOT_OTA_Destroy(cur_ota_context->ota_handle); + HAL_Free(cur_ota_context); + return QCLOUD_RET_SUCCESS; + } + pre_ota_context = cur_ota_context; + cur_ota_context = cur_ota_context->next; + } + + return QCLOUD_ERR_FAILURE; +} + +static char *_get_subdev_fw_running_version(char *product_id, char *device_name) +{ + Log_i("%s-%s FW running version: %s", STRING_PTR_PRINT_SANITY_CHECK(product_id), + STRING_PTR_PRINT_SANITY_CHECK(device_name), FW_RUNNING_VERSION); + return FW_RUNNING_VERSION; +} + +static bool _subdev_process_upgrade(OTAContextData *ota_ctx) +{ + Log_i("%s-%s download success, fw name:%s, fw size:%d, fw version:%s, now to upgrade subdevice ...", + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->product_id), STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->device_name), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->fw_file_path), ota_ctx->fw_file_size, + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->remote_version)); + + return true; +} + +// main OTA cycle +bool process_ota(OTAContextData *ota_ctx) +{ + bool download_finished = false; + bool upgrade_fetch_success = true; + char buf_ota[OTA_BUF_LEN]; + int rc; + void *h_ota = ota_ctx->ota_handle; + + do { + // recv the upgrade cmd + if (IOT_OTA_IsFetching(h_ota)) { + IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &ota_ctx->fw_file_size, 4); + IOT_OTA_Ioctl(h_ota, IOT_OTAG_VERSION, ota_ctx->remote_version, FW_VERSION_MAX_LEN); + + HAL_Snprintf(ota_ctx->fw_file_path, FW_FILE_PATH_MAX_LEN, "./FW_%s%s_%s.bin", + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->product_id), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->device_name), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->remote_version)); + HAL_Snprintf(ota_ctx->fw_info_file_path, FW_FILE_PATH_MAX_LEN, "./FW_%s%s.json", + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->product_id), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->device_name)); + + /* check if pre-downloading finished or not */ + /* if local FW downloaded size (ota_ctx->downloaded_size) is not zero, it will do resuming download */ + _update_fw_downloaded_size(ota_ctx); + + /*set offset and start http connect*/ + rc = IOT_OTA_StartDownload(h_ota, ota_ctx->downloaded_size, ota_ctx->fw_file_size); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("OTA download start err,rc:%d", rc); + upgrade_fetch_success = false; + break; + } + + // download and save the fw + do { + int len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1); + if (len > 0) { + rc = _save_fw_data_to_file(ota_ctx->fw_file_path, ota_ctx->downloaded_size, buf_ota, len); + if (rc) { + Log_e("write data to file failed"); + upgrade_fetch_success = false; + break; + } + } else if (len < 0) { + Log_e("download fail rc=%d", len); + upgrade_fetch_success = false; + break; + } + + /* get OTA information and update local info */ + IOT_OTA_Ioctl(h_ota, IOT_OTAG_FETCHED_SIZE, &ota_ctx->downloaded_size, 4); + rc = _update_local_fw_info(ota_ctx); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("update local fw info err,rc:%d", rc); + } + + // quit ota process as something wrong with mqtt + rc = IOT_Gateway_Yield(ota_ctx->gateway_client, 100); + if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("MQTT error: %d", rc); + return false; + } + + } while (!IOT_OTA_IsFetchFinish(h_ota)); + + /* Must check MD5 match or not */ + if (upgrade_fetch_success) { + // download is finished, delete the fw info file + _delete_fw_info_file(ota_ctx->fw_info_file_path); + + uint32_t firmware_valid; + IOT_OTA_Ioctl(h_ota, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4); + if (0 == firmware_valid) { + Log_e("The firmware is invalid"); + upgrade_fetch_success = false; + } else { + Log_i("The firmware is valid"); + upgrade_fetch_success = true; + } + } + + download_finished = true; + } + + if (!download_finished) + HAL_SleepMs(1000); + + } while (!download_finished); + + if (upgrade_fetch_success) { + IOT_OTA_ReportUpgradeBegin(h_ota); + + // do some post-download stuff for your need + upgrade_fetch_success = _subdev_process_upgrade(ota_ctx); + } + + // report result + int packet_id; + if (upgrade_fetch_success) { + Log_i("%s-%s upgrade success", STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->product_id), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->device_name)); + packet_id = IOT_OTA_ReportUpgradeSuccess(h_ota, NULL); + } else { + Log_i("%s-%s upgrade failed", STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->product_id), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->device_name)); + packet_id = IOT_OTA_ReportUpgradeFail(h_ota, NULL); + } + _wait_for_pub_ack(ota_ctx, packet_id); + + return upgrade_fetch_success; +} + +/*****************************************************************************************************************/ + +void _event_handler(void *client, void *context, MQTTEventMsg *msg) +{ + MQTTMessage *mqtt_message = (MQTTMessage *)msg->msg; + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_i( + "topic message arrived but without any related handle: topic=%.*s, " + "topic_msg=%.*s", + mqtt_message->topic_len, STRING_PTR_PRINT_SANITY_CHECK(mqtt_message->ptopic), mqtt_message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(mqtt_message->payload)); + break; + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + sg_sub_packet_id = packet_id; + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + sg_sub_packet_id = packet_id; + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + sg_sub_packet_id = packet_id; + break; + + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + sg_pub_packet_id = packet_id; + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} + +static int _setup_gw_init_params(GatewayInitParam *gw_init_params, GatewayDeviceInfo *gw_dev_info) +{ + MQTTInitParams *init_params = &gw_init_params->init_param; + DeviceInfo * dev_info = &gw_dev_info->gw_info; + init_params->product_id = dev_info->product_id; + init_params->device_name = dev_info->device_name; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(init_params->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_cert_file_name)); + HAL_Snprintf(init_params->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_key_file_name)); +#else + HAL_Snprintf(init_params->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_cert_file_name)); + HAL_Snprintf(init_params->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_key_file_name)); +#endif + +#else + init_params->device_secret = dev_info->device_secret; +#endif + + init_params->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + init_params->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + + init_params->auto_connect_enable = 1; + init_params->event_handle.h_fp = _event_handler; + init_params->event_handle.context = NULL; + + return QCLOUD_RET_SUCCESS; +} + +static int parse_arguments(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "c:l:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + case 'l': + sg_loop_count = atoi(utils_optarg); + if (sg_loop_count > 10000) + sg_loop_count = 10000; + else if (sg_loop_count < 0) + sg_loop_count = 1; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n" + " [-l ] \n", + argv[0]); + return -1; + } + return 0; +} + +/** + * show gateway dynamic bind/unbind sub-devices + */ +#ifdef GATEWAY_DYN_BIND_SUBDEV_ENABLED +static int add_new_binded_sub_dev(GatewayDeviceInfo *pGateway, DeviceInfo *pNewSubDev) +{ + int ret; + if (pGateway->sub_dev_num < MAX_NUM_SUB_DEV) { + memcpy((char *)&pGateway->sub_dev_info[pGateway->sub_dev_num], (char *)pNewSubDev, sizeof(DeviceInfo)); + pGateway->sub_dev_num++; + ret = QCLOUD_RET_SUCCESS; // you can save gateway info to local flash for persistent storage + } else { + ret = QCLOUD_ERR_FAILURE; + } + + return ret; +} + +static int show_subdev_bind_unbind(void *client, GatewayParam *param) +{ + int rc; + + // adjust for your bind device info + DeviceInfo subDev; + memset((char *)&subDev, 0, sizeof(DeviceInfo)); + strncpy(subDev.product_id, "BIND_PID", MAX_SIZE_OF_PRODUCT_ID); + strncpy(subDev.device_name, "BIND_DEV_NAME", MAX_SIZE_OF_DEVICE_NAME); +#ifdef AUTH_MODE_CERT + strncpy(subDev.dev_cert_file_name, "BIND_CERT_FILE_NAME", MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); + strncpy(subDev.dev_key_file_name, "BIND_KEY_FILE_NAME", MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); + +#else + strncpy(subDev.device_secret, "BIND_DEV_PSK", MAX_SIZE_OF_DEVICE_SECRET); +#endif + Log_d("bind subdev %s/%s", subDev.product_id, subDev.device_name); + + // bind sub dev + rc = IOT_Gateway_Subdev_Bind(client, param, &subDev); + if (QCLOUD_ERR_BIND_REPEATED_REQ == rc) { + Log_d("%s/%s has been binded", subDev.product_id, subDev.device_name); + rc = IOT_Gateway_Subdev_Unbind(client, param, &subDev); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("unbind %s/%s fail,rc:%d", subDev.product_id, subDev.device_name, rc); + } else { + Log_d("unbind %s/%s success", subDev.product_id, subDev.device_name); + rc = IOT_Gateway_Subdev_Bind(client, param, &subDev); + } + } + + if (QCLOUD_RET_SUCCESS == rc) { + Log_d("bind %s/%s success", subDev.product_id, subDev.device_name); + add_new_binded_sub_dev(&sg_GWdevInfo, &subDev); + } else { + Log_e("bind %s/%s fail,rc:%d", subDev.product_id, subDev.device_name, rc); + } + + return rc; +} + +#endif + +/*Gateway should enable multithread*/ +int main(int argc, char **argv) +{ + int rc = QCLOUD_ERR_FAILURE; + int errCount = 0; + int i; + void * client = NULL; + GatewayDeviceInfo *gw = &sg_GWdevInfo; + GatewayParam param = DEFAULT_GATEWAY_PARAMS; + DeviceInfo * subDevInfo; + OTAContextData * ota_ctx = NULL; + bool ota_success; + SubdevOtaContext * ota_context = NULL; + + IOT_Log_Set_Level(eLOG_DEBUG); + // parse arguments for device info file and loop test; + rc = parse_arguments(argc, argv); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("parse arguments error, rc = %d", rc); + return rc; + } + + ota_ctx = (OTAContextData *)HAL_Malloc(sizeof(OTAContextData)); + if (ota_ctx == NULL) { + Log_e("malloc failed"); + return QCLOUD_ERR_FAILURE; + } + memset(ota_ctx, 0, sizeof(OTAContextData)); + + rc = HAL_GetGwDevInfo((void *)gw); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("Get gateway dev info err,rc:%d", rc); + return rc; + } + + GatewayInitParam init_params = DEFAULT_GATEWAY_INIT_PARAMS; + rc = _setup_gw_init_params(&init_params, gw); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + return rc; + } + + client = IOT_Gateway_Construct(&init_params); + if (client == NULL) { + Log_e("client constructed failed."); + return QCLOUD_ERR_FAILURE; + } + +#ifdef MULTITHREAD_ENABLED + /* Start the default loop thread to read and handle MQTT packet*/ + rc = IOT_MQTT_StartLoop(IOT_Gateway_Get_Mqtt_Client(client)); + if (rc) { + Log_e("MQTT start loop failed: %d", rc); + rc = IOT_MQTT_Destroy(&client); + return rc; + } +#endif + + // set GateWay device info + param.product_id = gw->gw_info.product_id; + param.device_name = gw->gw_info.device_name; + + // make sub-device online + gw->sub_dev_info = sg_subdev_info; + gw->sub_dev_num = sizeof(sg_subdev_info) / sizeof(DeviceInfo); + + for (i = 0; i < gw->sub_dev_num; i++) { + subDevInfo = &gw->sub_dev_info[i]; + param.subdev_product_id = subDevInfo->product_id; + param.subdev_device_name = subDevInfo->device_name; + + rc = IOT_Gateway_Subdev_Online(client, ¶m); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("subDev Pid:%s devName:%s online fail.", subDevInfo->product_id, subDevInfo->device_name); + errCount++; + } else { + Log_d("subDev Pid:%s devName:%s online success.", subDevInfo->product_id, subDevInfo->device_name); + // ota init; + // init OTA context + ota_context = _subdev_ota_context_create(client, subDevInfo->product_id, subDevInfo->device_name); + if (NULL == ota_context) { + Log_e("subDev %s-%s initialize OTA Handle failed", subDevInfo->product_id, subDevInfo->device_name); + errCount++; + } else { + Log_d("subDev Pid:%s devName:%s initialize OTA Handle success.", subDevInfo->product_id, + subDevInfo->device_name); + char *curr_version = _get_subdev_fw_running_version(subDevInfo->product_id, subDevInfo->device_name); + // online report version + rc = IOT_OTA_ReportVersion(ota_context->ota_handle, curr_version); + if (rc < 0) { + Log_e("%s-%s report OTA version failed", subDevInfo->product_id, subDevInfo->device_name); + } else { + rc = QCLOUD_RET_SUCCESS; + } + } + } + } + + if (errCount > 0) { + Log_e("%d of %d sub devices online fail", errCount, gw->sub_dev_num); + } + + // gateway yield, loop proc ota + while (QCLOUD_RET_SUCCESS == rc) { + rc = IOT_Gateway_Yield(client, 200); + if (QCLOUD_RET_SUCCESS != rc) { + Log_d("Gateway Yield without mqtt err, rc:%d", rc); + break; + } + ota_context = _subdev_ota_context_get_fetch(); + if (NULL != ota_context) { + ota_ctx->ota_handle = ota_context->ota_handle; + ota_ctx->gateway_client = client; + ota_ctx->product_id = ota_context->product_id; + ota_ctx->device_name = ota_context->device_name; + + // OTA process + ota_success = process_ota(ota_ctx); + if (!ota_success) { + Log_e("process ota failed, subdevice %s-%s", STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->product_id), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->device_name)); + } else { + Log_e("process ota success subdevice %s-%s", STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->product_id), + STRING_PTR_PRINT_SANITY_CHECK(ota_ctx->device_name)); + } + } else { + Log_i("wait for ota upgrade command..."); + HAL_SleepMs(2000); + } + } + + // set GateWay device info + param.product_id = gw->gw_info.product_id; + param.device_name = gw->gw_info.device_name; + + // make sub-device offline + errCount = 0; + for (i = 0; i < gw->sub_dev_num; i++) { + subDevInfo = &gw->sub_dev_info[i]; + param.subdev_product_id = subDevInfo->product_id; + param.subdev_device_name = subDevInfo->device_name; + + rc = _subdev_ota_context_destory(subDevInfo->product_id, subDevInfo->device_name); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("subDev %s-%s offline ota destory fail.", subDevInfo->product_id, subDevInfo->device_name); + } else { + Log_d("subDev %s-%s offline ota destory success.", subDevInfo->product_id, subDevInfo->device_name); + } + + rc = IOT_Gateway_Subdev_Offline(client, ¶m); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("subDev Pid:%s devName:%s offline fail.", subDevInfo->product_id, subDevInfo->device_name); + errCount++; + } else { + Log_d("subDev Pid:%s devName:%s offline success.", subDevInfo->product_id, subDevInfo->device_name); + } + } + if (errCount > 0) { + Log_e("%d of %d sub devices offline fail", errCount, gw->sub_dev_num); + } + + rc = IOT_Gateway_Destroy(client); + + HAL_Free(ota_ctx); + + return rc; +} diff --git a/samples/rrpc/rrpc_sample.c b/samples/rrpc/rrpc_sample.c new file mode 100755 index 00000000..12931ae4 --- /dev/null +++ b/samples/rrpc/rrpc_sample.c @@ -0,0 +1,237 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" + +// MQTT event callback +static void _mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + MQTTMessage *mqtt_messge = (MQTTMessage *)msg->msg; + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + mqtt_messge->topic_len, STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->ptopic), mqtt_messge->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(mqtt_messge->payload)); + break; + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} + +// Setup MQTT construct parameters +static int _setup_connect_init_params(MQTTInitParams *initParams, DeviceInfo *device_info) +{ + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); +#endif + +#else + initParams->device_secret = device_info->device_secret; +#endif + + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = _mqtt_event_handler; + initParams->event_handle.context = NULL; + + return QCLOUD_RET_SUCCESS; +} + +// User callback +static void _rrpc_message_handler(void *pClient, const char *msg, uint32_t msgLen) +{ + char sg_rrpc_reply_buffer[128] = {0}; + size_t sg_rrpc_reply_buffersize = sizeof(sg_rrpc_reply_buffer) / sizeof(sg_rrpc_reply_buffer[0]); + + Log_i("rrpc message=%.*s", msgLen, STRING_PTR_PRINT_SANITY_CHECK(msg)); + + // add your logic here and set reply param which will be reported by IOT_RRPC_Reply + sg_rrpc_reply_buffer[0] = 'o'; + sg_rrpc_reply_buffer[1] = 'k'; + + IOT_RRPC_Reply(pClient, sg_rrpc_reply_buffer, sg_rrpc_reply_buffersize, NULL); +} + +static int sg_loop_count = 5; +static int parse_arguments(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "c:l:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + case 'l': + sg_loop_count = atoi(utils_optarg); + if (sg_loop_count > 10000) + sg_loop_count = 10000; + else if (sg_loop_count < 0) + sg_loop_count = 1; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n" + " [-l ] \n", + argv[0]); + return -1; + } + return 0; +} + +int main(int argc, char **argv) +{ + int rc; + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + // parse arguments for device info file and loop test; + rc = parse_arguments(argc, argv); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("parse arguments error, rc = %d", rc); + return rc; + } + + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + return rc; + } + + // init connection + MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; + rc = _setup_connect_init_params(&init_params, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params error, rc = %d", rc); + return rc; + } + + // create MQTT client and connect with server + void *client = IOT_MQTT_Construct(&init_params); + if (client != NULL) { + Log_i("Cloud Device Construct Success"); + } else { + Log_e("MQTT Construct failed!"); + IOT_Log_Upload(true); + return QCLOUD_ERR_FAILURE; + } + + // subscribe rrpc topics + rc = IOT_RRPC_Init(client, _rrpc_message_handler); + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + do { + rc = IOT_MQTT_Yield(client, 500); + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + HAL_SleepMs(1000); + + } while (--sg_loop_count > 0); + + rc = IOT_MQTT_Destroy(&client); + + return rc; +} diff --git a/samples/samples.mk b/samples/samples.mk deleted file mode 100755 index 64ceaf20..00000000 --- a/samples/samples.mk +++ /dev/null @@ -1,136 +0,0 @@ -DEPENDS := src/platform -LDFLAGS := $(FINAL_DIR)/lib/libiot_sdk.a -LDFLAGS += $(FINAL_DIR)/lib/libiot_platform.a -ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) -LDFLAGS += $(FINAL_DIR)/lib/libmbedtls.a $(FINAL_DIR)/lib/libmbedx509.a $(FINAL_DIR)/lib/libmbedcrypto.a -endif -CFLAGS := $(filter-out -ansi,$(CFLAGS)) - -ifneq (,$(filter -DMQTT_COMM_ENABLED,$(CFLAGS))) -mqtt_sample: - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports) - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/mqtt/$@.c $(LDFLAGS) -o $@ - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/scenarized/door_$@.c $(LDFLAGS) -o door_$@ - - $(TOP_Q) \ - mv door_$@ $(FINAL_DIR)/bin && \ - mv $@ $(FINAL_DIR)/bin - -ifneq (,$(filter -DMULTITHREAD_TEST_ENABLED,$(CFLAGS))) -multi_thread_mqtt_sample: - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports -pthread) - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/mqtt/$@.c $(LDFLAGS) -o $@ - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/bin -endif - -ifneq (,$(filter -DOTA_COMM_ENABLED,$(CFLAGS))) -ifneq (,$(filter -DOTA_MQTT_CHANNEL,$(CFLAGS))) -ota_mqtt_sample: - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports) - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/ota/$@.c $(LDFLAGS) -o $@ - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/bin -endif -endif -endif - -ifneq (,$(filter -DMQTT_DEVICE_SHADOW,$(CFLAGS))) -shadow_sample: - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports -I$(TOP_DIR)/src/utils/lite) - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/shadow/$@.c $(LDFLAGS) -o $@ - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/scenarized/aircond_$@.c $(LDFLAGS) -o aircond_$@ - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/scenarized/aircond_$@_v2.c $(LDFLAGS) -o aircond_$@_v2 - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/bin && \ - mv aircond_$@ $(FINAL_DIR)/bin && \ - mv aircond_$@_v2 $(FINAL_DIR)/bin -endif - -ifneq (,$(filter -DCOAP_COMM_ENABLED,$(CFLAGS))) -coap_sample: - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports) - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/coap/$@.c $(LDFLAGS) -o $@ - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/scenarized/door_$@.c $(LDFLAGS) -o door_$@ - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/bin - - $(TOP_Q) \ - mv door_$@ $(FINAL_DIR)/bin -ifneq (,$(filter -DOTA_COMM_ENABLED,$(CFLAGS))) -ifneq (,$(filter -DOTA_COAP_CHANNEL,$(CFLAGS))) -ota_coap_sample: - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports) - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/ota/$@.c $(LDFLAGS) -o $@ - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/bin -endif -endif -endif - -ifneq (,$(filter -DNBIOT_COMM_ENABLED,$(CFLAGS))) -nbiot_sample: - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports) - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/nbiot/$@.c $(LDFLAGS) -o $@ - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/bin -endif - -ifneq (,$(filter -DGATEWAY_ENABLED,$(CFLAGS))) -gateway_sample: - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports) - - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/gateway/$@.c $(LDFLAGS) -o $@ - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/bin -endif - -samples_final: - $(eval CFLAGS := $(filter-out -I$(TOP_DIR)/src/sdk-impl,$(CFLAGS)) \ - $(IOTSDK_INCLUDE_FILES)) - $(TOP_Q) \ - cp -rf $(TOP_DIR)/src/sdk-impl/qcloud_iot_*port.h $(FINAL_DIR)/include/ - - $(TOP_Q) \ - cp -rf $(TOP_DIR)/src/sdk-impl/exports $(FINAL_DIR)/include/ - - $(TOP_Q) \ - cp -rf $(TOP_DIR)/certs $(FINAL_DIR)/bin/ diff --git a/samples/scenarized/aircond_shadow_sample.c b/samples/scenarized/aircond_shadow_sample.c old mode 100644 new mode 100755 index 03aec14c..e5903c7b --- a/samples/scenarized/aircond_shadow_sample.c +++ b/samples/scenarized/aircond_shadow_sample.c @@ -1,308 +1,293 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "lite-utils.h" - -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" - -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" - - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 - -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" -#endif - -#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 - -#define ROOM_TEMPERATURE 32.0f -static float sg_desire_temperature = 20.0f; -static float sg_report_temperature = ROOM_TEMPERATURE; - -static float sg_energy_consumption = 0.0f; -static bool sg_airconditioner_openned = false; - -static MQTTEventType sg_subscribe_event_result = MQTT_EVENT_UNDEF; - -#define MAX_RECV_LEN (512 + 1) - -/** - * 比较浮点数是否相等 - * - * @param left 左值 - * @param right 左值 - */ -bool _is_value_equal(float left, float right) -{ - if((leftright-0.01)) - return true; - else - return false; -} - -/** - * 模拟室内温度 - * - * @param roomTemperature - */ -static void _simulate_room_temperature(float *roomTemperature) { - float delta_change = 0; - - if (!sg_airconditioner_openned) { - if(!_is_value_equal(*roomTemperature, ROOM_TEMPERATURE)) { - delta_change = (*roomTemperature)>ROOM_TEMPERATURE ? -0.5: 0.5; - } - } else { - sg_energy_consumption += 1; - if (!_is_value_equal(*roomTemperature, sg_desire_temperature)) { - delta_change = (*roomTemperature)>sg_desire_temperature ? -1.0: 1.0; - } - } - - *roomTemperature += delta_change; -} - -static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_SUBCRIBE_SUCCESS: - sg_subscribe_event_result = msg->event_type; - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - sg_subscribe_event_result = msg->event_type; - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - sg_subscribe_event_result = msg->event_type; - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } -} - -/** - * MQTT消息接收处理函数 - * - * @param topicName topic主题 - * @param topicNameLen topic长度 - * @param message 已订阅消息的结构 - * @param userData 消息负载 - */ -static void on_message_callback(void *pClient, MQTTMessage *message, void *userData) -{ - if (message == NULL) - return; - - const char *topicName = message->ptopic; - size_t topicNameLen = message->topic_len; - - if (topicName == NULL || topicNameLen == 0) { - return; - } - - Log_i("Receive Message With topicName:%.*s, payload:%.*s", - (int) topicNameLen, topicName, (int) message->payload_len, (char *) message->payload); - - - static char cloud_rcv_buf[MAX_RECV_LEN + 1]; - size_t len = (message->payload_len > MAX_RECV_LEN)?MAX_RECV_LEN:(message->payload_len); - - if(message->payload_len > MAX_RECV_LEN){ - Log_e("paload len exceed buffer size"); - } - - memcpy(cloud_rcv_buf, message->payload, len); - cloud_rcv_buf[len] = '\0'; // jsmn_parse relies on a string - - char* value = LITE_json_value_of("action", cloud_rcv_buf); - if (value != NULL) { - if(strcmp(value, "come_home") == 0) - { - sg_airconditioner_openned = true; - } - else if(strcmp(value, "leave_home") == 0) - { - sg_airconditioner_openned = false; - } - } - - HAL_Free(value); -} - -/** - * 设置MQTT connet初始化参数 - * - * @param initParams MQTT connet初始化参数 - * - * @return 0: 参数初始化成功 非0: 失败 - */ -static int _setup_connect_init_params(ShadowInitParams* initParams) -{ - initParams->device_name = QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = QCLOUD_IOT_MY_PRODUCT_ID; - -#ifdef AUTH_MODE_CERT - // 获取CA证书、客户端证书以及私钥文件的路径 - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - initParams->cert_file = sg_cert_file; - initParams->key_file = sg_key_file; -#else - initParams->device_secret = QCLOUD_IOT_DEVICE_SECRET; -#endif - - initParams->auto_connect_enable = 1; - initParams->event_handle.h_fp = event_handler; - - return QCLOUD_ERR_SUCCESS; -} - -/** - * 订阅关注topic和注册相应回调处理 - * - */ -static int _register_subscribe_topics(void *client) -{ - static char topic_name[128] = {0}; - int size = HAL_Snprintf(topic_name, sizeof(topic_name), "%s/%s/%s", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME, "control"); - if (size < 0 || size > sizeof(topic_name) - 1) - { - Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); - return QCLOUD_ERR_FAILURE; - } - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.on_message_handler = on_message_callback; - return IOT_Shadow_Subscribe(client, topic_name, &sub_params); -} - -int main(int argc, char **argv) { - int rc; - - //init log level - IOT_Log_Set_Level(DEBUG); - - //init connection - ShadowInitParams init_params = DEFAULT_SHAWDOW_INIT_PARAMS; - rc = _setup_connect_init_params(&init_params); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - void *client = IOT_Shadow_Construct(&init_params); - if (client != NULL) { - Log_i("Cloud Device Construct Success"); - } else { - Log_e("Cloud Device Construct Failed"); - return QCLOUD_ERR_FAILURE; - } - - //register subscribe topics here - rc = _register_subscribe_topics(client); - if (rc < 0) { - Log_e("Client Subscribe Topic Failed: %d", rc); - return rc; - } - - while (IOT_Shadow_IsConnected(client) || rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT || rc == QCLOUD_ERR_MQTT_RECONNECTED) { - - rc = IOT_Shadow_Yield(client, 200); - - if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { - sleep(1); - continue; - } - else if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("Exit loop caused of errCode: %d", rc); - } - - if (sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_SUCCESS && - sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_TIMEOUT && - sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_NACK) - { - Log_i("Wait for subscribe result,sg_subscribe_event_result = %d", sg_subscribe_event_result); - sleep(1); - continue; - } - - _simulate_room_temperature(&sg_report_temperature); - Log_i("airConditioner state: %s", sg_airconditioner_openned ? "open" : "close"); - Log_i("currentTemperature: %f, energyConsumption: %f", sg_report_temperature, sg_energy_consumption); - - sleep(1); - } - - rc = IOT_Shadow_Destroy(client); - - //注意进程异常退出情况 - - return rc; -} +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "lite-utils.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" + +static DeviceInfo sg_devInfo; + +#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 + +#define ROOM_TEMPERATURE 32.0f +static float sg_desire_temperature = 20.0f; +static float sg_report_temperature = ROOM_TEMPERATURE; + +static float sg_energy_consumption = 0.0f; +static bool sg_airconditioner_openned = false; + +static MQTTEventType sg_subscribe_event_result = MQTT_EVENT_UNDEF; + +#define MAX_RECV_LEN (512 + 1) + +// compare float value +bool _is_value_equal(float left, float right) +{ + if ((left < right + 0.01) && (left > right - 0.01)) + return true; + else + return false; +} + +// simulate room temperature change +static void _simulate_room_temperature(float *roomTemperature) +{ + float delta_change = 0; + + if (!sg_airconditioner_openned) { + if (!_is_value_equal(*roomTemperature, ROOM_TEMPERATURE)) { + delta_change = (*roomTemperature) > ROOM_TEMPERATURE ? -0.5 : 0.5; + } + } else { + sg_energy_consumption += 1; + if (!_is_value_equal(*roomTemperature, sg_desire_temperature)) { + delta_change = (*roomTemperature) > sg_desire_temperature ? -1.0 : 1.0; + } + } + + *roomTemperature += delta_change; +} + +// MQTT event callback +static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_SUBCRIBE_SUCCESS: + sg_subscribe_event_result = msg->event_type; + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + sg_subscribe_event_result = msg->event_type; + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + sg_subscribe_event_result = msg->event_type; + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} + +// callback when MQTT msg arrives +static void on_message_callback(void *pClient, MQTTMessage *message, void *userData) +{ + if (message == NULL) + return; + + const char *topicName = message->ptopic; + size_t topicNameLen = message->topic_len; + + if (topicName == NULL || topicNameLen == 0) { + return; + } + + Log_i("Receive Message With topicName:%.*s, payload:%.*s", (int)topicNameLen, topicName, (int)message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); + + static char cloud_rcv_buf[MAX_RECV_LEN + 1]; + size_t len = (message->payload_len > MAX_RECV_LEN) ? MAX_RECV_LEN : (message->payload_len); + + if (message->payload_len > MAX_RECV_LEN) { + Log_e("paload len exceed buffer size"); + } + + memcpy(cloud_rcv_buf, message->payload, len); + cloud_rcv_buf[len] = '\0'; // jsmn_parse relies on a string + + char *value = LITE_json_value_of("action", cloud_rcv_buf); + if (value != NULL) { + if (strcmp(value, "come_home") == 0) { + sg_airconditioner_openned = true; + } else if (strcmp(value, "leave_home") == 0) { + sg_airconditioner_openned = false; + } + } + + HAL_Free(value); +} + +// Setup MQTT construct parameters +static int _setup_connect_init_params(ShadowInitParams *initParams) +{ + int ret; + + ret = HAL_GetDevInfo((void *)&sg_devInfo); + if (QCLOUD_RET_SUCCESS != ret) { + return ret; + } + + initParams->device_name = sg_devInfo.device_name; + initParams->product_id = sg_devInfo.product_id; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_key_file_name)); +#endif + +#else + initParams->device_secret = sg_devInfo.device_secret; +#endif + + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = event_handler; + + return QCLOUD_RET_SUCCESS; +} + +// subscrib MQTT topic +static int _register_subscribe_topics(void *client) +{ + static char topic_name[128] = {0}; + int size = + HAL_Snprintf(topic_name, sizeof(topic_name), "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.product_id), + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.device_name), "control"); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.on_message_handler = on_message_callback; + return IOT_Shadow_Subscribe(client, topic_name, &sub_params); +} + +int main(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "c:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n", + argv[0]); + + return -1; + } + + int rc; + + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + // init connection + ShadowInitParams init_params = DEFAULT_SHAWDOW_INIT_PARAMS; + rc = _setup_connect_init_params(&init_params); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + return rc; + } + + void *client = IOT_Shadow_Construct(&init_params); + if (client != NULL) { + Log_i("Cloud Device Construct Success"); + } else { + Log_e("Cloud Device Construct Failed"); + return QCLOUD_ERR_FAILURE; + } + + // register subscribe topics here + rc = _register_subscribe_topics(client); + if (rc < 0) { + Log_e("Client Subscribe Topic Failed: %d", rc); + return rc; + } + + while (IOT_Shadow_IsConnected(client) || rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT || + rc == QCLOUD_RET_MQTT_RECONNECTED) { + rc = IOT_Shadow_Yield(client, 200); + + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS) { + Log_e("Exit loop caused of errCode: %d", rc); + } + + if (sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_SUCCESS && + sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_TIMEOUT && + sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_NACK) { + Log_i("Wait for subscribe result. sg_subscribe_event_result = %d", sg_subscribe_event_result); + HAL_SleepMs(1000); + continue; + } + + _simulate_room_temperature(&sg_report_temperature); + Log_i("airConditioner state: %s", sg_airconditioner_openned ? "open" : "close"); + Log_i("currentTemperature: %f, energyConsumption: %f", sg_report_temperature, sg_energy_consumption); + + HAL_SleepMs(1000); + } + + rc = IOT_Shadow_Destroy(client); + + return rc; +} diff --git a/samples/scenarized/aircond_shadow_sample_v2.c b/samples/scenarized/aircond_shadow_sample_v2.c old mode 100644 new mode 100755 index 28ed0e8d..905783ce --- a/samples/scenarized/aircond_shadow_sample_v2.c +++ b/samples/scenarized/aircond_shadow_sample_v2.c @@ -1,460 +1,450 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "lite-utils.h" - -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" - -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" - - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 - -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" -#endif - -#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 -#define ROOM_TEMPERATURE 32.0f -#define MAX_RECV_LEN (512 + 1) - - -static float sg_desire_temperature = 20.0f; -static float sg_report_temperature = ROOM_TEMPERATURE; - -static float sg_energy_consumption = 0.0f; -static bool sg_airconditioner_openned = false; - -static DeviceProperty sg_energy_consumption_prop; -static DeviceProperty sg_temperature_desire_prop; - -static bool sg_message_arrived_on_delta = false; - -static MQTTEventType sg_subscribe_event_result = MQTT_EVENT_UNDEF; -static bool sg_finish_shadow_get = false; - -char sg_document_buffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER]; -size_t sg_document_buffersize = sizeof(sg_document_buffer) / sizeof(sg_document_buffer[0]); - - -static int _register_config_shadow_property(void *client); -static int _register_subscribe_topics(void *client); - - -/** - * 比较浮点数是否相等 - */ -bool _is_value_equal(float left, float right) -{ - if((leftright-0.01)) - return true; - else - return false; -} - -/** - * 模拟室内温度 - */ -static void _simulate_room_temperature(float *roomTemperature) -{ - float delta_change = 0; - - if (!sg_airconditioner_openned) { - if(!_is_value_equal(*roomTemperature, ROOM_TEMPERATURE)) { - delta_change = (*roomTemperature) > ROOM_TEMPERATURE ? -0.5: 0.5; - } - } else { - sg_energy_consumption += 1; - if (!_is_value_equal(*roomTemperature, sg_desire_temperature)) { - delta_change = (*roomTemperature) > sg_desire_temperature ? -1.0: 1.0; - } - } - - *roomTemperature += delta_change; -} - -/** - * 文档操作请求返回回调函数 - */ -static void on_request_handler(void *pClient, Method method, RequestAck status, const char *jsonDoc, void *userData) -{ - - char *shadow_status = NULL; - char *shadow_method = NULL; - - if (status == ACK_TIMEOUT) { - shadow_status = "ACK_TIMEOUT"; - } else if (status == ACK_ACCEPTED) { - shadow_status = "ACK_ACCEPTED"; - } else if (status == ACK_REJECTED) { - shadow_status = "ACK_REJECTED"; - } - - if (method == GET) { - shadow_method = "GET"; - } else if (method == UPDATE) { - shadow_method = "UPDATE"; - } - - Log_i("Method=%s|Ack=%s", shadow_method, shadow_status); - Log_i("received jsonString=%s", jsonDoc); - - if (status == ACK_ACCEPTED && method == UPDATE) { - if (sg_message_arrived_on_delta) // 等待清空desired字段完成 - sg_message_arrived_on_delta = false; - Log_i("Update Shadow Success"); - } else if (status == ACK_ACCEPTED && method == GET) { - Log_i("Get Shadow Document Success"); - sg_finish_shadow_get = true; - } else if (status == ACK_TIMEOUT && method == UPDATE) { - Log_e("Update Shadow Fail!"); - exit(1); - } -} - -/** - * MQTT消息接收处理函数 - */ -static void on_message_callback(void *pClient, MQTTMessage *message, void *userData) -{ - if (message == NULL) - return; - - const char *topicName = message->ptopic; - uint16_t topicNameLen = message->topic_len; - - if (topicName == NULL || topicNameLen == 0) { - return; - } - - Log_i("Receive Message With topicName:%.*s, payload:%.*s", - (int) topicNameLen, topicName, (int) message->payload_len, (char *) message->payload); - - static char cloud_rcv_buf[MAX_RECV_LEN + 1]; - size_t len = (message->payload_len > MAX_RECV_LEN)?MAX_RECV_LEN:(message->payload_len); - - if(message->payload_len > MAX_RECV_LEN){ - Log_e("paload len exceed buffer size"); - } - memcpy(cloud_rcv_buf, message->payload, len); - cloud_rcv_buf[len] = '\0'; // jsmn_parse relies on a string - - char* value = LITE_json_value_of("action", cloud_rcv_buf); - if (value != NULL) { - if(strcmp(value, "come_home") == 0) - { - sg_airconditioner_openned = true; - } - else if(strcmp(value, "leave_home") == 0) - { - sg_airconditioner_openned = false; - } - } - - HAL_Free(value); -} - -/** - * delta消息回调处理函数 - */ -static void on_temperature_actuate_callback(void *pClient, const char *jsonResponse, uint32_t responseLen, DeviceProperty *context) -{ - Log_i("actuate callback jsonString=%s|dataLen=%u", jsonResponse, responseLen); - - if (context != NULL) { - Log_i("modify desire temperature to: %f", *(float *) context->data); - sg_message_arrived_on_delta = true; - } -} - -static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_SUBCRIBE_SUCCESS: - sg_subscribe_event_result = msg->event_type; - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - sg_subscribe_event_result = msg->event_type; - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - sg_subscribe_event_result = msg->event_type; - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } -} - -/** - * report energy consumption - */ -static int _do_report_energy_consumption(void *client) -{ - int rc = IOT_Shadow_JSON_ConstructReport(client, sg_document_buffer, sg_document_buffersize, 1, &sg_energy_consumption_prop); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow construct report failed: %d", rc); - return rc; - } - - Log_i("Update Shadow: %s", sg_document_buffer); - rc = IOT_Shadow_Update(client, sg_document_buffer, sg_document_buffersize, on_request_handler, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_i("Update Shadow Failed: %d", rc); - return rc; - } - - return rc; -} - -static int _do_report_temperature_desire(void *client) -{ - /* - * 如果收到delta消息,或者get时有desired内容,那么需要将 所有 的属性执行完毕之后,上报清空desried消息,否则后台的记录一直存在。 - * 如果没有执行变更属性值操作,那么不用上报desired字段。 - */ - - int rc; - rc = IOT_Shadow_JSON_ConstructReportAndDesireAllNull(client, sg_document_buffer, sg_document_buffersize, 1, &sg_temperature_desire_prop); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow construct report failed: %d", rc); - return rc; - } - - Log_i("update desire temperature: %s", sg_document_buffer); - rc = IOT_Shadow_Update(client, sg_document_buffer, sg_document_buffersize, on_request_handler, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_i("Update Shadow Failed: %d", rc); - return rc; - } else { - Log_i("Update Shadow Success"); - } - - return rc; -} - -/** - * 设置MQTT connet初始化参数 - */ -static int _setup_connect_init_params(ShadowInitParams* initParams) -{ - initParams->device_name = QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = QCLOUD_IOT_MY_PRODUCT_ID; - -#ifdef AUTH_MODE_CERT - // 获取CA证书、客户端证书以及私钥文件的路径 - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - initParams->cert_file = sg_cert_file; - initParams->key_file = sg_key_file; -#else - initParams->device_secret = QCLOUD_IOT_DEVICE_SECRET; -#endif - - initParams->auto_connect_enable = 1; - initParams->event_handle.h_fp = event_handler; - - return QCLOUD_ERR_SUCCESS; -} - -/** - * 设置shadow相关属性参数 - */ -static void _setup_shadow_data() -{ - //s_temperatureReportProp: device ---> shadow <---> app - sg_energy_consumption_prop.key = "energyConsumption"; - sg_energy_consumption_prop.data = &sg_energy_consumption; - sg_energy_consumption_prop.type = JFLOAT; - //s_temperatureDesireProp: app ---> shadow ---> device - sg_temperature_desire_prop.key = "temperatureDesire"; - sg_temperature_desire_prop.data = &sg_desire_temperature; - sg_temperature_desire_prop.type = JFLOAT; -} - -/** - * 注册shadow配置型属性 - */ -static int _register_config_shadow_property(void *client) -{ - return IOT_Shadow_Register_Property(client, &sg_temperature_desire_prop, on_temperature_actuate_callback); -} - -/** - * 订阅关注topic和注册相应回调处理 - */ -static int _register_subscribe_topics(void *client) -{ - static char topic_name[128] = {0}; - - int size = HAL_Snprintf(topic_name, sizeof(topic_name), "%s/%s/%s", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME, "control"); - if (size < 0 || size > sizeof(topic_name) - 1) - { - Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); - return QCLOUD_ERR_FAILURE; - } - - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.qos = QOS1; - sub_params.on_message_handler = on_message_callback; - return IOT_Shadow_Subscribe(client, topic_name, &sub_params); -} - -int main(int argc, char **argv) { - int rc; - - //init log level - IOT_Log_Set_Level(DEBUG); - - //init connection - ShadowInitParams init_params = DEFAULT_SHAWDOW_INIT_PARAMS; - rc = _setup_connect_init_params(&init_params); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - void *client = IOT_Shadow_Construct(&init_params); - if (client != NULL) { - Log_i("Cloud Device Construct Success"); - } else { - Log_e("Cloud Device Construct Failed"); - return QCLOUD_ERR_FAILURE; - } - - //init shadow data - _setup_shadow_data(); - - //register config shadow propertys here - rc = _register_config_shadow_property(client); - if (rc == QCLOUD_ERR_SUCCESS) { - Log_i("Cloud Device Register Delta Success"); - } else { - Log_e("Cloud Device Register Delta Failed: %d", rc); - return rc; - } - - //pull shadow document and update local shadow version - IOT_Shadow_Get(client, on_request_handler, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - while(sg_finish_shadow_get == false) - { - Log_i("Wait for Shadow Get Result"); - IOT_Shadow_Yield(client, 200); - sleep(1); - } - - //register subscribe topics here - rc = _register_subscribe_topics(client); - if (rc < 0) { - Log_e("Client Subscribe Topic Failed: %d", rc); - return rc; - } - - while (IOT_Shadow_IsConnected(client) || rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT || rc == QCLOUD_ERR_MQTT_RECONNECTED) { - - rc = IOT_Shadow_Yield(client, 200); - - if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { - sleep(1); - continue; - } - else if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("Exit loop caused of errCode: %d", rc); - } - - if (sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_SUCCESS && - sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_TIMEOUT && - sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_NACK) - { - Log_i("Wait for subscribe result,sg_subscribe_event_result = %d", sg_subscribe_event_result); - sleep(1); - continue; - } - - _simulate_room_temperature(&sg_report_temperature); - Log_i("airConditioner state: %s", sg_airconditioner_openned ? "open" : "close"); - Log_i("currentTemperature: %f, energyConsumption: %f", sg_report_temperature, sg_energy_consumption); - - if (sg_message_arrived_on_delta) - _do_report_temperature_desire(client); - - if (sg_message_arrived_on_delta == false) - _do_report_energy_consumption(client); - - sleep(3); - } - - rc = IOT_Shadow_Destroy(client); - - return rc; -} +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "lite-utils.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" + +static DeviceInfo sg_devInfo; + +#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 +#define ROOM_TEMPERATURE 32.0f +#define MAX_RECV_LEN (512 + 1) + +static float sg_desire_temperature = 20.0f; +static float sg_report_temperature = ROOM_TEMPERATURE; + +static float sg_energy_consumption = 0.0f; +static bool sg_airconditioner_openned = false; + +static DeviceProperty sg_energy_consumption_prop; +static DeviceProperty sg_temperature_desire_prop; + +static bool sg_message_arrived_on_delta = false; + +static MQTTEventType sg_subscribe_event_result = MQTT_EVENT_UNDEF; +static bool sg_finish_shadow_get = false; + +char sg_document_buffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER]; +size_t sg_document_buffersize = sizeof(sg_document_buffer) / sizeof(sg_document_buffer[0]); + +static int _register_config_shadow_property(void *client); +static int _register_subscribe_topics(void *client); + +// compare float value +bool _is_value_equal(float left, float right) +{ + if ((left < right + 0.01) && (left > right - 0.01)) + return true; + else + return false; +} + +// simulate room temperature change +static void _simulate_room_temperature(float *roomTemperature) +{ + float delta_change = 0; + + if (!sg_airconditioner_openned) { + if (!_is_value_equal(*roomTemperature, ROOM_TEMPERATURE)) { + delta_change = (*roomTemperature) > ROOM_TEMPERATURE ? -0.5 : 0.5; + } + } else { + sg_energy_consumption += 1; + if (!_is_value_equal(*roomTemperature, sg_desire_temperature)) { + delta_change = (*roomTemperature) > sg_desire_temperature ? -1.0 : 1.0; + } + } + + *roomTemperature += delta_change; +} + +// callback for request response arrives +static void on_request_handler(void *pClient, Method method, RequestAck status, const char *jsonDoc, void *userData) +{ + char *shadow_status = NULL; + char *shadow_method = NULL; + + if (status == ACK_TIMEOUT) { + shadow_status = "ACK_TIMEOUT"; + } else if (status == ACK_ACCEPTED) { + shadow_status = "ACK_ACCEPTED"; + } else if (status == ACK_REJECTED) { + shadow_status = "ACK_REJECTED"; + } + + if (method == GET) { + shadow_method = "GET"; + } else if (method == UPDATE) { + shadow_method = "UPDATE"; + } + + Log_i("Method=%s|Ack=%s", shadow_method, shadow_status); + Log_i("received jsonString=%s", jsonDoc); + + if (status == ACK_ACCEPTED && method == UPDATE) { + if (sg_message_arrived_on_delta) + sg_message_arrived_on_delta = false; + Log_i("Update Shadow Success"); + } else if (status == ACK_ACCEPTED && method == GET) { + Log_i("Get Shadow Document Success"); + sg_finish_shadow_get = true; + } else if (status == ACK_TIMEOUT && method == UPDATE) { + Log_e("Update Shadow Fail!"); + exit(1); + } +} + +// callback when MQTT msg arrives +static void on_message_callback(void *pClient, MQTTMessage *message, void *userData) +{ + if (message == NULL) + return; + + const char *topicName = message->ptopic; + uint16_t topicNameLen = message->topic_len; + + if (topicName == NULL || topicNameLen == 0) { + return; + } + + Log_i("Receive Message With topicName:%.*s, payload:%.*s", (int)topicNameLen, topicName, (int)message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); + + static char cloud_rcv_buf[MAX_RECV_LEN + 1]; + size_t len = (message->payload_len > MAX_RECV_LEN) ? MAX_RECV_LEN : (message->payload_len); + + if (message->payload_len > MAX_RECV_LEN) { + Log_e("paload len exceed buffer size"); + } + memcpy(cloud_rcv_buf, message->payload, len); + cloud_rcv_buf[len] = '\0'; // jsmn_parse relies on a string + + char *value = LITE_json_value_of("action", cloud_rcv_buf); + if (value != NULL) { + if (strcmp(value, "come_home") == 0) { + sg_airconditioner_openned = true; + } else if (strcmp(value, "leave_home") == 0) { + sg_airconditioner_openned = false; + } + } + + HAL_Free(value); +} + +// callback for delta msg +static void on_temperature_actuate_callback(void *pClient, const char *jsonResponse, uint32_t responseLen, + DeviceProperty *context) +{ + Log_i("actuate callback jsonString=%s|dataLen=%u", STRING_PTR_PRINT_SANITY_CHECK(jsonResponse), responseLen); + + if (context != NULL) { + Log_i("modify desire temperature to: %f", *(float *)context->data); + sg_message_arrived_on_delta = true; + } +} + +// MQTT event callback +static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + uintptr_t packet_id = (uintptr_t)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_SUBCRIBE_SUCCESS: + sg_subscribe_event_result = msg->event_type; + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + sg_subscribe_event_result = msg->event_type; + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + sg_subscribe_event_result = msg->event_type; + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} + +// report energy consumption +static int _do_report_energy_consumption(void *client) +{ + int rc = IOT_Shadow_JSON_ConstructReport(client, sg_document_buffer, sg_document_buffersize, 1, + &sg_energy_consumption_prop); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow construct report failed: %d", rc); + return rc; + } + + Log_i("Update Shadow: %s", sg_document_buffer); + rc = IOT_Shadow_Update(client, sg_document_buffer, sg_document_buffersize, on_request_handler, NULL, + QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_i("Update Shadow Failed: %d", rc); + return rc; + } + + return rc; +} + +static int _do_report_temperature_desire(void *client) +{ + /* + * report desire as null if recv delta or desire msg, otherwise server will keep desire record + */ + + int rc; + rc = IOT_Shadow_JSON_ConstructReportAndDesireAllNull(client, sg_document_buffer, sg_document_buffersize, 1, + &sg_temperature_desire_prop); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow construct report failed: %d", rc); + return rc; + } + + Log_i("update desire temperature: %s", sg_document_buffer); + rc = IOT_Shadow_Update(client, sg_document_buffer, sg_document_buffersize, on_request_handler, NULL, + QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_i("Update Shadow Failed: %d", rc); + return rc; + } else { + Log_i("Update Shadow Success"); + } + + return rc; +} + +// Setup MQTT construct parameters +static int _setup_connect_init_params(ShadowInitParams *initParams) +{ + int ret; + + ret = HAL_GetDevInfo((void *)&sg_devInfo); + if (QCLOUD_RET_SUCCESS != ret) { + return ret; + } + + initParams->device_name = sg_devInfo.device_name; + initParams->product_id = sg_devInfo.product_id; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_key_file_name)); +#endif + +#else + initParams->device_secret = sg_devInfo.device_secret; +#endif + + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = event_handler; + + return QCLOUD_RET_SUCCESS; +} + +// setup shadow properties +static void _setup_shadow_data() +{ + // s_temperatureReportProp: device ---> shadow <---> app + sg_energy_consumption_prop.key = "energyConsumption"; + sg_energy_consumption_prop.data = &sg_energy_consumption; + sg_energy_consumption_prop.type = JFLOAT; + // s_temperatureDesireProp: app ---> shadow ---> device + sg_temperature_desire_prop.key = "temperatureDesire"; + sg_temperature_desire_prop.data = &sg_desire_temperature; + sg_temperature_desire_prop.type = JFLOAT; +} + +// register properties +static int _register_config_shadow_property(void *client) +{ + return IOT_Shadow_Register_Property(client, &sg_temperature_desire_prop, on_temperature_actuate_callback); +} + +// subscrib MQTT topic +static int _register_subscribe_topics(void *client) +{ + static char topic_name[128] = {0}; + + int size = + HAL_Snprintf(topic_name, sizeof(topic_name), "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.product_id), + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.device_name), "control"); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.qos = QOS1; + sub_params.on_message_handler = on_message_callback; + return IOT_Shadow_Subscribe(client, topic_name, &sub_params); +} + +int main(int argc, char **argv) +{ + int c; + while ((c = utils_getopt(argc, argv, "c:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + default: + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n", + argv[0]); + + return -1; + } + + int rc; + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + // init connection + ShadowInitParams init_params = DEFAULT_SHAWDOW_INIT_PARAMS; + rc = _setup_connect_init_params(&init_params); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + return rc; + } + + void *client = IOT_Shadow_Construct(&init_params); + if (client != NULL) { + Log_i("Cloud Device Construct Success"); + } else { + Log_e("Cloud Device Construct Failed"); + return QCLOUD_ERR_FAILURE; + } + + // init shadow data + _setup_shadow_data(); + + // register config shadow propertys here + rc = _register_config_shadow_property(client); + if (rc == QCLOUD_RET_SUCCESS) { + Log_i("Cloud Device Register Delta Success"); + } else { + Log_e("Cloud Device Register Delta Failed: %d", rc); + return rc; + } + + // pull shadow document and update local shadow version + IOT_Shadow_Get(client, on_request_handler, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + while (sg_finish_shadow_get == false) { + Log_i("Wait for Shadow Get Result"); + IOT_Shadow_Yield(client, 200); + HAL_SleepMs(1000); + } + + // register subscribe topics here + rc = _register_subscribe_topics(client); + if (rc < 0) { + Log_e("Client Subscribe Topic Failed: %d", rc); + return rc; + } + + while (IOT_Shadow_IsConnected(client) || rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT || + rc == QCLOUD_RET_MQTT_RECONNECTED) { + rc = IOT_Shadow_Yield(client, 200); + + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS) { + Log_e("Exit loop caused of errCode: %d", rc); + } + + if (sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_SUCCESS && + sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_TIMEOUT && + sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_NACK) { + Log_i("Wait for subscribe result, sg_subscribe_event_result = %d", sg_subscribe_event_result); + HAL_SleepMs(1000); + continue; + } + + _simulate_room_temperature(&sg_report_temperature); + Log_i("airConditioner state: %s", sg_airconditioner_openned ? "open" : "close"); + Log_i("currentTemperature: %f, energyConsumption: %f", sg_report_temperature, sg_energy_consumption); + + if (sg_message_arrived_on_delta) + _do_report_temperature_desire(client); + + if (sg_message_arrived_on_delta == false) + _do_report_energy_consumption(client); + + HAL_SleepMs(3000); + } + + rc = IOT_Shadow_Destroy(client); + + return rc; +} diff --git a/samples/scenarized/door_coap_sample.c b/samples/scenarized/door_coap_sample.c old mode 100644 new mode 100755 index c4f1c2c2..93579c3c --- a/samples/scenarized/door_coap_sample.c +++ b/samples/scenarized/door_coap_sample.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,161 +13,182 @@ * */ +#include #include #include -#include #include -#include -#include #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" +#include "utils_getopt.h" #define MAX_SIZE_OF_TOPIC_CONTENT 100 -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" +#define PROGRAM_NAME "door_coap_sample" + +void printUsage() +{ + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n" + " [-t ]\n" + " [-a ]\n", + PROGRAM_NAME); +} + +void event_handler(void *pcontext, CoAPEventMessage *message) +{ + switch (message->event_type) { + case COAP_EVENT_RECEIVE_ACK: + Log_i("message received ACK, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_RECEIVE_RESPCONTENT: /* not supported currently */ + break; + case COAP_EVENT_UNAUTHORIZED: + Log_i("coap client auth token expired or invalid, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_FORBIDDEN: + Log_i("coap URI is invalid for this device, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_INTERNAL_SERVER_ERROR: + Log_i("coap server internal error, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_ACK_TIMEOUT: + Log_i("message receive ACK timeout, msgid: %d", (unsigned)(uintptr_t)message->message); + break; + case COAP_EVENT_SEPRESP_TIMEOUT: /* not supported currently */ + break; + default: + Log_e("unrecogonized event type: %d", message->event_type); + break; + } +} + +static int _setup_connect_init_params(CoAPInitParams *initParams, DeviceInfo *device_info) +{ + initParams->product_id = device_info->product_id; + initParams->device_name = device_info->device_name; #ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); #else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(device_info->dev_key_file_name)); #endif -void printUsage() -{ - printf("1. ./door_coap come_home [targetDeviceName]\n"); - printf("2. ./door_coap leave_home [targetDeviceName]\n"); -} +#else + initParams->device_secret = device_info->device_secret; +#endif + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->event_handle.h_fp = event_handler; + initParams->max_retry_count = 3; -void event_handler(void *pcontext, CoAPEventMessage *message) -{ - switch (message->event_type) { - case COAP_EVENT_RECEIVE_ACK: - Log_i("message received ACK, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_RECEIVE_RESPCONTENT: /* 暂不支持消息交互,仅支持数据上报 */ - break; - case COAP_EVENT_UNAUTHORIZED: - Log_i("coap client auth token expired or invalid, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_FORBIDDEN: - Log_i("coap URI is invalid for this device, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_INTERNAL_SERVER_ERROR: - Log_i("coap server internal error, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_ACK_TIMEOUT: - Log_i("message receive ACK timeout, msgid: %d", (unsigned)(uintptr_t)message->message); - break; - case COAP_EVENT_SEPRESP_TIMEOUT: /* 暂不支持消息交互,仅支持数据上报 */ - break; - default: - Log_e("unrecogonized event type: %d", message->event_type); - break; - } + return QCLOUD_RET_SUCCESS; } int main(int argc, char **argv) { - if(argc != 3) - { - printUsage(); - return -1; + int c; + char action[16] = {0}; + char target_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = {0}; + + while ((c = utils_getopt(argc, argv, "c:t:a:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + case 't': + strncpy(target_device_name, utils_optarg, MAX_SIZE_OF_DEVICE_NAME); + break; + + case 'a': + strncpy(action, utils_optarg, sizeof(action) - 1); + break; + + default: + printUsage(); + + return -1; + } + + int rc = QCLOUD_RET_SUCCESS; + IOT_Log_Set_Level(eLOG_DEBUG); + + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + return rc; } - IOT_Log_Set_Level(DEBUG); + CoAPInitParams init_params = DEFAULT_COAPINIT_PARAMS; + rc = _setup_connect_init_params(&init_params, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + return rc; + } - CoAPInitParams init_params = DEFAULT_COAPINIT_PARAMS; - init_params.product_id = QCLOUD_IOT_MY_PRODUCT_ID; - init_params.device_name = QCLOUD_IOT_MY_DEVICE_NAME; + void *coap_client = IOT_COAP_Construct(&init_params); + if (coap_client == NULL) { + Log_e("COAP Client construct failed."); + return QCLOUD_ERR_FAILURE; + } else { + Log_e("%p", coap_client); + } -#ifdef AUTH_MODE_CERT - // 获取CA证书、客户端证书以及私钥文件的路径 - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - init_params.cert_file = sg_cert_file; - init_params.key_file = sg_key_file; -#else - init_params.device_secret = QCLOUD_IOT_DEVICE_SECRET; -#endif + if (strcmp(action, "come_home") == 0 || strcmp(action, "leave_home") == 0) { + char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; + SendMsgParams send_params = DEFAULT_SENDMSG_PARAMS; - init_params.command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - init_params.event_handle.h_fp = event_handler; - init_params.max_retry_count = 3; - - void *coap_client = IOT_COAP_Construct(&init_params); - if (coap_client == NULL) { - Log_e("COAP Client construct failed."); - return QCLOUD_ERR_FAILURE; - } - else { - Log_e("%p", coap_client); - } - - int rc = QCLOUD_ERR_SUCCESS; - char* action = argv[1]; - char* target_device_name = argv[2]; - - if(strcmp(action, "come_home") == 0 || strcmp(action, "leave_home") == 0) - { - char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; - SendMsgParams send_params = DEFAULT_SENDMSG_PARAMS; - - int size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"%s\", \"targetDevice\": \"%s\"}", action, target_device_name); - if (size < 0 || size > sizeof(topic_content) - 1) - { + int size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"%s\", \"targetDevice\": \"%s\"}", + action, target_device_name); + if (size < 0 || size > sizeof(topic_content) - 1) { Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); return -3; } - send_params.pay_load = topic_content; - send_params.pay_load_len = strlen(topic_content); + send_params.pay_load = topic_content; + send_params.pay_load_len = strlen(topic_content); char topicName[128] = ""; - sprintf(topicName, "%s/%s/event", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME); + sprintf(topicName, "%s/%s/event", device_info.product_id, device_info.device_name); Log_i("topic name is %s", topicName); rc = IOT_COAP_SendMessage(coap_client, topicName, &send_params); - if (rc < 0) { - Log_e("client publish topic failed :%d.", rc); - } - else { - Log_d("client topic has been sent, msg_id: %d", rc); - } - - rc = IOT_COAP_Yield(coap_client, 200); - - if (rc != QCLOUD_ERR_SUCCESS){ - Log_e("exit with error: %d", rc); - } - } - else - { + if (rc < 0) { + Log_e("client publish topic failed :%d.", rc); + } else { + Log_d("client topic has been sent, msg_id: %d", rc); + } + + rc = IOT_COAP_Yield(coap_client, 200); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("exit with error: %d", rc); + } + } else { printUsage(); return -2; } IOT_COAP_Destroy(&coap_client); - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } diff --git a/samples/scenarized/door_mqtt_sample.c b/samples/scenarized/door_mqtt_sample.c old mode 100644 new mode 100755 index 70e559d5..3c363b5b --- a/samples/scenarized/door_mqtt_sample.c +++ b/samples/scenarized/door_mqtt_sample.c @@ -1,238 +1,238 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" - -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" - -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" - - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 - -#else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" -#endif - -#define MAX_SIZE_OF_TOPIC_CONTENT 100 - -static bool sg_has_rev_ack = false; - - -void printUsage() -{ - printf("1. ./door come_home [targetDeviceName]\n"); - printf("2. ./door leave_home [targetDeviceName]\n"); -} - -bool log_handler(const char* message) { - //实现日志回调的写方法 - //实现内容后请返回true - return false; -} - -static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - sg_has_rev_ack = true; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } -} - -/** - * 设置MQTT connet初始化参数 - * - * @param initParams MQTT connet初始化参数 - * - * @return 0: 参数初始化成功 非0: 失败 - */ -static int _setup_connect_init_params(MQTTInitParams* initParams) -{ - initParams->device_name = QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = QCLOUD_IOT_MY_PRODUCT_ID; - -#ifdef AUTH_MODE_CERT - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - initParams->cert_file = sg_cert_file; - initParams->key_file = sg_key_file; -#else - initParams->device_secret = QCLOUD_IOT_DEVICE_SECRET; -#endif - - initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; - initParams->auto_connect_enable = 1; - initParams->event_handle.h_fp = event_handler; - - return QCLOUD_ERR_SUCCESS; -} - -/** - * 发送topic消息 - * - * @param action 行为 - */ -static int _publish_msg(void *client, char* action, char* targetDeviceName) -{ - if(NULL == action || NULL == targetDeviceName) - return -1; - - char topic_name[128] = {0}; - sprintf(topic_name,"%s/%s/%s", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME, "event"); - - PublishParams pub_params = DEFAULT_PUB_PARAMS; - pub_params.qos = QOS1; - - char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; - if(strcmp(action, "come_home") == 0 || strcmp(action, "leave_home") == 0) - { - int size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"%s\", \"targetDevice\": \"%s\"}", action, targetDeviceName); - if (size < 0 || size > sizeof(topic_content) - 1) - { - Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); - return -3; - } - - pub_params.payload = topic_content; - pub_params.payload_len = strlen(topic_content); - } - else - { - printUsage(); - return -2; - } - - int rc = IOT_MQTT_Publish(client, topic_name, &pub_params); - if (rc < 0) { - Log_e("Client publish Topic:%s Failed :%d with content: %s", topic_name, rc, (char*)pub_params.payload); - return rc; - } - return 0; -} - -int main(int argc, char **argv) -{ - if(argc != 3) { - printUsage(); - return -1; - } - - //init log level - IOT_Log_Set_Level(DEBUG); - IOT_Log_Set_MessageHandler(log_handler); - - int rc; - - //init connection - MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; - rc = _setup_connect_init_params(&init_params); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - void *client = IOT_MQTT_Construct(&init_params); - if (client != NULL) { - Log_i("Cloud Device Construct Success"); - } else { - Log_e("Cloud Device Construct Failed"); - return QCLOUD_ERR_FAILURE; - } - - //publish msg - char* action = argv[1]; - char* target_device_name = argv[2]; - rc = _publish_msg(client, action, target_device_name); - if (rc < 0) { - Log_e("Demo publish fail rc=%d", rc); - } - - while (IOT_MQTT_IsConnected(client) || - rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT || - rc == QCLOUD_ERR_MQTT_RECONNECTED ) - { - if (false != sg_has_rev_ack) break; - Log_i("Wait for publish ack"); - rc = IOT_MQTT_Yield(client, 200); - sleep(1); - } - - rc = IOT_MQTT_Destroy(&client); - - return rc; -} +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_getopt.h" + +#define MAX_SIZE_OF_TOPIC_CONTENT 100 + +static DeviceInfo sg_devInfo; + +static bool sg_has_rev_ack = false; + +#define PROGRAM_NAME "door_mqtt_sample" +void printUsage() +{ + HAL_Printf( + "usage: %s [options]\n" + " [-c ] \n" + " [-t ]\n" + " [-a ]\n", + PROGRAM_NAME); +} + +static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) +{ + uintptr_t packet_id = (uintptr_t)msg->msg; + sg_has_rev_ack = true; + + switch (msg->event_type) { + case MQTT_EVENT_UNDEF: + Log_i("undefined event occur."); + break; + + case MQTT_EVENT_DISCONNECT: + Log_i("MQTT disconnect."); + break; + + case MQTT_EVENT_RECONNECT: + Log_i("MQTT reconnect."); + break; + + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_SUCCESS: + Log_i("publish success, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_TIMEOUT: + Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); + break; + + case MQTT_EVENT_PUBLISH_NACK: + Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); + break; + default: + Log_i("Should NOT arrive here."); + break; + } +} + +// Setup MQTT construct parameters +static int _setup_connect_init_params(MQTTInitParams *initParams) +{ + int ret; + + ret = HAL_GetDevInfo((void *)&sg_devInfo); + if (QCLOUD_RET_SUCCESS != ret) { + return ret; + } + + initParams->device_name = sg_devInfo.device_name; + initParams->product_id = sg_devInfo.product_id; + +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_key_file_name)); +#else + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(sg_devInfo.dev_key_file_name)); +#endif + +#else + initParams->device_secret = sg_devInfo.device_secret; +#endif + + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + initParams->auto_connect_enable = 1; + initParams->event_handle.h_fp = event_handler; + + return QCLOUD_RET_SUCCESS; +} + +// publish MQTT msg +static int _publish_msg(void *client, char *action, char *targetDeviceName) +{ + if (NULL == action || NULL == targetDeviceName) + return -1; + + char topic_name[128] = {0}; + sprintf(topic_name, "%s/%s/%s", sg_devInfo.product_id, sg_devInfo.device_name, "event"); + + PublishParams pub_params = DEFAULT_PUB_PARAMS; + pub_params.qos = QOS1; + + char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0}; + if (strcmp(action, "come_home") == 0 || strcmp(action, "leave_home") == 0) { + int size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"%s\", \"targetDevice\": \"%s\"}", + action, STRING_PTR_PRINT_SANITY_CHECK(targetDeviceName)); + if (size < 0 || size > sizeof(topic_content) - 1) { + Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content)); + return -3; + } + + pub_params.payload = topic_content; + pub_params.payload_len = strlen(topic_content); + } else { + printUsage(); + return -2; + } + + int rc = IOT_MQTT_Publish(client, topic_name, &pub_params); + if (rc < 0) { + Log_e("Client publish Topic:%s Failed :%d with content: %s", topic_name, rc, + STRING_PTR_PRINT_SANITY_CHECK((char *)pub_params.payload)); + return rc; + } + return 0; +} + +int main(int argc, char **argv) +{ + int c; + char action[16] = {0}; + char target_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = {0}; + + while ((c = utils_getopt(argc, argv, "c:t:a:")) != EOF) switch (c) { + case 'c': + if (HAL_SetDevInfoFile(utils_optarg)) + return -1; + break; + + case 't': + strncpy(target_device_name, utils_optarg, MAX_SIZE_OF_DEVICE_NAME); + break; + + case 'a': + strncpy(action, utils_optarg, sizeof(action) - 1); + break; + + default: + printUsage(); + + return -1; + } + + // init log level + IOT_Log_Set_Level(eLOG_DEBUG); + + int rc; + + // init connection + MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS; + rc = _setup_connect_init_params(&init_params); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + return rc; + } + + void *client = IOT_MQTT_Construct(&init_params); + if (client != NULL) { + Log_i("Cloud Device Construct Success"); + } else { + Log_e("Cloud Device Construct Failed"); + return QCLOUD_ERR_FAILURE; + } + + // publish msg + rc = _publish_msg(client, action, target_device_name); + if (rc < 0) { + Log_e("Demo publish fail rc=%d", rc); + } + + while (IOT_MQTT_IsConnected(client) || rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT || + rc == QCLOUD_RET_MQTT_RECONNECTED) { + if (false != sg_has_rev_ack) + break; + Log_i("Wait for publish ack"); + rc = IOT_MQTT_Yield(client, 200); + HAL_SleepMs(1000); + } + + rc = IOT_MQTT_Destroy(&client); + + return rc; +} diff --git a/samples/shadow/shadow_sample.c b/samples/shadow/shadow_sample.c old mode 100644 new mode 100755 index 73d266c3..563b6d94 --- a/samples/shadow/shadow_sample.c +++ b/samples/shadow/shadow_sample.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,155 +13,174 @@ * */ +#include #include #include -#include #include -#include -#include -#include + #include "qcloud_iot_export.h" -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "YOUR_PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "YOUR_DEVICE_NAME" +void OnDeltaCallback(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength, DeviceProperty *pProperty) +{ + Log_i(">>>>> Delta str: %s", STRING_PTR_PRINT_SANITY_CHECK(pJsonValueBuffer)); + pProperty->delta_arrived = true; +} -#ifdef AUTH_MODE_CERT - /* 客户端证书文件名 非对称加密使用*/ - #define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" - /* 客户端私钥文件名 非对称加密使用*/ - #define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" +void OnShadowUpdateCallback(void *pClient, Method method, RequestAck requestAck, const char *pJsonDocument, + void *pUserdata) +{ + Log_i("recv shadow update response, response ack: %d", requestAck); +} + +static int _report_desire_null(void *handle, char *jsonBuffer, size_t sizeOfBuffer) +{ + /* device data updated, desire should be set null */ + int rc = IOT_Shadow_JSON_ConstructDesireAllNull(handle, jsonBuffer, sizeOfBuffer); + if (rc == QCLOUD_RET_SUCCESS) { + rc = IOT_Shadow_Update(handle, jsonBuffer, sizeOfBuffer, OnShadowUpdateCallback, "desire_null", + QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + if (rc == QCLOUD_RET_SUCCESS) { + Log_d("shadow update(desired) success"); + } else { + Log_e("shadow update(desired) failed, err: %d", rc); + } + + } else { + Log_e("construct desire failed, err: %d", rc); + } + + return rc; +} - static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 - static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 +static int _setup_connect_init_params(ShadowInitParams *initParams, DeviceInfo *dev_info) +{ + initParams->device_name = dev_info->device_name; + initParams->product_id = dev_info->product_id; +#ifdef AUTH_MODE_CERT + char certs_dir[16] = "certs"; + char current_path[128]; + char *cwd = getcwd(current_path, sizeof(current_path)); + + if (cwd == NULL) { + Log_e("getcwd return NULL"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef WIN32 + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_key_file_name)); #else - #define QCLOUD_IOT_DEVICE_SECRET "YOUR_IOT_PSK" + HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_cert_file_name)); + HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->dev_key_file_name)); #endif -static char sg_shadow_update_buffer[200]; -size_t sg_shadow_update_buffersize = sizeof(sg_shadow_update_buffer) / sizeof(sg_shadow_update_buffer[0]); - -static DeviceProperty sg_shadow_property; -static int sg_current_update_count = 0; -static bool sg_delta_arrived = false; - -void OnDeltaCallback(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength, DeviceProperty *pProperty) { - int rc = IOT_Shadow_JSON_ConstructDesireAllNull(pClient, sg_shadow_update_buffer, sg_shadow_update_buffersize); +#else + initParams->device_secret = dev_info->device_secret; +#endif - if (rc == QCLOUD_ERR_SUCCESS) { - sg_delta_arrived = true; - } - else { - Log_e("construct desire failed, err: %d", rc); - } -} + initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; + initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; + initParams->auto_connect_enable = 1; -void OnShadowUpdateCallback(void *pClient, Method method, RequestAck requestAck, const char *pJsonDocument, void *pUserdata) { - Log_i("recv shadow update response, response ack: %d", requestAck); + return QCLOUD_RET_SUCCESS; } int demo_device_shadow() { - int rc = QCLOUD_ERR_FAILURE; - - void* shadow_client = NULL; - - ShadowInitParams init_params = DEFAULT_SHAWDOW_INIT_PARAMS; - init_params.product_id = QCLOUD_IOT_MY_PRODUCT_ID; - init_params.device_name = QCLOUD_IOT_MY_DEVICE_NAME; - -#ifdef AUTH_MODE_CERT - // 获取CA证书、客户端证书以及私钥文件的路径 - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - - init_params.cert_file = sg_cert_file; - init_params.key_file = sg_key_file; -#else - init_params.device_secret = QCLOUD_IOT_DEVICE_SECRET; -#endif - - init_params.command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - init_params.auto_connect_enable = 1; - - shadow_client = IOT_Shadow_Construct(&init_params); - if (shadow_client == NULL) { - Log_e("shadow client constructed failed."); - return QCLOUD_ERR_FAILURE; - } - - //注册delta属性 - sg_shadow_property.key = "updateCount"; - sg_shadow_property.data = &sg_current_update_count; - sg_shadow_property.type = JINT32; - rc = IOT_Shadow_Register_Property(shadow_client, &sg_shadow_property, OnDeltaCallback); - if (rc != QCLOUD_ERR_SUCCESS) { - rc = IOT_Shadow_Destroy(shadow_client); - Log_e("register device shadow property failed, err: %d", rc); - return rc; - } - - //进行Shdaow Update操作的之前,最后进行一次同步操作,否则可能本机上shadow version和云上不一致导致Shadow Update操作失败 - rc = IOT_Shadow_Get_Sync(shadow_client, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("get device shadow failed, err: %d", rc); - return rc; - } - - while (IOT_Shadow_IsConnected(shadow_client) || QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT == rc || - QCLOUD_ERR_MQTT_RECONNECTED == rc || QCLOUD_ERR_SUCCESS == rc) { - - rc = IOT_Shadow_Yield(shadow_client, 200); - - if (QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT == rc) { - sleep(1); - continue; - } - else if (rc != QCLOUD_ERR_SUCCESS && rc != QCLOUD_ERR_MQTT_RECONNECTED) { - Log_e("exit with error: %d", rc); - return rc; - } - - if (sg_delta_arrived) { - rc = IOT_Shadow_Update_Sync(shadow_client, sg_shadow_update_buffer, sg_shadow_update_buffersize, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - sg_delta_arrived = false; - if (rc == QCLOUD_ERR_SUCCESS) - Log_i("shadow update success"); - } - - IOT_Shadow_JSON_ConstructReport(shadow_client, sg_shadow_update_buffer, sg_shadow_update_buffersize, 1, &sg_shadow_property); - rc = IOT_Shadow_Update(shadow_client, sg_shadow_update_buffer, sg_shadow_update_buffersize, OnShadowUpdateCallback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - sg_current_update_count++; - - // sleep for some time in seconds - sleep(1); - } - - Log_e("loop exit with error: %d", rc); - - rc = IOT_Shadow_Destroy(shadow_client); - - return rc; + int rc = QCLOUD_ERR_FAILURE; + + void *shadow_client = NULL; + + char shadow_json_buffer[200]; + size_t shadow_json_buf_size = sizeof(shadow_json_buffer) / sizeof(shadow_json_buffer[0]); + + DeviceProperty shadow_property; + int current_update_count = 0; + + DeviceInfo device_info = {0}; + rc = HAL_GetDevInfo((void *)&device_info); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get device info failed: %d", rc); + return rc; + } + + // init connection + ShadowInitParams init_params = DEFAULT_SHAWDOW_INIT_PARAMS; + rc = _setup_connect_init_params(&init_params, &device_info); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("init params err,rc=%d", rc); + return rc; + } + + shadow_client = IOT_Shadow_Construct(&init_params); + if (shadow_client == NULL) { + Log_e("shadow client constructed failed."); + return QCLOUD_ERR_FAILURE; + } + + // register delta property + shadow_property.key = "updateCount"; + shadow_property.data = ¤t_update_count; + shadow_property.type = JINT32; + rc = IOT_Shadow_Register_Property(shadow_client, &shadow_property, OnDeltaCallback); + if (rc != QCLOUD_RET_SUCCESS) { + rc = IOT_Shadow_Destroy(shadow_client); + Log_e("register device shadow property failed, err: %d", rc); + return rc; + } + + // do get and sync operation before update + rc = IOT_Shadow_Get_Sync(shadow_client, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("get device shadow failed, err: %d", rc); + return rc; + } + + while (IOT_Shadow_IsConnected(shadow_client) || QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT == rc || + QCLOUD_RET_MQTT_RECONNECTED == rc || QCLOUD_RET_SUCCESS == rc) { + rc = IOT_Shadow_Yield(shadow_client, 500); + + if (QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT == rc) { + HAL_SleepMs(1000); + continue; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("exit with error: %d", rc); + break; + } + + if (shadow_property.delta_arrived) { + _report_desire_null(shadow_client, shadow_json_buffer, shadow_json_buf_size); + + shadow_property.delta_arrived = false; + } + + IOT_Shadow_JSON_ConstructReport(shadow_client, shadow_json_buffer, shadow_json_buf_size, 1, &shadow_property); + rc = IOT_Shadow_Update(shadow_client, shadow_json_buffer, shadow_json_buf_size, OnShadowUpdateCallback, NULL, + QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); + current_update_count++; + + // sleep for some time + HAL_SleepMs(3000); + } + + Log_e("loop exit with error: %d", rc); + + rc = IOT_Shadow_Destroy(shadow_client); + shadow_client = NULL; + + return rc; } int main() { - IOT_Log_Set_Level(DEBUG); - - // to avoid process crash when writing to a broken socket - signal(SIGPIPE, SIG_IGN); + IOT_Log_Set_Level(eLOG_DEBUG); - demo_device_shadow(); + demo_device_shadow(); - return 0; + return 0; } diff --git a/sdk-tests/multi_thread_test/multi_thread_test.c b/sdk-tests/multi_thread_test/multi_thread_test.c deleted file mode 100644 index bea8e6df..00000000 --- a/sdk-tests/multi_thread_test/multi_thread_test.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" - -/* 产品名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_PRODUCT_ID "PRODUCT_ID" -/* 设备名称, 与云端同步设备状态时需要 */ -#define QCLOUD_IOT_MY_DEVICE_NAME "ThreadTestDev0" - - -#ifndef AUTH_WITH_NOTLS - -/* 客户端证书文件名 非对称加密使用*/ -#define QCLOUD_IOT_CERT_FILENAME "YOUR_DEVICE_NAME_cert.crt" -/* 客户端私钥文件名 非对称加密使用*/ -#define QCLOUD_IOT_KEY_FILENAME "YOUR_DEVICE_NAME_private.key" - -static char sg_cert_file[PATH_MAX + 1]; //客户端证书全路径 -static char sg_key_file[PATH_MAX + 1]; //客户端密钥全路径 - -#endif - -#define MAX_PUB_THREAD_COUNT 3 -#define PUBLISH_COUNT 10 -#define THREAD_SLEEP_INTERVAL_USEC 500000 -#define CONNECT_MAX_ATTEMPT_COUNT 3 -#define RX_RECEIVE_PERCENTAGE 99.0f -#define INTEGRATION_TEST_TOPIC ""QCLOUD_IOT_MY_PRODUCT_ID"/"QCLOUD_IOT_MY_DEVICE_NAME"/Thread" // 需要创建设备的时候配置权限 - -static void *sg_pClient; - -static bool sg_terminate_yield_thread; -static bool sg_terminate_subUnsub_thread; - -static unsigned int sg_countArray[MAX_PUB_THREAD_COUNT][PUBLISH_COUNT]; // 订阅回调函数中,每次成功收订阅topic返回的数据的时候,记录每个订阅的成功次数 -static unsigned int sg_rxMsgBufferTooBigCounter; // 记录收到消息长度过长的次数 -static unsigned int sg_rxUnexpectedNumberCounter; // 记录收到错误消息的次数 -static unsigned int sg_rePublishCount; // 记录重新发布的次数 -static unsigned int sg_wrongYieldCount; // 记录yield失败的次数 -static unsigned int sg_threadStatus[MAX_PUB_THREAD_COUNT]; // 记录所有线程的状态 - -typedef struct ThreadData { - int threadId; - void *client; -} ThreadData; - - - -void event_handler(void *pcontext, void *pclient, MQTTEventMsg *msg) { - MQTTMessage* mqtt_messge = (MQTTMessage*)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_PUBLISH_RECVEIVED: - Log_i("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - mqtt_messge->topic_len, - mqtt_messge->ptopic, - mqtt_messge->payload_len, - mqtt_messge->payload); - break; - default: - break; - } -} - -static int _setup_connect_init_params(MQTTInitParams* initParams) -{ - initParams->device_name = QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = QCLOUD_IOT_MY_PRODUCT_ID; - -#ifndef AUTH_WITH_NOTLS - char certs_dir[PATH_MAX + 1] = "certs"; - char current_path[PATH_MAX + 1]; - char *cwd = getcwd(current_path, sizeof(current_path)); - if (cwd == NULL) - { - Log_e("getcwd return NULL"); - return QCLOUD_ERR_FAILURE; - } - sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, QCLOUD_IOT_KEY_FILENAME); - -#ifdef AUTH_MODE_CERT - initParams->cert_file = sg_cert_file; - initParams->key_file = sg_key_file; -#else -#endif -#endif - - initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; - - initParams->auto_connect_enable = 1; - initParams->event_handle.h_fp = event_handler; - - return QCLOUD_ERR_SUCCESS; -} - -/** - * 订阅topic回调函数 - */ -static void _iot_mqtt_tests_message_aggregator(void *pClient, MQTTMessage *message, void *userData) { - // int rc; - char *temp = NULL; - - if (message == NULL) { - return; - } - - if(30 >= message->payload_len) { - /* 解析 payload */ - char tempBuf[30]; - unsigned int tempRow = 0, tempCol = 0; - - HAL_Snprintf(tempBuf, message->payload_len, "%s", (char *)message->payload); - printf("\nMessage received : %s\n", tempBuf); - temp = strtok(tempBuf, " ,:"); - if(NULL == temp) { - return; - } - temp = strtok(NULL, " ,:"); - if(NULL == temp) { - return; - } - tempRow = atoi(temp); - temp = strtok(NULL, " ,:"); - if(NULL == temp) { - return; - } - temp = strtok(NULL, " ,:"); - if(NULL == temp) { - return; - } - tempCol = atoi(temp); - - if(((tempRow - 1) < MAX_PUB_THREAD_COUNT) && (tempCol < PUBLISH_COUNT)) { - sg_countArray[tempRow - 1][tempCol]++; - } else { - Log_e(" Unexpected Thread : %d, Message : %d ", tempRow, tempCol); - sg_rxUnexpectedNumberCounter++; - } - } else { - sg_rxMsgBufferTooBigCounter++; - } -} - -/** - * yield 测试线程函数 - */ -static void *_iot_mqtt_tests_yield_thread_runner(void *ptr) { - int rc = QCLOUD_ERR_SUCCESS; - void *pClient = ptr; - while(QCLOUD_ERR_SUCCESS == rc && false == sg_terminate_yield_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - //DEBUG("\n Yielding \n"); - rc = IOT_MQTT_Yield(pClient, 200); - } while(rc != QCLOUD_ERR_SUCCESS && rc != QCLOUD_ERR_MQTT_RECONNECTED); - - if(QCLOUD_ERR_SUCCESS != rc) { - Log_e("\nYield Returned : %d ", rc); - } - } - return NULL; -} - -/** - * subscribe/unsubscribe 测试线程函数 - * 函数中会在一个单独的线程中先订阅相关主题,然后再取消订阅 - */ -static void *_iot_mqtt_tests_sub_unsub_thread_runner(void *ptr) { - int rc = QCLOUD_ERR_SUCCESS; - void *pClient = ptr; - char testTopic[128]; - HAL_Snprintf(testTopic, 128, "%s_temp", INTEGRATION_TEST_TOPIC); - - while(QCLOUD_ERR_SUCCESS == rc && false == sg_terminate_subUnsub_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.qos = QOS1; - sub_params.on_message_handler = _iot_mqtt_tests_message_aggregator; - rc = IOT_MQTT_Subscribe(pClient, testTopic, &sub_params); - - } while(QCLOUD_ERR_MQTT_NO_CONN == rc || QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); - - if(rc < 0) { - Log_e("Subscribe Returned : %d ", rc); - } - - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = IOT_MQTT_Unsubscribe(pClient, testTopic); - } while(QCLOUD_ERR_MQTT_NO_CONN == rc|| QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); - - if(QCLOUD_ERR_SUCCESS != rc) { - Log_e("Unsubscribe Returned : %d ", rc); - } - } - return NULL; -} - -/** - * 在子线程上进行subscribe操作 - * 这里会记录发布前/后的时间,并保存到pSubscribeTime中 - */ -static int _iot_mqtt_tests_subscribe_to_test_topic(void *pClient, QoS qos, struct timeval *pSubscribeTime) { - int rc; - struct timeval start, end; - - gettimeofday(&start, NULL); - - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.on_message_handler = _iot_mqtt_tests_message_aggregator; - rc = IOT_MQTT_Subscribe(pClient, INTEGRATION_TEST_TOPIC, &sub_params); - - printf("\n## Sub response rc : %d|topic : %s\n", rc, INTEGRATION_TEST_TOPIC); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -/** - * 在子线程上进行publish操作 - * 这里会循环PUBLISH_COUNT次,发布topic - * 如果第一次publish失败,则进行第二次发布,并且记录失败的次数 - */ -static void *_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int itr = 0; - char cPayload[30]; - - PublishParams params; - int rc = QCLOUD_ERR_SUCCESS; - ThreadData *threadData = (ThreadData *) ptr; - void *pClient = threadData->client; - int threadId = threadData->threadId; - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - snprintf(cPayload, 30, "Thread : %d, Msg : %d", threadId, itr); - printf("\nMsg being published: %s \n", cPayload); - params.payload = (void *) cPayload; - params.payload_len = strlen(cPayload) + 1; - params.qos = QOS1; - - do { - rc = IOT_MQTT_Publish(pClient, INTEGRATION_TEST_TOPIC, ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(/*MUTEX_LOCK_ERROR == rc || */QCLOUD_ERR_MQTT_NO_CONN == rc || QCLOUD_ERR_MQTT_REQUEST_TIMEOUT == rc); - - // 发布失败的时候进行一次重新发布,并且记录重新发布的次数 - if(QCLOUD_ERR_SUCCESS != rc) { - Log_e("Failed attempt 1 Publishing Thread : %d, Msg : %d, cs : %d ", threadId, itr, rc); - do { - rc = IOT_MQTT_Publish(pClient, INTEGRATION_TEST_TOPIC, ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(QCLOUD_ERR_MQTT_NO_CONN == rc); - sg_rePublishCount++; - if(QCLOUD_ERR_SUCCESS != rc) { - Log_e("Failed attempt 2 Publishing Thread : %d, Msg : %d, cs : %d Second Attempt ", threadId, itr, rc); - } - } - } - sg_threadStatus[threadId - 1] = 1; - return 0; -} - -/** - * 线程安全测试函数 - */ -static int _iot_mqtt_tests_multi_threading_validation(void) -{ - pthread_t publish_thread[MAX_PUB_THREAD_COUNT]; // 用来保存所有publish的线程 - pthread_t yield_thread; // yield的线程 - pthread_t sub_unsub_thread; // 订阅/取消订阅的线程 - - MQTTInitParams initParams; - _setup_connect_init_params(&initParams); - - int rc = QCLOUD_ERR_SUCCESS; - int test_result = 0; - - unsigned int connectCounter = 0; // 记录client连接的次数 - int threadId[MAX_PUB_THREAD_COUNT]; // 记录线程id - int pubThreadReturn[MAX_PUB_THREAD_COUNT]; // 保存pub线程创建函数返回结果 - int yieldThreadReturn = 0; // 保存yield线程创建函数返回结果 - int subUnsubThreadReturn = 0; // 保存sub线程创建函数返回结果 - float percentOfRxMsg = 0.0; // 记录从pub到sub整个流程的成功率 - int finishedThreadCount = 0; // 记录publish_thread线程数组中, 已经执行完pub操作的线程数 - - int i, rxMsgCount = 0, j = 0; // 记录订阅回调函数成功的次数 - struct timeval connectTime; // 记录client连接的时间 - struct timeval subscribeTopic; // 记录订阅topic的时间 - - ThreadData threadData[MAX_PUB_THREAD_COUNT]; // 对client和threadId进行包装,在publish线程函数中进行传递 - - void* client; - sg_terminate_yield_thread = false; - sg_rxMsgBufferTooBigCounter = 0; - sg_rxUnexpectedNumberCounter = 0; - sg_rePublishCount = 0; - sg_wrongYieldCount = 0; - - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - threadId[j] = j + 1; // 设置线程id,区间:1 - MAX_PUB_THREAD_COUNT - sg_threadStatus[j] = 0; // 设置线程状态:0 - for(i = 0; i < PUBLISH_COUNT; i++) { - sg_countArray[j][i] = 0; - } - } - - printf("\nConnecting Client "); - do { - client = IOT_MQTT_Construct(&initParams); - sg_pClient = client; - if(NULL == client) { - rc = QCLOUD_ERR_FAILURE; - Log_e("ERROR Construct!"); - return -1; - } - - connectCounter++; - } while(QCLOUD_ERR_SUCCESS != rc && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(QCLOUD_ERR_SUCCESS == rc) { - printf("\n## Connect Success. Time sec: %lu, usec: %lu\n", connectTime.tv_sec, connectTime.tv_usec); - } else { - Log_e("## Connect Failed. error code %d\n", rc); - return -1; - } - - _iot_mqtt_tests_subscribe_to_test_topic(sg_pClient, QOS1, &subscribeTopic); - - printf("\nRunning Test! "); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, _iot_mqtt_tests_yield_thread_runner, client); - subUnsubThreadReturn = pthread_create(&sub_unsub_thread, NULL, _iot_mqtt_tests_sub_unsub_thread_runner, client); - - printf("\nyieldThreadReturn=%d|subUnsubThreadReturn=%d ", yieldThreadReturn, subUnsubThreadReturn); - - /* 创建多个线程单独测试publish */ - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - threadData[i].client = sg_pClient; - threadData[i].threadId = threadId[i]; - pubThreadReturn[i] = pthread_create(&publish_thread[i], NULL, _iot_mqtt_tests_publish_thread_runner, - &threadData[i]); - - printf("\ni=%d|pubThreadReturn=%d ", i, pubThreadReturn[i]); - } - - /* 等待所有publish线程执行完 */ - do { - finishedThreadCount = 0; - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - finishedThreadCount += sg_threadStatus[i]; - } - printf("\nFinished thread count : %d \n", finishedThreadCount); - sleep(1); - } while(finishedThreadCount < MAX_PUB_THREAD_COUNT); - - printf("\nFinished publishing!!"); - - sg_terminate_yield_thread = true; - sg_terminate_subUnsub_thread = true; - - /* Allow time for yield_thread and sub_sunsub thread to exit */ - sleep(1); - - /* Not using pthread_join because all threads should have terminated gracefully at this point. If they haven't, - * which should not be possible, something below will fail. */ - - printf("\n\nCalculating Results!! \n\n"); - for(i = 0; i < PUBLISH_COUNT; i++) { - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - if(sg_countArray[j][i] > 0) { - rxMsgCount++; - } - } - } - - printf("\n\nResult : \n"); - percentOfRxMsg = (float) rxMsgCount * 100 / (PUBLISH_COUNT * MAX_PUB_THREAD_COUNT); - - if(RX_RECEIVE_PERCENTAGE <= percentOfRxMsg && // 成功率达标 - 0 == sg_rxMsgBufferTooBigCounter && // 返回数据buffer没有越界 - 0 == sg_rxUnexpectedNumberCounter && // 返回预期范围内的数据 - 0 == sg_wrongYieldCount) // yield过程中没有发生失败 - { - // 测试成功 - printf("\nSuccess: %f %%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT * MAX_PUB_THREAD_COUNT, rxMsgCount); - printf("QoS 1 re publish count %u\n", sg_rePublishCount); - printf("Connection Attempts %u\n", connectCounter); - printf("Yield count without error during callback %u\n", sg_wrongYieldCount); - test_result = 0; - } else { - // 测试失败 - printf("\nFailure: %f\n", percentOfRxMsg); - printf("\"Received message was too big than anything sent\" count: %u\n", sg_rxMsgBufferTooBigCounter); - printf("\"The number received is out of the range\" count: %u\n", sg_rxUnexpectedNumberCounter); - printf("Yield count without error during callback %u\n", sg_wrongYieldCount); - test_result = -2; - } - IOT_MQTT_Destroy(&client); - sg_pClient = NULL; - return test_result; -} - -static int _run_thread_test(void) -{ - printf("\n\n"); - printf("******************************************************************\n"); - printf("* Starting MQTT Version 3.1.1 Multithreading Validation Test *\n"); - printf("******************************************************************\n"); - int rc = _iot_mqtt_tests_multi_threading_validation(); - if(0 != rc) { - printf("\n*******************************************************************\n"); - printf("*MQTT Version 3.1.1 Multithreading Validation Test FAILED! RC : %d \n", rc); - printf("*******************************************************************\n"); - return 1; - } - - printf("******************************************************************\n"); - printf("* MQTT Version 3.1.1 Multithreading Validation Test SUCCESS!! *\n"); - printf("******************************************************************\n"); - - return 0; -} - -int main(int argc, char **argv) { - return _run_thread_test(); -} diff --git a/sdk-tests/multi_thread_test/multi_thread_test.mk b/sdk-tests/multi_thread_test/multi_thread_test.mk deleted file mode 100644 index 5dd29e71..00000000 --- a/sdk-tests/multi_thread_test/multi_thread_test.mk +++ /dev/null @@ -1,23 +0,0 @@ -DEPENDS := src/platform -LDFLAGS := $(FINAL_DIR)/lib/libiot_sdk.a -LDFLAGS += $(FINAL_DIR)/lib/libiot_platform.a -ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) -LDFLAGS += $(FINAL_DIR)/lib/libmbedtls.a $(FINAL_DIR)/lib/libmbedx509.a $(FINAL_DIR)/lib/libmbedcrypto.a -endif -CFLAGS := $(filter-out -ansi,$(CFLAGS)) -CFLAGS += -pthread - -ifneq (,$(filter -DSDKTESTS_ENABLED,$(CFLAGS))) - -run_multi_thread_test:$(TESTS_DIR)/multi_thread_test/multi_thread_test.c - $(eval CFLAGS := $(filter-out $(IOTSDK_INCLUDE_FILES),$(CFLAGS)) \ - -I$(TOP_DIR)/src/sdk-impl -I$(TOP_DIR)/src/sdk-impl/exports) - - $(call Brief_Log,"LD") - $(TOP_Q) \ - $(PLATFORM_CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/unittest \ - -endif \ No newline at end of file diff --git a/sdk-tests/unit_test/include/iot_unit_config.h b/sdk-tests/unit_test/include/iot_unit_config.h deleted file mode 100644 index ac65c77f..00000000 --- a/sdk-tests/unit_test/include/iot_unit_config.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef MQTT_CLIENT_C_IOT_UNIT_TEST_H -#define MQTT_CLIENT_C_IOT_UNIT_TEST_H - -// 这些信息可以从控制台获取得到 -#define QCLOUD_IOT_MY_PRODUCT_ID "27N9Y8PCPO" // 产品名称, 与云端同步设备状态时需要 -#define QCLOUD_IOT_MY_DEVICE_NAME "unittest0" // 设备名称, 与云端同步设备状态时需要 -#define QCLOUD_IOT_CA_FILENAME "root-ca.crt" // CA根证书文件名 -#define QCLOUD_IOT_CERT_FILENAME "unittest_cert.crt" // 客户端证书文件名 -#define QCLOUD_IOT_KEY_FILENAME "unittest_private.key" // 客户端私钥文件名 - -#endif //MQTT_CLIENT_C_IOT_UNIT_TEST_H diff --git a/sdk-tests/unit_test/include/unit_helper_functions.h b/sdk-tests/unit_test/include/unit_helper_functions.h deleted file mode 100644 index e45d6973..00000000 --- a/sdk-tests/unit_test/include/unit_helper_functions.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef MQTT_CLIENT_C_UNIT_HELPER_FUNCTIONS_H -#define MQTT_CLIENT_C_UNIT_HELPER_FUNCTIONS_H - -#include "mqtt_client.h" -#include "iot_unit_config.h" - - -#define QCLOUD_TOPIC_PATH "/"//"$qcloud/devices/" -#define SHADOW_TOPIC "$shadow/" -#define ACCEPTED_TOPIC "accepted/" -#define REJECTED_TOPIC "rejected/" -#define UPDATE_TOPIC "update/" -#define GET_TOPIC "get/" -#define DELETE_TOPIC "delete/" - - -#define GET_ACCEPTED_TOPIC SHADOW_TOPIC GET_TOPIC ACCEPTED_TOPIC QCLOUD_IOT_MY_PRODUCT_ID QCLOUD_TOPIC_PATH QCLOUD_IOT_MY_DEVICE_NAME -#define GET_REJECTED_TOPIC SHADOW_TOPIC GET_TOPIC REJECTED_TOPIC QCLOUD_IOT_MY_PRODUCT_ID QCLOUD_TOPIC_PATH QCLOUD_IOT_MY_DEVICE_NAME -#define GET_PUB_TOPIC SHADOW_TOPIC GET_TOPIC QCLOUD_IOT_MY_PRODUCT_ID QCLOUD_TOPIC_PATH QCLOUD_IOT_MY_DEVICE_NAME - -#define DELETE_ACCEPTED_TOPIC SHADOW_TOPIC DELETE_TOPIC ACCEPTED_TOPIC QCLOUD_IOT_MY_PRODUCT_ID QCLOUD_TOPIC_PATH QCLOUD_IOT_MY_DEVICE_NAME -#define DELETE_REJECTED_TOPIC SHADOW_TOPIC DELETE_TOPIC REJECTED_TOPIC QCLOUD_IOT_MY_PRODUCT_ID QCLOUD_TOPIC_PATH QCLOUD_IOT_MY_DEVICE_NAME - -#define UPDATE_ACCEPTED_TOPIC SHADOW_TOPIC UPDATE_TOPIC ACCEPTED_TOPIC QCLOUD_IOT_MY_PRODUCT_ID QCLOUD_TOPIC_PATH QCLOUD_IOT_MY_DEVICE_NAME -#define UPDATE_REJECTED_TOPIC SHADOW_TOPIC UPDATE_TOPIC REJECTED_TOPIC QCLOUD_IOT_MY_PRODUCT_ID QCLOUD_TOPIC_PATH QCLOUD_IOT_MY_DEVICE_NAME - -#define SIZE_OF_JSON_BUFFER 256 - - -void MQTTInitParamsSetup(MQTTInitParams *pParams, bool enableAutoReconnect); - -void ConnectMQTTParamsSetup_Detailed(MQTTConnectParams *connectParams, MQTTInitParams *initParams, - QoS qos, bool isCleanSession, bool isWillMsgPresent, - char *pWillTopicName, char *pWillMessage, char *pUsername); - -void SetupMQTTConnectInitParams(MQTTInitParams* initParams); - -void SetupShadowConnectInitParams(ShadowInitParams* initParams); - - -void ConnectParamsSetup(MQTTConnectParams *connectParams, MQTTInitParams *initParams); - -#endif //MQTT_CLIENT_C_UNIT_HELPER_FUNCTIONS_H diff --git a/sdk-tests/unit_test/run_unit_test.cpp b/sdk-tests/unit_test/run_unit_test.cpp deleted file mode 100644 index 71964f53..00000000 --- a/sdk-tests/unit_test/run_unit_test.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// #include "shadow_test.h" -// #include - -// int main(int argc, char* argv[]) -// { -// ::testing::InitGoogleTest(&argc, argv); -// return RUN_ALL_TESTS(); -// } \ No newline at end of file diff --git a/sdk-tests/unit_test/src/unit_connect_test.cpp b/sdk-tests/unit_test/src/unit_connect_test.cpp deleted file mode 100644 index 1759d72c..00000000 --- a/sdk-tests/unit_test/src/unit_connect_test.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include "unit_helper_functions.h" -#include "qcloud_iot_export_mqtt.h" -#include "mqtt_client.h" -#include "iot_unit_config.h" - -static bool isMqttConnected = false; - -static Qcloud_IoT_Client *client; -static MQTTInitParams initParams; -static MQTTConnectParams connectParams = DEFAULT_MQTTCONNECT_PARAMS; - -PublishParams testPubMsgParams; - -SubscribeParams testTopicParams; - -#define NO_MSG_XXXX "XXXX" -// static char CallbackMsgStringclean[100] = NO_MSG_XXXX; - -using namespace std; - -class MQTTConnectTests : public testing::Test -{ -protected: - virtual void SetUp() - { - IOT_Log_Set_Level(DEBUG); - std::cout << "MQTTConnectTests Test Begin \n"; - isMqttConnected = false; - } - virtual void TearDown() - { - sleep(1); - std::cout << "MQTTConnectTests Test End \n"; -// IOT_MQTT_Destroy(&client); - } - -}; - -/** - * 1. Connect success - */ -TEST_F(MQTTConnectTests, ConnectSuccess) { - SetupMQTTConnectInitParams(&initParams); - void * client = IOT_MQTT_Construct(&initParams); - ASSERT_TRUE(client != NULL); -} - -/** - * 2. Init with NULL MQTTInitParams Struct - */ -TEST_F(MQTTConnectTests, nullParamsInit) { - Log_d("2. Init with NULL MQTTInitParams Struct"); - void *client_ptr = IOT_MQTT_Construct(NULL); - ASSERT_TRUE(NULL == client_ptr); -} - -/** - * 3. Init with NULL Cert File Path - */ -TEST_F(MQTTConnectTests, nullCert) { - Log_d("4. Init with NULL Cert File Path"); - SetupMQTTConnectInitParams(&initParams); -#ifndef AUTH_WITH_NOTLS -#ifdef AUTH_MODE_CERT - initParams.cert_file = NULL; -#else - -#endif -#endif - void *client_ptr = IOT_MQTT_Construct(&initParams); - ASSERT_TRUE(NULL == client_ptr); -} - -/** - * 4. Init with NULL Key File Path - */ -TEST_F(MQTTConnectTests, nullKeyFile) { - SetupMQTTConnectInitParams(&initParams); -#ifndef AUTH_WITH_NOTLS -#ifdef AUTH_MODE_CERT - initParams.key_file = NULL; -#else - -#endif -#endif - void *client_ptr = IOT_MQTT_Construct(&initParams); - ASSERT_TRUE(NULL == client_ptr); -} - -/** - * 5. Connect with NULL/Empty Client ID - */ -TEST_F(MQTTConnectTests, nullClientID) { - - // if NULL Client ID - SetupMQTTConnectInitParams(&initParams); - void *client_ptr = IOT_MQTT_Construct(&initParams); - ASSERT_TRUE(NULL == client_ptr); - - // if Empty Client ID - SetupMQTTConnectInitParams(&initParams); - client_ptr = IOT_MQTT_Construct(&initParams); - ASSERT_TRUE(NULL == client_ptr); -} - -/** - * 6. Connect with Invalid Cert - */ -TEST_F(MQTTConnectTests, InvalidCert) { - char invalidCert[20]; - snprintf(invalidCert, 20, "invalid"); - - SetupMQTTConnectInitParams(&initParams); -#ifndef AUTH_WITH_NOTLS -#ifdef AUTH_MODE_CERT - initParams.cert_file = invalidCert; -#else - -#endif -#endif - void *client_ptr = IOT_MQTT_Construct(&initParams); - ASSERT_TRUE(NULL == client_ptr); -} - -/** - * 7. Connect with Invalid Key - */ -TEST_F(MQTTConnectTests, InvalidKey) { - char invalidKey[20]; - snprintf(invalidKey, 20, "invalid"); - - SetupMQTTConnectInitParams(&initParams); -#ifndef AUTH_WITH_NOTLS -#ifdef AUTH_MODE_CERT - initParams.key_file = invalidKey; -#else - -#endif -#endif - void *client_ptr = IOT_MQTT_Construct(&initParams); - ASSERT_TRUE(NULL == client_ptr); -} - -/** - * 8. Connect, with no Response timeout - */ -TEST_F(MQTTConnectTests, NoResponseTimeout) { - int rc; - - MQTTInitParamsSetup(&initParams, false); - rc = qcloud_iot_mqtt_init(client, &initParams); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - ConnectParamsSetup(&connectParams, &initParams); - rc = qcloud_iot_mqtt_connect(client, &connectParams); - ASSERT_TRUE(rc != QCLOUD_ERR_SUCCESS); -} - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} - diff --git a/sdk-tests/unit_test/src/unit_delta_test.cpp b/sdk-tests/unit_test/src/unit_delta_test.cpp deleted file mode 100644 index 37608796..00000000 --- a/sdk-tests/unit_test/src/unit_delta_test.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include "mqtt_client.h" -#include -#include -#include "shadow_client.h" - -static Qcloud_IoT_Shadow *client; -static ShadowInitParams initParams; - -static char receivedNestedObject[100] = ""; -static char sentNestedObjectData[100] = "{\"sensor1\":23}"; -static char shadowDeltaTopic[MAX_SIZE_OF_CLOUD_TOPIC]; - -#define SHADOW_DELTA_UPDATE "$shadow/update/delta/%s/%s" - -#undef QCLOUD_IOT_MY_DEVICE_NAME -#define QCLOUD_IOT_MY_DEVICE_NAME "QCLOUD-IoT-C-SDK" - -class ShadowDeltaTest : public testing::Test -{ -protected: - virtual void SetUp() - { - std::cout << "ShadowDeltaTest Test Begin \n"; - SetupShadowConnectInitParams(&initParams); - client = (Qcloud_IoT_Shadow *)IOT_Shadow_Construct(&initParams); - snprintf(shadowDeltaTopic, MAX_SIZE_OF_CLOUD_TOPIC, (char *)SHADOW_DELTA_UPDATE, (char *)QCLOUD_IOT_MY_PRODUCT_ID, (char *)QCLOUD_IOT_MY_DEVICE_NAME); - } - virtual void TearDown() - { - std::cout << "ShadowDeltaTest Test End \n"; - IOT_Shadow_Destroy(client); - } - -}; - -void genericCallback(void *pClient, const char *pJsonStringData, uint32_t JsonStringDataLen, DeviceProperty *pContext) { - printf("======================\nkey[%s]==Data[%.*s]\n======================\n", pContext->key, JsonStringDataLen, pJsonStringData); -} - -void nestedObjectCallback(void *pClient, const char *pJsonStringData, uint32_t JsonStringDataLen, DeviceProperty *pContext) { - printf("======================\nkey[%s]==Data[%.*s]\n======================\n", pContext->key, JsonStringDataLen, pJsonStringData); - snprintf(receivedNestedObject, 100, "%.*s", JsonStringDataLen, pJsonStringData); - printf("receivedNestedObject: %s", receivedNestedObject); -} - - -TEST_F(ShadowDeltaTest, registerDeltaSuccess) { - DeviceProperty windowHandler; - char deltaJSONString[SIZE_OF_JSON_BUFFER] = {0};//"{\"state\":{\"delta\":{\"window\":true}},\"version\":1}"; - bool windowOpenData = false; - int ret_val; - - windowHandler.key = (char*)"window"; - windowHandler.type = JBOOL; - windowHandler.data = &windowOpenData; - - ret_val = IOT_Shadow_Register_Property(client, &windowHandler, genericCallback); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - windowOpenData = true; - ret_val = IOT_Shadow_JSON_ConstructDesireAllNull(client, deltaJSONString, SIZE_OF_JSON_BUFFER); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - windowOpenData = false; - ret_val = IOT_Shadow_Update(client, deltaJSONString, SIZE_OF_JSON_BUFFER, NULL, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - ret_val = IOT_Shadow_Yield(client, 3000); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - ASSERT_EQ(true, windowOpenData); -} - - -TEST_F(ShadowDeltaTest, registerDeltaInt) { - int ret_val; - DeviceProperty intHandler; - int intData = 0; - char deltaJSONString[SIZE_OF_JSON_BUFFER] = {0};//"{\"state\":{\"delta\":{\"length\":23}},\"version\":1}"; - - intHandler.key = (char*)"length"; - intHandler.type = JINT32; - intHandler.data = &intData; - - ret_val = IOT_Shadow_Register_Property(client, &intHandler, genericCallback); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - intData = 23; - ret_val = IOT_Shadow_JSON_ConstructDesireAllNull(client, deltaJSONString, SIZE_OF_JSON_BUFFER); - intData = 0; - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - ret_val = IOT_Shadow_Update(client, deltaJSONString, SIZE_OF_JSON_BUFFER, NULL, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - IOT_Shadow_Yield(client, 3000); - ASSERT_EQ(23, intData); -} - -TEST_F(ShadowDeltaTest, registerDeltaIntNoCallback) { - int ret_val; - DeviceProperty intHandler; - int intData = 0; - intHandler.key = (char*)"length_nocb"; - intHandler.type = JINT32; - intHandler.data = &intData; - - ret_val = IOT_Shadow_Register_Property(client, &intHandler, NULL); - ASSERT_EQ(QCLOUD_ERR_INVAL, ret_val); -} - -TEST_F(ShadowDeltaTest, DeltaNestedObject) { - int ret_val; - - DeviceProperty nestedObjectHandler; - char *nestedObject = sentNestedObjectData; - char deltaJSONString[SIZE_OF_JSON_BUFFER] = {0}; - - nestedObjectHandler.key = (char*)"sensors"; - nestedObjectHandler.type = JOBJECT; - nestedObjectHandler.data = nestedObject; - - ret_val = IOT_Shadow_Register_Property(client, &nestedObjectHandler, nestedObjectCallback); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - ret_val = IOT_Shadow_JSON_ConstructDesireAllNull(client, deltaJSONString, SIZE_OF_JSON_BUFFER); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - ret_val = IOT_Shadow_Update(client, deltaJSONString, SIZE_OF_JSON_BUFFER, NULL, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - IOT_Shadow_Yield(client, 3000); - ASSERT_TRUE( strstr(receivedNestedObject, sentNestedObjectData) != NULL ); -} - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdk-tests/unit_test/src/unit_disconnect_test.cpp b/sdk-tests/unit_test/src/unit_disconnect_test.cpp deleted file mode 100644 index d810dd56..00000000 --- a/sdk-tests/unit_test/src/unit_disconnect_test.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include -#include - -static MQTTConnectParams connectParams; -static MQTTInitParams initParams; -static Qcloud_IoT_Client iotClient; - -static bool handlerInvoked = false; - -void disconnectTestHandler(void) { - handlerInvoked = true; -} - -void event_handle(void *pcontext, void *pclient, MQTTEventMsg *msg) -{ - switch (msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_d("MQTT_EVENT_UNDEF|undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_d("MQTT_EVENT_DISCONNECT|MQTT disconnect."); - disconnectTestHandler(); - break; - - default: - Log_d("Should NOT arrive here."); - break; - } -} - - -class DisconnectTests : public testing::Test -{ -protected: - virtual void SetUp() - { - std::cout << "DisconnectTests Test Begin \n"; - - int rc; - MQTTInitParamsSetup(&initParams, true); - rc = qcloud_iot_mqtt_init(&iotClient, &initParams); - initParams.event_handle.h_fp = event_handle; - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - ConnectParamsSetup(&connectParams, &initParams); - connectParams.keep_alive_interval = 5; - rc = qcloud_iot_mqtt_connect(&iotClient, &connectParams); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - } - virtual void TearDown() - { - std::cout << "DisconnectTests Test End \n"; - } - -}; - - -/* F:1 - Disconnect with Null/empty client instance */ -TEST_F(DisconnectTests, NullClientDisconnect) { - int rc = qcloud_iot_mqtt_disconnect(NULL); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -// /* F:2 - Set Disconnect Handler with Null/empty Client */ -// TEST_F(DisconnectTests, NullClientSetDisconnectHandler) { -// int rc = qcloud_iot_mqtt_set_disconnect_handler(NULL, disconnectTestHandler); -// ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -// } - -// /* F:3 - Call Set Disconnect handler with Null handler */ -// TEST_F(DisconnectTests, SetDisconnectHandlerNullHandler) { -// int rc = qcloud_iot_mqtt_set_disconnect_handler(&iotClient, NULL); -// ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); -// } - -/* F:4 - Disconnect attempt, not connected */ -TEST_F(DisconnectTests, disconnectNotConnected) { - int rc; - - /* First make sure client is disconnected */ - rc = qcloud_iot_mqtt_disconnect(&iotClient); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - /* Check client is disconnected */ - ASSERT_TRUE(false == IOT_MQTT_IsConnected(&iotClient)); - - /* Now call disconnect again */ - rc = qcloud_iot_mqtt_disconnect(&iotClient); - ASSERT_EQ(QCLOUD_ERR_MQTT_NO_CONN, rc); -} - -/* F:5 - Disconnect success */ -TEST_F(DisconnectTests, disconnectNoAckSuccess) { - int rc; - rc = qcloud_iot_mqtt_disconnect(&iotClient); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); -} - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdk-tests/unit_test/src/unit_helper_functions.c b/sdk-tests/unit_test/src/unit_helper_functions.c deleted file mode 100644 index 7f6f96ec..00000000 --- a/sdk-tests/unit_test/src/unit_helper_functions.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "unit_helper_functions.h" - -#include -#include -#include -#include -#include -#include - -#include "qcloud_iot_export.h" -#include "iot_unit_config.h" -#include "device.h" - -static char g_clientCert[PATH_MAX + 1]; -static char g_clientKey[PATH_MAX + 1]; - -static void _make_client_id(MQTTConnectParams *connectParams) { - DeviceInfo *info = iot_device_info_get(); - - int clientid_len = strlen(info->product_id) + strlen(info->device_name) + 1; - connectParams->client_id = (char*)HAL_Malloc(clientid_len); - sprintf(connectParams->client_id, "%s%s", info->product_id, info->device_name); -} - -/** - * 设置初始化参数 - * - * @param pParams - * @param pHost - * @param port - * @param enableAutoReconnect - * @param callback - */ -void MQTTInitParamsSetup(MQTTInitParams *pParams, bool enableAutoReconnect) -{ - pParams->auto_connect_enable = enableAutoReconnect; - - char cert_dir[PATH_MAX + 1] = "certs"; - - sprintf(g_clientCert, "%s/%s", cert_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(g_clientKey, "%s/%s", cert_dir, QCLOUD_IOT_KEY_FILENAME); -#ifndef AUTH_WITH_NOTLS -#ifdef AUTH_MODE_CERT - pParams->cert_file = g_clientCert; - pParams->key_file = g_clientKey; -#else - -#endif -#endif - - pParams->device_name = (char *)QCLOUD_IOT_MY_DEVICE_NAME; - pParams->product_id = (char *)QCLOUD_IOT_MY_PRODUCT_ID; - pParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; -} - -void ConnectMQTTParamsSetup_Detailed(MQTTConnectParams *connectParams, MQTTInitParams *initParams, - QoS qos, bool isCleanSession, bool isWillMsgPresent, - char *pWillTopicName, char *pWillMessage, char *pUsername) -{ - connectParams->keep_alive_interval = 10; - connectParams->clean_session = isCleanSession; - connectParams->mqtt_version = MQTT_3_1_1; - connectParams->username = pUsername; - - iot_device_info_init(); - iot_device_info_set(initParams->product_id, initParams->device_name); - _make_client_id(connectParams); -} - -/** - * 设置连接参数 - * - * @param pParams - * @param pClientId - */ -void ConnectParamsSetup(MQTTConnectParams *connectParams, MQTTInitParams *initParams) -{ - connectParams->mqtt_version = MQTT_3_1_1; - connectParams->keep_alive_interval = (uint16_t)QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; - connectParams->clean_session = initParams->clean_session; - connectParams->auto_connect_enable = initParams->auto_connect_enable; - - iot_device_info_init(); - iot_device_info_set(initParams->product_id, initParams->device_name); - _make_client_id(connectParams); -} - -void SetupMQTTConnectInitParams(MQTTInitParams* pInitParams) -{ - pInitParams->device_name = (char *)QCLOUD_IOT_MY_DEVICE_NAME; - pInitParams->product_id = (char *)QCLOUD_IOT_MY_PRODUCT_ID; - - char cert_dir[PATH_MAX + 1] = "certs"; - sprintf(g_clientCert, "%s/%s", cert_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(g_clientKey, "%s/%s", cert_dir, QCLOUD_IOT_KEY_FILENAME); -#ifndef AUTH_WITH_NOTLS -#ifdef AUTH_MODE_CERT - pInitParams->cert_file = g_clientCert; - pInitParams->key_file = g_clientKey; -#else - -#endif -#endif - - pInitParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT; - pInitParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL; - -} - -void SetupShadowConnectInitParams(ShadowInitParams* initParams) -{ - initParams->device_name = (char *)QCLOUD_IOT_MY_DEVICE_NAME; - initParams->product_id = (char *)QCLOUD_IOT_MY_PRODUCT_ID; - - char cert_dir[PATH_MAX + 1] = "certs"; - sprintf(g_clientCert, "%s/%s", cert_dir, QCLOUD_IOT_CERT_FILENAME); - sprintf(g_clientKey, "%s/%s", cert_dir, QCLOUD_IOT_KEY_FILENAME); -#ifndef AUTH_WITH_NOTLS -#ifdef AUTH_MODE_CERT - initParams->cert_file = g_clientCert; - initParams->key_file = g_clientKey; -#else - -#endif -#endif -} diff --git a/sdk-tests/unit_test/src/unit_http_test.cpp b/sdk-tests/unit_test/src/unit_http_test.cpp deleted file mode 100644 index 5a4abece..00000000 --- a/sdk-tests/unit_test/src/unit_http_test.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include - -#include "qcloud_iot_export_log.h" -#include "qcloud_iot_import.h" -#include "ca.h" -#include "utils_httpc.h" - -class HTTPClientTests : public testing::Test -{ -protected: - virtual void SetUp() - { - IOT_Log_Set_Level(DEBUG); - std::cout << "HTTPClientTests Test Begin \n"; - } - virtual void TearDown() - { - std::cout << "HTTPClientTests Test End \n"; - } - -}; - -TEST_F(HTTPClientTests, HTTPDownload) { - HTTPClient *http_client = (HTTPClient *)HAL_Malloc(sizeof(HTTPClient)); - HTTPClientData *http_data = (HTTPClientData *)HAL_Malloc(sizeof(HTTPClientData)); - memset(http_client, 0, sizeof(HTTPClient)); - memset(http_data, 0, sizeof(HTTPClientData)); - - char *buf = (char *)HAL_Malloc(2046); - memset(buf, 0, 2046); - http_data->response_buf = buf; - http_data->response_buf_len = 2046; - http_client->header = (char *)"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \ - "Accept-Encoding: gzip, deflate\r\n"; - - FILE *fp; - char *file_path = (char*)"htts_down.txt"; - if (NULL == (fp = fopen(file_path, "wb+"))) { - ASSERT_TRUE(NULL != fp); - } - - char *url = (char *)"https://ota-1251132654.cos.ap-guangzhou.myqcloud.com/3.txt?sign=2iYBFIhf9qG3YLVzehkFSs25M7phPTEyNTExMzI2NTQmaz1BS0lEdnp2bjhDbGM3Q2swTDB1Ujh5SVUzQ3NqbG5mbnJ4anMmZT0xNTIwMzkwMzkxJnQ9MTUxNzc5ODM5MSZyPTEzMTQ2ODYxNDMmZj0vMy50eHQmYj1vdGE="; - const char *ca_crt = iot_https_ca_get(); - // char *url = (char*)"https://cloud.tencent.com/"; - uint32_t timeout_ms = 5000; - int rc; - bool read_finish = false; - - qcloud_http_client_common(http_client, url, 443, ca_crt, HTTP_GET, http_data); - - while (!read_finish) { - int diff = http_data->response_content_len - http_data->retrieve_len; - - rc = qcloud_http_recv_data(http_client, timeout_ms, http_data); - - int32_t len = http_data->response_content_len - http_data->retrieve_len - diff; - read_finish = len == 0; - if (len > 0) { - rc = fwrite(http_data->response_buf, len, 1, fp); - } - ASSERT_TRUE(rc == 1); - } - - fclose(fp); - HAL_Free(buf); - HAL_Free(http_client); -} diff --git a/sdk-tests/unit_test/src/unit_publish_test.cpp b/sdk-tests/unit_test/src/unit_publish_test.cpp deleted file mode 100644 index f31b4c21..00000000 --- a/sdk-tests/unit_test/src/unit_publish_test.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include "qcloud_iot_export.h" - - -// static MQTTConnectParams connectParams; -static MQTTInitParams initParams; -static PublishParams testPubMsgParams; - -static char subTopic[100] = {0}; - -static Qcloud_IoT_Client *iotClient; -char cPayload[100]; - - -class PublishTests : public testing::Test -{ -protected: - virtual void SetUp() - { - std::cout << "PublishTests Test Begin \n"; - - sprintf(subTopic, "%s/%s/abc", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME); - SetupMQTTConnectInitParams(&initParams); - iotClient = (Qcloud_IoT_Client *)IOT_MQTT_Construct(&initParams); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.retained = 0; - sprintf(cPayload, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payload_len = strlen(cPayload); - } - virtual void TearDown() - { - std::cout << "PublishTests Test End \n"; - void *c = (void*)iotClient; - IOT_MQTT_Destroy(&c); - } - -}; - - -/* E:1 - Publish with Null/empty client instance */ -TEST_F(PublishTests, PublishNullClient) { - int rc; - - testPubMsgParams.qos = QOS1; - testPubMsgParams.retained = 0; - testPubMsgParams.payload = (void *)"Message"; - testPubMsgParams.payload_len = 7; - - rc = qcloud_iot_mqtt_publish(NULL, subTopic, &testPubMsgParams); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* E:2 - Publish with Null/empty Topic Name */ -TEST_F(PublishTests, PublishNullTopic) { - int rc; - - testPubMsgParams.qos = QOS1; - testPubMsgParams.retained = 0; - testPubMsgParams.payload = (void *)"Message"; - testPubMsgParams.payload_len = 7; - - rc = qcloud_iot_mqtt_publish(iotClient, NULL, &testPubMsgParams); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); - - rc = qcloud_iot_mqtt_publish(iotClient, (char *)"", &testPubMsgParams); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* E:3 - Publish with Null/empty payload */ -TEST_F(PublishTests, PublishNullParams) { - int rc; - - rc = qcloud_iot_mqtt_publish(iotClient, subTopic, NULL); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.retained = 0; - testPubMsgParams.payload = NULL; - testPubMsgParams.payload_len = 0; - - rc = qcloud_iot_mqtt_publish(iotClient, subTopic, &testPubMsgParams); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* E:4 - Publish with network disconnected */ -TEST_F(PublishTests, PublishNetworkDisconnected) { - int rc; - - /* Ensure network is disconnected */ - rc = qcloud_iot_mqtt_disconnect(iotClient); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.retained = 0; - testPubMsgParams.payload = (void *)"Message"; - testPubMsgParams.payload_len = 7; - - rc = qcloud_iot_mqtt_publish(iotClient, subTopic, &testPubMsgParams); - ASSERT_EQ(QCLOUD_ERR_MQTT_NO_CONN, rc); -} - -/* E:6 - Publish QoS0 success */ -TEST_F(PublishTests, publishQoS0NoPubackSuccess) { - int rc; - - testPubMsgParams.qos = QOS0; // switch to a Qos0 PUB - rc = IOT_MQTT_Publish(iotClient, subTopic, &testPubMsgParams); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); -} - -/* E:7 - Publish with QoS1 send success, Puback received */ -TEST_F(PublishTests, publishQoS1Success) { - int rc; - - testPubMsgParams.qos = QOS1; - rc = IOT_MQTT_Publish(iotClient, subTopic, &testPubMsgParams); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); -} - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdk-tests/unit_test/src/unit_shadow_json_builder_test.cpp b/sdk-tests/unit_test/src/unit_shadow_json_builder_test.cpp deleted file mode 100644 index 52746bf8..00000000 --- a/sdk-tests/unit_test/src/unit_shadow_json_builder_test.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include - -#include "shadow_client.h" -#include "shadow_client_json.h" -#include "unit_helper_functions.h" -#include "lite-utils.h" - -static DeviceProperty dataFloatHandler; -static DeviceProperty dataDoubleHandler; -static DeviceProperty dataIntegerHandler; - -static int integerData = 1; -static double doubleData = 4.0908f; -static float floatData = 3.445f; - -static ShadowInitParams g_initParams; -static Qcloud_IoT_Shadow *g_shadow_ptr; - -using namespace std; - -class ShadowJsonBuilderTests : public testing::Test -{ -protected: - virtual void SetUp() - { - std::cout << "ShadowJsonBuilderTests Test Begin \n"; - SetupShadowConnectInitParams(&g_initParams); - void *client = IOT_Shadow_Construct(&g_initParams); - g_shadow_ptr = (Qcloud_IoT_Shadow *)client; - - dataFloatHandler.data = &floatData; - dataFloatHandler.key = (char*)"floatData"; - dataFloatHandler.type = JFLOAT; - - dataDoubleHandler.data = &doubleData; - dataDoubleHandler.key = (char*)"doubleData"; - dataDoubleHandler.type = JDOUBLE; - - dataIntegerHandler.data = &integerData; - dataIntegerHandler.key = (char*)"integerData"; - dataIntegerHandler.type = JINT32; - } - virtual void TearDown() - { - std::cout << "ShadowJsonBuilderTests Test End \n"; - IOT_Shadow_Destroy(g_shadow_ptr); - } -}; - -#define TEST_JSON_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" QCLOUD_IOT_MY_PRODUCT_ID "-0\"}" -#define TEST_JSON_EMPTY_GET_DELETE_DOCUMENT "{\"clientToken\":\"" QCLOUD_IOT_MY_PRODUCT_ID "-0\"}" - -#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"integerData\":24}}, \"clientToken\":\"" QCLOUD_IOT_MY_PRODUCT_ID "-0\", \"version\":1, \"code\": 200, \"message\": \"OK\"}" - -#define SIZE_OF_UPFATE_BUF 200 - -TEST_F(ShadowJsonBuilderTests, BuildEmptyJson) -{ - char getOrDeleteRequestJson[SIZE_OF_UPFATE_BUF] = {0}; - build_empty_json(&(g_shadow_ptr->inner_data.token_num), getOrDeleteRequestJson); - ASSERT_STREQ(TEST_JSON_EMPTY_GET_DELETE_DOCUMENT, getOrDeleteRequestJson); -} - -TEST_F(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder) -{ - int ret_val; - char updateRequestJson[SIZE_OF_UPFATE_BUF]; - // size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]); - - Log_d("\n-->Running Cloud Json Builder Tests - Update the Json document builder \n"); - - ret_val = IOT_Shadow_JSON_ConstructReport(g_shadow_ptr, updateRequestJson, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler); - - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - ASSERT_STREQ(TEST_JSON_UPDATE_DOCUMENT, updateRequestJson); -} - -TEST_F(ShadowJsonBuilderTests, PassingNullValue) -{ - int ret_val; - - Log_d("\n-->Running Cloud Json Builder Tests - Passing Null value to Shadow json builder \n"); - - ret_val = IOT_Shadow_JSON_ConstructReport(g_shadow_ptr, NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler); - ASSERT_EQ(QCLOUD_ERR_INVAL, ret_val); - ret_val = IOT_Shadow_JSON_ConstructDesireAllNull(g_shadow_ptr, NULL, SIZE_OF_UPFATE_BUF); - ASSERT_EQ(QCLOUD_ERR_INVAL, ret_val); -} - -TEST_F(ShadowJsonBuilderTests, SmallBuffer) -{ - int ret_val; - char updateRequestJson[14]; - size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]); - - Log_d("\n-->Running Shadow Json Builder Tests - Json Buffer is too small \n"); - - ret_val = IOT_Shadow_JSON_ConstructReport(g_shadow_ptr, updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - ASSERT_EQ(QCLOUD_ERR_JSON_BUFFER_TRUNCATED, ret_val); - ret_val = IOT_Shadow_JSON_ConstructDesireAllNull(g_shadow_ptr, updateRequestJson, jsonBufSize); - ASSERT_EQ(QCLOUD_ERR_JSON_BUFFER_TRUNCATED, ret_val); -} - -TEST_F(ShadowJsonBuilderTests, UpdateValueIfKeyMatch) -{ - bool ret_val; - - ret_val = update_value_if_key_match((char*)TEST_JSON_RESPONSE_UPDATE_DOCUMENT, &dataIntegerHandler); - integerData = *(int *) dataIntegerHandler.data; - ASSERT_EQ(1, (int) ret_val); - ASSERT_EQ(24, integerData); - - ret_val = update_value_if_key_match((char*)TEST_JSON_RESPONSE_UPDATE_DOCUMENT, &dataDoubleHandler); - ASSERT_EQ(0, (int) ret_val); -} - -TEST_F(ShadowJsonBuilderTests, ParseClientToken) -{ - bool ret_val; - char* clientToken; - char expected[100]; - strcpy(expected, QCLOUD_IOT_MY_PRODUCT_ID); - strcat(expected, "-0"); - - ret_val = parse_client_token((char*)TEST_JSON_RESPONSE_UPDATE_DOCUMENT, &clientToken); - - ASSERT_EQ(1, (int) ret_val); - ASSERT_STREQ(expected, clientToken); -} - -TEST_F(ShadowJsonBuilderTests, ParseVersionNum) -{ - bool ret_val; - uint32_t version; - uint32_t expected = 1; - - ret_val = parse_version_num((char*)TEST_JSON_RESPONSE_UPDATE_DOCUMENT, &version); - - ASSERT_EQ(1, (int) ret_val); - ASSERT_EQ(expected, version); -} diff --git a/sdk-tests/unit_test/src/unit_shadow_null_field_test.cpp b/sdk-tests/unit_test/src/unit_shadow_null_field_test.cpp deleted file mode 100644 index c548f608..00000000 --- a/sdk-tests/unit_test/src/unit_shadow_null_field_test.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#include -#include -#include -#include -#include - -#include -#include -#include "qcloud_iot_export_shadow.h" -#include "qcloud_iot_export_error.h" - - -static Qcloud_IoT_Client *g_client_ptr; -static ShadowInitParams g_initParams; - -static RequestAck ackStatusRx; -static Method actionRx; -static char jsonFullDocument[200]; - - -static void onRequestCallback(void *pClient, Method method, RequestAck requestAck, const char *pReceivedJsonDocument, void *pUserdata) -{ - actionRx = method; - ackStatusRx = requestAck; - if (ACK_TIMEOUT != requestAck) { - strcpy(jsonFullDocument, pReceivedJsonDocument); - } -} - -using namespace std; - -class ShadowNullFieldsTest : public testing::Test -{ -protected: - virtual void SetUp() - { - std::cout << "ShadowNullFieldsTest Test Begin \n"; - } - virtual void TearDown() - { - std::cout << "ShadowNullFieldsTest Test End \n"; - } - - -}; - -TEST_F(ShadowNullFieldsTest, NullClientConnect) -{ - void *client = IOT_Shadow_Construct(NULL); - ASSERT_TRUE(client == NULL); -} - -TEST_F(ShadowNullFieldsTest, NullUpdateDocument) -{ - SetupShadowConnectInitParams(&g_initParams); - g_client_ptr = (Qcloud_IoT_Client *)IOT_Shadow_Construct(&g_initParams); - int rc = IOT_Shadow_Update(g_client_ptr, NULL, 0, onRequestCallback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); - IOT_Shadow_Destroy(g_client_ptr); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); -} - -TEST_F(ShadowNullFieldsTest, NullClientYield) -{ - int rc = IOT_Shadow_Yield(NULL, 1000); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -TEST_F(ShadowNullFieldsTest, NullClientDisconnect) -{ - int rc = IOT_Shadow_Destroy(NULL); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -TEST_F(ShadowNullFieldsTest, NullClientShadowGet) -{ - int rc = IOT_Shadow_Get(NULL, onRequestCallback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -TEST_F(ShadowNullFieldsTest, NullClientShadowUpdate) -{ - int rc = IOT_Shadow_Update(NULL, jsonFullDocument, 200, onRequestCallback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -TEST_F(ShadowNullFieldsTest, NullClientShadowDelete) -{ -// int rc = IOT_Shadow_Delete(NULL, onRequestCallback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); -// ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdk-tests/unit_test/src/unit_shadow_test.cpp b/sdk-tests/unit_test/src/unit_shadow_test.cpp deleted file mode 100644 index ef8e5b4e..00000000 --- a/sdk-tests/unit_test/src/unit_shadow_test.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include - -#include "unit_helper_functions.h" -#include "qcloud_iot_export_shadow.h" -#include "qcloud_iot_export_error.h" -#include "qcloud_iot_import.h" -#include "shadow_client.h" - - -#define SIZE_OF_UPDATE_DOCUMENT 200 -#define TEST_JSON_RESPONSE_FULL_DOCUMENT "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" QCLOUD_IOT_MY_PRODUCT_ID "-1\"}" -#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" QCLOUD_IOT_MY_PRODUCT_ID "-1\"}" - - -static Qcloud_IoT_Shadow *sg_pshadow; -static ShadowInitParams sg_initParams; - -static RequestAck sg_ack_status_rx; -static Method sg_method_rx; -static char sg_json_full_document[200]; - -using namespace std; - -static void on_request_callback(void *pClient, Method method, RequestAck status, const char *pReceivedJsonDocument, void *pUserdata) -{ - sg_method_rx = method; - sg_ack_status_rx = status; - if (ACK_NONE != status) { - char* clientTokenString; - char* stateString; - - char* pReceivedJsonDocument_bak = (char*)HAL_Malloc(strlen(pReceivedJsonDocument)); - if (pReceivedJsonDocument_bak == NULL) { - return; - } - strcpy(pReceivedJsonDocument_bak, pReceivedJsonDocument); - - if (parse_shadow_state(pReceivedJsonDocument_bak, &stateString) && - parse_client_token(pReceivedJsonDocument_bak, &clientTokenString)) { - HAL_Snprintf(sg_json_full_document, SIZE_OF_JSON_BUFFER, "{\"state\":%s, \"clientToken\":\"%s\"}", stateString, clientTokenString); - } - } -} - -static void get_the_full_document_callback(void *pClient, Method method, RequestAck status, const char *pReceivedJsonDocument, void *pUserdata) -{ - sg_method_rx = method; - sg_ack_status_rx = status; - Log_d("method = %d|status = %d", sg_method_rx, sg_ack_status_rx); -} - -class ShadowTest : public testing::Test -{ -protected: - virtual void SetUp() - { - IOT_Log_Set_Level(DEBUG); - sg_ack_status_rx = ACK_NONE; - - SetupShadowConnectInitParams(&sg_initParams); - - void *client = IOT_Shadow_Construct(&sg_initParams); - sg_pshadow = (Qcloud_IoT_Shadow *)client; - } - - virtual void TearDown() - { - if (NULL != sg_pshadow) - IOT_Shadow_Destroy(sg_pshadow); - } -}; - - -TEST_F(ShadowTest, ShadowIsConnected) -{ - bool isConnected = IOT_Shadow_IsConnected(sg_pshadow); - - ASSERT_EQ(true, isConnected); -} - -TEST_F(ShadowTest, ShadowDestroy) -{ - bool isConnected = IOT_Shadow_IsConnected((void *)sg_pshadow); - ASSERT_EQ(true, isConnected); - - int rc = IOT_Shadow_Destroy(sg_pshadow); - sg_pshadow = NULL; - ASSERT_TRUE(rc == 0); -} - -TEST_F(ShadowTest, GetTheFullJSONDocument) -{ - int ret_val; - - char deltaJSONString[SIZE_OF_JSON_BUFFER] = {0}; - DeviceProperty property; - int intData = 98; - property.key = (char*)"sensor1"; - property.type = JINT16; - property.data = &intData; - ret_val = IOT_Shadow_JSON_ConstructReport(sg_pshadow, deltaJSONString, SIZE_OF_JSON_BUFFER, 1, &property); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - ret_val = IOT_Shadow_Update(sg_pshadow, deltaJSONString, SIZE_OF_JSON_BUFFER, get_the_full_document_callback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - while (sg_ack_status_rx == ACK_NONE) { - Log_d("wait for sub ack!"); - ret_val = IOT_Shadow_Yield(sg_pshadow, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - sleep(1); - } - sg_ack_status_rx = ACK_NONE; - - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - while (sg_ack_status_rx == ACK_NONE) { - ret_val = IOT_Shadow_Yield(sg_pshadow, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - sleep(1); - } - - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - ASSERT_STREQ(TEST_JSON_RESPONSE_FULL_DOCUMENT, sg_json_full_document); - ASSERT_EQ(GET, sg_method_rx); - ASSERT_EQ(ACK_ACCEPTED, sg_ack_status_rx); -} - -TEST_F(ShadowTest, UpdateTheJSONDocument) -{ - int ret_val; - char updateRequestJson[SIZE_OF_UPDATE_DOCUMENT] = {0}; - char expectedUpdateRequestJson[SIZE_OF_UPDATE_DOCUMENT] = {0}; - - double doubleData = 4.090800f; - float floatData = 3.44500f; - - DeviceProperty dataFloatHandler; - DeviceProperty dataDoubleHandler; - - dataFloatHandler.data = &floatData; - dataFloatHandler.key = (char*)"floatData"; - dataFloatHandler.type = JFLOAT; - - dataDoubleHandler.data = &doubleData; - dataDoubleHandler.key = (char*)"doubleData"; - dataDoubleHandler.type = JDOUBLE; - - ret_val = IOT_Shadow_Get_Sync(sg_pshadow, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - ret_val = IOT_Shadow_JSON_ConstructReport(sg_pshadow, updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 2, &dataDoubleHandler, &dataFloatHandler); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - snprintf(expectedUpdateRequestJson, SIZE_OF_UPDATE_DOCUMENT, - "{\"version\":%d, \"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"%s-1\"}", - sg_pshadow->inner_data.version, QCLOUD_IOT_MY_PRODUCT_ID); - ASSERT_STREQ(expectedUpdateRequestJson, updateRequestJson); - - ret_val = IOT_Shadow_Update(sg_pshadow, updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, on_request_callback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - while (sg_ack_status_rx == ACK_NONE) { - ret_val = IOT_Shadow_Yield(sg_pshadow, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - sleep(1); - } - - ASSERT_STREQ(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, sg_json_full_document); - ASSERT_EQ(UPDATE, sg_method_rx); - ASSERT_EQ(ACK_ACCEPTED, sg_ack_status_rx); -} - -TEST_F(ShadowTest, ACKWaitingMoreThanAllowed) -{ - int ret_val; - - uint32_t time_out = 100 * 1000; - - // 1st - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 2nd - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 3rd - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 4th - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 5th - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 6th - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 7th - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 8th - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 9th - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 10th - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_SUCCESS, ret_val); - - // 11th - // Should return some error code, since we are running out of ACK space - ret_val = IOT_Shadow_Get(sg_pshadow, on_request_callback, NULL, time_out);// 100 sec to timeout - ASSERT_EQ(QCLOUD_ERR_MAX_APPENDING_REQUEST, ret_val); -} - -// TODO: -// 1.如果update的字符串不符合json格式是否能提示处理 -// 2.当设备update的数据过长的时候是否能正确处理过长的数据 -// 3.当设备shadow get回来的数据很大的时候是否能正确处理 - - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdk-tests/unit_test/src/unit_subscribe_test.cpp b/sdk-tests/unit_test/src/unit_subscribe_test.cpp deleted file mode 100644 index 61119ee5..00000000 --- a/sdk-tests/unit_test/src/unit_subscribe_test.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include "qcloud_iot_export.h" - -static MQTTConnectParams connectParams; -static MQTTInitParams initParams; - -static PublishParams testPubMsgParams; -static SubscribeParams testSubParams; - -static Qcloud_IoT_Client client; - -static char subTopic[32] = "A58FGENPD7/Air_0/Test0"; -static char CallbackMsgString[100]; -char cPayload[100]; - -static char CallbackMsgString1[100] = {"XXXX"}; -static char CallbackMsgString2[100] = {"XXXX"}; -static char CallbackMsgString3[100] = {"XXXX"}; -static char CallbackMsgString4[100] = {"XXXX"}; -static char CallbackMsgString5[100] = {"XXXX"}; -static char CallbackMsgString6[100] = {"XXXX"}; - -static bool sg_callback_status1 = false; -static bool sg_callback_status2 = false; -static bool sg_callback_status3 = false; -static bool sg_callback_status4 = false; -static bool sg_callback_status5 = false; -static bool sg_callback_status6 = false; - - -static void iot_subscribe_callback_handler(void *pClient, MQTTMessage *params, void *pUserdata) { - - if (params == NULL) { - return; - } - - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void -iot_subscribe_callback_handler1(void *pClient, MQTTMessage *params, void *pUserdata) { - if (params == NULL) { - return; - } - - char *tmp = (char *)params->payload; - unsigned int i; - - printf("callback topic %.*s\n", (int) params->topic_len, params->ptopic); - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString1[i] = tmp[i]; - } - sg_callback_status1 = true; -} - -static void -iot_subscribe_callback_handler2(void *pClient, MQTTMessage *params, void *pUserdata) { - if (params == NULL) { - return; - } - - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString2[i] = tmp[i]; - } - sg_callback_status2 = true; -} - -static void -iot_subscribe_callback_handler3(void *pClient, MQTTMessage *params, void *pUserdata) { - if (params == NULL) { - return; - } - - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString3[i] = tmp[i]; - } - sg_callback_status3 = true; -} - -static void -iot_subscribe_callback_handler4(void *pClient, MQTTMessage *params, void *pUserdata) { - if (params == NULL) { - return; - } - - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString4[i] = tmp[i]; - } - sg_callback_status4 = true; -} - -static void -iot_subscribe_callback_handler5(void *pClient, MQTTMessage *params, void *pUserdata) { - if (params == NULL) { - return; - } - - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString5[i] = tmp[i]; - } - sg_callback_status5 = true; -} - -static void -iot_subscribe_callback_handler6(void *pClient, MQTTMessage *params, void *pUserdata) { - if (params == NULL) { - return; - } - - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString6[i] = tmp[i]; - } - sg_callback_status6 = true; -} - -static void -event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_PUBLISH_RECVEIVED: - break; - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - // if (strcmp(topic, sg_topic1) == 0) { - // sg_event_handler_status1 = true; - // } else if (strcmp(topic, sg_topic2) == 0) { - // sg_event_handler_status2 = true; - // } else if (strcmp(topic, sg_topic3) == 0) { - // sg_event_handler_status3 = true; - // } else if (strcmp(topic, sg_topic4) == 0) { - // sg_event_handler_status4 = true; - // } else if (strcmp(topic, sg_topic5) == 0) { - // sg_event_handler_status5 = true; - // } else if (strcmp(topic, sg_topic6) == 0) { - // sg_event_handler_status6 = true; - // } - break; - - case MQTT_EVENT_UNSUBCRIBE_SUCCESS: - Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_NACK: - Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } -} - -class SubscribeTests : public testing::Test -{ -protected: - virtual void SetUp() - { - std::cout << "SubscribeTests Test Begin \n"; - - IOT_Log_Set_Level(DEBUG); - - int rc; - MQTTInitParamsSetup(&initParams, false); - initParams.event_handle.h_fp = event_handler; - rc = qcloud_iot_mqtt_init(&client, &initParams); - if (rc != QCLOUD_ERR_SUCCESS) - { - std::cout << "qcloud_iot_mqtt_init fail \n"; - } - - ConnectParamsSetup(&connectParams, &initParams); - - rc = qcloud_iot_mqtt_connect(&client, &connectParams); - - if (rc != QCLOUD_ERR_SUCCESS) - { - std::cout << "!qcloud_iot_mqtt_connect fail \n"; - } else { - std::cout << "!qcloud_iot_mqtt_connect success \n"; - } - - testPubMsgParams.qos = QOS1; - testPubMsgParams.retained = 0; - snprintf(cPayload, 100, "%s : %d ", (char *)"hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payload_len = strlen(cPayload); - - testSubParams.qos = QOS1; - testSubParams.on_message_handler = iot_subscribe_callback_handler; - - } - virtual void TearDown() - { - std::cout << "SubscribeTests Test End \n"; - int rc = qcloud_iot_mqtt_disconnect(&client); - if (rc != QCLOUD_ERR_SUCCESS) { - std::cout << "qcloud_iot_mqtt_disconnect fail \n"; - } - } - -}; - -/* C:1 - Subscribe with Null/empty Client Instance */ -TEST_F(SubscribeTests, SubscribeNullClient) { - int rc = qcloud_iot_mqtt_subscribe(NULL, subTopic, &testSubParams); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* C:2 - Subscribe with Null/empty Topic Name */ -TEST_F(SubscribeTests, SubscribeNullTopic) { - int rc = qcloud_iot_mqtt_subscribe(&client, NULL, &testSubParams); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); - - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"", &testSubParams); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* C:3 - Subscribe with Null client callback */ -// TEST_F(SubscribeTests, SubscribeNullSubscribeHandler) { -// testSubParams.on_message_handler = NULL; -// int rc = qcloud_iot_mqtt_subscribe(&client, subTopic, &testSubParams); -// ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -// } - -/* C:4 - Subscribe with Null subParams*/ -TEST_F(SubscribeTests, SubscribeNullParams) { - int rc = qcloud_iot_mqtt_subscribe(&client, subTopic, NULL); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* C:5 - Subscribe with no connection */ -TEST_F(SubscribeTests, SubscribeNoConnection) { - /* Disconnect first */ - int rc = qcloud_iot_mqtt_disconnect(&client); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - rc = qcloud_iot_mqtt_subscribe(&client, subTopic, &testSubParams); - ASSERT_EQ(QCLOUD_ERR_MQTT_NO_CONN, rc); -} - -/* C:6 - Subscribe, multiple topics, messages on each topic */ -TEST_F(SubscribeTests, SubscribeToMultipleTopicsSuccess) { - int rc; - char expectedCallbackString[] = ""; - - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test1", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler2; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test2", &testSubParams); - - ASSERT_TRUE(0 < rc); - - int count = 10; - while (count) { - rc = qcloud_iot_mqtt_yield(&client, 200); - count--; - sleep(0.5); - } - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - ASSERT_STREQ(expectedCallbackString, CallbackMsgString); -} - -/* C:7 - Subscribe, max topics, messages on each topic */ -TEST_F(SubscribeTests, SubcribeToMaxAllowedTopicsSuccess) { - int rc; - char expectedCallbackString[] = "XXXX"; - char expectedCallbackString2[] = "XXXX"; - char expectedCallbackString3[] = "XXXX"; - char expectedCallbackString4[] = "XXXX"; - char expectedCallbackString5[] = "XXXX"; - - testSubParams.on_message_handler = iot_subscribe_callback_handler1; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test1", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler2; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test2", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler3; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test3", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler4; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test4", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler5; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test5", &testSubParams); - ASSERT_TRUE(0 < rc); - - /* - rc = qcloud_iot_mqtt_yield(&client, 1000); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - rc = qcloud_iot_mqtt_yield(&client, 1000); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - rc = qcloud_iot_mqtt_yield(&client, 1000); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - rc = qcloud_iot_mqtt_yield(&client, 1000); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - rc = qcloud_iot_mqtt_yield(&client, 1000); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - */ - - int count = 10; - while (count) { - rc = qcloud_iot_mqtt_yield(&client, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - count--; - sleep(0.2); - } - - ASSERT_STREQ(expectedCallbackString, CallbackMsgString1); - ASSERT_STREQ(expectedCallbackString2, CallbackMsgString2); - ASSERT_STREQ(expectedCallbackString3, CallbackMsgString3); - ASSERT_STREQ(expectedCallbackString4, CallbackMsgString4); - ASSERT_STREQ(expectedCallbackString5, CallbackMsgString5); - -} - -/* C:8 - Subscribe, max topics, another subscribe */ -TEST_F(SubscribeTests, SubcribeToMaxPlusOneAllowedTopicsFailure) { - int rc; - - testSubParams.on_message_handler = iot_subscribe_callback_handler1; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test1", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler2; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test2", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler3; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test3", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler4; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test4", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler5; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test5", &testSubParams); - ASSERT_TRUE(0 < rc); - - testSubParams.on_message_handler = iot_subscribe_callback_handler6; - rc = qcloud_iot_mqtt_subscribe(&client, (char *)"A58FGENPD7/Air_0/Test6", &testSubParams); - ASSERT_EQ(QCLOUD_ERR_MQTT_MAX_SUBSCRIPTIONS, rc); -} - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdk-tests/unit_test/src/unit_unsubscribe_test.cpp b/sdk-tests/unit_test/src/unit_unsubscribe_test.cpp deleted file mode 100644 index d47c3f50..00000000 --- a/sdk-tests/unit_test/src/unit_unsubscribe_test.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include - -#include -#include - -static MQTTInitParams initParams; -static PublishParams testPubMsgParams; -static SubscribeParams testSubParams; - -static Qcloud_IoT_Client iotClient; -static char CallbackMsgString[100]; -char cPayload[100]; - -static char *sg_topic0 = (char *)"A58FGENPD7/Air_0/Test0"; - -static MQTTEventType sg_callback_status0 = MQTT_EVENT_UNDEF; -static MQTTEventType sg_callback_status1 = MQTT_EVENT_UNDEF; -static MQTTEventType sg_callback_status2 = MQTT_EVENT_UNDEF; -static MQTTEventType sg_callback_status3 = MQTT_EVENT_UNDEF; -static MQTTEventType sg_callback_status4 = MQTT_EVENT_UNDEF; -static MQTTEventType sg_callback_status5 = MQTT_EVENT_UNDEF; -static MQTTEventType sg_callback_status6 = MQTT_EVENT_UNDEF; - -static bool sg_time_out_status = false; - -static int sg_packet_id_0 = 0; -static int sg_packet_id_1 = 0; -static int sg_packet_id_2 = 0; -static int sg_packet_id_3 = 0; -static int sg_packet_id_4 = 0; -static int sg_packet_id_5 = 0; -static int sg_packet_id_6 = 0; - -static bool sg_has_call_sub_handler = false; - -static void handle_callback_status_in_event(int packetId, MQTTEventType type) -{ - if (packetId == sg_packet_id_0) { - sg_callback_status0 = type; - } else if (packetId == sg_packet_id_1) { - sg_callback_status1 = type; - } else if (packetId == sg_packet_id_2) { - sg_callback_status2 = type; - } else if (packetId == sg_packet_id_3) { - sg_callback_status3 = type; - } else if (packetId == sg_packet_id_4) { - sg_callback_status4 = type; - } else if (packetId == sg_packet_id_5) { - sg_callback_status5 = type; - } else if (packetId == sg_packet_id_6) { - sg_callback_status6 = type; - } -} - -static void reset_all_status(void) -{ - sg_packet_id_0 = 0; - sg_packet_id_1 = 0; - sg_packet_id_2 = 0; - sg_packet_id_3 = 0; - sg_packet_id_4 = 0; - sg_packet_id_5 = 0; - sg_packet_id_6 = 0; - - sg_callback_status0 = MQTT_EVENT_UNDEF; - sg_callback_status1 = MQTT_EVENT_UNDEF; - sg_callback_status2 = MQTT_EVENT_UNDEF; - sg_callback_status3 = MQTT_EVENT_UNDEF; - sg_callback_status4 = MQTT_EVENT_UNDEF; - sg_callback_status5 = MQTT_EVENT_UNDEF; - sg_callback_status6 = MQTT_EVENT_UNDEF; -} - -static void iot_subscribe_callback_handler(void *pClient, MQTTMessage *params, void *pUserdata) -{ - sg_has_call_sub_handler = true; - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler1(void *pClient, MQTTMessage *params, void *pUserdata) { - - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < (params->payload_len); i++) { - CallbackMsgString[i] = tmp[i]; - } - Log_d("tmp=%s|payload_len=%u", tmp, params->payload_len); -} - -static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_i("undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_i("MQTT disconnect."); - break; - - case MQTT_EVENT_RECONNECT: - Log_i("MQTT reconnect."); - break; - - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_SUCCESS: - Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); - sg_time_out_status = true; - break; - - case MQTT_EVENT_UNSUBCRIBE_NACK: - Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_SUCCESS: - Log_i("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_TIMEOUT: - Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case MQTT_EVENT_PUBLISH_NACK: - Log_i("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - default: - Log_i("Should NOT arrive here."); - break; - } - handle_callback_status_in_event((int)packet_id, msg->event_type); -} - -class UnsubscribeTests : public testing::Test -{ -protected: - virtual void SetUp() - { - std::cout << "UnsubscribeTests Test Begin \n"; - - IOT_Log_Set_Level(DEBUG); - reset_all_status(); - - int rc; - MQTTInitParamsSetup(&initParams, false); - initParams.event_handle.h_fp = event_handler; - rc = qcloud_iot_mqtt_init(&iotClient, &initParams); - if (QCLOUD_ERR_SUCCESS != rc) - Log_e("qcloud_iot_mqtt_init fail!!"); - - ConnectParamsSetup(&iotClient.options, &initParams); - rc = qcloud_iot_mqtt_connect(&iotClient, &iotClient.options); - if (QCLOUD_ERR_SUCCESS != rc) - Log_e("qcloud_iot_mqtt_connect fail!!"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.retained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payload_len = strlen(cPayload); - - testSubParams.qos = QOS1; - testSubParams.on_message_handler = iot_subscribe_callback_handler; - - } - virtual void TearDown() - { - std::cout << "UnsubscribeTests Test End \n"; - } - -}; - -/* D:1 - Unsubscribe with Null/empty client instance */ -TEST_F(UnsubscribeTests, UnsubscribeNullClient) -{ - int rc = qcloud_iot_mqtt_unsubscribe(NULL, sg_topic0); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* D:2 - Unsubscribe with Null/empty topic name */ -TEST_F(UnsubscribeTests, UnsubscribeNullTopic) { - int rc = qcloud_iot_mqtt_unsubscribe(&iotClient, NULL); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* D:3 - Unsubscribe, Not subscribed to topic */ -TEST_F(UnsubscribeTests, UnsubscribeNotSubscribed) { - int rc = qcloud_iot_mqtt_unsubscribe(&iotClient, sg_topic0); - ASSERT_EQ(QCLOUD_ERR_FAILURE, rc); -} - -/* D:4 - Unsubscribe, QoS0, No response, timeout */ -TEST_F(UnsubscribeTests, UnsubscribeQoS0FailureOnNoUnsuback) { - int rc; - - // First, subscribe to a topic - testSubParams.qos = QOS0; - rc = qcloud_iot_mqtt_subscribe(&iotClient, sg_topic0, &testSubParams); - if (rc > 0) { - // Then, unsubscribe - rc = qcloud_iot_mqtt_unsubscribe(&iotClient, sg_topic0); - ASSERT_EQ(QCLOUD_ERR_MQTT_REQUEST_TIMEOUT, rc); - } -} - -/* D:5 - Unsubscribe, QoS1, No response, timeout */ -TEST_F(UnsubscribeTests, UnsubscribeQoS1FailureOnNoUnsuback) { - int rc; - - // First, subscribe to a topic - testSubParams.qos = QOS1; - rc = qcloud_iot_mqtt_subscribe(&iotClient, sg_topic0, &testSubParams); - if (rc > 0) { - // Then, unsubscribe - while (sg_packet_id_0 != rc) { - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - sleep(0.2); - } - - rc = qcloud_iot_mqtt_unsubscribe(&iotClient, sg_topic0); - while (sg_time_out_status == false) { - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(7); - } - ASSERT_TRUE(sg_time_out_status == true); - } - -} - -/* D:6 - Unsubscribe, QoS0, success */ -TEST_F(UnsubscribeTests, UnsubscribeQoS0WithUnsubackSuccess) { - int rc; - - // First, subscribe to a topic - testSubParams.qos = QOS0; - rc = qcloud_iot_mqtt_subscribe(&iotClient, sg_topic0, &testSubParams); - if (rc > 0) { - sg_packet_id_0 = rc; - // Then, unsubscribe - while (sg_callback_status0 == MQTT_EVENT_UNDEF) { - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - sg_callback_status0 = MQTT_EVENT_UNDEF; - - sg_packet_id_0 = qcloud_iot_mqtt_unsubscribe(&iotClient, sg_topic0); - while(sg_callback_status0 == MQTT_EVENT_UNDEF) { - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - ASSERT_EQ(sg_callback_status0, MQTT_EVENT_UNSUBCRIBE_SUCCESS); - } -} - -// /* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */ -// TEST_F(UnsubscribeTests, UnsubscribeQoS0WithDelayedUnsubackSuccess) { -// int rc; - -// // First, subscribe to a topic -// testSubParams.qos = QOS0; -// rc = qcloud_iot_mqtt_subscribe(&iotClient, sg_topic0, &testSubParams); -// if (rc > 0) { -// rc = qcloud_iot_mqtt_unsubscribe(&iotClient, sg_topic0); -// ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); -// } - -// } - -/* D:8 - Unsubscribe, QoS1, success */ -TEST_F(UnsubscribeTests, UnsubscribeQoS1WithUnsubackSuccess) { - int rc; - - // First, subscribe to a topic - testSubParams.qos = QOS1; - rc = qcloud_iot_mqtt_subscribe(&iotClient, sg_topic0, &testSubParams); - if (rc > 0) { - // Then, unsubscribe - sg_packet_id_0 = rc; - while (sg_callback_status0 == MQTT_EVENT_UNDEF) { - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - sg_callback_status0 = MQTT_EVENT_UNDEF; - - sg_packet_id_0 = qcloud_iot_mqtt_unsubscribe(&iotClient, sg_topic0); - while(sg_callback_status0 == MQTT_EVENT_UNDEF) { - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - ASSERT_EQ(sg_callback_status0, MQTT_EVENT_UNSUBCRIBE_SUCCESS); - } -} - -/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */ -// TEST_F(UnsubscribeTests, UnsubscribeQoS1WithDelayedUnsubackSuccess) { -// int rc; - -// // First, subscribe to a topic -// testSubParams.qos = QOS1; -// rc = qcloud_iot_mqtt_subscribe(&iotClient, sg_topic0, &testSubParams); -// if (rc > 0) { -// rc = qcloud_iot_mqtt_unsubscribe(&iotClient, sg_topic0); -// ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); -// } - -// } - -/* D:10 - Unsubscribe, success, message on topic ignored - * 1. Subscribe to topic 1 - * 2. Send message and receive it - * 3. Unsubscribe to topic 1 - * 4. Should not receive message - */ -TEST_F(UnsubscribeTests, MsgAfterUnsubscribe) { - int rc; - char expectedCallbackString[100]; - - // 1. - testSubParams.qos = QOS0; - testSubParams.on_message_handler = iot_subscribe_callback_handler; - rc = qcloud_iot_mqtt_subscribe(&iotClient, sg_topic0, &testSubParams); - ASSERT_TRUE(rc > 0); - sg_packet_id_0 = rc; - while (sg_callback_status0 == MQTT_EVENT_UNDEF) { - // 2. - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - snprintf(expectedCallbackString, 100, "%s", (char *)""); - ASSERT_STREQ(expectedCallbackString, CallbackMsgString); - sg_callback_status0 = MQTT_EVENT_UNDEF; - - //3. - rc = qcloud_iot_mqtt_unsubscribe(&iotClient, sg_topic0); - ASSERT_TRUE(rc > 0); - sg_packet_id_0 = rc; - while (sg_callback_status0 == MQTT_EVENT_UNDEF) { - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - sg_callback_status0 = MQTT_EVENT_UNDEF; - //reset the string - snprintf(CallbackMsgString, 100, "%s", " "); - - // 4. - // Have a new message published to that topic coming in - snprintf(expectedCallbackString, 100, "%s", (char *)""); - - char *pub_payload = (char *)"Have a new message published to that topic coming in"; - PublishParams pub_msg_params; - pub_msg_params.qos = QOS1; - pub_msg_params.retained = 0; - pub_msg_params.payload = (void *)pub_payload; - pub_msg_params.payload_len = strlen(pub_payload); - rc = qcloud_iot_mqtt_publish(&iotClient, sg_topic0, &pub_msg_params); - sg_packet_id_0 = rc; - ASSERT_TRUE(rc > 0); - while (sg_callback_status0 == MQTT_EVENT_UNDEF) { - rc = qcloud_iot_mqtt_yield(&iotClient, 200); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - // No new msg was received - ASSERT_STREQ(" ", CallbackMsgString); -} - -/* D:11 - Unsubscribe after max topics reached - * 1. Subscribe to max topics + 1 fail for last subscription - * 2. Unsubscribe from one topic - * 3. Subscribe again and should have no error - * 4. Receive msg test - last subscribed topic - */ -TEST_F(UnsubscribeTests, MaxTopicsSubscription) { - int rc; - int i; - char topics[MAX_MESSAGE_HANDLERS + 1][100]; - char expectedCallbackString[] = "MaxTopicsSubscription"; - - // 1. - for (i = 0; i < MAX_MESSAGE_HANDLERS; i++) { - snprintf(topics[i], 100, "A58FGENPD7/Air_0/Test%d", i); - testSubParams.qos = QOS0; - testSubParams.on_message_handler = iot_subscribe_callback_handler1; - rc = qcloud_iot_mqtt_subscribe(&iotClient, topics[i], &testSubParams); - if (i == 0) sg_packet_id_0 = rc; - sleep(0.5); - ASSERT_TRUE(0 < rc); - } - - snprintf(topics[i], 100, "A58FGENPD7/Air_0/Test%d", i); - testSubParams.qos = QOS0; - testSubParams.on_message_handler = iot_subscribe_callback_handler1; - rc = qcloud_iot_mqtt_subscribe(&iotClient, topics[i], &testSubParams); - ASSERT_EQ(QCLOUD_ERR_MQTT_MAX_SUBSCRIPTIONS, rc); - - while (sg_callback_status0 == MQTT_EVENT_UNDEF) { - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - sg_callback_status0 = MQTT_EVENT_UNDEF; - - // 2. - rc = qcloud_iot_mqtt_unsubscribe(&iotClient, topics[0]); - ASSERT_TRUE(0 < rc); - unsigned int count = 0; - while (count < 5) { - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - count++; - sleep(0.5); - } - - //3. - rc = qcloud_iot_mqtt_subscribe(&iotClient, topics[0], &testSubParams); - ASSERT_TRUE(0 < rc); - - count = 0; - while (count < 5) { - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - count++; - sleep(0.5); - } - - char *pub_payload = expectedCallbackString; - PublishParams pub_msg_params; - pub_msg_params.qos = QOS1; - pub_msg_params.retained = 0; - pub_msg_params.payload = (void *)pub_payload; - pub_msg_params.payload_len = strlen(expectedCallbackString); - rc = qcloud_iot_mqtt_publish(&iotClient, sg_topic0, &pub_msg_params); - sg_packet_id_0 = rc; - ASSERT_TRUE(rc > 0); - count = 0; - while (count < 5) { - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - count++; - sleep(0.5); - } - - //4. - ASSERT_STREQ(expectedCallbackString, CallbackMsgString); -} - -/* D:12 - Repeated Subscribe and Unsubscribe - * 1. subscribe and unsubscribe for more than the max subscribed topic - * 2. ensure every time the subscribed topic msg is received - */ -TEST_F(UnsubscribeTests, RepeatedSubUnSub) { - int i; - char expectedCallbackString[100]; - char topics[MAX_MESSAGE_HANDLERS][100]; - - for (i = 0; i < MAX_MESSAGE_HANDLERS; i++) { - //1. - int rc; - snprintf(topics[i], 100, "A58FGENPD7/Air_0/Test%d", i); - testSubParams.qos = QOS0; - testSubParams.on_message_handler = iot_subscribe_callback_handler; - rc = qcloud_iot_mqtt_subscribe(&iotClient, topics[i], &testSubParams); - ASSERT_TRUE(0 < rc); - - sg_packet_id_0 = rc; - sg_callback_status0 = MQTT_EVENT_UNDEF; - while (sg_callback_status0 != MQTT_EVENT_SUBCRIBE_SUCCESS) { - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - - sprintf(expectedCallbackString, "%s%d", "expectedCallbackString", i); - char *pub_payload = expectedCallbackString; - PublishParams pub_msg_params; - pub_msg_params.qos = QOS1; - pub_msg_params.retained = 0; - pub_msg_params.payload = (void *)pub_payload; - pub_msg_params.payload_len = strlen(expectedCallbackString); - rc = qcloud_iot_mqtt_publish(&iotClient, topics[i], &pub_msg_params); - ASSERT_TRUE(0 < rc); - sg_packet_id_0 = rc; - sg_callback_status0 = MQTT_EVENT_UNDEF; - while (sg_has_call_sub_handler == false) { - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - ASSERT_STREQ(expectedCallbackString, CallbackMsgString); - memset(CallbackMsgString, 0x0, 100); - - //2. - rc = qcloud_iot_mqtt_unsubscribe(&iotClient, topics[i]); - ASSERT_TRUE(0 < rc); - sg_packet_id_0 = rc; - sg_callback_status0 = MQTT_EVENT_UNDEF; - while (sg_callback_status0 != MQTT_EVENT_UNSUBCRIBE_SUCCESS) { - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - sleep(1); - } - - sg_has_call_sub_handler = false; - ASSERT_TRUE(sg_callback_status0 == MQTT_EVENT_UNSUBCRIBE_SUCCESS); - } - -} - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdk-tests/unit_test/src/unit_yield_test.cpp b/sdk-tests/unit_test/src/unit_yield_test.cpp deleted file mode 100644 index b613cfc8..00000000 --- a/sdk-tests/unit_test/src/unit_yield_test.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include - -#include -#include -#include "iot_unit_config.h" - - -static MQTTInitParams initParams; -static MQTTConnectParams connectParams; - -static Qcloud_IoT_Client iotClient; - -static PublishParams testPubMsgParams; -static SubscribeParams testSubParams; - -static char CallbackMsgString[100]; -static char subTopic[SIZE_OF_JSON_BUFFER] = "sdk/Test"; -static uint16_t subTopicLen = SIZE_OF_JSON_BUFFER; - -static bool dcHandlerInvoked = false; - -static void iot_tests_unit_acr_subscribe_callback_handler(void *pClient, MQTTMessage *params, void *pUserdata) { - char *tmp = (char *)params->payload; - unsigned int i; - subTopicLen = 9; - for (i = 0; i < params->payload_len; i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void iot_tests_unit_yield_test_subscribe_callback_handler(void *pClient, MQTTMessage *params, void *pUserdata) -{ - char *tmp = (char *)params->payload; - unsigned int i; - - for (i = 0; i < params->payload_len; i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -void iot_tests_unit_disconnect_handler(void) -{ - dcHandlerInvoked = true; -} - -void event_handle(void *pcontext, void *pclient, MQTTEventMsg *msg) -{ - switch (msg->event_type) { - case MQTT_EVENT_UNDEF: - Log_d("MQTT_EVENT_UNDEF|undefined event occur."); - break; - - case MQTT_EVENT_DISCONNECT: - Log_d("MQTT_EVENT_DISCONNECT|MQTT disconnect."); - iot_tests_unit_disconnect_handler(); - break; - - default: - Log_d("Should NOT arrive here."); - break; - } -} - -class YieldTests : public testing::Test -{ -protected: - virtual void SetUp() - { - std::cout << "YieldTests Test Begin \n"; - - int rc; - dcHandlerInvoked = false; - - MQTTInitParamsSetup(&initParams, false); - initParams.event_handle.h_fp = event_handle; - rc = qcloud_iot_mqtt_init(&iotClient, &initParams); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - ConnectMQTTParamsSetup_Detailed(&connectParams, &initParams, QOS1, false, true, (char *)"willTopicName", (char *)"willMsg", NULL); - initParams.keep_alive_interval_ms = 5000; - - HAL_Snprintf(subTopic, subTopicLen, "%s/%s/get", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME); - - // void * client = IOT_MQTT_Construct(&initParams); - // iotClient = *((Qcloud_IoT_Client *)client); - // ASSERT_TRUE(client != NULL); - rc = qcloud_iot_mqtt_connect(&iotClient, &connectParams); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - rc = qcloud_iot_mqtt_set_autoreconnect(&iotClient, false); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - } - virtual void TearDown() - { - std::cout << "YieldTests Test End \n"; - qcloud_iot_mqtt_disconnect(&iotClient); - sleep(1); - } - -}; - - -/* G:1 - Yield with Null/empty Client Instance */ -TEST_F(YieldTests, NullClientYield) { - int rc = qcloud_iot_mqtt_yield(NULL, 1000); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* G:2 - Yield with zero yield timeout */ -TEST_F(YieldTests, ZeroTimeoutYield) { - int rc = qcloud_iot_mqtt_yield(&iotClient, 0); - ASSERT_EQ(QCLOUD_ERR_INVAL, rc); -} - -/* G:3 - Yield, network disconnected, never connected */ -TEST_F(YieldTests, YieldNetworkDisconnectedNeverConnected) { - Qcloud_IoT_Client tempIotClient; - int rc; - - MQTTInitParamsSetup(&initParams, false); - rc = qcloud_iot_mqtt_init(&tempIotClient, &initParams); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - rc = qcloud_iot_mqtt_yield(&tempIotClient, 1000); - ASSERT_EQ(QCLOUD_ERR_MQTT_NO_CONN, rc); -} - -/* G:4 - Yield, network disconnected, disconnected manually */ -TEST_F(YieldTests, YieldNetworkDisconnectedDisconnectedManually) { - int rc = qcloud_iot_mqtt_disconnect(&iotClient); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - rc = qcloud_iot_mqtt_yield(&iotClient, 1000); - ASSERT_EQ(QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED, rc); -} - -/* G:5 - Yield, network connected, yield called while in subscribe application callback */ -TEST_F(YieldTests, YieldInSubscribeCallback) { - int rc; - - testSubParams.qos = QOS1; - testSubParams.on_message_handler = iot_tests_unit_yield_test_subscribe_callback_handler; - rc = qcloud_iot_mqtt_subscribe(&iotClient, subTopic, &testSubParams); - if (0 < rc) { - testPubMsgParams.qos = QOS1; - rc = qcloud_iot_mqtt_yield(&iotClient, 1000); - if (QCLOUD_ERR_SUCCESS == rc) { - char expectedCallbackString[] = "0xA5A5A3"; - ASSERT_STREQ(expectedCallbackString, CallbackMsgString); - } - } - -} - -/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */ -TEST_F(YieldTests, disconnectNoAutoReconnect) { - int rc; - - rc = qcloud_iot_mqtt_set_autoreconnect(&iotClient, true); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - ASSERT_EQ(true, IOT_MQTT_IsConnected(&iotClient)); - ASSERT_EQ(true, qcloud_iot_mqtt_is_autoreconnect_enabled(&iotClient)); - - /* Disable Autoreconnect, then let ping request time out and call yield */ - qcloud_iot_mqtt_set_autoreconnect(&iotClient, false); - sleep((uint16_t) (iotClient.options.keep_alive_interval - 1)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - // sleep(iotClient.options.keep_alive_interval); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - /* Let ping request time out and call yield */ - sleep(iotClient.options.keep_alive_interval + 1); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_MQTT_NO_CONN, rc); - ASSERT_EQ(0, IOT_MQTT_IsConnected(&iotClient)); - ASSERT_EQ(true, dcHandlerInvoked); -} - -/* G:7 - Yield, network connected, no incoming messages */ -TEST_F(YieldTests, YieldSuccessNoMessages) { - int rc; - int i; - - for (i = 0; i < 100; i++) { - CallbackMsgString[i] = 'x'; - } - - rc = qcloud_iot_mqtt_yield(&iotClient, 1000); - if (QCLOUD_ERR_SUCCESS == rc) { - /* Check no messages were received */ - for (i = 0; i < 100; i++) { - if ('x' != CallbackMsgString[i]) { - rc = QCLOUD_ERR_FAILURE; - } - } - } - - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); -} - -/* G:8 - Yield, network connected, ping request/response */ -TEST_F(YieldTests, PingRequestPingResponse) { - int rc; - int i = 0; - int j = 0; - int attempt = 3; - - for (i = 0; i < attempt; i++) { - - for (j = 0; j <= iotClient.options.keep_alive_interval; j++) { - sleep(1); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - } - } - -} - -/* G:9 - Yield, disconnected, Auto-reconnect timed-out */ -TEST_F(YieldTests, disconnectAutoReconnectTimeout) { - int rc; - - rc = qcloud_iot_mqtt_set_autoreconnect(&iotClient, true); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - ASSERT_EQ(true, IOT_MQTT_IsConnected(&iotClient)); - ASSERT_EQ(true, qcloud_iot_mqtt_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.options.keep_alive_interval); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - /* Let ping request time out and call yield */ - sleep(iotClient.options.keep_alive_interval + 1); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT, rc); - ASSERT_EQ(0, IOT_MQTT_IsConnected(&iotClient)); - ASSERT_EQ(true, dcHandlerInvoked); - -} - -/* G:10 - Yield, disconnected, Auto-reconnect successful */ -TEST_F(YieldTests, disconnectAutoReconnectSuccess) { - int rc; - - rc = qcloud_iot_mqtt_set_autoreconnect(&iotClient, true); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - ASSERT_EQ(true, IOT_MQTT_IsConnected(&iotClient)); - ASSERT_EQ(true, qcloud_iot_mqtt_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.options.keep_alive_interval); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - /* Let ping request time out and call yield */ - sleep(iotClient.options.keep_alive_interval + 10); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT, rc); - - sleep(2); /* Default min reconnect delay is 1 sec */ - printf("\nWakeup"); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - ASSERT_EQ(true, IOT_MQTT_IsConnected(&iotClient)); - ASSERT_EQ(true, dcHandlerInvoked); -} - -/* G:11 - Yield, disconnected, Manual reconnect */ -TEST_F(YieldTests, disconnectManualAutoReconnect) { - int rc; - - ASSERT_TRUE(IOT_MQTT_IsConnected(&iotClient)); - - /* Disable Autoreconnect, then let ping request time out and call yield */ - qcloud_iot_mqtt_set_autoreconnect(&iotClient, false); - ASSERT_TRUE(!qcloud_iot_mqtt_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.options.keep_alive_interval); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - /* Let ping request time out and call yield */ - sleep(iotClient.options.keep_alive_interval + 5); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_MQTT_NO_CONN, rc); - ASSERT_TRUE(!IOT_MQTT_IsConnected(&iotClient)); - ASSERT_EQ(true, dcHandlerInvoked); - - dcHandlerInvoked = false; - rc = qcloud_iot_mqtt_attempt_reconnect(&iotClient); - ASSERT_EQ(QCLOUD_ERR_MQTT_RECONNECTED, rc); - - ASSERT_TRUE(IOT_MQTT_IsConnected(&iotClient)); - ASSERT_TRUE(false == dcHandlerInvoked); -} - -/* G:12 - Yield, resubscribe to all topics on reconnect */ -TEST_F(YieldTests, resubscribeSuccessfulReconnect) { - int rc; - bool connected; - bool autoReconnectEnabled = false; - char expectedCallbackString[100]; - - rc = qcloud_iot_mqtt_set_autoreconnect(&iotClient, true); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - connected = IOT_MQTT_IsConnected(&iotClient); - ASSERT_EQ(1, connected); - - /* Subscribe to a topic */ - testSubParams.qos = QOS1; - testSubParams.on_message_handler = iot_tests_unit_acr_subscribe_callback_handler; - rc = qcloud_iot_mqtt_subscribe(&iotClient, subTopic, &testSubParams); - ASSERT_TRUE(0 < rc); - - /* Check subscribe */ - // snprintf(expectedCallbackString, 100, "Message for %s after resub", subTopic); - snprintf(expectedCallbackString, 100, "%s", "{\"action\":\"come_home\",\"targetDevice\":\"air\"}"); - while(subTopicLen != 9){ - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - sleep(2); - } - - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - ASSERT_STREQ(expectedCallbackString, CallbackMsgString); - - autoReconnectEnabled = qcloud_iot_mqtt_is_autoreconnect_enabled(&iotClient); - ASSERT_EQ(1, autoReconnectEnabled); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.options.keep_alive_interval); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - - /* Let ping request time out and call yield */ - sleep(iotClient.options.keep_alive_interval + 5); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT, rc); - - sleep(2); /* Default min reconnect delay is 1 sec */ - - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_MQTT_RECONNECTED, rc); - - /* Test if reconnect worked */ - connected = IOT_MQTT_IsConnected(&iotClient); - ASSERT_EQ(true, connected); - - /* Check subscribe */ - // snprintf(expectedCallbackString, 100, "Message for %s after resub", subTopic); - snprintf(expectedCallbackString, 100, "%s", "{\"action\":\"come_home\",\"targetDevice\":\"air\"}"); - rc = qcloud_iot_mqtt_yield(&iotClient, 100); - ASSERT_EQ(QCLOUD_ERR_SUCCESS, rc); - ASSERT_STREQ(expectedCallbackString, CallbackMsgString); - ASSERT_EQ(true, dcHandlerInvoked); - -} - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/sdk-tests/unit_test/unit_test.mk b/sdk-tests/unit_test/unit_test.mk deleted file mode 100644 index 32118a80..00000000 --- a/sdk-tests/unit_test/unit_test.mk +++ /dev/null @@ -1,40 +0,0 @@ -CXX := g++ -LDFLAGS := $(FINAL_DIR)/lib/libiot_sdk.a -LDFLAGS += $(FINAL_DIR)/lib/libiot_platform.a -ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) -LDFLAGS += $(FINAL_DIR)/lib/libmbedtls.a $(FINAL_DIR)/lib/libmbedx509.a $(FINAL_DIR)/lib/libmbedcrypto.a -endif - -UNIT_SRC_DIR = ${TESTS_DIR}/unit_test/src -UNIT_SRC_FILES = $(wildcard $(UNIT_SRC_DIR)/*.cpp) - -HELPER_C_FILES = $(wildcard $(UNIT_SRC_DIR)/*.c) -TLS_C_FILES = $(wildcard ${TESTS_DIR}/unit_test/tls_mock/*.c) - -unit_objects = $(patsubst %.cpp,%, $(UNIT_SRC_FILES)) - -ifneq (,$(filter -DSDKTESTS_ENABLED,$(CFLAGS))) -run_unit_test: update gtest ${unit_objects} - -update: - $(TOP_Q) \ - chmod a+x $(SCRIPT_DIR)/update_gtest.sh - $(TOP_Q) \ - $(SCRIPT_DIR)/update_gtest.sh > /dev/null - -gtest: - $(TOP_Q) \ - make -s -C $(TEST_LIB_DIR) - -${unit_objects}:%:%.cpp - $(call Brief_Log,"LD") - $(TOP_Q) \ - $(CXX) $(CFLAGS) -I$(TEST_LIB_DIR)/include -I$(TESTS_DIR)/unit_test/include \ - -I$(TESTS_DIR)/unit_test/tls_mock -pthread \ - $^ $(HELPER_C_FILES) $(TLS_C_FILES) $(LDFLAGS) ${TEST_LIB_DIR}/libgtest.a \ - -o $@ - - $(TOP_Q) \ - mv $@ $(FINAL_DIR)/unittest - -endif diff --git a/sdk_src/CMakeLists.txt b/sdk_src/CMakeLists.txt new file mode 100755 index 00000000..25401c56 --- /dev/null +++ b/sdk_src/CMakeLists.txt @@ -0,0 +1,117 @@ + +# UTILS +file(GLOB src_utils ${CMAKE_CURRENT_SOURCE_DIR}/utils/*.c) +set(src_sdk ${src_utils}) + +# MQTT +if(${FEATURE_MQTT_COMM_ENABLED} STREQUAL "ON") + # mqtt + file(GLOB src_mqtt ${CMAKE_CURRENT_SOURCE_DIR}/protocol/mqtt/*.c) + list(APPEND src_sdk ${src_mqtt}) + + # shadow + if(${FEATURE_MQTT_DEVICE_SHADOW} STREQUAL "ON") + file(GLOB src_shadow ${CMAKE_CURRENT_SOURCE_DIR}/services/shadow/*.c) + list(APPEND src_sdk ${src_shadow}) + endif() + + # ota mqtt + if(${FEATURE_OTA_COMM_ENABLED} STREQUAL "ON" AND ${FEATURE_OTA_SIGNAL_CHANNEL} STREQUAL "MQTT") + file(GLOB src_mqtt_ota + ${CMAKE_CURRENT_SOURCE_DIR}/services/ota/ota_client.c + ${CMAKE_CURRENT_SOURCE_DIR}/services/ota/ota_fetch.c + ${CMAKE_CURRENT_SOURCE_DIR}/services/ota/ota_lib.c + ${CMAKE_CURRENT_SOURCE_DIR}/services/ota/ota_mqtt.c) + list(APPEND src_sdk ${src_mqtt_ota}) + endif() + + # gateway + if(${FEATURE_GATEWAY_ENABLED} STREQUAL "ON") + file(GLOB src_gateway ${CMAKE_CURRENT_SOURCE_DIR}/services/gateway/*.c) + list(APPEND src_sdk ${src_gateway}) + endif() +endif() + +# COAP +if(${FEATURE_COAP_COMM_ENABLED} STREQUAL "ON") + # coap + file(GLOB src_coap ${CMAKE_CURRENT_SOURCE_DIR}/protocol/coap/*.c) + list(APPEND src_sdk ${src_coap}) + + # ota coap + if(${FEATURE_OTA_COMM_ENABLED} STREQUAL "ON" AND ${FEATURE_OTA_SIGNAL_CHANNEL} STREQUAL "COAP") + file(GLOB src_coap_ota + ${CMAKE_CURRENT_SOURCE_DIR}/services/ota/ota_client.c + ${CMAKE_CURRENT_SOURCE_DIR}/services/ota/ota_fetch.c + ${CMAKE_CURRENT_SOURCE_DIR}/services/ota/ota_lib.c + ${CMAKE_CURRENT_SOURCE_DIR}/services/ota/ota_coap.c) + list(APPEND src_sdk ${src_coap_ota}) + endif() +endif() + +# HTTP +if(${FEATURE_OTA_COMM_ENABLED} STREQUAL "ON" OR ${FEATURE_DEV_DYN_REG_ENABLED} STREQUAL "ON" OR ${FEATURE_LOG_UPLOAD_ENABLED} STREQUAL "ON") + # http + file(GLOB src_http ${CMAKE_CURRENT_SOURCE_DIR}/protocol/http/*.c) + list(APPEND src_sdk ${src_http}) +endif() + +# AT OR TCP +if(${FEATURE_AT_TCP_ENABLED} STREQUAL "ON") + # at + file(GLOB src_at_socket ${CMAKE_CURRENT_SOURCE_DIR}/network/at_socket/*.c) + list(APPEND src_sdk ${src_at_socket}) +endif() + +# TLS +if(${FEATURE_AUTH_WITH_NOTLS} STREQUAL "OFF") + file(GLOB src_tls ${CMAKE_CURRENT_SOURCE_DIR}/network/tls/*.c) + list(APPEND src_sdk ${src_tls}) +endif() + +# NETWORK +# tcp +file(GLOB src_socket ${CMAKE_CURRENT_SOURCE_DIR}/network/socket/*.c) +list(APPEND src_sdk ${src_socket}) +# interface +file(GLOB src_network ${CMAKE_CURRENT_SOURCE_DIR}/network/*.c) +list(APPEND src_sdk ${src_network}) + +# OTHRE SERVICES +if(${FEATURE_LOG_UPLOAD_ENABLED} STREQUAL "ON") + file(GLOB src_log_upload ${CMAKE_CURRENT_SOURCE_DIR}/services/log/*.c) + list(APPEND src_sdk ${src_log_upload}) +endif() + +if(${FEATURE_DEV_DYN_REG_ENABLED} STREQUAL "ON") + file(GLOB src_dyn_reg ${CMAKE_CURRENT_SOURCE_DIR}/services/dynreg/*.c) + list(APPEND src_sdk ${src_dyn_reg}) +endif() + + +if(${FEATURE_SYSTEM_COMM_ENABLED} STREQUAL "ON") + file(GLOB src_system ${CMAKE_CURRENT_SOURCE_DIR}/services/system/*.c) + list(APPEND src_sdk ${src_system}) +endif() + +if(${FEATURE_REMOTE_CONFIG_MQTT_ENABLED} STREQUAL "ON") + file(GLOB src_config_mqtt ${CMAKE_CURRENT_SOURCE_DIR}/services/config/*.c) + list(APPEND src_sdk ${src_config_mqtt}) +endif() + +if(${FEATURE_BROADCAST_ENABLED} STREQUAL "ON") + file(GLOB src_broadcast ${CMAKE_CURRENT_SOURCE_DIR}/services/broadcast/*.c) + list(APPEND src_sdk ${src_broadcast}) +endif() + +if(${FEATURE_RRPC_ENABLED} STREQUAL "ON") + file(GLOB src_rrpc ${CMAKE_CURRENT_SOURCE_DIR}/services/rrpc/*.c) + list(APPEND src_sdk ${src_rrpc}) +endif() + +if(${EXTRACT_SRC} STREQUAL "ON") + file(COPY ${src_sdk} DESTINATION ${PROJECT_SOURCE_DIR}/output/qcloud_iot_c_sdk/sdk_src/) +endif() +set(service_target "iot_sdk") +SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output/${BUILD_TYPE}/lib/) +add_library(${service_target} STATIC ${src_sdk}) diff --git a/sdk_src/internal_inc/at_client.h b/sdk_src/internal_inc/at_client.h new file mode 100755 index 00000000..6bad1f88 --- /dev/null +++ b/sdk_src/internal_inc/at_client.h @@ -0,0 +1,160 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __AT_CLIENT_H__ +#define __AT_CLIENT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" +#include "stddef.h" +#include "utils_ringbuff.h" + +#define AT_FRAME_VERSION "1.0.0" + +#define AT_CMD_NAME_LEN 16 +#define AT_END_MARK_LEN 4 + +#define CLINET_BUFF_LEN (1024) +#define RING_BUFF_LEN CLINET_BUFF_LEN // uart ring buffer len +#define GET_CHAR_TIMEOUT_MS (5000) +#define CMD_RESPONSE_INTERVAL_MS (100) + +typedef void (*ParserFunc)(void *userContex); + +typedef enum { + AT_STATUS_UNINITIALIZED = 0, + AT_STATUS_INITIALIZED = 0x55, + AT_STATUS_BUSY = 0xaa, +} at_status; + +enum at_resp_status { + AT_RESP_OK = 0, /* AT response end is OK */ + AT_RESP_ERROR = -1, /* AT response end is ERROR */ + AT_RESP_TIMEOUT = -2, /* AT response is timeout */ + AT_RESP_BUFF_FULL = -3, /* AT response buffer is full */ +}; + +typedef enum at_resp_status at_resp_status_t; + +typedef struct _at_response_ { + /* response buffer */ + char *buf; + /* the maximum response buffer size */ + int buf_size; + /* the number of setting response lines + * == 0: the response data will auto return when received 'OK' or 'ERROR' + * != 0: the response data will return when received setting lines number data */ + int line_num; + /* the count of received response lines */ + int line_counts; + /* the maximum response time */ + uint32_t timeout; +} at_response; + +typedef at_response *at_response_t; + +/* URC(Unsolicited Result Code) object, such as: 'RING', 'READY' request by AT server */ +typedef struct _at_urc_ { + const char *cmd_prefix; + const char *cmd_suffix; + void (*func)(const char *data, size_t size); +} at_urc; + +typedef at_urc *at_urc_t; + +typedef struct _at_client_ { + at_status status; + char end_sign; + + ring_buff_t pRingBuff; + + char * recv_buffer; + uint32_t recv_bufsz; + uint32_t cur_recv_len; + void * lock; // pre cmd take the lock wait for resp , another cmd need wait for unlock + + at_response_t resp; + at_resp_status_t resp_status; + + const at_urc *urc_table; + uint16_t urc_table_size; + +#ifdef AT_OS_USED + void * resp_sem; // resp received, send sem to notic ack wait + ParserFunc parser; // RX parser +#else + // bool resp_notice; +#endif +} at_client; + +typedef at_client *at_client_t; + +/* AT client initialize and start*/ +int at_client_init(at_client_t *pClient); + +/* AT client deinitial*/ +int at_client_deinit(at_client_t pClient); + +/* get AT client handle*/ +at_client_t at_client_get(void); + +/*AT connect detect*/ +int at_client_wait_connect(uint32_t timeout); + +/*wrapper for os and nonos delay*/ +void at_delayms(uint32_t delayms); +void at_setFlag(uint32_t flag); +void at_clearFlag(uint32_t flag); +uint32_t at_getFlag(void); +bool at_waitFlag(uint32_t flag, uint32_t timeout); + +/* ========================== multiple AT client function ============================ */ +/* set AT client a line end sign */ +void at_set_end_sign(char ch); + +/* Set URC(Unsolicited Result Code) table */ +void at_set_urc_table(at_client_t client, const at_urc_t table, uint32_t size); + +/* AT client send or receive data */ +int at_client_send(at_client_t client, const char *buf, int size, uint32_t timeout); +int at_client_obj_recv(char *buf, int size, int timeout); + +/* AT client send commands to AT server and waiter response */ +int at_obj_exec_cmd(at_response_t resp, const char *cmd_expr, ...); + +#define at_exec_cmd(resp, ...) at_obj_exec_cmd(resp, __VA_ARGS__) +#define at_client_recv(buf, size, timeout) at_client_obj_recv(buf, size, timeout) + +/* AT response object create and delete */ +at_response_t at_create_resp(uint32_t buf_size, uint32_t line_num, uint32_t timeout); +void at_delete_resp(at_response_t resp); + +/* AT response line buffer get and parse response buffer arguments */ +const char *at_resp_get_line(at_response_t resp, uint32_t resp_line); +const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword); +int at_resp_parse_line_args(at_response_t resp, uint32_t resp_line, const char *resp_expr, ...); +int at_resp_parse_line_args_by_kw(at_response_t resp, const char *keyword, const char *resp_expr, ...); + +/* ========================== single AT client function ============================ */ +void at_client_yeild(at_urc *expect_urc, uint32_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* __AT_H__ */ diff --git a/sdk_src/internal_inc/at_socket_inf.h b/sdk_src/internal_inc/at_socket_inf.h new file mode 100755 index 00000000..bd4aa987 --- /dev/null +++ b/sdk_src/internal_inc/at_socket_inf.h @@ -0,0 +1,87 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _AT_SOCKET_INF_H_ +#define _AT_SOCKET_INF_H_ + +#include +#include + +#include "utils_list.h" + +#define UNUSED_SOCKET (-1) +#define MAX_AT_SOCKET_NUM (5) +#define AT_SOCKET_SEND_TIMEOUT_MS (1000) +#define AT_SOCKET_RECV_TIMEOUT_MS (1000) +#define IPV4_STR_MAX_LEN (16) + +typedef enum { eNET_TCP = 6, eNET_UDP = 17, eNET_DEFAULT = 0xff } eNetProto; + +typedef enum { eSOCKET_ALLOCED = 0, eSOCKET_CONNECTED, eSOCKET_CLOSED } eSocketState; + +/* AT receive package list structure */ +typedef struct at_recv_pkt { + List list; + size_t bfsz_totle; + size_t bfsz_index; + char * buff; +} at_recv_pkt; + +typedef enum { + AT_SOCKET_EVT_RECV = 0, + AT_SOCKET_EVT_CLOSED, +} at_socket_evt_t; + +typedef void (*at_evt_cb_t)(int fd, at_socket_evt_t event, char *buff, size_t bfsz); + +/*at device driver ops, use at_device_op_register register to at socket*/ +typedef struct { + int (*init)(void); + int (*get_local_mac)(char *macbuff, size_t bufflen); + int (*get_local_ip)(char *ip, size_t iplen, char *gw, size_t gwlen, char *mask, size_t masklen); + int (*parse_domain)(const char *host_name, char *host_ip, size_t host_ip_len); + int (*connect)(const char *ip, uint16_t port, eNetProto proto); + int (*send)(int fd, const void *buf, size_t len); + int (*recv_timeout)(int fd, void *buf, size_t len, uint32_t timeout); + int (*close)(int fd); + void (*set_event_cb)(at_socket_evt_t event, at_evt_cb_t cb); + char *deviceName; +} at_device_op_t; + +/*at socket context*/ +typedef struct { + int fd; /** socket fd */ + List * recvpkt_list; + char remote_ip[IPV4_STR_MAX_LEN]; + uint16_t remote_port; + uint32_t send_timeout_ms; + uint32_t recv_timeout_ms; + void * recv_lock; + at_device_op_t *dev_op; + eNetProto net_type; + eSocketState state; +} at_socket_ctx_t; + +// at socket api +int at_device_op_register(at_device_op_t *device_op); +int at_socket_init(void); +int at_socket_parse_domain(const char *host_name, char *host_ip, size_t host_ip_len); +int at_socket_get_local_mac(char *macbuff, size_t bufflen); +int at_socket_get_local_ip(char *ip, size_t iplen, char *gw, size_t gwlen, char *mask, size_t masklen); +int at_socket_connect(const char *host, uint16_t port, eNetProto eProto); +int at_socket_close(int fd); +int at_socket_send(int fd, const void *buf, size_t len); +int at_socket_recv(int fd, void *buf, size_t len); +#endif diff --git a/sdk_src/internal_inc/at_uart_hal.h b/sdk_src/internal_inc/at_uart_hal.h new file mode 100755 index 00000000..9a1360f9 --- /dev/null +++ b/sdk_src/internal_inc/at_uart_hal.h @@ -0,0 +1,103 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __AT_UART_HAL_H__ +#define __AT_UART_HAL_H__ + +/* + * UART data width + */ +typedef enum { + BAUDRATE_2400 = 2400, + BAUDRATE_4800 = 4800, + BAUDRATE_9600 = 9600, + BAUDRATE_19200 = 19200, + BAUDRATE_115200 = 115200, + BAUDRATE_921600 = 921600, + BAUDRATE_DEFAULT = 115200 +} hal_uart_baudr_t; + +/* + * 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 state + */ +typedef enum { + eUNUSED = 0, + eOPENED = 1, + eCLOSED = 2, +} hal_uart_state_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 { +#ifdef __linux__ + int fd; /* uart fd */ +#else + void *uart_handle; /* uart handle,like stm32 UART_HandleTypeDef */ +#endif + hal_uart_state_t state; /* uart state */ + uart_config_t config; /* uart config */ +} uart_dev_t; + +#ifdef __cplusplus +} +#endif + +#endif /* __AT_H__ */ diff --git a/sdk_src/internal_inc/at_utils.h b/sdk_src/internal_inc/at_utils.h new file mode 100755 index 00000000..cd68b196 --- /dev/null +++ b/sdk_src/internal_inc/at_utils.h @@ -0,0 +1,46 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _AT_UTILS_H_ +#define _AT_UTILS_H_ + +#include +#include +#include + +#define WIDTH_SIZE 32 + +#ifndef __INT_MAX__ +#define __INT_MAX__ 2147483647 +#endif + +#ifndef INT_MAX +#define INT_MAX (__INT_MAX__) +#endif + +#define AT_CMD_COMMA_MARK ',' +#define AT_CMD_DQUOTES_MARK '"' + +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') + +int at_vprintfln(const char *format, va_list args); +void at_print_raw_cmd(const char *name, const char *cmd, int size); +const char *at_get_last_cmd(int *cmd_size); +int at_req_parse_args(const char *req_args, const char *req_expr, ...); +int at_sscanf(const char *buf, const char *fmt, va_list args); +void at_strip(char *str, const char patten); +void chr_strip(char *str, const char patten); + +#endif diff --git a/sdk_src/internal_inc/coap_client.h b/sdk_src/internal_inc/coap_client.h new file mode 100755 index 00000000..b7e4235f --- /dev/null +++ b/sdk_src/internal_inc/coap_client.h @@ -0,0 +1,471 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef IOT_COAP_CLIENT_H_ +#define IOT_COAP_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "coap_client_net.h" +#include "network_interface.h" +#include "qcloud_iot_common.h" +#include "qcloud_iot_export.h" +#include "utils_list.h" +#include "utils_timer.h" + +/* COAP protocol version */ +#define COAP_MSG_VER (0x01) + +/* COAP init token */ +#define COAP_MSG_INIT_TOKEN (0x01020304) + +/* Minimal command timeout of CoAP ACK/RESP */ +#define MIN_COMMAND_TIMEOUT (500) + +/* Maximal command timeout of CoAP ACK/RESP */ +#define MAX_COMMAND_TIMEOUT (5000) + +/* Max size of conn Id */ +#define COAP_MAX_CONN_ID_LEN (6) + +/* Max size of Message id */ +#define COAP_MSG_MAX_MSG_ID ((1 << 16) - 1) + +/* Max size of Topic length */ +#define URI_PATH_MAX_LEN (128) + +/* CoAP auth success */ +#define COAP_TRUE (1) + +/* CoAP auth fail */ +#define COAP_FALSE (0) + +/* unique CoAP auth URI */ +#define COAP_AUTH_URI ("txauth9w0BAQsFA") + +/* Max size of token */ +#define COAP_MSG_MAX_TOKEN_LEN (8) + +/* COAP Max code class */ +#define COAP_MSG_MAX_CODE_CLASS (7) + +/* COAP Max code detail */ +#define COAP_MSG_MAX_CODE_DETAIL (31) + +/* Get field of Option num */ +#define COAP_MSG_OPTION_NUM(option) ((option)->option_num) + +/* Get field of Next Option */ +#define COAP_MSG_OP_NEXT(option) ((option)->next) + +/* If COAP msg is empty */ +#define COAP_MSG_IS_EMPTY(message) (((message)->code_class == 0) && ((message)->code_detail == 0)) + +/* If COAP msg is empty ACK */ +#define COAP_MSG_IS_EMPTY_ACK(message) (((message)->code_class == 2) && ((message)->code_detail == 3)) + +/* If COAP msg is RESP */ +#define COAP_MSG_IS_EMPTY_RSP(message) (((message)->code_class == 2) && ((message)->code_detail == 5)) + +/** + * @brief COAP msg type + */ +typedef enum { + COAP_MSG_REQ = 0, + COAP_MSG_SUCCESS = 2, + COAP_MSG_CLIENT_ERR = 4, + COAP_MSG_SERVER_ERR = 5, + COAP_MSG_SDKINTERNAL_ERR = 6, +} CoAPMessageClass; + +/** + * @brief COAP msg type + */ +typedef enum { COAP_MSG_GET = 1, COAP_MSG_POST = 2, COAP_MSG_PUT = 3, COAP_MSG_DELETE = 4 } CoAPRequestMethod; + +typedef enum { + /* CoAP Success Response code detail */ + COAP_MSG_CODE_201_CREATED = 01, /* Mapping to CoAP codeClass.codeDetail 2.01 */ + COAP_MSG_CODE_202_DELETED = 02, /* Mapping to CoAP codeClass.codeDetail 2.02 */ + COAP_MSG_CODE_203_VALID = 03, /* Mapping to CoAP codeClass.codeDetail 2.03 */ + COAP_MSG_CODE_204_CHANGED = 04, /* Mapping to CoAP codeClass.codeDetail 2.04 */ + COAP_MSG_CODE_205_CONTENT = 05, /* Mapping to CoAP codeClass.codeDetail 2.05 */ + COAP_MSG_CODE_231_CONTINUE = 31, /* Mapping to CoAP codeClass.codeDetail 2.31 */ + + /* CoAP Client Error Response code detail */ + COAP_MSG_CODE_400_BAD_REQUEST = 00, /* Mapping to CoAP codeClass.codeDetail 4.00 */ + COAP_MSG_CODE_401_UNAUTHORIZED = 01, /* Mapping to CoAP codeClass.codeDetail 4.01 */ + COAP_MSG_CODE_402_BAD_OPTION = 02, /* Mapping to CoAP codeClass.codeDetail 4.02 */ + COAP_MSG_CODE_403_FORBIDDEN = 03, /* Mapping to CoAP codeClass.codeDetail 4.03 */ + COAP_MSG_CODE_404_NOT_FOUND = 04, /* Mapping to CoAP codeClass.codeDetail 4.04 */ + COAP_MSG_CODE_405_METHOD_NOT_ALLOWED = 05, /* Mapping to CoAP codeClass.codeDetail 4.05 */ + COAP_MSG_CODE_406_NOT_ACCEPTABLE = 06, /* Mapping to CoAP codeClass.codeDetail 4.06 */ + COAP_MSG_CODE_408_REQUEST_ENTITY_INCOMPLETE = 8, /* Mapping to CoAP codeClass.codeDetail 4.08 */ + COAP_MSG_CODE_412_PRECONDITION_FAILED = 12, /* Mapping to CoAP codeClass.codeDetail 4.12 */ + COAP_MSG_CODE_413_REQUEST_ENTITY_TOO_LARGE = 13, /* Mapping to CoAP codeClass.codeDetail 4.13 */ + COAP_MSG_CODE_415_UNSUPPORTED_CONTENT_FORMAT = 15, /* Mapping to CoAP codeClass.codeDetail 4.15 */ + + /* CoAP Server Error Response code detail */ + COAP_MSG_CODE_500_INTERNAL_SERVER_ERROR = 00, /* Mapping to CoAP codeClass.codeDetail 5.00 */ + COAP_MSG_CODE_501_NOT_IMPLEMENTED = 01, /* Mapping to CoAP codeClass.codeDetail 5.01 */ + COAP_MSG_CODE_502_BAD_GATEWAY = 02, /* Mapping to CoAP codeClass.codeDetail 5.02 */ + COAP_MSG_CODE_503_SERVICE_UNAVAILABLE = 03, /* Mapping to CoAP codeClass.codeDetail 5.03 */ + COAP_MSG_CODE_504_GATEWAY_TIMEOUT = 04, /* Mapping to CoAP codeClass.codeDetail 5.04 */ + COAP_MSG_CODE_505_PROXYING_NOT_SUPPORTED = 05, /* Mapping to CoAP codeClass.codeDetail 5.05 */ + COAP_MSG_CODE_600_TIMEOUT = 00, /* Mapping to self define CoAP codeClass.codeDetail 6.00 */ +} CoAPRespCodeDetail; + +/** + * @brief Option number enumeration + */ +typedef enum { + COAP_MSG_IF_MATCH = 1, // If-Match option number + COAP_MSG_URI_HOST = 3, // URI-Host option number + COAP_MSG_ETAG = 4, // Entity-Tag option number + COAP_MSG_IF_NONE_MATCH = 5, // If-None-Match option number + COAP_MSG_URI_PORT = 7, // URI-Port option number + COAP_MSG_LOCATION_PATH = 8, // Location-Path option number + COAP_MSG_URI_PATH = 11, // URI-Path option number + COAP_MSG_CONTENT_FORMAT = 12, // Content-Format option number + COAP_MSG_MAX_AGE = 14, // Max-Age option number + COAP_MSG_URI_QUERY = 15, // URI-Query option number + COAP_MSG_ACCEPT = 17, // Accept option number + COAP_MSG_LOCATION_QUERY = 20, // Location-Query option number + COAP_MSG_BLOCK2 = 23, // Block2 option number + COAP_MSG_BLOCK1 = 27, // Block1 option number + COAP_MSG_SIZE2 = 28, // Size2 option number + COAP_MSG_PROXY_URI = 35, // Proxy-URI option number + COAP_MSG_PROXY_SCHEME = 39, // Proxy-Scheme option number + COAP_MSG_SIZE1 = 60, // Size1 option number + COAP_MSG_AUTH_TOKEN = 61, // auth token option number + COAP_MSG_NEED_RESP = 62, // CoAP need content response +} CoAPMsgOptionNum; + +/* CoAP QCloud IoT Client structure */ +typedef struct Client { + char is_authed; // CoAP Client auth or not + char conn_id[COAP_MAX_CONN_ID_LEN]; // conn id for a CoAP connection + + unsigned int message_token; // msg token + + char *auth_token; // auth token + int auth_token_len; + + uint16_t next_msg_id; // COAP msg id + + size_t send_buf_size; // size of write buffer + size_t read_buf_size; // size of read buffer + + unsigned char send_buf[COAP_SENDMSG_MAX_BUFLEN]; + unsigned char recv_buf[COAP_RECVMSG_MAX_BUFLEN]; + + void *lock_send_buf; // mutex/lock for write buffer + void *lock_list_wait_ack; // mutex/lock for wait ack list + + Network network_stack; // MQTT network stack + + uint32_t command_timeout_ms; // CoAP command timeout, unit:ms + + List *message_list; // msg list + + unsigned char max_retry_count; // Max retry count + + CoAPEventHandler event_handle; // event callback + + DeviceInfo device_info; + + char host_addr[HOST_STR_LENGTH]; + +#ifdef AUTH_MODE_CERT + char cert_file_path[FILE_PATH_MAX_LEN]; // full path of device cert file + char key_file_path[FILE_PATH_MAX_LEN]; // full path of device key file +#else + unsigned char psk_decode[DECODE_PSK_LENGTH]; +#endif + +} CoAPClient; + +/** + * @brief CoAP Option + */ +typedef struct coap_msg_op { + unsigned short option_num; // Option number + unsigned val_len; // Option length + char * val; // Pointer to a buffer containing the option value + struct coap_msg_op *next; // Pointer to the next option structure in the list +} CoAPMsgOption; + +/** + * @brief CoAP Option list + */ +typedef struct { + CoAPMsgOption *first; // Pointer to the first option structure in the list + CoAPMsgOption *last; // Pointer to the last option structure in the list +} CoAPMsgOptionList; + +/** + * @brief CoAP node state + */ +typedef enum { + COAP_NODE_STATE_NORMANL = 0, + COAP_NODE_STATE_INVALID, +} CoAPNodeState; + +typedef struct { + CoAPNodeState node_state; + void * user_context; + unsigned short msg_id; + char acked; + unsigned char token_len; + unsigned char token[COAP_MSG_MAX_TOKEN_LEN]; + unsigned char retrans_count; + Timer start_time; + unsigned char *message; + unsigned int msglen; + OnRespCallback handler; +} CoAPMsgSendInfo; + +/** + * @brief COAP msg type + */ +typedef enum { + COAP_MSG_CON = 0x0, /**< msg need to wait for ACK */ + COAP_MSG_NON = 0x1, /**< msg no need to wait for ACK */ + COAP_MSG_ACK = 0x2, /**< msg ACK */ + COAP_MSG_RST = 0x3 /**< msg Reset */ +} CoAPMsgType; + +/** + * @brief CoAP message structure + */ +typedef struct { + unsigned version; // CoAP protocol version + CoAPMsgType type; // msg type + + unsigned code_class; // Code class + unsigned code_detail; // Code detail + + unsigned short msg_id; // msg id + + char * pay_load; // msg payload + size_t pay_load_len; // length of payload + + char token[COAP_MSG_MAX_TOKEN_LEN]; // msg token + unsigned token_len; // length of token + + CoAPMsgOptionList op_list; // Option list + + OnRespCallback handler; // CoAP Response msg callback + void * user_context; // user context +} CoAPMessage; + +#define DEFAULT_COAP_MESSAGE \ + { \ + COAP_MSG_VER, COAP_MSG_CON, COAP_MSG_REQ, COAP_MSG_POST, 0, NULL, 0, {0}, 0, {0}, NULL, NULL \ + } + +/** + * @brief Init CoAPClient + * + * @param pClient reference to CoAP client + * @param pParams CoAP init parameters + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_coap_init(CoAPClient *pClient, CoAPInitParams *pParams); + +/** + * @brief Generate next CoAPMessage msg Id + * + * @param pClient reference to CoAP client + * @return msg Id + */ +uint16_t get_next_coap_msg_id(CoAPClient *pClient); + +/** + * @brief Generate next CoAPMessage msg token + * + * @param pClient reference to CoAP client + * @param tokenData msg token + * @return token length + */ +unsigned int get_coap_message_token(CoAPClient *client, char *tokenData); + +/** + * @brief set message type + * + * @param message CoAP msg + * @param + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_type_set(CoAPMessage *message, unsigned type); + +/** + * @brief set message code + * + * @param message CoAP msg + * @param code_class CoAPMessageClass + * @param code_detail + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_code_set(CoAPMessage *message, unsigned code_class, unsigned code_detail); + +/** + * @brief set message Id + * + * @param message CoAP msg + * @param msg_id + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_id_set(CoAPMessage *message, unsigned msg_id); + +/** + * @brief set msg token + * + * @param message CoAP msg + * @param buf token string + * @param len token length + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_token_set(CoAPMessage *message, char *buf, size_t len); + +/** + * @brief set msg payload + * + * @param message CoAP msg + * @param buf msg payload buffer + * @param len length of payload + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_payload_set(CoAPMessage *message, char *buf, size_t len); + +/** + * @brief add msg option + * + * @param message CoAP msg + * @param num option number + * @param len option length + * @param val option string + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_option_add(CoAPMessage *message, unsigned num, unsigned len, const char *val); + +/** + * @brief set msg callback + * + * @param message CoAP msg + * @param callback + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_callback_set(CoAPMessage *message, OnRespCallback callback); + +/** + * @brief set user context + * + * @param message CoAP msg + * @param userContext + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_context_set(CoAPMessage *message, void *userContext); + +/** + * @brief create CoAPMsgOption from option number/len/val + * + * @param num CoAP option number + * @param len CoAP option string len + * @param val CoAP option string value + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +CoAPMsgOption *qcloud_iot_coap_option_init(unsigned num, unsigned len, const char *val); + +/** + * @brief destroy CoAPMessage + * + * @param[in,out] message + */ +void coap_message_destroy(CoAPMessage *message); + +/** + * @brief Read and handle CoAP msg + * + * @param pClient CoAPClient + * @param timeout_ms timeout value in millisecond + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_message_cycle(CoAPClient *client, uint32_t timeout_ms); + +/** + * @brief Send CoAP msg + * + * @param client CoAPClient + * @param message msg to send + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +ssize_t coap_message_send(CoAPClient *client, CoAPMessage *message); + +/** + * @brief Read CoAP msg + * + * @param client CoAPClient + * @param timeout_ms timeout value in millisecond + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +ssize_t coap_message_recv(CoAPClient *client, uint32_t timeout_ms); + +/** + * @brief do CoAPClient auth + * + * @param client CoAPClient + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int coap_client_auth(CoAPClient *client); + +/** + * @brief Parse a message + * + * @param[in,out] message Pointer to a message structure + * @param[in] buf Pointer to a buffer containing the message + * @param[in] len Length of the buffer + * + * @returns Operation status + * @retval 0 Success + * @retval <0 Error + */ +ssize_t deserialize_coap_message(CoAPMessage *message, char *buf, size_t len); + +/** + * @brief Format a message + * + * @param[in] message Pointer to a message structure + * @param[out] buf Pointer to a buffer to contain the formatted message + * @param[in] len Length of the buffer + * + * @returns Length of the formatted message or error code + * @retval >0 Length of the formatted message + * @retval <0 Error + */ +ssize_t serialize_coap_message(CoAPMessage *message, char *buf, size_t len); + +void coap_msg_dump(CoAPMessage *msg); + +#ifdef __cplusplus +} +#endif + +#endif /* IOT_COAP_CLIENT_H_ */ diff --git a/src/coap/include/coap_client_net.h b/sdk_src/internal_inc/coap_client_net.h old mode 100644 new mode 100755 similarity index 87% rename from src/coap/include/coap_client_net.h rename to sdk_src/internal_inc/coap_client_net.h index e3edd58f..047afa94 --- a/src/coap/include/coap_client_net.h +++ b/sdk_src/internal_inc/coap_client_net.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -22,12 +22,10 @@ extern "C" { #include -#include "utils_net.h" - - +#include "network_interface.h" + int qcloud_iot_coap_network_init(Network *pNetwork); - #ifdef __cplusplus } #endif diff --git a/sdk_src/internal_inc/gateway_common.h b/sdk_src/internal_inc/gateway_common.h new file mode 100644 index 00000000..2511ad58 --- /dev/null +++ b/sdk_src/internal_inc/gateway_common.h @@ -0,0 +1,117 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef IOT_GATEWAY_COMMON_H_ +#define IOT_GATEWAY_COMMON_H_ + +#include "qcloud_iot_export.h" + +#define GATEWAY_PAYLOAD_BUFFER_LEN 1024 +#define GATEWAY_RECEIVE_BUFFER_LEN 1024 +#define GATEWAY_LOOP_MAX_COUNT 100 +#define SUBDEV_BIND_SIGN_LEN 64 +#define BIND_SIGN_KEY_SIZE MAX_SIZE_OF_DEVICE_SECRET +#define GATEWAY_ONLINE_OP_STR "online" +#define GATEWAY_OFFLIN_OP_STR "offline" +#define GATEWAY_BIND_OP_STR "bind" +#define GATEWAY_UNBIND_OP_STR "unbind" +#define GATEWAY_DESCRIBE_SUBDEVIES_OP_STR "describe_sub_devices" + +/* The format of operation of gateway topic */ +#define GATEWAY_TOPIC_OPERATION_FMT "$gateway/operation/%s/%s" + +/* The format of operation result of gateway topic */ +#define GATEWAY_TOPIC_OPERATION_RESULT_FMT "$gateway/operation/result/%s/%s" + +/* The format of gateway client id */ +#define GATEWAY_CLIENT_ID_FMT "%s/%s" + +/* The format of operation result of gateway topic */ +#define GATEWAY_PAYLOAD_STATUS_FMT \ + "{\"type\":\"%s\",\"payload\":{\"devices\":[{\"product_id\":\"%s\"," \ + "\"device_name\":\"%s\"}]}}" + +/* The format of bind cmd payload */ +#define GATEWAY_PAYLOAD_OP_FMT \ + "{\"type\":\"%s\",\"payload\":{\"devices\":[{\"product_id\":\"%s\"," \ + "\"device_name\":\"%s\",\"signature\":\"%s\",\"random\":%d,\"timestamp\":%d," \ + "\"signmethod\":\"%s\",\"authtype\":\"%s\"}]}}" + +/* Subdevice seesion status */ +typedef enum _SubdevSessionStatus { + /* Initial */ + SUBDEV_SEESION_STATUS_INIT, + + /* Online */ + SUBDEV_SEESION_STATUS_ONLINE, + + /* Offline */ + SUBDEV_SEESION_STATUS_OFFLINE, + + /* Maximum number of seesion status type */ + SUBDEV_SEESION_STATUS_MAX +} SubdevSessionStatus; + +/* The structure of subdevice session */ +typedef struct _SubdevSession { + char product_id[MAX_SIZE_OF_PRODUCT_ID + 1]; + char device_name[MAX_SIZE_OF_DEVICE_NAME + 1]; + SubdevSessionStatus session_status; + struct _SubdevSession *next; +} SubdevSession; + +/* The structure of common reply data */ +typedef struct _ReplyData { + int32_t result; + char client_id[MAX_SIZE_OF_CLIENT_ID + 1]; +} ReplyData; + +/* The structure of gateway data */ +typedef struct _GatewayData { + int32_t sync_status; + ReplyData online; + ReplyData offline; + ReplyData bind; + ReplyData unbind; + ReplyData get_bindlist; +} GatewayData; + +/* The structure of gateway context */ +typedef struct _Gateway { + void * mqtt; + SubdevSession * session_list; + SubdevBindList bind_list; + GatewayData gateway_data; + MQTTEventHandler event_handle; + int is_construct; + char recv_buf[GATEWAY_RECEIVE_BUFFER_LEN]; +} Gateway; + +SubdevSession *subdev_add_session(Gateway *gateway, char *product_id, char *device_name); + +SubdevSession *subdev_find_session(Gateway *gateway, char *product_id, char *device_name); + +int subdev_remove_session(Gateway *gateway, char *product_id, char *device_name); + +int gateway_subscribe_unsubscribe_topic(Gateway *gateway, char *topic_filter, SubscribeParams *params, + int is_subscribe); + +int gateway_subscribe_unsubscribe_default(Gateway *gateway, GatewayParam *param); + +int gateway_publish_sync(Gateway *gateway, char *topic, PublishParams *params, int32_t *result); + +int subdev_bind_hmac_sha1_cal(DeviceInfo *pDevInfo, char *signout, int max_signlen, int nonce, long timestamp); + +#endif /* IOT_GATEWAY_COMMON_H_ */ diff --git a/src/utils/lite/json_parser.h b/sdk_src/internal_inc/json_parser.h old mode 100644 new mode 100755 similarity index 52% rename from src/utils/lite/json_parser.h rename to sdk_src/internal_inc/json_parser.h index d0b81965..a88a767e --- a/src/utils/lite/json_parser.h +++ b/sdk_src/internal_inc/json_parser.h @@ -1,23 +1,17 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. * */ -/** - * Edit by shockcao@tencent.com 2018/3/15 - */ #ifndef __JSON_PARSER_H__ #define __JSON_PARSER_H__ @@ -27,62 +21,47 @@ /** The descriptions of the json value node type **/ -enum JSONTYPE { - JSNONE = -1, - JSSTRING = 0, - JSOBJECT, - JSARRAY, - JSNUMBER, - JSBOOLEAN, - JSTYPEMAX -}; +enum JSONTYPE { JSNONE = -1, JSSTRING = 0, JSOBJECT, JSARRAY, JSNUMBER, JSBOOLEAN, JSNULL, JSTYPEMAX }; /** The error codes produced by the JSON parsers **/ -enum JSON_PARSE_CODE { - JSON_PARSE_ERR, - JSON_PARSE_OK, - JSON_PARSE_FINISH -}; +enum JSON_PARSE_CODE { JSON_PARSE_ERR, JSON_PARSE_OK, JSON_PARSE_FINISH }; /** The return codes produced by the JSON parsers **/ -enum JSON_PARSE_RESULT { - JSON_RESULT_ERR = -1, - JSON_RESULT_OK -}; +enum JSON_PARSE_RESULT { JSON_RESULT_ERR = -1, JSON_RESULT_OK }; typedef int (*json_parse_cb)(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType, void *p_Result); /** -* @brief Parse the JSON string, and iterate through all keys and values, -* then handle the keys and values by callback function. -* -* @param[in] p_cJsonStr @n The JSON string -* @param[in] iStrLen @n The JSON string length -* @param[in] pfnCB @n Callback function -* @param[out] p_CBData @n User data -* @return JSON_RESULT_OK success, JSON_RESULT_ERR failed -* @see None. -* @note None. -**/ + * @brief Parse the JSON string, and iterate through all keys and values, + * then handle the keys and values by callback function. + * + * @param[in] p_cJsonStr @n The JSON string + * @param[in] iStrLen @n The JSON string length + * @param[in] pfnCB @n Callback function + * @param[out] p_CBData @n User data + * @return JSON_RESULT_OK success, JSON_RESULT_ERR failed + * @see None. + * @note None. + **/ int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData); /** -* @brief Get the value by a specified key from a json string -* -* @param[in] p_cJsonStr @n the JSON string -* @param[in] iStrLen @n the JSON string length -* @param[in] p_cName @n the specified key string -* @param[out] p_iValueLen @n the value length -* @param[out] p_iValueType @n the value type -* @return A pointer to the value -* @see None. -* @note None. -**/ + * @brief Get the value by a specified key from a json string + * + * @param[in] p_cJsonStr @n the JSON string + * @param[in] iStrLen @n the JSON string length + * @param[in] p_cName @n the specified key string + * @param[out] p_iValueLen @n the value length + * @param[out] p_iValueType @n the value type + * @return A pointer to the value + * @see None. + * @note None. + **/ char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType); /** @@ -111,8 +90,8 @@ char *json_get_next_object(int type, char *str, char **key, int *key_len, char * * @note None. */ #define json_object_for_each_kv(str, pos, key, klen, val, vlen, vtype) \ - for (pos = json_get_object(JSOBJECT, str); \ - pos!=0 && *pos!=0 && (pos=json_get_next_object(JSOBJECT, pos, &key, &klen, &val, &vlen, &vtype))!=0; ) + for (pos = json_get_object(JSOBJECT, str); \ + pos != 0 && *pos != 0 && (pos = json_get_next_object(JSOBJECT, pos, &key, &klen, &val, &vlen, &vtype)) != 0;) /** * @brief retrieve each entry from the json array @@ -126,9 +105,8 @@ char *json_get_next_object(int type, char *str, char **key, int *key_len, char * * @note None. */ #define json_array_for_each_entry(str, pos, entry, len, type) \ - for (pos = json_get_object(JSARRAY, str); \ - pos!=0 && *pos!=0 && (pos=json_get_next_object(JSARRAY, ++pos, 0, 0, &entry, &len, &type))!=0; ) - + for (pos = json_get_object(JSARRAY, str); \ + pos != 0 && *pos != 0 && (pos = json_get_next_object(JSARRAY, ++pos, 0, 0, &entry, &len, &type)) != 0;) /** * @brief backup the last character to register parameters, @@ -140,9 +118,10 @@ char *json_get_next_object(int type, char *str, char **key, int *key_len, char * * @see None. * @note None. */ -#define backup_json_str_last_char(json_str, str_len, register) { \ - register = *((char *)json_str + str_len); \ - *((char *)json_str + str_len) = '\0'; \ +#define backup_json_str_last_char(json_str, str_len, register) \ + { \ + register = *((char *)json_str + str_len); \ + *((char *)json_str + str_len) = '\0'; \ } /** @@ -154,8 +133,9 @@ char *json_get_next_object(int type, char *str, char **key, int *key_len, char * * @see None. * @note None. */ -#define restore_json_str_last_char(json_str, str_len, register) { \ - *((char *)json_str + str_len) = register; \ +#define restore_json_str_last_char(json_str, str_len, register) \ + { \ + *((char *)json_str + str_len) = register; \ } -#endif /* __JSON_PARSER_H__ */ +#endif /* __JSON_PARSER_H__ */ diff --git a/src/system/include/log_upload.h b/sdk_src/internal_inc/log_upload.h old mode 100644 new mode 100755 similarity index 71% rename from src/system/include/log_upload.h rename to sdk_src/internal_inc/log_upload.h index 05efa9a8..af08a660 --- a/src/system/include/log_upload.h +++ b/sdk_src/internal_inc/log_upload.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -19,16 +19,26 @@ #ifdef __cplusplus extern "C" { #endif - -#include "qcloud_iot_export_log.h" +#include "qcloud_iot_export_log.h" /** * @brief init the log upload functions * * @param init_params + * @return QCLOUD_RET_SUCCESS when success + */ +int init_log_uploader(LogUploadInitParams *init_params); + +/** + * @brief free log buffer and finish the log upload functions */ -void init_log_uploader(LogUploadInitParams *init_params); +void fini_log_uploader(void); + +/** + * @brief check if log uploader is init or not + */ +bool is_log_uploader_init(void); /** * @brief append one log item to upload buffer @@ -42,15 +52,16 @@ int append_to_upload_buffer(const char *log_content, size_t log_size); /** * @brief clear current upload buffer * - * @return + * @return */ -void clear_upload_buffer(); +void clear_upload_buffer(void); /** * @brief do one upload to server * - * @param force_upload if true, it will do upload right away, otherwise it will check log_level, buffer left and upload interval - * @return QCLOUD_ERR_SUCCESS when success or no log to upload or timer is not expired + * @param force_upload if true, it will do upload right away, otherwise it will check log_level, buffer left and upload + * interval + * @return QCLOUD_RET_SUCCESS when success or no log to upload or timer is not expired */ int do_log_upload(bool force_upload); @@ -73,22 +84,20 @@ void set_log_upload_in_comm_err(bool value); * * @param client * @param log_level - * @return QCLOUD_ERR_SUCCESS when success + * @return QCLOUD_RET_SUCCESS when success */ -int qcloud_get_log_level(void* client, int *log_level); +int qcloud_get_log_level(void *client, int *log_level); /** * @brief subscribe to upload log_level topic * * @param client - * @return QCLOUD_ERR_SUCCESS when success + * @return QCLOUD_RET_SUCCESS when success */ int qcloud_log_topic_subscribe(void *client); - #ifdef __cplusplus } #endif -#endif //QCLOUD_IOT_LOG_UPLOAD_H_ - +#endif // QCLOUD_IOT_LOG_UPLOAD_H_ diff --git a/sdk_src/internal_inc/mqtt_client.h b/sdk_src/internal_inc/mqtt_client.h new file mode 100755 index 00000000..597858f0 --- /dev/null +++ b/sdk_src/internal_inc/mqtt_client.h @@ -0,0 +1,585 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef IOT_MQTT_CLIENT_H_ +#define IOT_MQTT_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "mqtt_client_net.h" +#include "qcloud_iot_common.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_list.h" +#include "utils_param_check.h" +#include "utils_timer.h" + +/* packet id, random from [1 - 65536] */ +#define MAX_PACKET_ID (65535) + +/* Max size of conn Id */ +#define MAX_CONN_ID_LEN (6) + +/* Max number of topic subscribed */ +#define MAX_MESSAGE_HANDLERS (10) + +/* Max number in repub list */ +#define MAX_REPUB_NUM (20) + +/* Minimal wait interval when reconnect */ +#define MIN_RECONNECT_WAIT_INTERVAL (1000) + +/* Minimal MQTT timeout value */ +#define MIN_COMMAND_TIMEOUT (500) + +/* Maxmal MQTT timeout value */ +#define MAX_COMMAND_TIMEOUT (20000) + +/* Max size of a topic name */ +#define MAX_SIZE_OF_CLOUD_TOPIC ((MAX_SIZE_OF_DEVICE_NAME) + (MAX_SIZE_OF_PRODUCT_ID) + 64 + 6) + +/* minimal TLS handshaking timeout value (unit: ms) */ +#define QCLOUD_IOT_TLS_HANDSHAKE_TIMEOUT (5 * 1000) + +#define MQTT_RMDUP_MSG_ENABLED + +/** + * @brief MQTT Message Type + */ +typedef enum msgTypes { + RESERVED = 0, // Reserved + CONNECT = 1, // Client request to connect to Server + CONNACK = 2, // Connect Acknowledgment + PUBLISH = 3, // Publish message + PUBACK = 4, // Publish Acknowledgment + PUBREC = 5, // Publish Received + PUBREL = 6, // Publish Release + PUBCOMP = 7, // Publish Complete + SUBSCRIBE = 8, // Client Subscribe request + SUBACK = 9, // Subscribe Acknowledgment + UNSUBSCRIBE = 10, // Client Unsubscribe request + UNSUBACK = 11, // Unsubscribe Acknowledgment + PINGREQ = 12, // PING Request + PINGRESP = 13, // PING Response + DISCONNECT = 14 // Client is Disconnecting +} MessageTypes; + +typedef enum { NOTCONNECTED = 0, CONNECTED = 1 } ConnStatus; + +/** + * MQTT byte 1: fixed header + * bits |7654: Message Type | 3:DUP flag | 21:QoS level | 0:RETAIN | + */ +#define MQTT_HEADER_TYPE_SHIFT 0x04 +#define MQTT_HEADER_TYPE_MASK 0xF0 +#define MQTT_HEADER_DUP_SHIFT 0x03 +#define MQTT_HEADER_DUP_MASK 0x08 +#define MQTT_HEADER_QOS_SHIFT 0x01 +#define MQTT_HEADER_QOS_MASK 0x06 +#define MQTT_HEADER_RETAIN_MASK 0x01 + +/** + * @brief MQTT will options sturcture + * + */ +typedef struct { + char struct_id[4]; // The eyecatcher for this structure. must be MQTW + uint8_t struct_version; // struct version = 0 + char * topic_name; + char * message; + uint8_t retained; + QoS qos; +} WillOptions; + +/** + * default MQTT will options + */ +#define DEFAULT_WILL_OPTIONS \ + { \ + {'M', 'Q', 'T', 'W'}, 0, NULL, NULL, 0, QOS0 \ + } + +/** + * @brief define MQTT connect parameters structure + * + */ +typedef struct { + char *client_id; // unique client id + char *username; // user name + char *password; // passwrod + + char conn_id[MAX_CONN_ID_LEN]; + + char struct_id[4]; // The eyecatcher for this structure. must be MQTC. + uint8_t struct_version; // struct version = 0 + uint8_t mqtt_version; // MQTT protocol version: 4 = 3.1.1 + + uint16_t keep_alive_interval; // keep alive interval, unit: second + uint8_t clean_session; // flag of clean session, refer to MQTT spec 3.1.2.4 + + uint8_t auto_connect_enable; // enable auto connection or not + +#ifdef AUTH_WITH_NOTLS + char *device_secret; // PSK + int device_secret_len; // length of PSK +#endif + +} MQTTConnectParams; + +/** + * default value of MQTT connect parameters structure + */ +#ifdef AUTH_WITH_NOTLS +#define DEFAULT_MQTTCONNECT_PARAMS \ + { \ + NULL, NULL, NULL, {0}, {'M', 'Q', 'T', 'C'}, 0, 4, 240, 1, 1, NULL, 0 \ + } +#else +#define DEFAULT_MQTTCONNECT_PARAMS \ + { \ + NULL, NULL, NULL, {0}, {'M', 'Q', 'T', 'C'}, 0, 4, 240, 1, 1 \ + } +#endif + +/** + * @brief data structure for topic subscription handle + */ +typedef struct SubTopicHandle { + const char * topic_filter; // topic name, wildcard filter is supported + OnMessageHandler message_handler; // callback when msg of this subscription arrives + OnSubEventHandler sub_event_handler; // callback when event of this subscription happens + void * handler_user_data; // user context for callback + QoS qos; // QoS +} SubTopicHandle; + +/** + * @brief data structure for system time service + */ +typedef struct _sys_mqtt_state { + bool topic_sub_ok; + bool result_recv_ok; + long time; + size_t ntptime1; + size_t ntptime2; +} SysMQTTState; + +/** + * @brief data structure for config service + */ +typedef struct _config_mqtt_state { + bool topic_sub_ok; + bool get_reply_ok; +} ConfigMQTTState; + +/** + * @brief MQTT QCloud IoT Client structure + */ +typedef struct Client { + uint8_t is_connected; + uint8_t was_manually_disconnected; + uint8_t is_ping_outstanding; // 1 = ping request is sent while ping response not arrived yet + + uint16_t next_packet_id; // MQTT random packet id + uint32_t command_timeout_ms; // MQTT command timeout, unit:ms + + uint32_t current_reconnect_wait_interval; // unit:ms + uint32_t counter_network_disconnected; // number of disconnection + + size_t write_buf_size; // size of MQTT write buffer + size_t read_buf_size; // size of MQTT read buffer + unsigned char write_buf[QCLOUD_IOT_MQTT_TX_BUF_LEN]; // MQTT write buffer + unsigned char read_buf[QCLOUD_IOT_MQTT_RX_BUF_LEN]; // MQTT read buffer + + void *lock_generic; // mutex/lock for this client struture + void *lock_write_buf; // mutex/lock for write buffer + + void *lock_list_pub; // mutex/lock for puback waiting list + void *lock_list_sub; // mutex/lock for suback waiting list + + List *list_pub_wait_ack; // puback waiting list + List *list_sub_wait_ack; // suback waiting list + + MQTTEventHandler event_handle; // callback for MQTT event + + MQTTConnectParams options; // handle to connection parameters + + Network network_stack; // MQTT network stack + + Timer ping_timer; // MQTT ping timer + Timer reconnect_delay_timer; // MQTT reconnect delay timer + + SubTopicHandle sub_handles[MAX_MESSAGE_HANDLERS]; // subscription handle array + + DeviceInfo device_info; + + char host_addr[HOST_STR_LENGTH]; + +#ifdef AUTH_MODE_CERT + char cert_file_path[FILE_PATH_MAX_LEN]; // full path of device cert file + char key_file_path[FILE_PATH_MAX_LEN]; // full path of device key file +#else + unsigned char psk_decode[DECODE_PSK_LENGTH]; +#endif + +#ifdef MQTT_RMDUP_MSG_ENABLED +#define MQTT_MAX_REPEAT_BUF_LEN 10 + uint16_t repeat_packet_id_buf[MQTT_MAX_REPEAT_BUF_LEN]; + unsigned int current_packet_id_cnt; +#endif + +#ifdef SYSTEM_COMM + SysMQTTState sys_state; +#endif + +#ifdef REMOTE_CONFIG_MQTT + ConfigMQTTState config_state; +#endif + +#ifdef BROADCAST_ENABLED + bool broadcast_state; // using in broadcast +#endif + +#ifdef RRPC_ENABLED + bool rrpc_state; +#endif + +#ifdef MULTITHREAD_ENABLED + bool thread_running; + int thread_exit_code; +#endif + +} Qcloud_IoT_Client; + +/** + * @brief MQTT protocol version + */ +typedef enum { MQTT_3_1_1 = 4 } MQTT_VERSION; + +typedef enum MQTT_NODE_STATE { + MQTT_NODE_STATE_NORMANL = 0, + MQTT_NODE_STATE_INVALID, +} MQTTNodeState; + +/* topic publish info */ +typedef struct REPUBLISH_INFO { + Timer pub_start_time; /* timer for puback waiting */ + MQTTNodeState node_state; /* node state in wait list */ + uint16_t msg_id; /* packet id */ + uint32_t len; /* msg length */ + unsigned char *buf; /* msg buffer */ +} QcloudIotPubInfo; + +/* topic subscribe/unsubscribe info */ +typedef struct SUBSCRIBE_INFO { + enum msgTypes type; /* type: sub or unsub */ + uint16_t msg_id; /* packet id */ + Timer sub_start_time; /* timer for suback waiting */ + MQTTNodeState node_state; /* node state in wait list */ + SubTopicHandle handler; /* handle of topic subscribed(unsubcribed) */ + uint16_t len; /* msg length */ + unsigned char *buf; /* msg buffer */ +} QcloudIotSubInfo; + +/** + * @brief Init MQTT client + * + * @param pClient handle to MQTT client + * @param pParams MQTT init parameters + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_init(Qcloud_IoT_Client *pClient, MQTTInitParams *pParams); + +/** + * @brief Release resources of MQTT client + * + * @param pClient handle to MQTT client + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_fini(Qcloud_IoT_Client *pClient); + +/** + * @brief Connect with MQTT server + * + * @param pClient handle to MQTT client + * @param pParams MQTT connect parameters + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_connect(Qcloud_IoT_Client *pClient, MQTTConnectParams *pParams); + +/** + * @brief Reconnect with MQTT server and re-subscribe topics if reconnected + * + * @param pClient handle to MQTT client + * + * @return QCLOUD_RET_MQTT_RECONNECTED for success, or err code for failure + */ +int qcloud_iot_mqtt_attempt_reconnect(Qcloud_IoT_Client *pClient); + +/** + * @brief Disconnect with MQTT server + * + * @param pClient handle to MQTT client + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_disconnect(Qcloud_IoT_Client *pClient); + +/** + * @brief Publish MQTT message + * + * @param pClient handle to MQTT client + * @param topicName MQTT topic name + * @param pParams publish parameters + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int qcloud_iot_mqtt_publish(Qcloud_IoT_Client *pClient, char *topicName, PublishParams *pParams); + +/** + * @brief Subscribe MQTT topic + * + * @param pClient handle to MQTT client + * @param topicFilter MQTT topic filter + * @param pParams subscribe parameters + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int qcloud_iot_mqtt_subscribe(Qcloud_IoT_Client *pClient, char *topicFilter, SubscribeParams *pParams); + +/** + * @brief Re-subscribe MQTT topics + * + * @param pClient handle to MQTT client + * + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_resubscribe(Qcloud_IoT_Client *pClient); + +/** + * @brief Unsubscribe MQTT topic + * + * @param pClient handle to MQTT client + * @param topicFilter MQTT topic filter + * + * @return packet id (>=0) when success, or err code (<0) for failure + */ +int qcloud_iot_mqtt_unsubscribe(Qcloud_IoT_Client *pClient, char *topicFilter); + +/** + * @brief check if MQTT topic has been subscribed or not + * + * @param pClient handle to MQTT client + * @param topicFilter MQTT topic filter + * + * @return true when successfully subscribed, or false if not yet + */ +bool qcloud_iot_mqtt_is_sub_ready(Qcloud_IoT_Client *pClient, char *topicFilter); + +/** + * @brief Check connection and keep alive state, read/handle MQTT message in synchronized way + * + * @param pClient handle to MQTT client + * @param timeout_ms timeout value (unit: ms) for this operation + * + * @return QCLOUD_RET_SUCCESS when success, QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT when try reconnecing, or err code for + * failure + */ +int qcloud_iot_mqtt_yield(Qcloud_IoT_Client *pClient, uint32_t timeout_ms); + +// workaround wrapper for qcloud_iot_mqtt_yield for multi-thread mode +int qcloud_iot_mqtt_yield_mt(Qcloud_IoT_Client *mqtt_client, uint32_t timeout_ms); + +/** + * @brief Check if auto reconnect is enabled or not + * + * @param pClient handle to MQTT client + * @return true if auto reconnect is enabled + */ +bool qcloud_iot_mqtt_is_autoreconnect_enabled(Qcloud_IoT_Client *pClient); + +/** + * @brief Set to enable auto reconnect or not + * + * @param pClient handle to MQTT client + * @param value enable or disable + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_set_autoreconnect(Qcloud_IoT_Client *pClient, bool value); + +/** + * @brief Get the count of disconnection + * + * @param pClient handle to MQTT client + * @return count of disconnection + */ +int qcloud_iot_mqtt_get_network_disconnected_count(Qcloud_IoT_Client *pClient); + +/** + * @brief Set the count of disconnection + * + * @param pClient handle to MQTT client + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_reset_network_disconnected_count(Qcloud_IoT_Client *pClient); + +/** + * @brief Get next packet id + * + * @param pClient + * @return + */ +uint16_t get_next_packet_id(Qcloud_IoT_Client *pClient); + +/** + * @brief Get next conn id + * + * @param options + * @return + */ +void get_next_conn_id(char *conn_id); + +/** + * @brief Init packet header + * @param header + * @param message_type + * @param qos + * @param dup + * @param retained + * @return + */ +int mqtt_init_packet_header(unsigned char *header, MessageTypes message_type, QoS qos, uint8_t dup, uint8_t retained); + +/** + * @brief Read and handle one MQTT msg/ack from server + * + * @param pClient + * @param timer + * @param packet_type + * @param qos + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int cycle_for_read(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_type, QoS qos); + +/** + * @brief Send the packet in buffer + * + * @param pClient + * @param length + * @param timer + * @return + */ +int send_mqtt_packet(Qcloud_IoT_Client *pClient, size_t length, Timer *timer); + +/** + * @brief wait for a specific packet with timeout + * + * only used in single-threaded mode where one command at a time is in process + * + * @param pClient MQTT Client + * @param packet_type MQTT packet type + * @param timer timer with timeout + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int wait_for_read(Qcloud_IoT_Client *pClient, uint8_t packet_type, Timer *timer, QoS qos); + +/** + * @brief Set MQTT connection state + * + * @param pClient MQTT Client + * @param connected 0: disconnected 1: connected + * @return + */ +void set_client_conn_state(Qcloud_IoT_Client *pClient, uint8_t connected); + +/** + * @brief Get MQTT connection state + * + * @param pClient MQTT Client + * @return 0: disconnected 1: connected + */ +uint8_t get_client_conn_state(Qcloud_IoT_Client *pClient); + +/** + * @brief Check Publish ACK waiting list, remove the node if PUBACK received or timeout + * + * @param pClient MQTT client + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_pub_info_proc(Qcloud_IoT_Client *pClient); + +/** + * @brief Check Subscribe ACK waiting list, remove the node if SUBACK received or timeout + * + * @param pClient MQTT client + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_iot_mqtt_sub_info_proc(Qcloud_IoT_Client *pClient); + +int push_sub_info_to(Qcloud_IoT_Client *c, int len, unsigned short msgId, MessageTypes type, SubTopicHandle *handler, + ListNode **node); + +int serialize_pub_ack_packet(unsigned char *buf, size_t buf_len, MessageTypes packet_type, uint8_t dup, + uint16_t packet_id, uint32_t *serialized_len); + +int serialize_packet_with_zero_payload(unsigned char *buf, size_t buf_len, MessageTypes packetType, + uint32_t *serialized_len); + +int deserialize_publish_packet(unsigned char *dup, QoS *qos, uint8_t *retained, uint16_t *packet_id, char **topicName, + uint16_t *topicNameLen, unsigned char **payload, size_t *payload_len, unsigned char *buf, + size_t buf_len); + +int deserialize_suback_packet(uint16_t *packet_id, uint32_t max_count, uint32_t *count, QoS *grantedQoSs, + unsigned char *buf, size_t buf_len); + +int deserialize_unsuback_packet(uint16_t *packet_id, unsigned char *buf, size_t buf_len); + +int deserialize_ack_packet(uint8_t *packet_type, uint8_t *dup, uint16_t *packet_id, unsigned char *buf, size_t buf_len); + +#ifdef MQTT_RMDUP_MSG_ENABLED + +void reset_repeat_packet_id_buffer(Qcloud_IoT_Client *pClient); + +#endif + +size_t get_mqtt_packet_len(size_t rem_len); + +size_t mqtt_write_packet_rem_len(unsigned char *buf, uint32_t length); + +int mqtt_read_packet_rem_len_form_buf(unsigned char *buf, uint32_t *value, uint32_t *readBytesLen); + +uint16_t mqtt_read_uint16_t(unsigned char **pptr); + +unsigned char mqtt_read_char(unsigned char **pptr); + +void mqtt_write_char(unsigned char **pptr, unsigned char c); + +void mqtt_write_uint_16(unsigned char **pptr, uint16_t anInt); + +void mqtt_write_utf8_string(unsigned char **pptr, const char *string); + +#ifdef __cplusplus +} +#endif + +#endif // IOT_MQTT_CLIENT_H_ diff --git a/src/mqtt/include/mqtt_client_net.h b/sdk_src/internal_inc/mqtt_client_net.h old mode 100644 new mode 100755 similarity index 76% rename from src/mqtt/include/mqtt_client_net.h rename to sdk_src/internal_inc/mqtt_client_net.h index 095f76d7..b9fb226b --- a/src/mqtt/include/mqtt_client_net.h +++ b/sdk_src/internal_inc/mqtt_client_net.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -20,13 +20,14 @@ extern "C" { #endif -#include "utils_net.h" +#include "network_interface.h" /** - * @brief 初始化TLS实现 + * @brief Init network stack * - * @param pNetwork 网络操作相关结构体 - * @return 返回0, 表示初始化成功 + * @param pNetwork + * @param pConnectParams + * @return 0 for success */ int qcloud_iot_mqtt_network_init(Network *pNetwork); @@ -34,4 +35,4 @@ int qcloud_iot_mqtt_network_init(Network *pNetwork); } #endif -#endif //IOT_MQTT_CLIENT_NET_H_ +#endif // IOT_MQTT_CLIENT_NET_H_ diff --git a/sdk_src/internal_inc/network_interface.h b/sdk_src/internal_inc/network_interface.h new file mode 100755 index 00000000..e6fa614b --- /dev/null +++ b/sdk_src/internal_inc/network_interface.h @@ -0,0 +1,127 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _NETWORK_INTERFACE_H_ +#define _NETWORK_INTERFACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "qcloud_iot_import.h" + +/* + * Type of network interface + */ + +typedef enum { NETWORK_TCP = 0, NETWORK_UDP = 1, NETWORK_TLS = 2, NETWORK_DTLS = 3 } NETWORK_TYPE; + +/** + * @brief Define structure for network stack + */ +typedef struct Network Network; + +/** + * @brief Define structure for network stack + * + * Network init/connect/read/write/disconnect/state + */ +struct Network { + int (*init)(Network *); + + int (*connect)(Network *); + + int (*read)(Network *, unsigned char *, size_t, uint32_t, size_t *); + + int (*write)(Network *, unsigned char *, size_t, uint32_t, size_t *); + + void (*disconnect)(Network *); + + int (*is_connected)(Network *); + + // connetion handle: + // for non-AT: 0 = not connected, non-zero = connected + // for AT: 0 = valid connection, MAX_UNSINGED_INT = invalid + uintptr_t handle; + +#ifndef AUTH_WITH_NOTLS + SSLConnectParams ssl_connect_params; +#endif + + const char * host; // server address + int port; // server port + NETWORK_TYPE type; +}; + +/* + * Init network stack + */ +int network_init(Network *pNetwork); + +/* return the handle */ +int is_network_connected(Network *pNetwork); + +/* network stack API */ +#ifdef AT_TCP_ENABLED + +#define AT_NO_CONNECTED_FD 0xffffffff + +int network_at_tcp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len); +int network_at_tcp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, + size_t *written_len); +void network_at_tcp_disconnect(Network *pNetwork); +int network_at_tcp_connect(Network *pNetwork); +int network_at_tcp_init(Network *pNetwork); + +#else +int network_tcp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len); +int network_tcp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len); +void network_tcp_disconnect(Network *pNetwork); +int network_tcp_connect(Network *pNetwork); +int network_tcp_init(Network *pNetwork); +#endif + +#ifndef AUTH_WITH_NOTLS +int network_tls_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len); +int network_tls_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len); +void network_tls_disconnect(Network *pNetwork); +int network_tls_connect(Network *pNetwork); +int network_tls_init(Network *pNetwork); +#endif + +#ifdef COAP_COMM_ENABLED +#ifdef AUTH_WITH_NOTLS +int network_udp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len); +int network_udp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len); +void network_udp_disconnect(Network *pNetwork); +int network_udp_connect(Network *pNetwork); +int network_udp_init(Network *pNetwork); +#else +int network_dtls_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len); +int network_dtls_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, + size_t *written_len); +void network_dtls_disconnect(Network *pNetwork); +int network_dtls_connect(Network *pNetwork); +int network_dtls_init(Network *pNetwork); +#endif +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _NETWORK_INTERFACE_H_ */ diff --git a/src/ota/include/ota_client.h b/sdk_src/internal_inc/ota_client.h old mode 100644 new mode 100755 similarity index 69% rename from src/ota/include/ota_client.h rename to sdk_src/internal_inc/ota_client.h index 4834d2f9..0cd57b0e --- a/src/ota/include/ota_client.h +++ b/sdk_src/internal_inc/ota_client.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -23,26 +23,24 @@ extern "C" { #include /* Specify the maximum characters of version */ -#define OTA_MAX_TOPIC_LEN (64) +#define OTA_MAX_TOPIC_LEN (64) -#define TYPE_FIELD "type" -#define MD5_FIELD "md5sum" -#define VERSION_FIELD "version" -#define URL_FIELD "url" -#define FILESIZE_FIELD "file_size" -#define RESULT_FIELD "result_code" +#define TYPE_FIELD "type" +#define MD5_FIELD "md5sum" +#define VERSION_FIELD "version" +#define URL_FIELD "url" +#define FILESIZE_FIELD "file_size" +#define RESULT_FIELD "result_code" -#define REPORT_VERSION_RSP "report_version_rsp" -#define UPDATE_FIRMWARE "update_firmware" +#define REPORT_VERSION_RSP "report_version_rsp" +#define UPDATE_FIRMWARE "update_firmware" -enum { - MQTT_CHANNEL, - COAP_CHANNEL -}; +enum { MQTT_CHANNEL, COAP_CHANNEL }; typedef void (*OnOTAMessageCallback)(void *pcontext, const char *msg, uint32_t msgLen); -void *qcloud_osc_init(const char *productId, const char *deviceName, void *channel, OnOTAMessageCallback callback, void *context); +void *qcloud_osc_init(const char *productId, const char *deviceName, void *channel, OnOTAMessageCallback callback, + void *context); int qcloud_osc_deinit(void *handle); diff --git a/src/ota/include/ota_fetch.h b/sdk_src/internal_inc/ota_fetch.h old mode 100644 new mode 100755 similarity index 86% rename from src/ota/include/ota_fetch.h rename to sdk_src/internal_inc/ota_fetch.h index 1655130f..ca1a222d --- a/src/ota/include/ota_fetch.h +++ b/sdk_src/internal_inc/ota_fetch.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -22,7 +22,7 @@ extern "C" { #include -void *ofc_Init(const char *url); +void *ofc_Init(const char *url, uint32_t offset, uint32_t size); int32_t qcloud_ofc_connect(void *handle); diff --git a/src/ota/include/ota_lib.h b/sdk_src/internal_inc/ota_lib.h old mode 100644 new mode 100755 similarity index 52% rename from src/ota/include/ota_lib.h rename to sdk_src/internal_inc/ota_lib.h index 73898f7c..8f340ce8 --- a/src/ota/include/ota_lib.h +++ b/sdk_src/internal_inc/ota_lib.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -20,8 +20,8 @@ extern "C" { #endif -#include #include +#include #include "qcloud_iot_export_ota.h" @@ -38,44 +38,42 @@ int qcloud_otalib_get_firmware_type(const char *json, char **type); int qcloud_otalib_get_report_version_result(const char *json); /** - * @brief 根据@json解析出来固件下载的相关信息 + * @brief Parse firmware info from JSON string * - * @param json JSON字符串 - * @param type 下发升级消息的时候,type为update_firmware - * @param url 解析得到的下载url - * @param version 解析得到的下载固件版本 - * @param md5 解析得到的下载固件MD5 - * @param fileSize 下载固件的大小 - * @return 返回QCLOUD_ERR_SUCCESS表示成功 + * @param json source JSON string + * @param type parsed type + * @param url parsed url + * @param version parsed version + * @param md5 parsed MD5 + * @param fileSize parsed file size + * @return QCLOUD_RET_SUCCESS for success, or err code for failure */ -int qcloud_otalib_get_params(const char *json, char **type, char **url, char **version, char *md5, - uint32_t *fileSize); - +int qcloud_otalib_get_params(const char *json, char **type, char **url, char **version, char *md5, uint32_t *fileSize); /** - * @brief 根据@id、@version生成固件信息,然后复制到@buf + * @brief Generate firmware info from id and version * - * @param buf 固件输出信息 - * @param bufLen 固件输出信息长度 - * @param id 固件id - * @param version 固件版本 - * @return 返回QCLOUD_ERR_SUCCESS表示成功 + * @param buf output buffer + * @param bufLen size of buffer + * @param id firmware id + * @param version firmware version + * @return QCLOUD_RET_SUCCESS for success, or err code for failure */ int qcloud_otalib_gen_info_msg(char *buf, size_t bufLen, uint32_t id, const char *version); - /** - * @brief 根据@id,@reportType生成报告信息 + * @brief Generate firmware report * - * @param buf 固件报告信息 - * @param bufLen 固件报告信息长度 - * @param id 固件id - * @param version 固件版本 - * @param progress 固件下载进度 - * @param reportType 报告类型 - * @return 返回QCLOUD_ERR_SUCCESS表示成功 + * @param buf output buffer + * @param bufLen size of buffer + * @param id firmware id + * @param version firmware version + * @param progress download progress + * @param reportType report type + * @return QCLOUD_RET_SUCCESS for success, or err code for failure */ -int qcloud_otalib_gen_report_msg(char *buf, size_t bufLen, uint32_t id, const char *version, int progress, IOT_OTAReportType reportType); +int qcloud_otalib_gen_report_msg(char *buf, size_t bufLen, uint32_t id, const char *version, int progress, + IOT_OTAReportType reportType); #ifdef __cplusplus } diff --git a/src/device/include/ca.h b/sdk_src/internal_inc/qcloud_iot_ca.h old mode 100644 new mode 100755 similarity index 90% rename from src/device/include/ca.h rename to sdk_src/internal_inc/qcloud_iot_ca.h index 10d9fa35..974bc76c --- a/src/device/include/ca.h +++ b/sdk_src/internal_inc/qcloud_iot_ca.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -28,6 +28,4 @@ const char *iot_https_ca_get(void); } #endif - - #endif /* IOT_CA_H_ */ diff --git a/sdk_src/internal_inc/qcloud_iot_common.h b/sdk_src/internal_inc/qcloud_iot_common.h new file mode 100755 index 00000000..5619b612 --- /dev/null +++ b/sdk_src/internal_inc/qcloud_iot_common.h @@ -0,0 +1,47 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_COMMON_H_ +#define QCLOUD_IOT_COMMON_H_ + +/* IoT C-SDK APPID */ +#define QCLOUD_IOT_DEVICE_SDK_APPID "21010406" + +/* MQTT server domain */ +#define QCLOUD_IOT_MQTT_DIRECT_DOMAIN "iotcloud.tencentdevices.com" +#define MQTT_SERVER_PORT_TLS 8883 +#define MQTT_SERVER_PORT_NOTLS 1883 + +/* CoAP server domain */ +#define QCLOUD_IOT_COAP_DEIRECT_DOMAIN "iotcloud.tencentdevices.com" +#define COAP_SERVER_PORT 5684 + +/* server domain for dynamic registering device */ +#define DYN_REG_SERVER_URL "gateway.tencentdevices.com" +#define DYN_REG_SERVER_PORT 80 +#define DYN_REG_SERVER_PORT_TLS 443 + +/* URL for doing log upload */ +#define LOG_UPLOAD_SERVER_URL "http://devicelog.iot.cloud.tencent.com/cgi-bin/report-log" +#define LOG_UPLOAD_SERVER_DOMAIN "devicelog.iot.cloud.tencent.com" +#define LOG_UPLOAD_SERVER_PORT 80 + +/* Max size of a host name */ +#define HOST_STR_LENGTH 64 + +/* Max size of base64 encoded PSK = 64, after decode: 64/4*3 = 48*/ +#define DECODE_PSK_LENGTH 48 + +#endif /* QCLOUD_IOT_COMMON_H_ */ diff --git a/src/device/include/device.h b/sdk_src/internal_inc/qcloud_iot_device.h old mode 100644 new mode 100755 similarity index 78% rename from src/device/include/device.h rename to sdk_src/internal_inc/qcloud_iot_device.h index 97b73859..6b17eef0 --- a/src/device/include/device.h +++ b/sdk_src/internal_inc/qcloud_iot_device.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -23,11 +23,7 @@ extern "C" { #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" -int iot_device_info_init(void); - -int iot_device_info_set(const char *product_id, const char *device_name); - -DeviceInfo* iot_device_info_get(void); +int iot_device_info_set(DeviceInfo *device_info, const char *product_id, const char *device_name); #ifdef __cplusplus } diff --git a/sdk_src/internal_inc/shadow_client.h b/sdk_src/internal_inc/shadow_client.h new file mode 100755 index 00000000..0a4e0fc4 --- /dev/null +++ b/sdk_src/internal_inc/shadow_client.h @@ -0,0 +1,121 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef IOT_SHADOW_CLIENT_H_ +#define IOT_SHADOW_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "mqtt_client.h" +#include "qcloud_iot_device.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "shadow_client_json.h" +#include "utils_param_check.h" + +/* Max number of requests in appending state */ +#define MAX_APPENDING_REQUEST_AT_ANY_GIVEN_TIME (10) + +/* Max size of clientToken */ +#define MAX_SIZE_OF_CLIENT_TOKEN (MAX_SIZE_OF_CLIENT_ID + 10) + +/* Max size of JSON string which only contain clientToken field */ +#define MAX_SIZE_OF_JSON_WITH_CLIENT_TOKEN (MAX_SIZE_OF_CLIENT_TOKEN + 20) + +/* Size of buffer to receive JSON document from server */ +#define CLOUD_IOT_JSON_RX_BUF_LEN (QCLOUD_IOT_MQTT_RX_BUF_LEN + 1) + +/** + * @brief define type of request parameters + */ +typedef struct _RequestParam { + Method method; // method type: GET, UPDATE, DELETE + + uint32_t timeout_sec; // request timeout in second + + OnRequestCallback request_callback; // request callback + + void *user_context; // user context for callback + +} RequestParams; + +#define DEFAULT_REQUEST_PARAMS {GET, 4, NULL, NULL}; + +/** + * @brief for property and it's callback + */ +typedef struct { + void *property; + + OnPropRegCallback callback; + +} PropertyHandler; + +typedef struct _ShadowInnerData { + uint32_t token_num; + int32_t sync_status; + List * request_list; + List * property_handle_list; + char * result_topic; +} ShadowInnerData; + +typedef struct _Shadow { + void * mqtt; + void * mutex; + eShadowType shadow_type; + MQTTEventHandler event_handle; + ShadowInnerData inner_data; + char shadow_recv_buf[CLOUD_IOT_JSON_RX_BUF_LEN]; +} Qcloud_IoT_Shadow; + +int qcloud_iot_shadow_init(Qcloud_IoT_Shadow *pShadow); + +void qcloud_iot_shadow_reset(void *pClient); + +/** + * @brief handle the expired requests in list + * + * @param pShadow shadow client + */ +void handle_expired_request(Qcloud_IoT_Shadow *pShadow); + +/** + * @brief Entry of all shadow JSON request + * + * @param pShadow shadow client + * @param pParams request param + * @param pJsonDoc JSON buffer + * @param sizeOfBuffer size of buffer + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int do_shadow_request(Qcloud_IoT_Shadow *pShadow, RequestParams *pParams, char *pJsonDoc, size_t sizeOfBuffer); + +/** + * @brief subscribe shadow topic $shadow/operation/result + * + * @param pShadow shadow client + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int subscribe_operation_result_to_cloud(Qcloud_IoT_Shadow *pShadow); + +#ifdef __cplusplus +} +#endif + +#endif /* IOT_SHADOW_CLIENT_H_ */ diff --git a/src/shadow/include/shadow_client_common.h b/sdk_src/internal_inc/shadow_client_common.h old mode 100644 new mode 100755 similarity index 62% rename from src/shadow/include/shadow_client_common.h rename to sdk_src/internal_inc/shadow_client_common.h index 7acd7939..a7f5f997 --- a/src/shadow/include/shadow_client_common.h +++ b/sdk_src/internal_inc/shadow_client_common.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -23,36 +23,36 @@ extern "C" { #include "shadow_client.h" /** - * @brief 如果没有订阅delta主题, 则进行订阅, 并注册相应设备属性 + * @brief register a device property * * @param pShadow shadow client - * @param pProperty 设备属性 - * @param callback 相应设备属性处理回调函数 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 + * @param pProperty device property + * @param callback callback when property changes + * @return QCLOUD_RET_SUCCESS for success, or err code for failure */ -int shadow_common_register_property_on_delta(Qcloud_IoT_Shadow *pShadow, DeviceProperty *pProperty, OnPropRegCallback callback); +int shadow_common_register_property_on_delta(Qcloud_IoT_Shadow *pShadow, DeviceProperty *pProperty, + OnPropRegCallback callback); /** - * @brief 移除注册过的设备属性 + * @brief remove a device property * * @param pShadow shadow client - * @param pProperty 设备属性 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 + * @param pProperty device property + * @return QCLOUD_RET_SUCCESS for success, or err code for failure */ int shadow_common_remove_property(Qcloud_IoT_Shadow *pshadow, DeviceProperty *pProperty); /** - * @brief 检查注册属性是否已经存在 + * @brief check if a device property exists * * @param pShadow shadow client - * @param pProperty 设备属性 - * @return 返回 0, 表示属性不存在 + * @param pProperty device property + * @return 0 = not existed */ int shadow_common_check_property_existence(Qcloud_IoT_Shadow *pshadow, DeviceProperty *pProperty); - #ifdef __cplusplus } #endif -#endif //IOT_SHADOW_CLIENT_COMMON_H_ +#endif // IOT_SHADOW_CLIENT_COMMON_H_ diff --git a/sdk_src/internal_inc/shadow_client_json.h b/sdk_src/internal_inc/shadow_client_json.h new file mode 100755 index 00000000..cd8d5eec --- /dev/null +++ b/sdk_src/internal_inc/shadow_client_json.h @@ -0,0 +1,186 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef IOT_SHADOW_CLIENT_JSON_H_ +#define IOT_SHADOW_CLIENT_JSON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#define VERSION_FIELD "version" +#define TYPE_FIELD "type" +#define CLIENT_TOKEN_FIELD "clientToken" +#define RESULT_FIELD "result" + +#define OPERATION_DELTA "delta" +#define OPERATION_GET "get" +#define OPERATION_UPDATE "update" + +#define PAYLOAD_STATE "payload.state" +#define PAYLOAD_VERSION "payload.version" +#define PAYLOAD_STATE_DELTA "payload.state.delta" + +#define REPLY_CODE "code" +#define REPLY_STATUS "status" + +/** + * add a JSON node to JSON string + * + * @param jsonBuffer JSON string buffer + * @param sizeOfBuffer size of buffer + * @param pKey key of JSON node + * @param pData value of JSON node + * @param type value type of JSON node + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int put_json_node(char *jsonBuffer, size_t sizeOfBuffer, const char *pKey, void *pData, JsonDataType type); + +/** + * add a event JSON node to JSON string + * + * @param jsonBuffer JSON string buffer + * @param sizeOfBuffer size of buffer + * @param pKey key of JSON node + * @param pData value of JSON node + * @param type value type of JSON node + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int event_put_json_node(char *jsonBuffer, size_t sizeOfBuffer, const char *pKey, void *pData, JsonDataType type); + +/** + * @brief generate a ClientToken + * + * @param pStrBuffer string buffer + * @param sizeOfBuffer size of buffer + * @param tokenNumber shadow token number, increment every time + * @param product_id device product ID + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int generate_client_token(char *pStrBuffer, size_t sizeOfBuffer, uint32_t *tokenNumber, char *product_id); + +/** + * @brief generate an empty JSON with only clientToken + * + * @param tokenNumber shadow token number, increment every time + * @param pJsonBuffer JSON string buffer + * @param product_id device product ID + */ +void build_empty_json(uint32_t *tokenNumber, char *pJsonBuffer, char *product_id); + +/** + * @brief parse field of clientToken from JSON string + * + * @param pJsonDoc source JSON string + * @param pClientToken pointer to field of ClientToken + * @return true for success + */ +bool parse_client_token(char *pJsonDoc, char **pClientToken); + +/** + * @brief parse field of status from JSON string + * + * @param pJsonDoc source JSON string + * @param pStatus pointer to field of status + * @return true for success + */ +bool parse_status_return(char *pJsonDoc, char **pStatus); + +/** + * @brief parse field of code from JSON string + * + * @param pJsonDoc source JSON string + * @param pCode pointer to field of Code + * @return true for success + */ +bool parse_code_return(char *pJsonDoc, int32_t *pCode); + +/** + * @brief parse field of version from JSON string + * + * @param pJsonDoc source JSON string + + * @param pVersionNumber pointer to version + * @return true for success + */ +bool parse_version_num(char *pJsonDoc, uint32_t *pVersionNumber); + +/** + * @brief parse field of state from JSON string + * + * @param pJsonDoc source JSON string + * @param pState pointer to field of state + * @return true for success + */ +bool parse_shadow_state(char *pJsonDoc, char **pState); + +/** + * @brief parse field of type from JSON string + * + * @param pJsonDoc source JSON string + * @param pType pointer to field of tyde + * @return true for success + */ +bool parse_shadow_operation_type(char *pJsonDoc, char **pType); + +/** + * @brief parse field of result from JSON string + * + * @param pJsonDoc source JSON string + * @param pResultCode pointer to result code + * @return true for success + */ +bool parse_shadow_operation_result_code(char *pJsonDoc, int16_t *pResultCode); + +/** + * @brief parse field of delta from JSON string + * + * @param pJsonDoc source JSON string + * @param pDelta pointer to field of delta + * @return true for success + */ +bool parse_shadow_operation_delta(char *pJsonDoc, char **pDelta); + +/** + * @brief parse field of get from JSON string + * + * @param pJsonDoc source JSON string + * @param pDelta pointer to field of delta + * @return true for success + */ +bool parse_shadow_operation_get(char *pJsonDoc, char **pDelta); + +/** + * @brief update value in JSON if key is matched, not for OBJECT type + * + * @param pJsonDoc JSON string + * @param pProperty device property + * @return true for success + */ +bool update_value_if_key_match(char *pJsonDoc, DeviceProperty *pProperty); + +#ifdef __cplusplus +} +#endif + +#endif // IOT_SHADOW_CLIENT_JSON_H_ diff --git a/sdk_src/internal_inc/utils_aes.h b/sdk_src/internal_inc/utils_aes.h new file mode 100755 index 00000000..b84e896c --- /dev/null +++ b/sdk_src/internal_inc/utils_aes.h @@ -0,0 +1,293 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef QCLOUD_IOT_UTILS_AES_H_ +#define QCLOUD_IOT_UTILS_AES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +//========Platform================================// +#define UTILS_AES_C +#define UTILS_CIPHER_MODE_CBC +//#define UTILS_SELF_TEST + +#define UTILS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */ +#define UTILS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */ + +/* Internal macros meant to be called only from within the library. */ +#define UTILS_INTERNAL_VALIDATE_RET(cond, ret) \ + do { \ + } while (0) +#define UTILS_INTERNAL_VALIDATE(cond) \ + do { \ + } while (0) +//==============================================// + +/* padlock.c and aesni.c rely on these values! */ +#define UTILS_AES_ENCRYPT 1 /**< AES encryption. */ +#define UTILS_AES_DECRYPT 0 /**< AES decryption. */ + +#define UTILS_AES_BLOCK_LEN 16 +#define AES_KEY_BITS_128 128 +#define AES_KEY_BITS_192 192 +#define AES_KEY_BITS_256 256 + +/* Error codes in range 0x0020-0x0022 */ +#define UTILS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define UTILS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0021-0x0025 */ +#define UTILS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ + +/* UTILS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ +#define UTILS_ERR_AES_FEATURE_UNAVAILABLE \ + -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ + +/* UTILS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define UTILS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if !defined(UTILS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct utils_aes_context { + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} utils_aes_context; + +#else /* UTILS_AES_ALT */ +#include "aes_alt.h" +#endif /* UTILS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. This must not be \c NULL. + */ +void utils_aes_init(utils_aes_context *ctx); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void utils_aes_free(utils_aes_context *ctx); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #UTILS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int utils_aes_setkey_enc(utils_aes_context *ctx, const unsigned char *key, unsigned int keybits); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #UTILS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int utils_aes_setkey_dec(utils_aes_context *ctx, const unsigned char *key, unsigned int keybits); + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * utils_aes_init(), and either utils_aes_setkey_enc() or + * utils_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #UTILS_AES_ENCRYPT or + * #UTILS_AES_DECRYPT. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. + + * \return \c 0 on success. + */ +int utils_aes_crypt_ecb(utils_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); + +#if defined(UTILS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. utils_aes_init(), and either + * utils_aes_setkey_enc() or utils_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #UTILS_AES_ENCRYPT or + * #UTILS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (\c 16 Bytes). + * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + * \return #UTILS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +int utils_aes_crypt_cbc(utils_aes_context *ctx, int mode, size_t length, unsigned char iv[16], + const unsigned char *input, unsigned char *output); +#endif /* UTILS_CIPHER_MODE_CBC */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c UTILS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +int utils_internal_aes_encrypt(utils_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c UTILS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +int utils_internal_aes_decrypt(utils_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); + +#if !defined(UTILS_DEPRECATED_REMOVED) +#if defined(UTILS_DEPRECATED_WARNING) +#define UTILS_DEPRECATED __attribute__((deprecated)) +#else +#define UTILS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by utils_internal_aes_encrypt() + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +UTILS_DEPRECATED void utils_aes_encrypt(utils_aes_context *ctx, const unsigned char input[16], + unsigned char output[16]); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by utils_internal_aes_decrypt() + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +UTILS_DEPRECATED void utils_aes_decrypt(utils_aes_context *ctx, const unsigned char input[16], + unsigned char output[16]); + +#undef UTILS_DEPRECATED +#endif /* !UTILS_DEPRECATED_REMOVED */ + +#if defined(UTILS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int utils_aes_self_test(int verbose); + +#endif /* UTILS_SELF_TEST */ + +int aes_sample(int verbose); + +int utils_aes_cbc(uint8_t *pInData, uint32_t datalen, uint8_t *pOutData, uint32_t outBuffLen, uint8_t mode, + uint8_t *pKey, uint16_t keybits, uint8_t *iv); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/utils/digest/utils_base64.h b/sdk_src/internal_inc/utils_base64.h old mode 100644 new mode 100755 similarity index 68% rename from src/utils/digest/utils_base64.h rename to sdk_src/internal_inc/utils_base64.h index c54fb938..45ef6a1e --- a/src/utils/digest/utils_base64.h +++ b/sdk_src/internal_inc/utils_base64.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -19,17 +19,15 @@ #ifdef __cplusplus extern "C" { #endif - + #include - -#include "qcloud_iot_export_log.h" + #include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_log.h" -int qcloud_iot_utils_base64encode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ); +int qcloud_iot_utils_base64encode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen); -int qcloud_iot_utils_base64decode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ); +int qcloud_iot_utils_base64decode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen); #ifdef __cplusplus } diff --git a/src/utils/digest/utils_hmac.h b/sdk_src/internal_inc/utils_hmac.h old mode 100644 new mode 100755 similarity index 83% rename from src/utils/digest/utils_hmac.h rename to sdk_src/internal_inc/utils_hmac.h index 9bf1de9e..c2882913 --- a/src/utils/digest/utils_hmac.h +++ b/sdk_src/internal_inc/utils_hmac.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -22,5 +22,6 @@ void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len); -#endif +int utils_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len); +#endif diff --git a/sdk_src/internal_inc/utils_httpc.h b/sdk_src/internal_inc/utils_httpc.h new file mode 100755 index 00000000..1e27c7a8 --- /dev/null +++ b/sdk_src/internal_inc/utils_httpc.h @@ -0,0 +1,76 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef QCLOUD_IOT_UTILS_HTTPC_H_ +#define QCLOUD_IOT_UTILS_HTTPC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "network_interface.h" + +#define HTTP_PORT 80 +#define HTTPS_PORT 443 + +typedef enum { HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_DELETE, HTTP_HEAD } HttpMethod; + +typedef struct { + int remote_port; + int response_code; + char * header; + char * auth_user; + char * auth_password; + Network network_stack; +} HTTPClient; + +typedef struct { + bool is_more; // if more data to check + bool is_chunked; // if response in chunked data + int retrieve_len; // length of retrieve + int response_content_len; // length of resposne content + int post_buf_len; // post data length + int response_buf_len; // length of response data buffer + char *post_content_type; // type of post content + char *post_buf; // post data buffer + char *response_buf; // response data buffer +} HTTPClientData; + +/** + * @brief do one http request + * + * @param client http client + * @param url server url + * @param port server port + * @param ca_crt_dir ca path + * @param method type of request + * @param client_data http data + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +int qcloud_http_client_common(HTTPClient *client, const char *url, int port, const char *ca_crt, HttpMethod method, + HTTPClientData *client_data); + +int qcloud_http_recv_data(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data); + +int qcloud_http_client_connect(HTTPClient *client, const char *url, int port, const char *ca_crt); + +void qcloud_http_client_close(HTTPClient *client); + +#ifdef __cplusplus +} +#endif +#endif /* QCLOUD_IOT_UTILS_HTTPC_H_ */ diff --git a/src/utils/farra/utils_list.h b/sdk_src/internal_inc/utils_list.h old mode 100644 new mode 100755 similarity index 80% rename from src/utils/farra/utils_list.h rename to sdk_src/internal_inc/utils_list.h index ac566607..b70211fd --- a/src/utils/farra/utils_list.h +++ b/sdk_src/internal_inc/utils_list.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -22,48 +22,43 @@ extern "C" { #include - /* - * ListNode迭代器的方向. + * ListNode iterator direction */ -typedef enum { - LIST_HEAD, - LIST_TAIL -} ListDirection; +typedef enum { LIST_HEAD, LIST_TAIL } ListDirection; /* - * 链表节点定义. + * define list node */ typedef struct ListNode { struct ListNode *prev; struct ListNode *next; - void *val; + void * val; } ListNode; /* - * 链表. + * Double Linked List */ typedef struct { - ListNode *head; - ListNode *tail; + ListNode * head; + ListNode * tail; unsigned int len; void (*free)(void *val); int (*match)(void *a, void *b); } List; /* - * 迭代器. + * list iterator */ typedef struct { - ListNode *next; + ListNode * next; ListDirection direction; } ListIterator; - -/* 节点. */ +/* create node */ ListNode *list_node_new(void *val); -/* 链表. */ +/* create list */ List *list_new(void); ListNode *list_rpush(List *self, ListNode *node); @@ -82,7 +77,7 @@ void list_remove(List *self, ListNode *node); void list_destroy(List *self); -/* 迭代器. */ +/* create iterator */ ListIterator *list_iterator_new(List *list, ListDirection direction); ListIterator *list_iterator_new_from_node(ListNode *node, ListDirection direction); @@ -94,4 +89,4 @@ void list_iterator_destroy(ListIterator *self); #ifdef __cplusplus } #endif -#endif //QCLOUD_IOT_UTILS_LIST_H_ +#endif // QCLOUD_IOT_UTILS_LIST_H_ diff --git a/src/utils/digest/utils_md5.h b/sdk_src/internal_inc/utils_md5.h old mode 100644 new mode 100755 similarity index 53% rename from src/utils/digest/utils_md5.h rename to sdk_src/internal_inc/utils_md5.h index 33a8beb0..3ce0a0b5 --- a/src/utils/digest/utils_md5.h +++ b/sdk_src/internal_inc/utils_md5.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,82 +13,84 @@ * */ - - #ifndef QCLOUD_IOT_UTILS_MD5_H_ #define QCLOUD_IOT_UTILS_MD5_H_ #include "qcloud_iot_import.h" 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 */ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ } iot_md5_context; - - /** - * @brief 初始化MD5上下文 +/** + * @brief init MD5 context * - * @param ctx MD5上下文指针 + * @param ctx MD5 context */ void utils_md5_init(iot_md5_context *ctx); /** - * @brief 清空MD5上下文 + * @brief free MD5 context * - * @param ctx MD5上下文指针 + * @param ctx MD5 context */ void utils_md5_free(iot_md5_context *ctx); /** - * @brief 拷贝MD5上下文 + * @brief clone MD5 context * - * @param dst 目标MD5上下文 - * @param src 源MD5上下文 + * @param dst destination MD5 context + * @param src source MD5 context */ -void utils_md5_clone(iot_md5_context *dst, - const iot_md5_context *src); +void utils_md5_clone(iot_md5_context *dst, const iot_md5_context *src); /** - * @brief 设置MD5上下文 + * @brief start MD5 calculation * - * @param ctx MD5上下文指针 + * @param ctx MD5 context */ void utils_md5_starts(iot_md5_context *ctx); /** - * @brief MD5过程缓冲区 + * @brief MD5 update * - * @param ctx MD5上下文指针 - * @param input 输入数据 - * @param ilen 输入数据长度 + * @param ctx MD5 context + * @param input input data + * @param ilen data length */ void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t ilen); /** - * @brief MD5数据 + * @brief finish MD5 calculation * - * @param ctx MD5上下文指针 - * @param output MD5校验和结果 + * @param ctx MD5 context + * @param output MD5 result */ void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]); -/* 内部使用 */ +/* MD5 internal process */ void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]); /** * @brief Output = MD5( input buffer ) * - * @param input 输入数据 - * @param ilen 输入数据长度 - * @param output MD5校验和结果 + * @param input data input + * @param ilen data lenght + * @param output MD5 result */ void utils_md5(const unsigned char *input, size_t ilen, unsigned char output[16]); +/** + * @brief Output = MD5( input buffer ) + * + * @param input data input + * @param ilen data lenght + * @param output string MD5 result + */ +void utils_md5_str(const unsigned char *input, size_t ilen, unsigned char *output); int8_t utils_hb2hex(uint8_t hb); - #endif - diff --git a/sdk_src/internal_inc/utils_param_check.h b/sdk_src/internal_inc/utils_param_check.h new file mode 100755 index 00000000..8c679ef6 --- /dev/null +++ b/sdk_src/internal_inc/utils_param_check.h @@ -0,0 +1,85 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _UTILS_PARAM_CHECK_H_ +#define _UTILS_PARAM_CHECK_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "qcloud_iot_export_log.h" + +#define NUMBERIC_SANITY_CHECK(num, err) \ + do { \ + if (0 == (num)) { \ + Log_e("Invalid argument, numeric 0"); \ + return (err); \ + } \ + } while (0) + +#define NUMBERIC_SANITY_CHECK_RTN(num) \ + do { \ + if (0 == (num)) { \ + Log_e("Invalid argument, numeric 0"); \ + return; \ + } \ + } while (0) + +#define POINTER_SANITY_CHECK(ptr, err) \ + do { \ + if (NULL == (ptr)) { \ + Log_e("Invalid argument, %s = %p", #ptr, ptr); \ + return (err); \ + } \ + } while (0) + +#define POINTER_SANITY_CHECK_RTN(ptr) \ + do { \ + if (NULL == (ptr)) { \ + Log_e("Invalid argument, %s = %p", #ptr, ptr); \ + return; \ + } \ + } while (0) + +#define STRING_PTR_SANITY_CHECK(ptr, err) \ + do { \ + if (NULL == (ptr)) { \ + Log_e("Invalid argument, %s = %p", #ptr, (ptr)); \ + return (err); \ + } \ + if (0 == strlen((ptr))) { \ + Log_e("Invalid argument, %s = '%s'", #ptr, (ptr)); \ + return (err); \ + } \ + } while (0) + +#define STRING_PTR_SANITY_CHECK_RTN(ptr) \ + do { \ + if (NULL == (ptr)) { \ + Log_e("Invalid argument, %s = %p", #ptr, (ptr)); \ + return; \ + } \ + if (0 == strlen((ptr))) { \ + Log_e("Invalid argument, %s = '%s'", #ptr, (ptr)); \ + return; \ + } \ + } while (0) + +#if defined(__cplusplus) +} +#endif + +#endif /* _UTILS_PARAM_CHECK_H_ */ diff --git a/sdk_src/internal_inc/utils_ringbuff.h b/sdk_src/internal_inc/utils_ringbuff.h new file mode 100755 index 00000000..42480cd9 --- /dev/null +++ b/sdk_src/internal_inc/utils_ringbuff.h @@ -0,0 +1,42 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __AT_RING_BUFF_H__ +#define __AT_RING_BUFF_H__ + +#include "stdbool.h" +#include "stdint.h" + +#define RINGBUFF_OK 0 /* No error, everything OK. */ +#define RINGBUFF_ERR -1 /* Out of memory error. */ +#define RINGBUFF_EMPTY -3 /* Timeout. */ +#define RINGBUFF_FULL -4 /* Routing problem. */ +#define RINGBUFF_TOO_SHORT -5 + +typedef struct _ring_buff_ { + uint32_t size; + uint32_t readpoint; + uint32_t writepoint; + char* buffer; + bool full; +} sRingbuff; + +typedef sRingbuff* ring_buff_t; + +int ring_buff_init(sRingbuff* ring_buff, char* buff, uint32_t size); +int ring_buff_flush(sRingbuff* ring_buff); +int ring_buff_push_data(sRingbuff* ring_buff, uint8_t* pData, int len); +int ring_buff_pop_data(sRingbuff* ring_buff, uint8_t* pData, int len); +#endif // __ringbuff_h__ diff --git a/src/utils/digest/utils_sha1.h b/sdk_src/internal_inc/utils_sha1.h old mode 100644 new mode 100755 similarity index 85% rename from src/utils/digest/utils_sha1.h rename to sdk_src/internal_inc/utils_sha1.h index 8aa12007..167c41d0 --- a/src/utils/digest/utils_sha1.h +++ b/sdk_src/internal_inc/utils_sha1.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -18,14 +18,13 @@ #include "qcloud_iot_import.h" - /** * \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 */ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ } iot_sha1_context; /** @@ -48,8 +47,7 @@ void utils_sha1_free(iot_sha1_context *ctx); * \param dst The destination context * \param src The context to be cloned */ -void utils_sha1_clone(iot_sha1_context *dst, - const iot_sha1_context *src); +void utils_sha1_clone(iot_sha1_context *dst, const iot_sha1_context *src); /** * \brief SHA-1 context setup diff --git a/src/utils/farra/utils_timer.h b/sdk_src/internal_inc/utils_timer.h old mode 100644 new mode 100755 similarity index 78% rename from src/utils/farra/utils_timer.h rename to sdk_src/internal_inc/utils_timer.h index 8cd33311..2f8d5de3 --- a/src/utils/farra/utils_timer.h +++ b/sdk_src/internal_inc/utils_timer.h @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -19,10 +19,23 @@ #ifdef __cplusplus extern "C" { #endif - + // Add the platform specific timer includes to define the Timer struct #include "qcloud_iot_import.h" +/** + * Define RTC DATE TIME structure + */ +typedef struct { + int year; + int month; + int day; + int hour; + int minute; + int sec; + int ms; +} RTC_DATE_TIME; + /** * @brief Check if a timer is expired * @@ -71,10 +84,20 @@ int left_ms(Timer *timer); * @param timer - pointer to the timer to be initialized */ void InitTimer(Timer *timer); - + +/** + * @brief Time stamp converted to date + * + * Time stamp converted to date + * + * @param timestamp_sec timestamp second + * @param date_time output date_time + * @param time_zone +-time_zone, 8 is china time zone + */ +void timestamp_to_date(size_t timestamp_sec, RTC_DATE_TIME *date_time, int8_t time_zone); + #ifdef __cplusplus } #endif -#endif //QCLOUD_IOT_UTILS_TIMER_H_ - +#endif // QCLOUD_IOT_UTILS_TIMER_H_ diff --git a/sdk_src/network/at_socket/at_client.c b/sdk_src/network/at_socket/at_client.c new file mode 100755 index 00000000..219e813a --- /dev/null +++ b/sdk_src/network/at_socket/at_client.c @@ -0,0 +1,874 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "at_client.h" + +#include +#include +#include +#include + +#include "at_utils.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" +#include "utils_timer.h" + +#define AT_RESP_END_OK "OK" +#define AT_RESP_END_ERROR "ERROR" +#define AT_RESP_END_FAIL "FAIL" +#define AT_END_CR_LF "\r\n" + +sRingbuff g_ring_buff; +static at_client sg_at_client = {0}; +static uint32_t sg_flags = 0; + +/*this function can be called only by at_uart_isr, just push the data to the at_client ringbuffer.*/ +void at_client_uart_rx_isr_cb(uint8_t *pdata, uint8_t len) +{ + (void)ring_buff_push_data(&g_ring_buff, pdata, len); +} + +/** + * Create response object. + * + * @param buf_size the maximum response buffer size + * @param line_num the number of setting response lines + * = 0: the response data will auto return when received 'OK' or 'ERROR' + * != 0: the response data will return when received setting lines number data + * @param timeout the maximum response time + * + * @return != NULL: response object + * = NULL: no memory + */ +at_response_t at_create_resp(uint32_t buf_size, uint32_t line_num, uint32_t timeout) +{ + at_response_t resp = NULL; + + resp = (at_response_t)HAL_Malloc(sizeof(at_response)); + if (resp == NULL) { + Log_e("AT create response object failed! No memory for response object!"); + return NULL; + } + + resp->buf = (char *)HAL_Malloc(buf_size); + if (resp->buf == NULL) { + Log_e("AT create response object failed! No memory for response buffer!"); + HAL_Free(resp); + return NULL; + } + + resp->buf_size = buf_size; + resp->line_num = line_num; + resp->line_counts = 0; + resp->timeout = timeout; + + return resp; +} + +/** + * Delete and free response object. + * + * @param resp response object + */ +void at_delete_resp(at_response_t resp) +{ + if (resp && resp->buf) { + HAL_Free(resp->buf); + } + + if (resp) { + HAL_Free(resp); + resp = NULL; + } +} + +void at_delayms(uint32_t delayms) +{ +#ifdef AT_OS_USED + HAL_SleepMs(delayms); +#else + HAL_DelayMs(delayms); +#endif +} + +void at_setFlag(uint32_t flag) +{ + sg_flags |= flag & 0xffffffff; +} + +void at_clearFlag(uint32_t flag) +{ + sg_flags &= (~flag) & 0xffffffff; +} + +uint32_t at_getFlag(void) +{ + return sg_flags; +} + +bool at_waitFlag(uint32_t flag, uint32_t timeout) +{ + Timer timer; + bool Ret = false; + + countdown_ms(&timer, timeout); + do { + if (flag == (at_getFlag() & flag)) { + Ret = true; + break; + } + at_delayms(1); + } while (!expired(&timer)); + + return Ret; +} + +/** + * Get one line AT response buffer by line number. + * + * @param resp response object + * @param resp_line line number, start from '1' + * + * @return != NULL: response line buffer + * = NULL: input response line error + */ +const char *at_resp_get_line(at_response_t resp, uint32_t resp_line) +{ + char *resp_buf = resp->buf; + char *resp_line_buf = NULL; + int line_num = 1; + + POINTER_SANITY_CHECK(resp, NULL); + + if (resp_line > resp->line_counts || resp_line == 0) { + Log_e("AT response get line failed! Input response line(%d) error!", resp_line); + return NULL; + } + + for (line_num = 1; line_num <= resp->line_counts; line_num++) { + if (resp_line == line_num) { + resp_line_buf = resp_buf; + + return resp_line_buf; + } + + resp_buf += strlen(resp_buf) + 1; + } + + return NULL; +} + +/** + * Get one line AT response buffer by keyword + * + * @param resp response object + * @param keyword query keyword + * + * @return != NULL: response line buffer + * = NULL: no matching data + */ +const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword) +{ + char *resp_buf = resp->buf; + char *resp_line_buf = NULL; + int line_num = 1; + + POINTER_SANITY_CHECK(resp, NULL); + POINTER_SANITY_CHECK(keyword, NULL); + + for (line_num = 1; line_num <= resp->line_counts; line_num++) { + if (strstr(resp_buf, keyword)) { + resp_line_buf = resp_buf; + + return resp_line_buf; + } + + resp_buf += strlen(resp_buf) + 1; + } + + return NULL; +} + +/** + * Get and parse AT response buffer arguments by line number. + * + * @param resp response object + * @param resp_line line number, start from '1' + * @param resp_expr response buffer expression + * + * @return -1 : input response line number error or get line buffer error + * 0 : parsed without match + * >0 : the number of arguments successfully parsed + */ +int at_resp_parse_line_args(at_response_t resp, uint32_t resp_line, const char *resp_expr, ...) +{ + va_list args; + int resp_args_num = 0; + const char *resp_line_buf = NULL; + + POINTER_SANITY_CHECK(resp, -1); + POINTER_SANITY_CHECK(resp_expr, -1); + if ((resp_line_buf = at_resp_get_line(resp, resp_line)) == NULL) { + return -1; + } + + va_start(args, resp_expr); + + resp_args_num = vsscanf(resp_line_buf, resp_expr, args); + + va_end(args); + + return resp_args_num; +} + +/** + * Get and parse AT response buffer arguments by keyword. + * + * @param resp response object + * @param keyword query keyword + * @param resp_expr response buffer expression + * + * @return -1 : input keyword error or get line buffer error + * 0 : parsed without match + * >0 : the number of arguments successfully parsed + */ +int at_resp_parse_line_args_by_kw(at_response_t resp, const char *keyword, const char *resp_expr, ...) +{ + va_list args; + int resp_args_num = 0; + const char *resp_line_buf = NULL; + + POINTER_SANITY_CHECK(resp, -1); + POINTER_SANITY_CHECK(resp_expr, -1); + if ((resp_line_buf = at_resp_get_line_by_kw(resp, keyword)) == NULL) { + return -1; + } + + va_start(args, resp_expr); + + resp_args_num = vsscanf(resp_line_buf, resp_expr, args); + + va_end(args); + + return resp_args_num; +} + +/** + * Send commands to AT server and wait response. + * + * @param client current AT client object + * @param resp AT response object, using NULL when you don't care response + * @param cmd_expr AT commands expression + * + * @return 0 : success + * -1 : response status error + * -2 : wait timeout + */ +int at_obj_exec_cmd(at_response_t resp, const char *cmd_expr, ...) +{ + POINTER_SANITY_CHECK(cmd_expr, QCLOUD_ERR_INVAL); + + va_list args; + int cmd_size = 0; + int result = QCLOUD_RET_SUCCESS; + const char *cmd = NULL; + at_client_t client = at_client_get(); + + if (client == NULL) { + Log_e("input AT Client object is NULL, please create or get AT Client object!"); + return QCLOUD_ERR_FAILURE; + } + + HAL_MutexLock(client->lock); + resp->line_counts = 0; + client->resp_status = AT_RESP_OK; + client->resp = resp; + + va_start(args, cmd_expr); + at_vprintfln(cmd_expr, args); + va_end(args); + + if (resp != NULL) { +#ifndef AT_OS_USED + client->resp_status = AT_RESP_TIMEOUT; + at_client_yeild(NULL, resp->timeout); + if (client->resp_status != AT_RESP_OK) { + cmd = at_get_last_cmd(&cmd_size); + Log_e("execute command (%.*s) failed!", cmd_size, cmd); + result = QCLOUD_ERR_FAILURE; + goto __exit; + } +#else + if (HAL_SemaphoreWait(client->resp_sem, resp->timeout) < 0) { + cmd = at_get_last_cmd(&cmd_size); + Log_e("execute command (%.*s) failed!", cmd_size, cmd); + result = QCLOUD_ERR_FAILURE; + goto __exit; + } + + if (client->resp_status != AT_RESP_OK) { + cmd = at_get_last_cmd(&cmd_size); + Log_e("execute command (%.*s) failed!", cmd_size, cmd); + result = QCLOUD_ERR_FAILURE; + goto __exit; + } +#endif + } + +__exit: + client->resp = NULL; + HAL_MutexUnlock(client->lock); + + return result; +} + +/** + * Send data to AT server, send data don't have end sign(eg: \r\n). + * + * @param client current AT client object + * @param buf send data buffer + * @param size send fixed data size + * @param timeout timeout for send + * + * @return >0: send data size + * =0: send failed + */ +int at_client_send(at_client_t client, const char *buf, int size, uint32_t timeout) +{ + POINTER_SANITY_CHECK(buf, 0); + + if (client == NULL) { + Log_e("input AT Client object is NULL, please create or get AT Client object!"); + return 0; + } + +#ifdef AT_DEBUG + at_print_raw_cmd("send", buf, size); +#endif + + return HAL_AT_Uart_Send((void *)buf, size); +} + +static int at_client_getchar(at_client_t client, char *pch, uint32_t timeout) +{ + int ret = QCLOUD_RET_SUCCESS; + Timer timer; + + countdown_ms(&timer, timeout); + do { +#ifndef AT_UART_RECV_IRQ + if (0 == HAL_AT_Uart_Recv((void *)pch, 1, NULL, timeout)) { + continue; + } +#else + if (0 == + ring_buff_pop_data(client->pRingBuff, (uint8_t *)pch, 1)) { // push data to ringbuff @ AT_UART_IRQHandler + continue; + } +#endif + else { + break; + } + } while (!expired(&timer)); + + if (expired(&timer)) { + ret = QCLOUD_ERR_FAILURE; + } + + return ret; +} + +/** + * AT client receive fixed-length data. + * + * @param client current AT client object + * @param buf receive data buffer + * @param size receive fixed data size + * @param timeout receive data timeout (ms) + * + * @note this function can only be used in execution function of URC data + * + * @return >0: receive data size + * =0: receive failed + */ +int at_client_obj_recv(char *buf, int size, int timeout) +{ + int read_idx = 0; + int result = QCLOUD_RET_SUCCESS; + char ch; + + POINTER_SANITY_CHECK(buf, 0); + at_client_t client = at_client_get(); + + if (client == NULL) { + Log_e("input AT Client object is NULL, please create or get AT Client object!"); + return 0; + } + + while (1) { + if (read_idx < size) { + result = at_client_getchar(client, &ch, timeout); + if (result != QCLOUD_RET_SUCCESS) { + Log_e("AT Client receive failed, uart device get data error(%d)", result); + return 0; + } + + buf[read_idx++] = ch; + } else { + break; + } + } + +#ifdef AT_DEBUG + at_print_raw_cmd("urc_recv", buf, size); +#endif + + return read_idx; +} + +/** + * AT client set end sign. + * + * @param client current AT client object + * @param ch the end sign, can not be used when it is '\0' + */ +void at_set_end_sign(char ch) +{ + at_client_t client = at_client_get(); + + if (client == NULL) { + Log_e("input AT Client object is NULL, please create or get AT Client object!"); + return; + } + + client->end_sign = ch; +} + +/** + * set URC(Unsolicited Result Code) table + * + * @param client current AT client object + * @param table URC table + * @param size table size + */ +void at_set_urc_table(at_client_t client, const at_urc_t urc_table, uint32_t table_sz) +{ + int idx; + + if (client == NULL) { + Log_e("input AT Client object is NULL, please create or get AT Client object!"); + return; + } + + for (idx = 0; idx < table_sz; idx++) { + POINTER_SANITY_CHECK_RTN(urc_table[idx].cmd_prefix); + POINTER_SANITY_CHECK_RTN(urc_table[idx].cmd_suffix); + } + + client->urc_table = urc_table; + client->urc_table_size = table_sz; +} + +at_client_t at_client_get(void) +{ + return &sg_at_client; +} + +static const at_urc *get_urc_obj(at_client_t client) +{ + int i, prefix_len, suffix_len; + int buf_sz; + char *buffer = NULL; + + if (client->urc_table == NULL) { + return NULL; + } + + buffer = client->recv_buffer; + buf_sz = client->cur_recv_len; + + for (i = 0; i < client->urc_table_size; i++) { + prefix_len = strlen(client->urc_table[i].cmd_prefix); + suffix_len = strlen(client->urc_table[i].cmd_suffix); + if (buf_sz < prefix_len + suffix_len) { + continue; + } + if ((prefix_len ? !strncmp(buffer, client->urc_table[i].cmd_prefix, prefix_len) : 1) && + (suffix_len ? !strncmp(buffer + buf_sz - suffix_len, client->urc_table[i].cmd_suffix, suffix_len) : 1)) { + // Log_d("matched:%s", client->urc_table[i].cmd_prefix); + return &client->urc_table[i]; + } + } + + return NULL; +} + +static int at_recv_readline(at_client_t client) +{ + int read_len = 0; + char ch = 0, last_ch = 0; + bool is_full = false; + int ret; + + memset(client->recv_buffer, 0x00, client->recv_bufsz); + client->cur_recv_len = 0; + + while (1) { + ret = at_client_getchar(client, &ch, GET_CHAR_TIMEOUT_MS); + + if (QCLOUD_RET_SUCCESS != ret) { + return -1; + } + + if (read_len < client->recv_bufsz) { + client->recv_buffer[read_len++] = ch; + client->cur_recv_len = read_len; + } else { + is_full = true; + } + + /* is newline or URC data */ + if ((ch == '\n' && last_ch == '\r') || (client->end_sign != 0 && ch == client->end_sign) || + get_urc_obj(client)) { + if (is_full) { + Log_e("read line failed. The line data length is out of buffer size(%d)!", client->recv_bufsz); + memset(client->recv_buffer, 0x00, client->recv_bufsz); + client->cur_recv_len = 0; + ring_buff_flush(client->pRingBuff); + return -1; + } + break; + } + last_ch = ch; + } + +#ifdef AT_DEBUG + at_print_raw_cmd("recvline", client->recv_buffer, read_len); +#endif + + return read_len; +} + +#ifdef AT_OS_USED +static void client_parser(void *userContex) +{ + int resp_buf_len = 0; + const at_urc *urc; + int line_counts = 0; + at_client_t client = at_client_get(); + + Log_d("client_parser start..."); + + while (1) { + if (at_recv_readline(client) > 0) { +#ifdef AT_DEBUG + const char *cmd = NULL; + int cmdsize = 0; + cmd = at_get_last_cmd(&cmdsize); + Log_d("last_cmd:(%.*s), readline:%s", cmdsize, cmd, client->recv_buffer); +#endif + if ((urc = get_urc_obj(client)) != NULL) { + /* current receive is request, try to execute related operations */ + if (urc->func != NULL) { + urc->func(client->recv_buffer, client->cur_recv_len); + } + + } else if (client->resp != NULL) { + if (client->end_sign != 0) { // handle endsign + if (client->recv_buffer[client->cur_recv_len - 1] != client->end_sign) { + continue; + } else { + goto exit; + } + } + + /* current receive is response */ + client->recv_buffer[client->cur_recv_len - 1] = '\0'; + if (resp_buf_len + client->cur_recv_len < client->resp->buf_size) { + /* copy response lines, separated by '\0' */ + memcpy(client->resp->buf + resp_buf_len, client->recv_buffer, client->cur_recv_len); + resp_buf_len += client->cur_recv_len; + + line_counts++; + } else { + client->resp_status = AT_RESP_BUFF_FULL; + Log_e("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", + client->resp->buf_size); + } + /* check response result */ + if (memcmp(client->recv_buffer, AT_RESP_END_OK, strlen(AT_RESP_END_OK)) == 0 && + client->resp->line_num == 0) { + /* get the end data by response result, return response state END_OK. */ + client->resp_status = AT_RESP_OK; + } else if (strstr(client->recv_buffer, AT_RESP_END_ERROR) || + (memcmp(client->recv_buffer, AT_RESP_END_FAIL, strlen(AT_RESP_END_FAIL)) == 0)) { + client->resp_status = AT_RESP_ERROR; + } else if (line_counts == client->resp->line_num && client->resp->line_num) { + /* get the end data by response line, return response state END_OK.*/ + client->resp_status = AT_RESP_OK; + } else { + continue; + } + exit: + client->resp->line_counts = line_counts; + client->resp = NULL; + resp_buf_len = 0; + line_counts = 0; + HAL_SemaphorePost(client->resp_sem); + } else { + // Log_d("unrecognized line: %.*s", client->cur_recv_len, client->recv_buffer); + } + } else { + // Log_d("read no new line"); + } + } +} +#else +void at_client_yeild(at_urc *expect_urc, uint32_t timeout) +{ + int resp_buf_len = 0; + const at_urc *urc; + int line_counts = 0; + int prefix_len; + int suffix_len; + Timer timer; + at_client_t client = at_client_get(); + + Log_d("Entry..."); + countdown_ms(&timer, timeout); + do { + if (at_recv_readline(client) > 0) { +#ifdef AT_DEBUG + const char *cmd = NULL; + int cmdsize = 0; + cmd = at_get_last_cmd(&cmdsize); + Log_d("last_cmd:(%.*s), readline:%s", cmdsize, cmd, client->recv_buffer); +#endif + if ((urc = get_urc_obj(client)) != NULL) { + /* current receive is request, try to execute related operations */ + if (urc->func != NULL) { + urc->func(client->recv_buffer, client->cur_recv_len); + } + + /*expect urc matched then break*/ + if (expect_urc != NULL) { + prefix_len = strlen(expect_urc->cmd_prefix); + suffix_len = strlen(expect_urc->cmd_suffix); + if ((prefix_len ? !strncmp(urc->cmd_prefix, expect_urc->cmd_prefix, prefix_len) : 1) && + (suffix_len ? !strncmp(urc->cmd_suffix, expect_urc->cmd_suffix, suffix_len) : 1)) { + client->resp_status = AT_RESP_OK; + break; + } + } + } else if (client->resp != NULL) { + if (client->end_sign != 0) { // handle endsign + if (client->recv_buffer[client->cur_recv_len - 1] != client->end_sign) { + continue; + } else { + client->resp_status = AT_RESP_OK; + client->resp->line_counts = line_counts; + client->resp = NULL; + // client->resp_notice = true; + resp_buf_len = 0; + line_counts = 0; + break; + } + } + + /* current receive is response */ + client->recv_buffer[client->cur_recv_len - 1] = '\0'; + if (resp_buf_len + client->cur_recv_len < client->resp->buf_size) { + /* copy response lines, separated by '\0' */ + memcpy(client->resp->buf + resp_buf_len, client->recv_buffer, client->cur_recv_len); + resp_buf_len += client->cur_recv_len; + + line_counts++; + } else { + client->resp_status = AT_RESP_BUFF_FULL; + Log_e("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", + client->resp->buf_size); + } + /* check response result */ + if (memcmp(client->recv_buffer, AT_RESP_END_OK, strlen(AT_RESP_END_OK)) == 0 && + client->resp->line_num == 0) { + /* get the end data by response result, return response state END_OK. */ + client->resp_status = AT_RESP_OK; + } else if (strstr(client->recv_buffer, AT_RESP_END_ERROR) || + (memcmp(client->recv_buffer, AT_RESP_END_FAIL, strlen(AT_RESP_END_FAIL)) == 0)) { + client->resp_status = AT_RESP_ERROR; + } else if (line_counts == client->resp->line_num && client->resp->line_num) { + /* get the end data by response line, return response state END_OK.*/ + client->resp_status = AT_RESP_OK; + } else { + if (!expired(&timer)) { + continue; + } else { + break; + } + } + + client->resp->line_counts = line_counts; + client->resp = NULL; + // client->resp_notice = true; + resp_buf_len = 0; + line_counts = 0; + break; + } else { + // Log_d("unrecognized line: %.*s", client->cur_recv_len, client->recv_buffer); + } + } else { + // Log_d("read no new line"); + } + } while (!expired(&timer)); +} +#endif + +/* initialize the client parameters */ +int at_client_para_init(at_client_t client) +{ + char *ringBuff = NULL; + char *recvBuff = NULL; + + client->lock = HAL_MutexCreate(); + if (NULL == client->lock) { + Log_e("create lock err"); + return QCLOUD_ERR_FAILURE; + } + +#ifdef AT_OS_USED + client->resp_sem = HAL_SemaphoreCreate(); + if (NULL == client->resp_sem) { + Log_e("create sem err"); + goto err_exit; + } + + client->parser = client_parser; +#endif + + ringBuff = HAL_Malloc(RING_BUFF_LEN); + if (NULL == ringBuff) { + Log_e("malloc ringbuff err"); + goto err_exit; + } + ring_buff_init(&g_ring_buff, ringBuff, RING_BUFF_LEN); + + recvBuff = HAL_Malloc(CLINET_BUFF_LEN); + if (NULL == recvBuff) { + Log_e("malloc recvbuff err"); + goto err_exit; + } + client->recv_buffer = recvBuff; + client->pRingBuff = &g_ring_buff; + client->recv_bufsz = CLINET_BUFF_LEN; + client->cur_recv_len = 0; + client->resp = NULL; + client->urc_table = NULL; + client->urc_table_size = 0; + client->end_sign = 0; + + return QCLOUD_RET_SUCCESS; + +err_exit: + if (client->lock) { + HAL_MutexDestroy(client->lock); + client->lock = NULL; + } + +#ifdef AT_OS_USED + if (client->resp_sem) { + HAL_SemaphoreDestroy(client->resp_sem); + client->resp_sem = NULL; + } +#endif + + HAL_Free(ringBuff); + HAL_Free(recvBuff); + + return QCLOUD_ERR_FAILURE; +} + +/** + * AT client initialize. + * + * @param pClient pinter of at client which to be inited + * @return @see eTidResault + */ +int at_client_init(at_client_t *pClient) +{ + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + at_client_t client; + int result; + + client = at_client_get(); + + if (NULL == client) { + Log_e("no at client get"); + result = QCLOUD_ERR_FAILURE; + goto exit; + } + + if (AT_STATUS_INITIALIZED == client->status) { + Log_e("at client has been initialized"); + result = QCLOUD_ERR_FAILURE; + goto exit; + } + + result = at_client_para_init(client); + if (result == QCLOUD_RET_SUCCESS) { + Log_d("AT client(V%s) initialize success.", AT_FRAME_VERSION); + client->status = AT_STATUS_INITIALIZED; + *pClient = client; + +#if defined(AT_OS_USED) && defined(MULTITHREAD_ENABLED) + // create thread for at parser + if (NULL != client->parser) { +#define AT_PARSER_THREAD_STACK 6144 +#define AT_PARSER_THREAD_PRIORITY 0 + static ThreadParams thread_params = {0}; + thread_params.thread_func = client->parser; + thread_params.thread_name = "at_client_parser"; + thread_params.user_arg = client; + thread_params.stack_size = AT_PARSER_THREAD_STACK; + thread_params.priority = AT_PARSER_THREAD_PRIORITY; + + result = HAL_ThreadCreate(&thread_params); + if (QCLOUD_RET_SUCCESS == result) { + Log_d("create at_parser thread success!"); + } else { + Log_e("create at_parser thread fail!"); + } + +#undef AT_PARSER_THREAD_STACK +#undef AT_PARSER_THREAD_PRIORITY + } +#endif + + } else { + *pClient = NULL; + client->status = AT_STATUS_UNINITIALIZED; + Log_e("AT client(V%s) initialize failed(%d).", AT_FRAME_VERSION, result); + } + +exit: + + return result; +} + +int at_client_deinit(at_client_t pClient) +{ + // TO DO: + return QCLOUD_RET_SUCCESS; +} diff --git a/sdk_src/network/at_socket/at_socket_inf.c b/sdk_src/network/at_socket/at_socket_inf.c new file mode 100755 index 00000000..6051e15f --- /dev/null +++ b/sdk_src/network/at_socket/at_socket_inf.c @@ -0,0 +1,412 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "at_socket_inf.h" + +#include +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/** The global array of available at */ +static at_socket_ctx_t at_socket_ctxs[MAX_AT_SOCKET_NUM]; + +/**at socket operation mutex */ +static void *sg_at_socket_mutex; + +/**at device driver ops*/ +static at_device_op_t *sg_at_device_ops = NULL; + +#define MAX_RECV_PKT_PER_CHAIN (10) + +static at_device_op_t *_at_device_op_get(void) +{ + return sg_at_device_ops; +} + +static int _at_socket_ctx_free(at_socket_ctx_t *pCtx) +{ + POINTER_SANITY_CHECK(pCtx, QCLOUD_ERR_INVAL); + + pCtx->fd = UNUSED_SOCKET; + pCtx->net_type = eNET_DEFAULT; + + if (pCtx->recvpkt_list) { + list_destroy(pCtx->recvpkt_list); + pCtx->recvpkt_list = NULL; + } + + if (pCtx->recv_lock) { + HAL_MutexDestroy(pCtx->recv_lock); + pCtx->recv_lock = NULL; + } + + return QCLOUD_RET_SUCCESS; +} + +static at_socket_ctx_t *_at_socket_ctx_alloc(void) +{ + int i; + + for (i = 0; i < MAX_AT_SOCKET_NUM; i++) { + if (at_socket_ctxs[i].state == eSOCKET_CLOSED) { + at_socket_ctxs[i].net_type = eNET_DEFAULT; + at_socket_ctxs[i].send_timeout_ms = AT_SOCKET_SEND_TIMEOUT_MS; + at_socket_ctxs[i].recv_timeout_ms = AT_SOCKET_RECV_TIMEOUT_MS; + at_socket_ctxs[i].dev_op = _at_device_op_get(); + + at_socket_ctxs[i].recv_lock = HAL_MutexCreate(); + if (NULL == at_socket_ctxs[i].recv_lock) { + Log_e("create recv lock fail"); + goto exit; + } + at_socket_ctxs[i].recvpkt_list = list_new(); + if (NULL != at_socket_ctxs[i].recvpkt_list) { + at_socket_ctxs[i].recvpkt_list->free = HAL_Free; + } else { + Log_e("no memory to allocate recvpkt_list"); + goto exit; + } + + at_socket_ctxs[i].state = eSOCKET_ALLOCED; + return &at_socket_ctxs[i]; + } + } + +exit: + + if (i < MAX_AT_SOCKET_NUM) { + _at_socket_ctx_free(&at_socket_ctxs[i]); + } + + return NULL; +} + +static at_socket_ctx_t *_at_socket_find(int fd) +{ + int i; + + for (i = 0; i < MAX_AT_SOCKET_NUM; i++) { + if (at_socket_ctxs[i].fd == fd) { + return &at_socket_ctxs[i]; + } + } + + return NULL; +} + +/* get a block to the AT socket receive list*/ +static int _at_recvpkt_put(List *rlist, const char *ptr, size_t length) +{ + at_recv_pkt *pkt = NULL; + + if (rlist->len > MAX_RECV_PKT_PER_CHAIN) { + Log_e("Too many recv packets wait for read"); + HAL_Free(pkt); + return QCLOUD_ERR_FAILURE; + } + + pkt = (at_recv_pkt *)HAL_Malloc(sizeof(struct at_recv_pkt)); + if (pkt == NULL) { + Log_e("No memory for receive packet table!"); + return QCLOUD_ERR_FAILURE; + } + + pkt->bfsz_totle = length; + pkt->bfsz_index = 0; + pkt->buff = (char *)ptr; + + ListNode *node = list_node_new(pkt); + if (NULL == node) { + Log_e("run list_node_new is error!"); + HAL_Free(pkt); + return QCLOUD_ERR_FAILURE; + } + + list_rpush(rlist, node); + + return length; +} + +/* get a block from AT socket receive list */ +static int _at_recvpkt_get(List *pkt_list, char *buff, size_t len) +{ + ListIterator *iter; + ListNode * node = NULL; + at_recv_pkt * pkt; + size_t readlen = 0, page_len = 0; + POINTER_SANITY_CHECK(buff, QCLOUD_ERR_INVAL); + + if (pkt_list->len) { + iter = list_iterator_new(pkt_list, LIST_HEAD); + if (NULL == iter) { + Log_e("new listiterator fail"); + return QCLOUD_ERR_TCP_READ_FAIL; + } + + /*traverse recv pktlist*/ + do { + node = list_iterator_next(iter); + if (!node) { + break; + } + + /*get recv packet*/ + pkt = (at_recv_pkt *)(node->val); + if (!pkt) { + Log_e("pkt is invalid!"); + list_remove(pkt_list, node); + continue; + } + + page_len = pkt->bfsz_totle - pkt->bfsz_index; + if (page_len >= (len - readlen)) { + memcpy(buff + readlen, pkt->buff + pkt->bfsz_index, (len - readlen)); + pkt->bfsz_index += len - readlen; + readlen = len; + break; + } else { + memcpy(buff + readlen, pkt->buff + pkt->bfsz_index, page_len); + readlen += page_len; + + /*delete pkt after read*/ + HAL_Free(pkt->buff); + list_remove(pkt_list, node); + } + } while (1); + + list_iterator_destroy(iter); + } + + return readlen; +} + +static void _at_socket_recv_cb(int fd, at_socket_evt_t event, char *buff, size_t bfsz) +{ + POINTER_SANITY_CHECK_RTN(buff); + at_socket_ctx_t *pAtSocket; + + if (event == AT_SOCKET_EVT_RECV) { + HAL_MutexLock(sg_at_socket_mutex); + pAtSocket = _at_socket_find(fd + MAX_AT_SOCKET_NUM); + if (_at_recvpkt_put(pAtSocket->recvpkt_list, buff, bfsz) < 0) { + Log_e("put recv package to list fail"); + HAL_Free(buff); + } + HAL_MutexUnlock(sg_at_socket_mutex); + } +} + +static void _at_socket_closed_cb(int fd, at_socket_evt_t event, char *buff, size_t bfsz) +{ + at_socket_ctx_t *pAtSocket; + pAtSocket = _at_socket_find(fd + MAX_AT_SOCKET_NUM); + + if (pAtSocket != NULL && event == AT_SOCKET_EVT_CLOSED) { + HAL_MutexLock(sg_at_socket_mutex); + pAtSocket->state = eSOCKET_CLOSED; + _at_socket_ctx_free(pAtSocket); + HAL_MutexUnlock(sg_at_socket_mutex); + } +} + +int at_device_op_register(at_device_op_t *device_op) +{ + int rc; + + if (NULL == sg_at_device_ops) { + sg_at_device_ops = device_op; + rc = QCLOUD_RET_SUCCESS; + } else { + Log_e("pre device op already register"); + rc = QCLOUD_ERR_FAILURE; + } + + return rc; +} + +int at_socket_init(void) +{ + int i; + int rc = QCLOUD_RET_SUCCESS; + + for (i = 0; i < MAX_AT_SOCKET_NUM; i++) { + at_socket_ctxs[i].fd = UNUSED_SOCKET; + at_socket_ctxs[i].state = eSOCKET_CLOSED; + at_socket_ctxs[i].dev_op = NULL; + at_socket_ctxs[i].recvpkt_list = NULL; + } + + sg_at_socket_mutex = HAL_MutexCreate(); + if (sg_at_socket_mutex == NULL) { + Log_e("create sg_at_socket_mutex fail \n"); + rc = QCLOUD_ERR_FAILURE; + } + + if (NULL != sg_at_device_ops) { + if (QCLOUD_RET_SUCCESS == sg_at_device_ops->init()) { + Log_d("at device %s init success", + (NULL == sg_at_device_ops->deviceName) ? "noname" : sg_at_device_ops->deviceName); + sg_at_device_ops->set_event_cb(AT_SOCKET_EVT_RECV, _at_socket_recv_cb); + sg_at_device_ops->set_event_cb(AT_SOCKET_EVT_CLOSED, _at_socket_closed_cb); + } else { + Log_e("at device %s init fail", + (NULL == sg_at_device_ops->deviceName) ? "noname" : sg_at_device_ops->deviceName); + } + } + + return rc; +} + +int at_socket_parse_domain(const char *host_name, char *host_ip, size_t host_ip_len) +{ + at_device_op_t *at_op = _at_device_op_get(); + POINTER_SANITY_CHECK(at_op, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(at_op->parse_domain, QCLOUD_ERR_INVAL); + + return at_op->parse_domain(host_name, host_ip, host_ip_len); +} + +int at_socket_get_local_mac(char *macbuff, size_t bufflen) +{ + at_device_op_t *at_op = _at_device_op_get(); + POINTER_SANITY_CHECK(at_op, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(at_op->get_local_mac, QCLOUD_ERR_INVAL); + + return at_op->get_local_mac(macbuff, bufflen); +} + +int at_socket_get_local_ip(char *ip, size_t iplen, char *gw, size_t gwlen, char *mask, size_t masklen) +{ + at_device_op_t *at_op = _at_device_op_get(); + POINTER_SANITY_CHECK(at_op, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(at_op->get_local_ip, QCLOUD_ERR_INVAL); + + return at_op->get_local_ip(ip, iplen, gw, gwlen, mask, masklen); +} + +int at_socket_connect(const char *host, uint16_t port, eNetProto eProto) +{ + at_socket_ctx_t *pAtSocket; + int fd; + + HAL_MutexLock(sg_at_socket_mutex); + pAtSocket = _at_socket_ctx_alloc(); + HAL_MutexUnlock(sg_at_socket_mutex); + + if ((NULL == pAtSocket) || (NULL == pAtSocket->dev_op) || (NULL == pAtSocket->dev_op->connect)) { + Log_e("alloc socket fail"); + return QCLOUD_ERR_FAILURE; + } + + fd = pAtSocket->dev_op->connect(host, port, eProto); + if (fd < 0) { + Log_e("dev_op connect fail,pls check at device driver!"); + _at_socket_ctx_free(pAtSocket); + } else { + pAtSocket->fd = fd + MAX_AT_SOCKET_NUM; + pAtSocket->state = eSOCKET_CONNECTED; + } + + return pAtSocket->fd; +} + +int at_socket_close(int fd) +{ + at_socket_ctx_t *pAtSocket; + + pAtSocket = _at_socket_find(fd); + if (NULL == pAtSocket) { // server close the connection + Log_e("socket was closed"); + return QCLOUD_ERR_TCP_PEER_SHUTDOWN; + } + + int rc; + if ((eSOCKET_CONNECTED == pAtSocket->state) && (NULL != pAtSocket->dev_op) && (NULL != pAtSocket->dev_op->close)) { + rc = pAtSocket->dev_op->close(pAtSocket->fd - MAX_AT_SOCKET_NUM); + } else { + rc = QCLOUD_ERR_FAILURE; + } + return rc; +} + +int at_socket_send(int fd, const void *buf, size_t len) +{ + at_socket_ctx_t *pAtSocket; + + pAtSocket = _at_socket_find(fd); + POINTER_SANITY_CHECK(pAtSocket, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pAtSocket->dev_op, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pAtSocket->dev_op->send, QCLOUD_ERR_INVAL); + + if (pAtSocket->state != eSOCKET_CONNECTED) { + Log_e("socket was closed"); + return QCLOUD_ERR_TCP_PEER_SHUTDOWN; + } else { + return pAtSocket->dev_op->send(fd - MAX_AT_SOCKET_NUM, buf, len); + } +} + +int at_socket_recv(int fd, void *buf, size_t len) +{ + at_socket_ctx_t *pAtSocket; + size_t recv_len; + + pAtSocket = _at_socket_find(fd); + POINTER_SANITY_CHECK(pAtSocket, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pAtSocket->dev_op, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pAtSocket->dev_op->recv_timeout, QCLOUD_ERR_INVAL); + + if (pAtSocket->state != eSOCKET_CONNECTED) { + Log_e("socket was closed"); + return QCLOUD_ERR_TCP_READ_FAIL; + } else { + HAL_MutexLock(pAtSocket->recv_lock); + + // call at device recv driver for os and nonos + if (pAtSocket->recvpkt_list->len == 0) { + if (pAtSocket->dev_op->recv_timeout(fd - MAX_AT_SOCKET_NUM, buf, len, pAtSocket->recv_timeout_ms) != + QCLOUD_RET_SUCCESS) { + Log_e("at device recv err"); // do not return yet + } + } + + /* receive packet list last transmission of remaining data */ + recv_len = _at_recvpkt_get(pAtSocket->recvpkt_list, (char *)buf, len); + HAL_MutexUnlock(pAtSocket->recv_lock); + } + + return recv_len; +} + +int at_socket_recv_timeout(int fd, void *buf, size_t len, uint32_t timeout) +{ + at_socket_ctx_t *pAtSocket; + + pAtSocket = _at_socket_find(fd); + POINTER_SANITY_CHECK(pAtSocket, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pAtSocket->dev_op, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pAtSocket->dev_op->recv_timeout, QCLOUD_ERR_INVAL); + + if (pAtSocket->state != eSOCKET_CONNECTED) { + Log_e("socket was closed"); + return QCLOUD_ERR_TCP_PEER_SHUTDOWN; + } else { + return pAtSocket->dev_op->recv_timeout(fd - MAX_AT_SOCKET_NUM, buf, len, timeout); + } +} diff --git a/sdk_src/network/at_socket/at_utils.c b/sdk_src/network/at_socket/at_utils.c new file mode 100755 index 00000000..9b0d5217 --- /dev/null +++ b/sdk_src/network/at_socket/at_utils.c @@ -0,0 +1,345 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "at_utils.h" + +#include +#include + +#include "at_client.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +static char send_buf[CLINET_BUFF_LEN]; +static int last_cmd_len = 0; + +/** + * dump hex format data to console device + * + * @param name name for hex object, it will show on log header + * @param buf hex buffer + * @param size buffer size + */ +void at_print_raw_cmd(const char *name, const char *buf, int size) +{ + int i, j; + + for (i = 0; i < size; i += WIDTH_SIZE) { + HAL_Printf("%s: %04X-%04X: ", name, i, i + WIDTH_SIZE); + for (j = 0; j < WIDTH_SIZE; j++) { + if (i + j < size) { + HAL_Printf("%02X ", buf[i + j]); + } else { + HAL_Printf(" "); + } + if ((j + 1) % 8 == 0) { + HAL_Printf(" "); + } + } + HAL_Printf(" "); + for (j = 0; j < WIDTH_SIZE; j++) { + if (i + j < size) { + HAL_Printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + } + } + HAL_Printf("\n\r"); + } +} + +const char *at_get_last_cmd(int *cmd_size) +{ + *cmd_size = last_cmd_len; + return send_buf; +} + +int at_vprintf(const char *format, va_list args) +{ + last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, args); + +#ifdef AT_DEBUG + at_print_raw_cmd("send", send_buf, last_cmd_len); +#endif + + return HAL_AT_Uart_Send((uint8_t *)send_buf, last_cmd_len); +} + +int at_vprintfln(const char *format, va_list args) +{ + int len; + + len = at_vprintf(format, args); + + HAL_AT_Uart_Send("\r\n", 2); + + return len + 2; +} + +/** + * at_sscanf - Unformat a buffer into a list of arguments, rewrite sscanf + * @buf: input buffer + * @fmt: format of buffer + * @args: arguments + */ +int at_sscanf(const char *buf, const char *fmt, va_list args) +{ + const char *str = buf; + char * next; + int num = 0; + int qualifier; + int base; + int field_width = -1; + int is_sign = 0; + + while (*fmt && *str) { + /* skip any white space in format */ + /* white space in format matchs any amount of + * white space, including none, in the input. + */ + if (isspace(*fmt)) { + while (isspace(*fmt)) ++fmt; + while (isspace(*str)) ++str; + } + + /* anything that is not a conversion must match exactly */ + if (*fmt != '%' && *fmt) { + if (*fmt++ != *str++) + break; + continue; + } + + if (!*fmt) + break; + ++fmt; + + /* skip this conversion. + * advance both strings to next white space + */ + if (*fmt == '*') { + while (!isspace(*fmt) && *fmt) fmt++; + while (!isspace(*str) && *str) str++; + continue; + } + + /* get field width */ + if (isdigit(*fmt)) + field_width = atoi(fmt); + + /* get conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') { + qualifier = *fmt; + fmt++; + } + base = 10; + is_sign = 0; + + if (!*fmt || !*str) + break; + + switch (*fmt++) { + case 'c': { + char *s = (char *)va_arg(args, char *); + if (field_width == -1) + field_width = 1; + do { + *s++ = *str++; + } while (field_width-- > 0 && *str); + num++; + } + continue; + case 's': { + char *s = (char *)va_arg(args, char *); + if (field_width == -1) + field_width = INT_MAX; + /* first, skip leading white space in buffer */ + while (isspace(*str)) str++; + + /* now copy until next white space */ + while (*str && ((*str) != ',')) { + if (isspace(*str)) { + str++; + } else { + *s++ = *str++; + } + } + *s = '\0'; + num++; + } + continue; + /* S for special handling for MQTTPUB JSON content */ + case 'S': { + char *s = (char *)va_arg(args, char *); + if (field_width == -1) + field_width = INT_MAX; + /* first, skip leading white space in buffer */ + while (isspace(*str)) str++; + + /* now copy until next white space */ + while (*str) { + if (isspace(*str)) { + str++; + } else { + *s++ = *str++; + } + } + *s = '\0'; + num++; + } + continue; + case 'n': + /* return number of characters read so far */ + { + int *i = (int *)va_arg(args, int *); + *i = str - buf; + } + continue; + case 'o': + base = 8; + break; + case 'x': + case 'X': + base = 16; + break; + case 'd': + case 'i': + is_sign = 1; + case 'u': + break; + case '%': + /* looking for '%' in str */ + if (*str++ != '%') + return num; + continue; + default: + /* invalid format; stop here */ + return num; + } + + /* have some sort of integer conversion. + * first, skip white space in buffer. + */ + while (isspace(*str)) str++; + + if (!*str || !isdigit(*str)) + break; + + switch (qualifier) { + case 'h': + if (is_sign) { + short *s = (short *)va_arg(args, short *); + *s = (short)strtol(str, &next, base); + } else { + unsigned short *s = (unsigned short *)va_arg(args, unsigned short *); + *s = (unsigned short)strtoul(str, &next, base); + } + break; + case 'l': + if (is_sign) { + long *l = (long *)va_arg(args, long *); + *l = strtol(str, &next, base); + } else { + unsigned long *l = (unsigned long *)va_arg(args, unsigned long *); + *l = strtoul(str, &next, base); + } + break; + case 'L': + if (is_sign) { + long long *l = (long long *)va_arg(args, long long *); + *l = strtoll(str, &next, base); + } else { + unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *); + *l = strtoull(str, &next, base); + } + break; + case 'Z': { + unsigned long *s = (unsigned long *)va_arg(args, unsigned long *); + *s = (unsigned long)strtoul(str, &next, base); + } break; + default: + if (is_sign) { + int *i = (int *)va_arg(args, int *); + *i = (int)strtol(str, &next, base); + } else { + unsigned int *i = (unsigned int *)va_arg(args, unsigned int *); + *i = (unsigned int)strtoul(str, &next, base); + } + break; + } + num++; + + if (!next) + break; + str = next; + } + return num; +} + +/** + * AT server request arguments parse arguments + * + * @param req_args request arguments + * @param req_expr request expression + * + * @return -1 : parse arguments failed + * 0 : parse without match + * >0 : The number of arguments successfully parsed + */ +int at_req_parse_args(const char *req_args, const char *req_expr, ...) +{ + va_list args; + int req_args_num = 0; + + POINTER_SANITY_CHECK(req_args, 0); + POINTER_SANITY_CHECK(req_expr, 0); + + va_start(args, req_expr); + + // req_args_num = vsscanf(req_args, req_expr, args); + req_args_num = at_sscanf(req_args, req_expr, args); + + va_end(args); + + return req_args_num; +} + +void at_strip(char *str, const char patten) +{ + char *start, *end; + + start = str; + end = str + strlen(str) - 1; + + if (*str == patten) { + start++; + } + + if (*end == patten) { + *end-- = '\0'; + } + + strcpy(str, start); +} + +void chr_strip(char *str, const char patten) +{ + char *end = str + strlen(str); + + while (*str != '\0') { + if (*str == patten) { + memmove(str, str + 1, end - str); + } + str++; + } +} diff --git a/sdk_src/network/at_socket/network_at_tcp.c b/sdk_src/network/at_socket/network_at_tcp.c new file mode 100755 index 00000000..3ce40876 --- /dev/null +++ b/sdk_src/network/at_socket/network_at_tcp.c @@ -0,0 +1,153 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifdef AT_TCP_ENABLED + +#include +#include +#include + +#include "at_socket_inf.h" +#include "network_interface.h" +#include "utils_param_check.h" +#include "utils_timer.h" + +int network_at_tcp_init(Network *pNetwork) +{ + int rc; + + /*at device init entry: at_client init, device driver register to at_socket*/ + rc = at_device_init(); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("at device init fail,rc:%d", rc); + return rc; + } + + /*do after at device init*/ + rc = at_socket_init(); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("at socket init fail,rc:%d", rc); + } + + return rc; +} + +int network_at_tcp_connect(Network *pNetwork) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int fd = at_socket_connect(pNetwork->host, pNetwork->port, eNET_TCP); + + if (fd < 0) { + Log_e("fail to connect with TCP server: %s:%u", STRING_PTR_PRINT_SANITY_CHECK(pNetwork->host), pNetwork->port); + pNetwork->handle = AT_NO_CONNECTED_FD; + return -1; + } else { + Log_d("connected with TCP server: %s:%u", pNetwork->host, pNetwork->port); + pNetwork->handle = fd; + return 0; + } +} + +int network_at_tcp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) +{ + int ret, err_code; + uint32_t len_recv; + Timer timer; + + InitTimer(&timer); + countdown_ms(&timer, timeout_ms); + + len_recv = 0; + err_code = 0; + + do { + if (expired(&timer)) { + err_code = QCLOUD_ERR_TCP_READ_TIMEOUT; + break; + } + + ret = at_socket_recv(pNetwork->handle, data + len_recv, datalen - len_recv); + + if (ret > 0) { + len_recv += ret; + } else if (ret == 0) { + err_code = QCLOUD_ERR_TCP_NOTHING_TO_READ; + } else { // ret < 0 + Log_e("recv fail\n"); + err_code = QCLOUD_ERR_TCP_READ_FAIL; + break; + } + + } while ((len_recv < datalen)); + + if (err_code == QCLOUD_ERR_TCP_READ_TIMEOUT && len_recv == 0) { + err_code = QCLOUD_ERR_TCP_NOTHING_TO_READ; + } + + *read_len = len_recv; + + return (datalen == len_recv) ? QCLOUD_RET_SUCCESS : err_code; +} + +int network_at_tcp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, + size_t *written_len) +{ + int ret; + uint32_t len_sent; + Timer timer; + int net_err = 0; + + InitTimer(&timer); + countdown_ms(&timer, timeout_ms); + + len_sent = 0; + ret = 1; /* send one time if timeout_ms is value 0 */ + + do { + ret = at_socket_send(pNetwork->handle, data + len_sent, datalen - len_sent); + + if (ret > 0) { + len_sent += ret; + } else if (0 == ret) { + Log_e("No data be sent\n"); + } else { + Log_e("send fail, ret:%d\n", ret); + net_err = 1; + break; + } + } while (!net_err && (len_sent < datalen) && (!expired(&timer))); + + *written_len = (size_t)len_sent; + + return (len_sent > 0 && net_err == 0) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_TCP_WRITE_FAIL; +} + +void network_at_tcp_disconnect(Network *pNetwork) +{ + int rc; + + rc = at_socket_close((int)pNetwork->handle); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("socket close error\n"); + } + + return; +} + +#endif diff --git a/sdk_src/network/network_interface.c b/sdk_src/network/network_interface.c new file mode 100755 index 00000000..ab8aa093 --- /dev/null +++ b/sdk_src/network/network_interface.c @@ -0,0 +1,111 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "network_interface.h" + +#include "qcloud_iot_export_error.h" +#include "utils_param_check.h" + +int is_network_connected(Network *pNetwork) +{ + return pNetwork->handle; +} + +#ifdef AT_TCP_ENABLED +int is_network_at_connected(Network *pNetwork) +{ + return pNetwork->handle == AT_NO_CONNECTED_FD ? 0 : pNetwork->handle == AT_NO_CONNECTED_FD; +} +#endif + +int network_init(Network *pNetwork) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + // to avoid process crash when writing to a broken socket +#if defined(__linux__) + signal(SIGPIPE, SIG_IGN); +#endif + + switch (pNetwork->type) { + case NETWORK_TCP: +#ifdef AT_TCP_ENABLED + pNetwork->init = network_at_tcp_init; + pNetwork->connect = network_at_tcp_connect; + pNetwork->read = network_at_tcp_read; + pNetwork->write = network_at_tcp_write; + pNetwork->disconnect = network_at_tcp_disconnect; + pNetwork->is_connected = is_network_at_connected; + pNetwork->handle = AT_NO_CONNECTED_FD; +#else + pNetwork->init = network_tcp_init; + pNetwork->connect = network_tcp_connect; + pNetwork->read = network_tcp_read; + pNetwork->write = network_tcp_write; + pNetwork->disconnect = network_tcp_disconnect; + pNetwork->is_connected = is_network_connected; + pNetwork->handle = 0; +#endif + break; + +#ifndef AUTH_WITH_NOTLS + case NETWORK_TLS: + pNetwork->init = network_tls_init; + pNetwork->connect = network_tls_connect; + pNetwork->read = network_tls_read; + pNetwork->write = network_tls_write; + pNetwork->disconnect = network_tls_disconnect; + pNetwork->is_connected = is_network_connected; + pNetwork->handle = 0; + break; +#endif + +#ifdef COAP_COMM_ENABLED +#ifdef AUTH_WITH_NOTLS + case NETWORK_UDP: + pNetwork->init = network_udp_init; + pNetwork->connect = network_udp_connect; + pNetwork->read = network_udp_read; + pNetwork->write = network_udp_write; + pNetwork->disconnect = network_udp_disconnect; + pNetwork->is_connected = is_network_connected; + pNetwork->handle = 0; + break; +#else + case NETWORK_DTLS: + pNetwork->init = network_dtls_init; + pNetwork->connect = network_dtls_connect; + pNetwork->read = network_dtls_read; + pNetwork->write = network_dtls_write; + pNetwork->disconnect = network_dtls_disconnect; + pNetwork->is_connected = is_network_connected; + pNetwork->handle = 0; + break; +#endif +#endif + default: + Log_e("unknown network type: %d", pNetwork->type); + return QCLOUD_ERR_INVAL; + } + return pNetwork->init(pNetwork); +} + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/network/socket/network_socket.c b/sdk_src/network/socket/network_socket.c new file mode 100755 index 00000000..184f0808 --- /dev/null +++ b/sdk_src/network/socket/network_socket.c @@ -0,0 +1,131 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "network_interface.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/* + * TCP/UDP socket API + */ + +int network_tcp_init(Network *pNetwork) +{ + return QCLOUD_RET_SUCCESS; +} + +int network_tcp_connect(Network *pNetwork) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + pNetwork->handle = HAL_TCP_Connect(pNetwork->host, pNetwork->port); + if (0 == pNetwork->handle) { + return -1; + } + + return 0; +} + +int network_tcp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int rc = 0; + + rc = HAL_TCP_Read(pNetwork->handle, data, (uint32_t)datalen, timeout_ms, read_len); + + return rc; +} + +int network_tcp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int rc = 0; + + rc = HAL_TCP_Write(pNetwork->handle, data, datalen, timeout_ms, written_len); + + return rc; +} + +void network_tcp_disconnect(Network *pNetwork) +{ + POINTER_SANITY_CHECK_RTN(pNetwork); + + if (0 == pNetwork->handle) { + return; + } + + HAL_TCP_Disconnect(pNetwork->handle); + pNetwork->handle = 0; + return; +} + +#if (defined COAP_COMM_ENABLED) && (defined AUTH_WITH_NOTLS) + +int network_udp_init(Network *pNetwork) +{ + return QCLOUD_RET_SUCCESS; +} + +int network_udp_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int ret = HAL_UDP_ReadTimeout(pNetwork->handle, data, datalen, timeout_ms); + if (ret > 0) { + *read_len = ret; + ret = 0; + } + + return ret; +} + +int network_udp_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int ret = HAL_UDP_Write(pNetwork->handle, data, datalen); + if (ret > 0) { + *written_len = ret; + ret = 0; + } + + return ret; +} + +void network_udp_disconnect(Network *pNetwork) +{ + POINTER_SANITY_CHECK_RTN(pNetwork); + + HAL_UDP_Disconnect(pNetwork->handle); + pNetwork->handle = 0; + + return; +} + +int network_udp_connect(Network *pNetwork) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + pNetwork->handle = HAL_UDP_Connect(pNetwork->host, pNetwork->port); + if (0 == pNetwork->handle) { + return -1; + } + return 0; +} + +#endif diff --git a/sdk_src/network/tls/network_tls.c b/sdk_src/network/tls/network_tls.c new file mode 100755 index 00000000..92697c2e --- /dev/null +++ b/sdk_src/network/tls/network_tls.c @@ -0,0 +1,117 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "network_interface.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/* + * TLS/DTLS network API + */ +#ifndef AUTH_WITH_NOTLS + +int network_tls_init(Network *pNetwork) +{ + return QCLOUD_RET_SUCCESS; +} + +int network_tls_connect(Network *pNetwork) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int ret = QCLOUD_ERR_SSL_CONNECT; + + pNetwork->handle = (uintptr_t)HAL_TLS_Connect(&(pNetwork->ssl_connect_params), pNetwork->host, pNetwork->port); + if (pNetwork->handle != 0) { + ret = QCLOUD_RET_SUCCESS; + } + + return ret; +} + +int network_tls_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int rc = HAL_TLS_Read(pNetwork->handle, data, datalen, timeout_ms, read_len); + + return rc; +} + +int network_tls_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int rc = HAL_TLS_Write(pNetwork->handle, data, datalen, timeout_ms, written_len); + + return rc; +} + +void network_tls_disconnect(Network *pNetwork) +{ + POINTER_SANITY_CHECK_RTN(pNetwork); + + HAL_TLS_Disconnect(pNetwork->handle); + pNetwork->handle = 0; +} + +#ifdef COAP_COMM_ENABLED + +int network_dtls_init(Network *pNetwork) +{ + return QCLOUD_RET_SUCCESS; +} + +int network_dtls_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + return HAL_DTLS_Read(pNetwork->handle, data, datalen, timeout_ms, read_len); +} + +int network_dtls_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + return HAL_DTLS_Write(pNetwork->handle, data, datalen, written_len); +} + +void network_dtls_disconnect(Network *pNetwork) +{ + POINTER_SANITY_CHECK_RTN(pNetwork); + + HAL_DTLS_Disconnect(pNetwork->handle); + pNetwork->handle = 0; + + return; +} + +int network_dtls_connect(Network *pNetwork) +{ + POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); + + int ret = QCLOUD_ERR_FAILURE; + + pNetwork->handle = (uintptr_t)HAL_DTLS_Connect(&(pNetwork->ssl_connect_params), pNetwork->host, pNetwork->port); + if (pNetwork->handle != 0) { + ret = QCLOUD_RET_SUCCESS; + } + + return ret; +} +#endif + +#endif diff --git a/sdk_src/protocol/coap/coap_client.c b/sdk_src/protocol/coap/coap_client.c new file mode 100755 index 00000000..aeab199c --- /dev/null +++ b/sdk_src/protocol/coap/coap_client.c @@ -0,0 +1,360 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "coap_client.h" + +#include +#include +#include +#include +#include + +#include "qcloud_iot_ca.h" +#include "qcloud_iot_common.h" +#include "qcloud_iot_device.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_base64.h" +#include "utils_param_check.h" + +static uint16_t _get_random_start_packet_id(void) +{ + srand((unsigned)time(NULL)); + return rand() % 65536 + 1; +} + +DeviceInfo *IOT_COAP_GetDeviceInfo(void *pClient) +{ + POINTER_SANITY_CHECK(pClient, NULL); + CoAPClient *coap_client = (CoAPClient *)pClient; + return &coap_client->device_info; +} + +void *IOT_COAP_Construct(CoAPInitParams *pParams) +{ + POINTER_SANITY_CHECK(pParams, NULL); + STRING_PTR_SANITY_CHECK(pParams->product_id, NULL); + STRING_PTR_SANITY_CHECK(pParams->device_name, NULL); + + CoAPClient *coap_client = NULL; + if ((coap_client = (CoAPClient *)HAL_Malloc(sizeof(CoAPClient))) == NULL) { + Log_e("memory not enough to malloc COAPClient"); + return NULL; + } + + int rc = qcloud_iot_coap_init(coap_client, pParams); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("coap init failed: %d", rc); + HAL_Free(coap_client); + return NULL; + } + + if (coap_client->network_stack.connect(&coap_client->network_stack) != QCLOUD_RET_SUCCESS) { + Log_e("coap connect to host: %s:%d failed: %d", STRING_PTR_PRINT_SANITY_CHECK(coap_client->network_stack.host), + coap_client->network_stack.port, rc); + HAL_Free(coap_client); + return NULL; + } else { + Log_i("coap connect to host: %s:%d success", coap_client->network_stack.host, coap_client->network_stack.port); + } + + coap_client_auth(coap_client); + while (coap_client->is_authed == -1) { + IOT_COAP_Yield(coap_client, 200); + } + + if (coap_client->is_authed == COAP_TRUE) { + Log_i("device auth successfully, connid: %s", coap_client->conn_id); + return coap_client; + } else { + Log_e("device auth failed, connid: %s", STRING_PTR_PRINT_SANITY_CHECK(coap_client->conn_id)); + void *client = coap_client; + IOT_COAP_Destroy(&client); + return NULL; + } +} + +void IOT_COAP_Destroy(void **pClient) +{ + POINTER_SANITY_CHECK_RTN(*pClient); + + CoAPClient *coap_client = (CoAPClient *)(*pClient); + + if ((coap_client)->network_stack.handle != 0) { + (coap_client)->network_stack.disconnect(&(coap_client)->network_stack); + } + + list_destroy(coap_client->message_list); + + HAL_MutexDestroy(coap_client->lock_send_buf); + HAL_MutexDestroy(coap_client->lock_list_wait_ack); + + if (coap_client->auth_token != NULL) { + HAL_Free(coap_client->auth_token); + coap_client->auth_token = NULL; + } + coap_client->auth_token_len = 0; + coap_client->is_authed = -1; + + HAL_Free(*pClient); + *pClient = NULL; + + Log_i("coap release!"); +} + +int IOT_COAP_Yield(void *pClient, uint32_t timeout_ms) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + CoAPClient *coap_client = (CoAPClient *)pClient; + + return coap_message_cycle(coap_client, timeout_ms); +} + +int IOT_COAP_SendMessage(void *pClient, char *topicName, SendMsgParams *sendParams) +{ + IOT_FUNC_ENTRY + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(topicName, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(sendParams, QCLOUD_ERR_INVAL); + + if (strlen(topicName) > URI_PATH_MAX_LEN) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH); + } + + int ret = QCLOUD_RET_SUCCESS; + + CoAPClient *coap_client = (CoAPClient *)pClient; + + CoAPMessage send_message = DEFAULT_COAP_MESSAGE; + + coap_message_type_set(&send_message, COAP_MSG_CON); + coap_message_code_set(&send_message, COAP_MSG_REQ, COAP_MSG_POST); + + coap_message_id_set(&send_message, get_next_coap_msg_id(coap_client)); + + char message_token[8] = {0}; + int len = get_coap_message_token(pClient, message_token); + coap_message_token_set(&send_message, message_token, len); + + send_message.pay_load = (char *)HAL_Malloc(sendParams->pay_load_len); + if (NULL == send_message.pay_load) + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); + + coap_message_payload_set(&send_message, sendParams->pay_load, sendParams->pay_load_len); + + coap_message_option_add(&send_message, COAP_MSG_URI_PATH, strlen(topicName), topicName); + coap_message_option_add(&send_message, COAP_MSG_AUTH_TOKEN, coap_client->auth_token_len, coap_client->auth_token); + if (sendParams->need_resp == false) { + coap_message_option_add(&send_message, COAP_MSG_NEED_RESP, 1, "0"); + coap_message_context_set(&send_message, sendParams->user_context); + } else { + coap_message_option_add(&send_message, COAP_MSG_NEED_RESP, 1, "1"); + coap_message_callback_set(&send_message, sendParams->resp_callback); + coap_message_context_set(&send_message, sendParams->user_context); + } + + ret = coap_message_send(coap_client, &send_message); + + HAL_Free(send_message.pay_load); + + if (ret != QCLOUD_RET_SUCCESS) { + IOT_FUNC_EXIT_RC(ret) + } + + IOT_FUNC_EXIT_RC(send_message.msg_id) +} + +int IOT_COAP_GetMessageId(void *pMessage) +{ + IOT_FUNC_ENTRY + + POINTER_SANITY_CHECK(pMessage, QCLOUD_ERR_INVAL); + CoAPMessage *message = (CoAPMessage *)pMessage; + + IOT_FUNC_EXIT_RC(message->msg_id) +} + +int IOT_COAP_GetMessagePayload(void *pMessage, char **payload, int *payloadLen) +{ + IOT_FUNC_ENTRY + + POINTER_SANITY_CHECK(pMessage, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(payload, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(payloadLen, QCLOUD_ERR_INVAL); + + CoAPMessage *message = (CoAPMessage *)pMessage; + if (message->code_class != COAP_MSG_SUCCESS || message->code_detail != COAP_MSG_CODE_205_CONTENT) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) + } + + *payload = message->pay_load; + *payloadLen = message->pay_load_len; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int IOT_COAP_GetMessageCode(void *pMessage) +{ + IOT_FUNC_ENTRY + + POINTER_SANITY_CHECK(pMessage, QCLOUD_ERR_INVAL); + + CoAPMessage *message = (CoAPMessage *)pMessage; + + int rc = COAP_EVENT_ACK_TIMEOUT; + + if (message->code_class == COAP_MSG_SUCCESS) { + rc = COAP_EVENT_RECEIVE_RESPCONTENT; + } else if (message->code_class == COAP_MSG_CLIENT_ERR) { + if (message->code_detail == COAP_MSG_CODE_401_UNAUTHORIZED) { + rc = COAP_EVENT_UNAUTHORIZED; + } else { + rc = COAP_EVENT_FORBIDDEN; + } + } else if (message->code_class == COAP_MSG_SERVER_ERR) { + rc = COAP_EVENT_INTERNAL_SERVER_ERROR; + } else if (message->code_class == COAP_MSG_SDKINTERNAL_ERR) { + rc = COAP_EVENT_SEPRESP_TIMEOUT; + } else { + /** + * no more error code + */ + Log_e("not supported code class: %d", message->code_class); + } + + IOT_FUNC_EXIT_RC(rc) +} + +int qcloud_iot_coap_init(CoAPClient *pClient, CoAPInitParams *pParams) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pParams, QCLOUD_ERR_INVAL); + + memset(pClient, 0x0, sizeof(CoAPClient)); + + int rc = iot_device_info_set(&(pClient->device_info), pParams->product_id, pParams->device_name); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("failed to set device info: %d", rc); + return rc; + } + + int size = + HAL_Snprintf(pClient->host_addr, HOST_STR_LENGTH, "%s.%s", pParams->product_id, QCLOUD_IOT_COAP_DEIRECT_DOMAIN); + if (size < 0 || size > HOST_STR_LENGTH - 1) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + pClient->is_authed = -1; + + if (pParams->command_timeout < MIN_COMMAND_TIMEOUT) + pParams->command_timeout = MIN_COMMAND_TIMEOUT; + if (pParams->command_timeout > MAX_COMMAND_TIMEOUT) + pParams->command_timeout = MAX_COMMAND_TIMEOUT; + pClient->command_timeout_ms = pParams->command_timeout; + +#ifndef AUTH_WITH_NOTLS +#ifdef AUTH_MODE_CERT + Log_d("cert file: %s", STRING_PTR_PRINT_SANITY_CHECK(pParams->cert_file)); + Log_d("key file: %s", STRING_PTR_PRINT_SANITY_CHECK(pParams->key_file)); + + strncpy(pClient->cert_file_path, pParams->cert_file, FILE_PATH_MAX_LEN - 1); + strncpy(pClient->key_file_path, pParams->key_file, FILE_PATH_MAX_LEN - 1); + + // device param for TLS connection + pClient->network_stack.ssl_connect_params.cert_file = pParams->cert_file; + pClient->network_stack.ssl_connect_params.key_file = pParams->key_file; + pClient->network_stack.ssl_connect_params.ca_crt = iot_ca_get(); + pClient->network_stack.ssl_connect_params.ca_crt_len = strlen(pClient->network_stack.ssl_connect_params.ca_crt); + +#else + pClient->network_stack.ssl_connect_params.psk_id = pClient->device_info.client_id; + if (pParams->device_secret != NULL) { + size_t src_len = strlen(pParams->device_secret); + size_t len; + memset(pClient->psk_decode, 0x00, DECODE_PSK_LENGTH); + qcloud_iot_utils_base64decode(pClient->psk_decode, DECODE_PSK_LENGTH, &len, + (unsigned char *)pParams->device_secret, src_len); + pClient->network_stack.ssl_connect_params.psk = (char *)pClient->psk_decode; + pClient->network_stack.ssl_connect_params.psk_length = len; + pClient->network_stack.ssl_connect_params.ca_crt = NULL; + pClient->network_stack.ssl_connect_params.ca_crt_len = 0; + } else { + Log_e("psk is empty!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); + } +#endif + + pClient->network_stack.host = pClient->host_addr; + pClient->network_stack.port = COAP_SERVER_PORT; +#else + pClient->network_stack.host = pClient->host_addr; + pClient->network_stack.port = COAP_SERVER_PORT; +#endif + + pClient->auth_token = NULL; + pClient->auth_token_len = 0; + // next_msg_id, random: 1- 65536 + pClient->next_msg_id = _get_random_start_packet_id(); + pClient->read_buf_size = COAP_RECVMSG_MAX_BUFLEN; + pClient->send_buf_size = COAP_SENDMSG_MAX_BUFLEN; + + pClient->lock_send_buf = HAL_MutexCreate(); + if (pClient->lock_send_buf == NULL) { + Log_e("create send buf lock failed"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + pClient->lock_list_wait_ack = HAL_MutexCreate(); + if (pClient->lock_list_wait_ack == NULL) { + Log_e("create send buf lock failed"); + goto error; + } + + pClient->message_list = list_new(); + pClient->max_retry_count = pParams->max_retry_count; + pClient->event_handle = pParams->event_handle; + + // init network stack + qcloud_iot_coap_network_init(&(pClient->network_stack)); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); + +error: + if (pClient->lock_send_buf != NULL) { + HAL_MutexDestroy(pClient->lock_send_buf); + pClient->lock_send_buf = NULL; + } + + if (pClient->lock_list_wait_ack != NULL) { + HAL_MutexDestroy(pClient->lock_list_wait_ack); + pClient->lock_list_wait_ack = NULL; + } + + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); +} + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/protocol/coap/coap_client_auth.c b/sdk_src/protocol/coap/coap_client_auth.c new file mode 100755 index 00000000..4d4d6ce1 --- /dev/null +++ b/sdk_src/protocol/coap/coap_client_auth.c @@ -0,0 +1,148 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "coap_client.h" +#include "qcloud_iot_common.h" +#include "qcloud_iot_device.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +static void _coap_client_auth_callback(void *message, void *userContext) +{ + IOT_FUNC_ENTRY + + POINTER_SANITY_CHECK_RTN(message); + POINTER_SANITY_CHECK_RTN(userContext); + + CoAPClient * client = (CoAPClient *)userContext; + CoAPMessage *msg = (CoAPMessage *)message; + + if (msg->code_class == COAP_MSG_SUCCESS && msg->code_detail == COAP_MSG_CODE_205_CONTENT) { + Log_i("auth token message success, code_class: %d code_detail: %d", msg->code_class, msg->code_detail); + if (msg->pay_load_len == 0 || msg->pay_load == NULL || strlen(msg->pay_load) == 0) { + client->is_authed = COAP_FALSE; + Log_e("auth token response empty"); + } else { + client->auth_token_len = msg->pay_load_len; + client->auth_token = HAL_Malloc(client->auth_token_len); + strncpy(client->auth_token, msg->pay_load, client->auth_token_len); + client->is_authed = COAP_TRUE; + Log_d("auth_token_len = %d, auth_token = %.*s", client->auth_token_len, client->auth_token_len, + STRING_PTR_PRINT_SANITY_CHECK(client->auth_token)); + } + } else { + client->is_authed = COAP_FALSE; + Log_e("auth token message failed, code_class: %d code_detail: %d", msg->code_class, msg->code_detail); + } + + IOT_FUNC_EXIT +} + +static void get_coap_next_conn_id(CoAPClient *pclient) +{ + int i = 0; + + srand((unsigned)time(0)); + + for (i = 0; i < COAP_MAX_CONN_ID_LEN - 1; i++) { + int flag = rand() % 3; + + switch (flag) { + case 0: + pclient->conn_id[i] = (rand() % 26) + 'a'; + break; + case 1: + pclient->conn_id[i] = (rand() % 26) + 'A'; + break; + case 2: + pclient->conn_id[i] = (rand() % 10) + '0'; + break; + } + } + + pclient->conn_id[COAP_MAX_CONN_ID_LEN - 1] = '\0'; + + return; +} + +int coap_client_auth(CoAPClient *pclient) +{ + IOT_FUNC_ENTRY + + POINTER_SANITY_CHECK(pclient, QCLOUD_ERR_COAP_NULL); + + int ret = QCLOUD_RET_SUCCESS; + + CoAPClient *coap_client = (CoAPClient *)pclient; + CoAPMessage send_message = DEFAULT_COAP_MESSAGE; + + coap_message_type_set(&send_message, COAP_MSG_CON); + coap_message_code_set(&send_message, COAP_MSG_REQ, COAP_MSG_POST); + + coap_message_id_set(&send_message, get_next_coap_msg_id(coap_client)); + + char message_token[8] = {0}; + int len = get_coap_message_token(pclient, message_token); + coap_message_token_set(&send_message, message_token, len); + + len = MAX_SIZE_OF_PRODUCT_ID + strlen(pclient->device_info.device_name) + strlen(COAP_AUTH_URI) + 4; + char *auth_path = (char *)HAL_Malloc(len); + HAL_Snprintf(auth_path, len, "%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(pclient->device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(pclient->device_info.device_name), COAP_AUTH_URI); + coap_message_option_add(&send_message, COAP_MSG_URI_PATH, strlen(auth_path), auth_path); + HAL_Free(auth_path); + + coap_message_option_add(&send_message, COAP_MSG_NEED_RESP, 1, "0"); + + coap_message_callback_set(&send_message, _coap_client_auth_callback); + coap_message_context_set(&send_message, pclient); + + get_coap_next_conn_id(coap_client); + + send_message.pay_load_len = strlen(QCLOUD_IOT_DEVICE_SDK_APPID) + COAP_MAX_CONN_ID_LEN + 2; + send_message.pay_load = (char *)HAL_Malloc(send_message.pay_load_len); + if (NULL == send_message.pay_load) + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); + + char *temp_pay_load = (char *)HAL_Malloc(send_message.pay_load_len); + if (NULL == temp_pay_load) { + HAL_Free(send_message.pay_load); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); + } + + HAL_Snprintf(temp_pay_load, send_message.pay_load_len, "%s;%s", QCLOUD_IOT_DEVICE_SDK_APPID, + STRING_PTR_PRINT_SANITY_CHECK(coap_client->conn_id)); + + coap_message_payload_set(&send_message, temp_pay_load, send_message.pay_load_len); + + ret = coap_message_send(coap_client, &send_message); + + HAL_Free(temp_pay_load); + HAL_Free(send_message.pay_load); + + IOT_FUNC_EXIT_RC(ret) +} + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/protocol/coap/coap_client_common.c b/sdk_src/protocol/coap/coap_client_common.c new file mode 100755 index 00000000..18b7ab8e --- /dev/null +++ b/sdk_src/protocol/coap/coap_client_common.c @@ -0,0 +1,284 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include "coap_client.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +/** + * @brief Free an option structure that was allocated by coap_msg_op_new + * + * @param[in,out] op Pointer to the option structure + */ +static void _coap_msg_op_delete(CoAPMsgOption *option) +{ + IOT_FUNC_ENTRY + HAL_Free(option->val); + HAL_Free(option); + IOT_FUNC_EXIT +} + +/** + * @brief Deinitialise an option linked-list structure + * + * @param[in,out] list Pointer to an option linked-list structure + */ +static void _coap_msg_op_list_destroy(CoAPMsgOptionList *list) +{ + IOT_FUNC_ENTRY + + CoAPMsgOption *prev = NULL; + CoAPMsgOption *option = NULL; + + option = list->first; + while (option != NULL) { + prev = option; + option = option->next; + _coap_msg_op_delete(prev); + } + memset(list, 0, sizeof(CoAPMsgOptionList)); + + IOT_FUNC_EXIT +} + +uint16_t get_next_coap_msg_id(CoAPClient *pClient) +{ + IOT_FUNC_ENTRY + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + unsigned int id = 0; + id = pClient->next_msg_id = + (uint16_t)((COAP_MSG_MAX_MSG_ID == pClient->next_msg_id) ? 1 : (pClient->next_msg_id + 1)); + + IOT_FUNC_EXIT_RC(id) +} + +unsigned int get_coap_message_token(CoAPClient *client, char *tokenData) +{ + unsigned int value = client->message_token; + tokenData[0] = ((value & 0x00FF) >> 0); + tokenData[1] = ((value & 0xFF00) >> 8); + tokenData[2] = ((value & 0xFF0000) >> 16); + tokenData[3] = ((value & 0xFF000000) >> 24); + client->message_token++; + return sizeof(unsigned int); +} + +int coap_message_type_set(CoAPMessage *message, unsigned type) +{ + IOT_FUNC_ENTRY + + if ((type != COAP_MSG_CON) && (type != COAP_MSG_NON) && (type != COAP_MSG_ACK) && (type != COAP_MSG_RST)) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) + } + message->type = type; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int coap_message_code_set(CoAPMessage *message, unsigned code_class, unsigned code_detail) +{ + IOT_FUNC_ENTRY + + if (code_class > COAP_MSG_MAX_CODE_CLASS) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) + } + if (code_detail > COAP_MSG_MAX_CODE_DETAIL) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) + } + message->code_class = code_class; + message->code_detail = code_detail; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int coap_message_id_set(CoAPMessage *message, unsigned msg_id) +{ + IOT_FUNC_ENTRY + + if (msg_id > COAP_MSG_MAX_MSG_ID) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) + } + message->msg_id = msg_id; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int coap_message_token_set(CoAPMessage *message, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + if (len > COAP_MSG_MAX_TOKEN_LEN) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) + } + memcpy(message->token, buf, len); + message->token_len = len; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int coap_message_payload_set(CoAPMessage *message, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + message->pay_load_len = 0; + + if (len > 0) { + if (message->pay_load == NULL) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) + } + + memcpy(message->pay_load, buf, len); + message->pay_load_len = len; + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int coap_message_option_add(CoAPMessage *message, unsigned num, unsigned len, const char *val) +{ + IOT_FUNC_ENTRY + + CoAPMsgOption * prev = NULL; + CoAPMsgOption * option = NULL; + CoAPMsgOptionList *list = &message->op_list; + + if ((option = qcloud_iot_coap_option_init(num, len, val)) == NULL) { + Log_e("allocate new option failed."); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) + } + + if (list->first == NULL) { + /* empty list */ + list->first = option; + list->last = option; + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) + } + + if (option->option_num < list->first->option_num) { + /* start of the list */ + option->next = list->first; + list->first = option; + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) + } + + prev = list->first; + while (prev != list->last) { + /* middle of the list */ + if ((prev->option_num <= option->option_num) && (option->option_num < prev->next->option_num)) { + option->next = prev->next; + prev->next = option; + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) + } + prev = prev->next; + } + + /* end of the list */ + list->last->next = option; + list->last = option; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int coap_message_callback_set(CoAPMessage *message, OnRespCallback callback) +{ + IOT_FUNC_ENTRY + + message->handler = callback; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int coap_message_context_set(CoAPMessage *message, void *userContext) +{ + IOT_FUNC_ENTRY + + message->user_context = userContext; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +CoAPMsgOption *qcloud_iot_coap_option_init(unsigned num, unsigned len, const char *val) +{ + IOT_FUNC_ENTRY + + CoAPMsgOption *option = NULL; + + option = (CoAPMsgOption *)HAL_Malloc(sizeof(CoAPMsgOption)); + if (option == NULL) { + Log_e("no space to malloc option"); + return NULL; + } + + option->option_num = num; + option->val_len = len; + option->val = (char *)HAL_Malloc(len); + if (option->val == NULL) { + HAL_Free(option); + option = NULL; + Log_e("no space to malloc option"); + return NULL; + } + + memcpy(option->val, val, len); + option->next = NULL; + + return option; +} + +void coap_message_destroy(CoAPMessage *message) +{ + IOT_FUNC_ENTRY + + _coap_msg_op_list_destroy(&message->op_list); + + if (message->pay_load != NULL) { + HAL_Free(message->pay_load); + } + + memset(message, 0, sizeof(CoAPMessage)); + + IOT_FUNC_EXIT +} + +void coap_msg_dump(CoAPMessage *msg) +{ + Log_i("msg->version = %u", msg->version); + Log_i("msg->type = %d", msg->type); + Log_i("msg->code_class = %u", msg->code_class); + Log_i("msg->code_detail = %u", msg->code_detail); + Log_i("msg->msg_id = %d", msg->msg_id); + Log_i("msg->pay_load_len = %d", msg->pay_load_len); + Log_i("msg->pay_load: %s", STRING_PTR_PRINT_SANITY_CHECK(msg->pay_load)); + + Log_i("msg->token_len = %u", msg->token_len); + Log_i("msg->token: %s", STRING_PTR_PRINT_SANITY_CHECK(msg->token)); + return; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/coap/src/coap_client_deserialize.c b/sdk_src/protocol/coap/coap_client_deserialize.c old mode 100644 new mode 100755 similarity index 69% rename from src/coap/src/coap_client_deserialize.c rename to sdk_src/protocol/coap/coap_client_deserialize.c index ef0db262..f6aaaecd --- a/src/coap/src/coap_client_deserialize.c +++ b/sdk_src/protocol/coap/coap_client_deserialize.c @@ -1,429 +1,387 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "coap_client.h" - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" - -#define COAP_MSG_OPLIST_LAST(list) ((list)->last) /**< Get the last option in an option linked-list */ -#define COAP_MSG_OPLIST_EMPTY(list) ((list)->first == NULL) /**< Indicate whether or not an option linked-list is empty */ - -#define Swap16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8)) - -/** - * @brief Check a message for correctness - * - * The following checks from RFC7252 are performed: - * - * An Empty message has the Code field set to 0.00. The Token Length - * field MUST be set to 0 and bytes of data MUST NOT be present after - * the Message ID field. If there are any bytes, they MUST be processed - * as a message format error. - * - * The Reset message MUST echo the Message ID of the Confirmable message - * and MUST be Empty. - * - * A Non-confirmable message always carries either a request or response - * and MUST NOT be Empty. - * - * @param[in] msg Pointer to a message structure - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int _coap_msg_check(CoAPMessage *msg) -{ - IOT_FUNC_ENTRY - - if ((msg->code_class == 0) && (msg->code_detail == 0)) - { - /* empty message */ - if ((msg->type == COAP_MSG_NON) || (msg->token_len != 0) || (!COAP_MSG_OPLIST_EMPTY(&msg->op_list)) - || (msg->pay_load_len != 0)) - { - Log_e("coap msg op list is not empty"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - } - else - { - /* non-empty message */ - if (msg->type == COAP_MSG_RST) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -/** - * @brief Allocate an option structure and add it to the end of an option linked-list structure - * - * @param[in,out] list Pointer to an option linked-list structure - * @param[in] num Option number - * @param[in] len Option length - * @param[in] val Pointer to a buffer containing the option value - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int _coap_msg_op_list_add_last(CoAPMsgOptionList *list, unsigned num, unsigned len, const char *val) { - IOT_FUNC_ENTRY - - CoAPMsgOption *option = NULL; - - if ((option = qcloud_iot_coap_option_init(num, len, val)) == NULL) { - Log_e("allocate new option failed."); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) - } - - if (list->first == NULL) - { - list->first = option; - list->last = option; - } - else - { - list->last->next = option; - list->last = option; - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -/** - * @brief Parse the header in a message - * - * @param[out] msg Pointer to a message structure - * @param[in] buf Pointer to a buffer containing the message - * @param[in] len Length of the buffer - * - * @returns Number of bytes parsed or error code - * @retval >0 Number of bytes parsed - * @retval <0 Error - */ -static ssize_t _coap_message_deserialize_header(CoAPMessage *msg, char *buf, size_t len) -{ - IOT_FUNC_ENTRY - - char *p = buf; - - if (len < 4) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - - msg->version = (p[0] >> 6) & 0x03; - if (msg->version != COAP_MSG_VER) - { - return -EINVAL; - } - - msg->type = (p[0] >> 4) & 0x03; - msg->token_len = p[0] & 0x0f; - if (msg->token_len > sizeof(msg->token)) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - - msg->code_detail = p[1] & 0x1f; - msg->code_class = (p[1] >> 5) & 0x07; - - if ((msg->code_class != COAP_MSG_REQ) && (msg->code_class != COAP_MSG_SUCCESS) - && (msg->code_class != COAP_MSG_CLIENT_ERR) && (msg->code_class != COAP_MSG_SERVER_ERR)) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_BADMSG) - } - - msg->msg_id = Swap16(*((uint16_t *)(&p[2]))); - p += 4; - len -= 4; - - IOT_FUNC_EXIT_RC(p - buf) -} - -/** - * @brief Parse the token in a message - * - * @param[out] msg Pointer to a message structure - * @param[in] buf Pointer to a buffer containing the message - * @param[in] len Length of the buffer - * - * @returns Number of bytes parsed or error code - * @retval >0 Number of bytes parsed - * @retval <0 Error - */ -static ssize_t _coap_message_deserialize_token(CoAPMessage *msg, char *buf, size_t len) -{ - IOT_FUNC_ENTRY - - if (len < msg->token_len) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - - memcpy(msg->token, buf, msg->token_len); - - IOT_FUNC_EXIT_RC(msg->token_len) -} - -/** - * @brief Parse an option in a message - * - * @param[in,out] msg Pointer to a message structure - * @param[in] buf Pointer to a buffer containing the message - * @param[in] len Length of the buffer - * - * @returns Number of bytes parsed or error code - * @retval >0 Number of bytes parsed - * @retval <0 Error - */ -static ssize_t _coap_message_deserialize_option(CoAPMessage *msg, char *buf, size_t len) -{ - IOT_FUNC_ENTRY - - CoAPMsgOption *prev = NULL; - unsigned op_delta = 0; - unsigned op_len = 0; - unsigned op_num = 0; - char *p = buf; - int ret = 0; - - if (len < 1) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - op_delta = (p[0] >> 4) & 0x0f; - op_len = p[0] & 0x0f; - if ((op_delta == 15) || (op_len == 15)) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - p++; - len--; - if (op_delta == 13) - { - if (len < 1) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - op_delta += p[0]; - p++; - len--; - } - else if (op_delta == 14) - { - if (len < 2) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - op_delta = 269 + Swap16(*((uint16_t *)(&p[0]))); - p += 2; - len -= 2; - } - if (op_len == 13) - { - if (len < 1) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - op_len += p[0]; - p++; - len--; - } - else if (op_len == 14) - { - if (len < 2) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - op_len = 269 + Swap16(*((uint16_t *)(&p[0]))); - p += 2; - len -= 2; - } - if (len < op_len) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - prev = COAP_MSG_OPLIST_LAST(&msg->op_list); - if (prev == NULL) - { - op_num = op_delta; - } - else - { - op_num = COAP_MSG_OPTION_NUM(prev) + op_delta; - } - ret = _coap_msg_op_list_add_last(&msg->op_list, op_num, op_len, p); - if (ret < 0) - { - IOT_FUNC_EXIT_RC(ret) - } - p += op_len; - - IOT_FUNC_EXIT_RC(p - buf) -} - -/** - * @brief Parse the options in a message - * - * @param[in,out] msg Pointer to a message structure - * @param[in] buf Pointer to a buffer containing the message - * @param[in] len Length of the buffer - * - * @returns Number of bytes parsed or error code - * @retval >0 Number of bytes parsed - * @retval <0 Error - */ -static ssize_t _coap_message_deserialize_options(CoAPMessage *msg, char *buf, size_t len) -{ - IOT_FUNC_ENTRY - - ssize_t num = 0; - char *p = buf; - - while (1) - { - if (((p[0] & 0xff) == 0xff) || (len == 0)) - { - break; - } - num = _coap_message_deserialize_option(msg, p, len); - if (num < 0) - { - return num; - } - p += num; - len -= num; - } - - IOT_FUNC_EXIT_RC(p - buf) -} - -/** - * @brief Parse the payload in a message - * - * @param[out] msg Pointer to a message structure - * @param[in] buf Pointer to a buffer containing the message - * @param[in] len Length of the buffer - * - * @returns Number of bytes parsed or error code - * @retval >0 Number of bytes parsed - * @retval <0 Error - */ -static ssize_t _coap_message_deserialize_payload(CoAPMessage *msg, char *buf, size_t len) -{ - IOT_FUNC_ENTRY - - char *p = buf; - - if (len == 0) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) - } - if ((p[0] & 0xff) != 0xff) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - p++; - len--; - if (len == 0) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - - msg->pay_load = (char *)HAL_Malloc(len); - - if (msg->pay_load == NULL) - { - return -ENOMEM; - } - - memcpy(msg->pay_load, p, len); - msg->pay_load_len = len; - p += len; - - IOT_FUNC_EXIT_RC(p - buf) -} - -ssize_t deserialize_coap_message(CoAPMessage *message, char *buf, size_t len) -{ - IOT_FUNC_ENTRY - - ssize_t num = 0; - char *p = buf; - - num = _coap_message_deserialize_header(message, p, len); - if (num < 0) - { - Log_e("coap_message_deserialize_header failed, num:%lu", num); - coap_message_destroy(message); - goto error; - } - - p += num; - len -= num; - num = _coap_message_deserialize_token(message, p, len); - if (num < 0) - { - Log_e("coap_message_deserialize_token failed, num:%lu", num); - coap_message_destroy(message); - goto error; - } - - p += num; - len -= num; - num = _coap_message_deserialize_options(message, p, len); - if (num < 0) - { - Log_e("coap_message_deserialize_options failed, num:%lu", num); - coap_message_destroy(message); - goto error; - } - - p += num; - len -= num; - num = _coap_message_deserialize_payload(message, p, len); - if (num < 0) - { - Log_e("coap_message_deserialize_payload failed, num:%lu", num); - coap_message_destroy(message); - goto error; - } - - IOT_FUNC_EXIT_RC(_coap_msg_check(message)) - -error: - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_INTERNAL) -} - -#ifdef __cplusplus -} -#endif - +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +#include "coap_client.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +#define COAP_MSG_OPLIST_LAST(list) ((list)->last) /**< Get the last option in an option linked-list */ +#define COAP_MSG_OPLIST_EMPTY(list) \ + ((list)->first == NULL) /**< Indicate whether or not an option linked-list is empty */ + +#define Swap16(A) ((((uint16_t)(A)&0xff00) >> 8) | (((uint16_t)(A)&0x00ff) << 8)) + +/** + * @brief Check a message for correctness + * + * The following checks from RFC7252 are performed: + * + * An Empty message has the Code field set to 0.00. The Token Length + * field MUST be set to 0 and bytes of data MUST NOT be present after + * the Message ID field. If there are any bytes, they MUST be processed + * as a message format error. + * + * The Reset message MUST echo the Message ID of the Confirmable message + * and MUST be Empty. + * + * A Non-confirmable message always carries either a request or response + * and MUST NOT be Empty. + * + * @param[in] msg Pointer to a message structure + * @returns Operation status + * @retval 0 Success + * @retval <0 Error + */ +static int _coap_msg_check(CoAPMessage *msg) +{ + IOT_FUNC_ENTRY + + if ((msg->code_class == 0) && (msg->code_detail == 0)) { + /* empty message */ + if ((msg->type == COAP_MSG_NON) || (msg->token_len != 0) || (!COAP_MSG_OPLIST_EMPTY(&msg->op_list)) || + (msg->pay_load_len != 0)) { + Log_e("coap msg op list is not empty"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + } else { + /* non-empty message */ + if (msg->type == COAP_MSG_RST) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +/** + * @brief Allocate an option structure and add it to the end of an option linked-list structure + * + * @param[in,out] list Pointer to an option linked-list structure + * @param[in] num Option number + * @param[in] len Option length + * @param[in] val Pointer to a buffer containing the option value + * + * @returns Operation status + * @retval 0 Success + * @retval <0 Error + */ +static int _coap_msg_op_list_add_last(CoAPMsgOptionList *list, unsigned num, unsigned len, const char *val) +{ + IOT_FUNC_ENTRY + + CoAPMsgOption *option = NULL; + + if ((option = qcloud_iot_coap_option_init(num, len, val)) == NULL) { + Log_e("allocate new option failed."); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) + } + + if (list->first == NULL) { + list->first = option; + list->last = option; + } else { + list->last->next = option; + list->last = option; + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +/** + * @brief Parse the header in a message + * + * @param[out] msg Pointer to a message structure + * @param[in] buf Pointer to a buffer containing the message + * @param[in] len Length of the buffer + * + * @returns Number of bytes parsed or error code + * @retval >0 Number of bytes parsed + * @retval <0 Error + */ +static ssize_t _coap_message_deserialize_header(CoAPMessage *msg, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + char *p = buf; + + if (len < 4) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + + msg->version = (p[0] >> 6) & 0x03; + if (msg->version != COAP_MSG_VER) { + return -EINVAL; + } + + msg->type = (p[0] >> 4) & 0x03; + msg->token_len = p[0] & 0x0f; + if (msg->token_len > sizeof(msg->token)) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + + msg->code_detail = p[1] & 0x1f; + msg->code_class = (p[1] >> 5) & 0x07; + + if ((msg->code_class != COAP_MSG_REQ) && (msg->code_class != COAP_MSG_SUCCESS) && + (msg->code_class != COAP_MSG_CLIENT_ERR) && (msg->code_class != COAP_MSG_SERVER_ERR)) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_BADMSG) + } + + msg->msg_id = Swap16(*((uint16_t *)(&p[2]))); + p += 4; + + IOT_FUNC_EXIT_RC(p - buf) +} + +/** + * @brief Parse the token in a message + * + * @param[out] msg Pointer to a message structure + * @param[in] buf Pointer to a buffer containing the message + * @param[in] len Length of the buffer + * + * @returns Number of bytes parsed or error code + * @retval >0 Number of bytes parsed + * @retval <0 Error + */ +static ssize_t _coap_message_deserialize_token(CoAPMessage *msg, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + if (len < msg->token_len) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + + memcpy(msg->token, buf, msg->token_len); + + IOT_FUNC_EXIT_RC(msg->token_len) +} + +/** + * @brief Parse an option in a message + * + * @param[in,out] msg Pointer to a message structure + * @param[in] buf Pointer to a buffer containing the message + * @param[in] len Length of the buffer + * + * @returns Number of bytes parsed or error code + * @retval >0 Number of bytes parsed + * @retval <0 Error + */ +static ssize_t _coap_message_deserialize_option(CoAPMessage *msg, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + CoAPMsgOption *prev = NULL; + unsigned op_delta = 0; + unsigned op_len = 0; + unsigned op_num = 0; + char * p = buf; + int ret = 0; + + if (len < 1) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + op_delta = (p[0] >> 4) & 0x0f; + op_len = p[0] & 0x0f; + if ((op_delta == 15) || (op_len == 15)) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + p++; + len--; + if (op_delta == 13) { + if (len < 1) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + op_delta += p[0]; + p++; + len--; + } else if (op_delta == 14) { + if (len < 2) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + op_delta = 269 + Swap16(*((uint16_t *)(&p[0]))); + p += 2; + len -= 2; + } + if (op_len == 13) { + if (len < 1) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + op_len += p[0]; + p++; + len--; + } else if (op_len == 14) { + if (len < 2) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + op_len = 269 + Swap16(*((uint16_t *)(&p[0]))); + p += 2; + len -= 2; + } + if (len < op_len) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + prev = COAP_MSG_OPLIST_LAST(&msg->op_list); + if (prev == NULL) { + op_num = op_delta; + } else { + op_num = COAP_MSG_OPTION_NUM(prev) + op_delta; + } + ret = _coap_msg_op_list_add_last(&msg->op_list, op_num, op_len, p); + if (ret < 0) { + IOT_FUNC_EXIT_RC(ret) + } + p += op_len; + + IOT_FUNC_EXIT_RC(p - buf) +} + +/** + * @brief Parse the options in a message + * + * @param[in,out] msg Pointer to a message structure + * @param[in] buf Pointer to a buffer containing the message + * @param[in] len Length of the buffer + * + * @returns Number of bytes parsed or error code + * @retval >0 Number of bytes parsed + * @retval <0 Error + */ +static ssize_t _coap_message_deserialize_options(CoAPMessage *msg, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + ssize_t num = 0; + char * p = buf; + + while (1) { + if (((p[0] & 0xff) == 0xff) || (len == 0)) { + break; + } + num = _coap_message_deserialize_option(msg, p, len); + if (num < 0) { + return num; + } + p += num; + len -= num; + } + + IOT_FUNC_EXIT_RC(p - buf) +} + +/** + * @brief Parse the payload in a message + * + * @param[out] msg Pointer to a message structure + * @param[in] buf Pointer to a buffer containing the message + * @param[in] len Length of the buffer + * + * @returns Number of bytes parsed or error code + * @retval >0 Number of bytes parsed + * @retval <0 Error + */ +static ssize_t _coap_message_deserialize_payload(CoAPMessage *msg, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + char *p = buf; + + if (len == 0) { + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) + } + if ((p[0] & 0xff) != 0xff) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + p++; + len--; + if (len == 0) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + + msg->pay_load = (char *)HAL_Malloc(len); + + if (msg->pay_load == NULL) { + return -ENOMEM; + } + + memcpy(msg->pay_load, p, len); + msg->pay_load_len = len; + p += len; + + IOT_FUNC_EXIT_RC(p - buf) +} + +ssize_t deserialize_coap_message(CoAPMessage *message, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + ssize_t num = 0; + char * p = buf; + + num = _coap_message_deserialize_header(message, p, len); + if (num < 0) { + Log_e("coap_message_deserialize_header failed, num:%lu", num); + coap_message_destroy(message); + goto error; + } + + p += num; + len -= num; + num = _coap_message_deserialize_token(message, p, len); + if (num < 0) { + Log_e("coap_message_deserialize_token failed, num:%lu", num); + coap_message_destroy(message); + goto error; + } + + p += num; + len -= num; + num = _coap_message_deserialize_options(message, p, len); + if (num < 0) { + Log_e("coap_message_deserialize_options failed, num:%lu", num); + coap_message_destroy(message); + goto error; + } + + p += num; + len -= num; + num = _coap_message_deserialize_payload(message, p, len); + if (num < 0) { + Log_e("coap_message_deserialize_payload failed, num:%lu", num); + coap_message_destroy(message); + goto error; + } + + IOT_FUNC_EXIT_RC(_coap_msg_check(message)) + +error: + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_INTERNAL) +} + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/protocol/coap/coap_client_message.c b/sdk_src/protocol/coap/coap_client_message.c new file mode 100755 index 00000000..c9bc1d22 --- /dev/null +++ b/sdk_src/protocol/coap/coap_client_message.c @@ -0,0 +1,418 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "coap_client.h" +#include "coap_client_net.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" +#include "utils_timer.h" + +#define PROCESS_ACK_CMD (0) +#define PROCESS_PIGGY_CMD (1) +#define PROCESS_RESP_CMD (2) +#define PROCESS_WAIT_CMD (3) + +static void _event_message_type_set(CoAPEventMessage *eventMsg, CoAPMessage *message, uint16_t processCmd) +{ + if (message->code_class == COAP_MSG_SUCCESS && message->code_detail == COAP_MSG_CODE_205_CONTENT) { + eventMsg->event_type = processCmd == PROCESS_RESP_CMD ? COAP_EVENT_RECEIVE_RESPCONTENT : COAP_EVENT_RECEIVE_ACK; + } else if (message->code_class == COAP_MSG_CLIENT_ERR && message->code_detail == COAP_MSG_CODE_401_UNAUTHORIZED) { + eventMsg->event_type = COAP_EVENT_UNAUTHORIZED; + Log_e("coap messagefailed, message id: %d, failure reason: %d.%d", message->msg_id, message->code_class, + message->code_detail); + } else if (message->code_class == COAP_MSG_CLIENT_ERR && message->code_detail == COAP_MSG_CODE_403_FORBIDDEN) { + eventMsg->event_type = COAP_EVENT_FORBIDDEN; + Log_e("coap message failed, message id: %d, failure reason: %d.%d", message->msg_id, message->code_class, + message->code_detail); + } else { + eventMsg->event_type = COAP_EVENT_INTERNAL_SERVER_ERROR; + Log_e("coap message failed, message id: %d, failure reason: %d.%d", message->msg_id, message->code_class, + message->code_detail); + } +} + +static int _coap_message_list_proc(CoAPClient *client, CoAPMessage *message, uint16_t processCmd) +{ + IOT_FUNC_ENTRY; + POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); + + HAL_MutexLock(client->lock_list_wait_ack); + + if (client->message_list->len <= 0) { + HAL_MutexUnlock(client->lock_list_wait_ack); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + ListIterator * iter; + ListNode * node = NULL; + ListNode * temp_node = NULL; + CoAPMsgSendInfo *send_info = NULL; + + if ((iter = list_iterator_new(client->message_list, LIST_TAIL)) == NULL) { + HAL_MutexUnlock(client->lock_list_wait_ack); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); + } + + for (;;) { + node = list_iterator_next(iter); + + if (NULL != temp_node) { + list_remove(client->message_list, temp_node); + Log_i("remove node"); + temp_node = NULL; + } + + if (NULL == node) { + break; + } + + send_info = (CoAPMsgSendInfo *)node->val; + if (NULL == send_info) { + Log_e("node's value is invalid!"); + continue; + } + + if (processCmd == PROCESS_ACK_CMD) { + if (send_info->msg_id == message->msg_id) { + send_info->acked = 1; /* ACK is received */ + InitTimer(&send_info->start_time); + countdown_ms(&send_info->start_time, client->command_timeout_ms); + } + } else if (processCmd == PROCESS_RESP_CMD) { + if (0 != send_info->token_len && send_info->token_len == message->token_len && + 0 == memcmp(send_info->token, message->token, message->token_len)) { + message->user_context = send_info->user_context; + + if (send_info->handler != NULL) { + send_info->handler(message, send_info->user_context); + } else if (NULL != client->event_handle.h_fp) { // event handle process + CoAPEventMessage event_msg = {0}; + _event_message_type_set(&event_msg, message, processCmd); + event_msg.message = message; + message->msg_id = send_info->msg_id; + client->event_handle.h_fp(client->event_handle.context, &event_msg); + } else { + Log_e("nether response callback nor event callback is set"); + } + + Log_d("remove the message id %d from list", send_info->msg_id); + send_info->node_state = COAP_NODE_STATE_INVALID; + } + } else if (processCmd == PROCESS_PIGGY_CMD) { + if (send_info->msg_id == message->msg_id) { + message->user_context = send_info->user_context; + + if (send_info->handler != NULL) { + send_info->handler(message, send_info->user_context); + } else if (NULL != client->event_handle.h_fp) { // event handle process + CoAPEventMessage event_msg = {0}; + _event_message_type_set(&event_msg, message, processCmd); + event_msg.message = (void *)(uintptr_t)(message->msg_id); + client->event_handle.h_fp(client->event_handle.context, &event_msg); + } else { + Log_e("nether response callback nor event callback is set"); + } + + Log_d("remove the message id %d from list", send_info->msg_id); + + send_info->acked = 1; /* ACK is received */ + send_info->node_state = COAP_NODE_STATE_INVALID; + } + } else if (processCmd == PROCESS_WAIT_CMD) { + if (COAP_NODE_STATE_INVALID == send_info->node_state) { + temp_node = node; + continue; + } + + if (left_ms(&send_info->start_time) > 0) { + continue; + } + + if (send_info->retrans_count < client->max_retry_count && (0 == send_info->acked)) { + InitTimer(&send_info->start_time); + countdown_ms(&send_info->start_time, client->command_timeout_ms); + send_info->retrans_count++; + Log_d("start to retansmit the message id %d len %d", send_info->msg_id, send_info->msglen); + size_t written_len = 0; + int ret = client->network_stack.write(&client->network_stack, send_info->message, send_info->msglen, + left_ms(&send_info->start_time), &written_len); + if (ret != QCLOUD_RET_SUCCESS) { + Log_e("retansmit the message id %d failed.", send_info->msg_id, send_info->msglen); + continue; + } + } else { + send_info->node_state = COAP_NODE_STATE_INVALID; + temp_node = node; + + if (send_info->handler != NULL) { + message->type = COAP_MSG_ACK; + message->user_context = send_info->user_context; + message->code_class = COAP_MSG_SDKINTERNAL_ERR; + message->code_detail = COAP_MSG_CODE_600_TIMEOUT; + message->msg_id = send_info->msg_id; + send_info->handler(message, send_info->user_context); + } else if (NULL != client->event_handle.h_fp) { + CoAPEventMessage event_msg = {0}; + if (send_info->acked) { + event_msg.event_type = COAP_EVENT_SEPRESP_TIMEOUT; + } else { + event_msg.event_type = COAP_EVENT_ACK_TIMEOUT; + } + event_msg.message = (void *)(uintptr_t)(send_info->msg_id); + client->event_handle.h_fp(client->event_handle.context, &event_msg); + } else { + Log_e("nether response callback nor event callback is set"); + } + + continue; + } + } + } + + list_iterator_destroy(iter); + HAL_MutexUnlock(client->lock_list_wait_ack); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +/** + * @brief Send ACK to server + * + * @param client reference to CoAP client + * @param msgId msg Id + * + * @returns Operation status + * @retval 0 Success + * @retval <0 Error + */ +static int _coap_client_send_ack(CoAPClient *client, int msgId) +{ + IOT_FUNC_ENTRY + + CoAPMessage ack = DEFAULT_COAP_MESSAGE; + int ret = 0; + + if ((ret = coap_message_type_set(&ack, COAP_MSG_ACK)) != QCLOUD_RET_SUCCESS) { + coap_message_destroy(&ack); + IOT_FUNC_EXIT_RC(ret) + } + + if ((ret = coap_message_id_set(&ack, msgId)) != QCLOUD_RET_SUCCESS) { + coap_message_destroy(&ack); + IOT_FUNC_EXIT_RC(ret) + } + + ret = coap_message_send(client, &ack); + coap_message_destroy(&ack); + + IOT_FUNC_EXIT_RC(ret) +} + +static int _coap_piggyresp_message_handle(CoAPClient *client, CoAPMessage *message) +{ + IOT_FUNC_ENTRY + + int rc = _coap_message_list_proc(client, message, PROCESS_PIGGY_CMD); + + IOT_FUNC_EXIT_RC(rc) +} + +static int _coap_ack_message_handle(CoAPClient *client, CoAPMessage *message) +{ + IOT_FUNC_ENTRY + + int rc = _coap_message_list_proc(client, message, PROCESS_ACK_CMD); + + IOT_FUNC_EXIT_RC(rc) +} + +static int _coap_resp_message_handle(CoAPClient *client, CoAPMessage *message) +{ + IOT_FUNC_ENTRY + + int rc = 0; + + if (COAP_MSG_CON == message->type) { + rc = _coap_client_send_ack(client, message->msg_id); + Log_d("send ack message for id: %d rc: %d", message->msg_id, rc); + } + + rc = _coap_message_list_proc(client, message, PROCESS_RESP_CMD); + + IOT_FUNC_EXIT_RC(rc) +} + +static void _coap_message_handle(CoAPClient *client, unsigned char *buf, unsigned short datalen) +{ + IOT_FUNC_ENTRY + + int rc = QCLOUD_RET_SUCCESS; + CoAPMessage recv_message; + memset(&recv_message, 0x00, sizeof(CoAPMessage)); + + if ((rc = deserialize_coap_message(&recv_message, (char *)buf, datalen)) != QCLOUD_RET_SUCCESS) { + Log_e("deserialize message failed: %d", rc); + } + + if (recv_message.type == COAP_MSG_ACK && COAP_MSG_IS_EMPTY_ACK(&recv_message)) { // empty ACK + Log_d("receive coap ACK message, id %d", recv_message.msg_id); + _coap_ack_message_handle(client, &recv_message); + } else if (recv_message.type == COAP_MSG_ACK && !COAP_MSG_IS_EMPTY(&recv_message)) { // piggy Response + Log_d("receive coap piggy ACK message, id %d", recv_message.msg_id); + _coap_piggyresp_message_handle(client, &recv_message); + } else if (recv_message.type == COAP_MSG_CON && COAP_MSG_IS_EMPTY_RSP(&recv_message)) { // payload Response + Log_d("receive coap response message, id: %d", recv_message.msg_id); + _coap_resp_message_handle(client, &recv_message); + } else if (recv_message.type == COAP_MSG_NON && COAP_MSG_IS_EMPTY_RSP(&recv_message)) { // payload Response + Log_d("receive coap response message, id: %d", recv_message.msg_id); + _coap_resp_message_handle(client, &recv_message); + } else { + Log_e("not recgonized recv message type"); + } + + if (recv_message.pay_load != NULL) { + HAL_Free(recv_message.pay_load); + recv_message.pay_load_len = 0; + } + + IOT_FUNC_EXIT +} + +static int _coap_message_list_add(CoAPClient *client, CoAPMessage *message, int len) +{ + IOT_FUNC_ENTRY + + CoAPMsgSendInfo *send_info = (CoAPMsgSendInfo *)HAL_Malloc(sizeof(CoAPMsgSendInfo)); + if (send_info == NULL) { + Log_e("no memory to malloc SendInfo"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) + } + + send_info->node_state = COAP_NODE_STATE_NORMANL; + send_info->acked = 0; + send_info->user_context = message->user_context; + send_info->msg_id = message->msg_id; + send_info->handler = message->handler; + send_info->msglen = len; + + if (COAP_MSG_CON == message->type) { + send_info->retrans_count = 0; + InitTimer(&send_info->start_time); + countdown_ms(&send_info->start_time, client->command_timeout_ms); + } else { + } + + send_info->token_len = message->token_len; + memcpy(send_info->token, message->token, message->token_len); + send_info->message = (unsigned char *)HAL_Malloc(len); + + if (NULL != send_info->message) { + memcpy(send_info->message, client->send_buf, len); + } + + ListNode *node = list_node_new(send_info); + if (NULL == node) { + Log_e("run list_node_new is error!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) + } + + HAL_MutexLock(client->lock_list_wait_ack); + list_rpush(client->message_list, node); + HAL_MutexUnlock(client->lock_list_wait_ack); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int coap_message_cycle(CoAPClient *client, uint32_t timeout_ms) +{ + POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); + + int rc = coap_message_recv(client, timeout_ms); + + if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_ERR_SSL_READ_TIMEOUT) { + IOT_FUNC_EXIT_RC(rc) + } + + CoAPMessage message = DEFAULT_COAP_MESSAGE; + rc = _coap_message_list_proc(client, &message, PROCESS_WAIT_CMD); + + IOT_FUNC_EXIT_RC(rc) +} + +ssize_t coap_message_send(CoAPClient *client, CoAPMessage *message) +{ + IOT_FUNC_ENTRY + + ssize_t ret; + size_t written_len = 0; + + HAL_MutexLock(client->lock_send_buf); + + if ((ret = serialize_coap_message(message, (char *)client->send_buf, client->send_buf_size)) < 0) { + Log_e("failed to serialize coap message"); + HAL_MutexUnlock(client->lock_send_buf); + IOT_FUNC_EXIT_RC(ret) + } + + ret = client->network_stack.write(&client->network_stack, client->send_buf, ret, 0, &written_len); + + if (ret == QCLOUD_RET_SUCCESS) { + if (message->type == COAP_MSG_CON && message->code_class == COAP_MSG_REQ) { + ret = _coap_message_list_add(client, message, written_len); + Log_i("add coap message id: %d into wait list ret: %d", message->msg_id, ret); + } else { + Log_i("The message doesn't need to be retransmitted"); + } + } else { + Log_e("coap net fail to write rc: %d", ret); + } + + HAL_MutexUnlock(client->lock_send_buf); + + IOT_FUNC_EXIT_RC(ret) +} + +ssize_t coap_message_recv(CoAPClient *client, uint32_t timeout_ms) +{ + IOT_FUNC_ENTRY + + size_t read_lean = 0; + int rc = 0; + + rc = client->network_stack.read(&client->network_stack, client->recv_buf, client->read_buf_size, timeout_ms, + &read_lean); + switch (rc) { + case QCLOUD_RET_SUCCESS: + _coap_message_handle(client, client->recv_buf, read_lean); + break; + case QCLOUD_ERR_SSL_READ_TIMEOUT: + break; + default: + break; + } + + IOT_FUNC_EXIT_RC(rc) +} + +#ifdef __cplusplus +} +#endif diff --git a/src/coap/src/coap_client_net.c b/sdk_src/protocol/coap/coap_client_net.c old mode 100644 new mode 100755 similarity index 74% rename from src/coap/src/coap_client_net.c rename to sdk_src/protocol/coap/coap_client_net.c index b687da39..6f6a3fcc --- a/src/coap/src/coap_client_net.c +++ b/sdk_src/protocol/coap/coap_client_net.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -19,12 +19,19 @@ extern "C" { #include "coap_client_net.h" -#include "utils_net.h" - +#include "network_interface.h" + int qcloud_iot_coap_network_init(Network *pNetwork) { int rc; - rc = utils_udp_net_init(pNetwork); + /* first choice: TLS */ + pNetwork->type = NETWORK_DTLS; + +#ifdef AUTH_WITH_NOTLS + pNetwork->type = NETWORK_UDP; +#endif + + rc = network_init(pNetwork); return rc; } diff --git a/src/coap/src/coap_client_serialize.c b/sdk_src/protocol/coap/coap_client_serialize.c old mode 100644 new mode 100755 similarity index 70% rename from src/coap/src/coap_client_serialize.c rename to sdk_src/protocol/coap/coap_client_serialize.c index 52ff80cb..8d33b638 --- a/src/coap/src/coap_client_serialize.c +++ b/sdk_src/protocol/coap/coap_client_serialize.c @@ -1,326 +1,292 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "coap_client.h" - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" - -#define COAP_MSG_OPLIST_FIRST(list) ((list)->first) /**< Get the first option from an option linked-list */ - -/** - * @brief Format the header in a message - * - * @param[in] message Pointer to a message structure - * @param[out] buf Pointer to a buffer to contain the formatted message - * @param[in] len Length of the buffer - * - * @returns Length of the formatted message or error code - * @retval >0 Length of the formatted message - * @retval <0 Error - */ -static ssize_t _coap_message_serialize_header(CoAPMessage *message, char *buf, size_t len) { - IOT_FUNC_ENTRY - - if (len < 4) - { - return -ENOSPC; - } - - buf[0] = (char)((COAP_MSG_VER << 6) - | ((message->type & 0x03) << 4) - | (message->token_len & 0x0f)); - buf[1] = (char)(((message->code_class & 0x07) << 5) - | (message->code_detail & 0x1f)); - - buf[2] = (message->msg_id & 0xFF00) >> 8; - buf[3] = (message->msg_id & 0x00FF); - - IOT_FUNC_EXIT_RC(4) -} - -/** - * @brief Format the token in a message - * - * @param[in] message Pointer to a message structure - * @param[out] buf Pointer to a buffer to contain the formatted message - * @param[in] len Length of the buffer - * - * @returns Length of the formatted message or error code - * @retval >0 Length of the formatted message - * @retval <0 Error - */ -static ssize_t _coap_message_serialize_token(CoAPMessage *message, char *buf, size_t len) { - IOT_FUNC_ENTRY - - if (len < message->token_len) - { - return -ENOSPC; - } - memcpy(buf, message->token, message->token_len); - - IOT_FUNC_EXIT_RC(message->token_len) -} - -/** - * @brief Format an option in a message - * - * @param[in] op Pointer to an option structure - * @param[in] prev_num option number of the previous option - * @param[out] buf Pointer to a buffer to contain the formatted message - * @param[in] len Length of the buffer - * - * @returns Length of the formatted message or error code - * @retval >0 Length of the formatted message - * @retval <0 Error - */ -static ssize_t _coap_msg_format_op(CoAPMsgOption *op, unsigned prev_num, char *buf, size_t len) { - IOT_FUNC_ENTRY - - unsigned short op_delta = 0; - unsigned num = 0; - char *p = buf; - - op_delta = op->option_num - prev_num; - num++; - - /* option delta */ - if (op_delta >= 269) - { - num += 2; - } - else if (op_delta >= 13) - { - num += 1; - } - - /* option length */ - if (op->val_len >= 269) - { - num += 2; - } - else if (op->option_num >= 13) - { - num += 1; - } - - /* option value */ - num += op->val_len; - if (num > len) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) - } - - /* option delta */ - if (op_delta >= 269) - { - p[0] = 14 << 4; - } - else if (op_delta >= 13) - { - p[0] = 13 << 4; - } - else - { - p[0] = op_delta << 4; - } - - /* option length */ - if (op->val_len >= 269) - { - p[0] |= 14; - } - else if (op->val_len >= 13) - { - p[0] |= 13; - } - else - { - p[0] |= op->val_len; - } - p++; - len--; - - /* option delta extended */ - if (op_delta >= 269) - { - *p = (unsigned char)(((op_delta - 269) & 0xFF00) >> 8); - *(p+1) = (unsigned char)(((op_delta - 269) & 0x00FF)); - p += 2; - len -= 2; - } - else if (op_delta >= 13) - { - p[0] = op_delta - 13; - p++; - len--; - } - - /* option length extended */ - if (op->val_len >= 269) - { - *p = (unsigned char)(((op->val_len - 269) & 0xFF00) >> 8); - *(p+1) = (unsigned char)(((op->val_len - 269) & 0x00FF)); - p += 2; - len -= 2; - } - else if (op->val_len >= 13) - { - p[0] = op->val_len - 13; - p++; - len--; - } - - /* option value */ - memcpy(p, op->val, op->val_len); - p += op->val_len; - - IOT_FUNC_EXIT_RC(p - buf) -} - -/** - * @brief Format the options in a message - * - * @param[in] message Pointer to a message structure - * @param[out] buf Pointer to a buffer to contain the formatted message - * @param[in] len Length of the buffer - * - * @returns Length of the formatted message or error code - * @retval >0 Length of the formatted message - * @retval <0 Error - */ -static ssize_t _coap_message_serialize_options(CoAPMessage *message, char *buf, size_t len) { - IOT_FUNC_ENTRY; - - CoAPMsgOption *op = NULL; - unsigned prev_num = 0; - ssize_t num = 0; - char *p = buf; - - op = COAP_MSG_OPLIST_FIRST(&message->op_list); - while (op != NULL) - { - num = _coap_msg_format_op(op, prev_num, p, len); - if (num < 0) - { - return num; - } - p += num; - len -= num; - prev_num = COAP_MSG_OPTION_NUM(op); - op = COAP_MSG_OP_NEXT(op); - } - - IOT_FUNC_EXIT_RC(p - buf) -} - -/** - * @brief Format the payload in a message - * - * @param[in] message Pointer to a message structure - * @param[out] buf Pointer to a buffer to contain the formatted message - * @param[in] len Length of the buffer - * - * @returns Length of the formatted message or error code - * @retval >0 Length of the formatted message - * @retval <0 Error - */ -static ssize_t _coap_message_serialize_payload(CoAPMessage *message, char *buf, size_t len) { - IOT_FUNC_ENTRY; - - if (message->pay_load_len == 0) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) - } - - if (message->pay_load_len + 1 > len) - { - return -ENOSPC; - } - - buf[0] = 0xff; - memcpy(&buf[1], message->pay_load, message->pay_load_len); - - IOT_FUNC_EXIT_RC(message->pay_load_len + 1) -} - -ssize_t serialize_coap_message(CoAPMessage *message, char *buf, size_t len) -{ - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(message, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); - - ssize_t num = 0; - char *p = buf; - - num = _coap_message_serialize_header(message, p, len); - if (num < 0) - { - Log_e("coap_message_serialize_header fail num=%lu", num); - goto error; - } - - p += num; - len -= num; - num = _coap_message_serialize_token(message, p, len); - if (num < 0) - { - Log_e("coap_message_serialize_token fail num=%lu", num); - goto error; - } - - p += num; - len -= num; - num = _coap_message_serialize_options(message, p, len); - if (num < 0) - { - Log_e("coap_message_serialize_options fail num=%lu", num); - goto error; - } - - p += num; - len -= num; - num = _coap_message_serialize_payload(message, p, len); - if (num < 0) - { - Log_e("coap_message_serialize_payload fail num=%lu", num); - goto error; - } - - p += num; - - IOT_FUNC_EXIT_RC(p - buf) - -error: - IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_INTERNAL) -} - -#ifdef __cplusplus -} -#endif - - +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +#include "coap_client.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_param_check.h" + +#define COAP_MSG_OPLIST_FIRST(list) ((list)->first) /**< Get the first option from an option linked-list */ + +/** + * @brief Format the header in a message + * + * @param[in] message Pointer to a message structure + * @param[out] buf Pointer to a buffer to contain the formatted message + * @param[in] len Length of the buffer + * + * @returns Length of the formatted message or error code + * @retval >0 Length of the formatted message + * @retval <0 Error + */ +static ssize_t _coap_message_serialize_header(CoAPMessage *message, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + if (len < 4) { + return -ENOSPC; + } + + buf[0] = (char)((COAP_MSG_VER << 6) | ((message->type & 0x03) << 4) | (message->token_len & 0x0f)); + buf[1] = (char)(((message->code_class & 0x07) << 5) | (message->code_detail & 0x1f)); + + buf[2] = (message->msg_id & 0xFF00) >> 8; + buf[3] = (message->msg_id & 0x00FF); + + IOT_FUNC_EXIT_RC(4) +} + +/** + * @brief Format the token in a message + * + * @param[in] message Pointer to a message structure + * @param[out] buf Pointer to a buffer to contain the formatted message + * @param[in] len Length of the buffer + * + * @returns Length of the formatted message or error code + * @retval >0 Length of the formatted message + * @retval <0 Error + */ +static ssize_t _coap_message_serialize_token(CoAPMessage *message, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + if (len < message->token_len) { + return -ENOSPC; + } + memcpy(buf, message->token, message->token_len); + + IOT_FUNC_EXIT_RC(message->token_len) +} + +/** + * @brief Format an option in a message + * + * @param[in] op Pointer to an option structure + * @param[in] prev_num option number of the previous option + * @param[out] buf Pointer to a buffer to contain the formatted message + * @param[in] len Length of the buffer + * + * @returns Length of the formatted message or error code + * @retval >0 Length of the formatted message + * @retval <0 Error + */ +static ssize_t _coap_msg_format_op(CoAPMsgOption *op, unsigned prev_num, char *buf, size_t len) +{ + IOT_FUNC_ENTRY + + unsigned short op_delta = 0; + unsigned num = 0; + char * p = buf; + + op_delta = op->option_num - prev_num; + num++; + + /* option delta */ + if (op_delta >= 269) { + num += 2; + } else if (op_delta >= 13) { + num += 1; + } + + /* option length */ + if (op->val_len >= 269) { + num += 2; + } else if (op->option_num >= 13) { + num += 1; + } + + /* option value */ + num += op->val_len; + if (num > len) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_DATA_SIZE) + } + + /* option delta */ + if (op_delta >= 269) { + p[0] = 14 << 4; + } else if (op_delta >= 13) { + p[0] = 13 << 4; + } else { + p[0] = op_delta << 4; + } + + /* option length */ + if (op->val_len >= 269) { + p[0] |= 14; + } else if (op->val_len >= 13) { + p[0] |= 13; + } else { + p[0] |= op->val_len; + } + p++; + len--; + + /* option delta extended */ + if (op_delta >= 269) { + *p = (unsigned char)(((op_delta - 269) & 0xFF00) >> 8); + *(p + 1) = (unsigned char)(((op_delta - 269) & 0x00FF)); + p += 2; + len -= 2; + } else if (op_delta >= 13) { + p[0] = op_delta - 13; + p++; + len--; + } + + /* option length extended */ + if (op->val_len >= 269) { + *p = (unsigned char)(((op->val_len - 269) & 0xFF00) >> 8); + *(p + 1) = (unsigned char)(((op->val_len - 269) & 0x00FF)); + p += 2; + len -= 2; + } else if (op->val_len >= 13) { + p[0] = op->val_len - 13; + p++; + len--; + } + + /* option value */ + memcpy(p, op->val, op->val_len); + p += op->val_len; + + IOT_FUNC_EXIT_RC(p - buf) +} + +/** + * @brief Format the options in a message + * + * @param[in] message Pointer to a message structure + * @param[out] buf Pointer to a buffer to contain the formatted message + * @param[in] len Length of the buffer + * + * @returns Length of the formatted message or error code + * @retval >0 Length of the formatted message + * @retval <0 Error + */ +static ssize_t _coap_message_serialize_options(CoAPMessage *message, char *buf, size_t len) +{ + IOT_FUNC_ENTRY; + + CoAPMsgOption *op = NULL; + unsigned prev_num = 0; + ssize_t num = 0; + char * p = buf; + + op = COAP_MSG_OPLIST_FIRST(&message->op_list); + while (op != NULL) { + num = _coap_msg_format_op(op, prev_num, p, len); + if (num < 0) { + return num; + } + p += num; + len -= num; + prev_num = COAP_MSG_OPTION_NUM(op); + op = COAP_MSG_OP_NEXT(op); + } + + IOT_FUNC_EXIT_RC(p - buf) +} + +/** + * @brief Format the payload in a message + * + * @param[in] message Pointer to a message structure + * @param[out] buf Pointer to a buffer to contain the formatted message + * @param[in] len Length of the buffer + * + * @returns Length of the formatted message or error code + * @retval >0 Length of the formatted message + * @retval <0 Error + */ +static ssize_t _coap_message_serialize_payload(CoAPMessage *message, char *buf, size_t len) +{ + IOT_FUNC_ENTRY; + + if (message->pay_load_len == 0) { + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) + } + + if (message->pay_load_len + 1 > len) { + return -ENOSPC; + } + + buf[0] = 0xff; + memcpy(&buf[1], message->pay_load, message->pay_load_len); + + IOT_FUNC_EXIT_RC(message->pay_load_len + 1) +} + +ssize_t serialize_coap_message(CoAPMessage *message, char *buf, size_t len) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(message, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); + + ssize_t num = 0; + char * p = buf; + + num = _coap_message_serialize_header(message, p, len); + if (num < 0) { + Log_e("coap_message_serialize_header fail num=%lu", num); + goto error; + } + + p += num; + len -= num; + num = _coap_message_serialize_token(message, p, len); + if (num < 0) { + Log_e("coap_message_serialize_token fail num=%lu", num); + goto error; + } + + p += num; + len -= num; + num = _coap_message_serialize_options(message, p, len); + if (num < 0) { + Log_e("coap_message_serialize_options fail num=%lu", num); + goto error; + } + + p += num; + len -= num; + num = _coap_message_serialize_payload(message, p, len); + if (num < 0) { + Log_e("coap_message_serialize_payload fail num=%lu", num); + goto error; + } + + p += num; + + IOT_FUNC_EXIT_RC(p - buf) + +error: + IOT_FUNC_EXIT_RC(QCLOUD_ERR_COAP_INTERNAL) +} + +#ifdef __cplusplus +} +#endif diff --git a/src/utils/farra/utils_httpc.c b/sdk_src/protocol/http/utils_httpc.c old mode 100644 new mode 100755 similarity index 68% rename from src/utils/farra/utils_httpc.c rename to sdk_src/protocol/http/utils_httpc.c index ce1f90c9..217aaa6c --- a/src/utils/farra/utils_httpc.c +++ b/sdk_src/protocol/http/utils_httpc.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -18,39 +18,37 @@ extern "C" { #endif #include "utils_httpc.h" - -#include + #include #include - -#include "ca.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_export.h" +#include "qcloud_iot_ca.h" +#include "qcloud_iot_common.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" #include "utils_timer.h" -#define HTTP_CLIENT_MIN(x,y) (((x)<(y))?(x):(y)) -#define HTTP_CLIENT_MAX(x,y) (((x)>(y))?(x):(y)) +#define HTTP_CLIENT_MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define HTTP_CLIENT_MAX(x, y) (((x) > (y)) ? (x) : (y)) + +#define HTTP_CLIENT_AUTHB_SIZE 128 -#define HTTP_CLIENT_AUTHB_SIZE 128 +#define HTTP_CLIENT_CHUNK_SIZE 1025 +#define HTTP_CLIENT_SEND_BUF_SIZE 1024 -#define HTTP_CLIENT_CHUNK_SIZE 1024 -#define HTTP_CLIENT_SEND_BUF_SIZE 1024 +#define HTTP_CLIENT_MAX_HOST_LEN 64 +#define HTTP_CLIENT_MAX_URL_LEN 1024 + +#define HTTP_RETRIEVE_MORE_DATA (1) -#define HTTP_CLIENT_MAX_HOST_LEN 64 -#define HTTP_CLIENT_MAX_URL_LEN 1024 - -#define HTTP_RETRIEVE_MORE_DATA (1) - #if defined(MBEDTLS_DEBUG_C) - #define DEBUG_LEVEL 2 +#define DEBUG_LEVEL 2 #endif - static void _http_client_base64enc(char *out, const char *in) { const char code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - int i = 0, x = 0, l = 0; + int i = 0, x = 0, l = 0; for (; *in; in++) { x = x << 8 | *in; @@ -68,14 +66,14 @@ static void _http_client_base64enc(char *out, const char *in) out[i] = '\0'; } -static int _http_client_parse_url(const char *url, char *scheme, uint32_t max_scheme_len, char *host, uint32_t maxhost_len, - int *port, char *path, uint32_t max_path_len) +static int _http_client_parse_url(const char *url, char *scheme, uint32_t max_scheme_len, char *host, + uint32_t maxhost_len, int *port, char *path, uint32_t max_path_len) { - char *scheme_ptr = (char *) url; - char *host_ptr = (char *) strstr(url, "://"); - uint32_t host_len = 0; + char * scheme_ptr = (char *)url; + char * host_ptr = (char *)strstr(url, "://"); + uint32_t host_len = 0; uint32_t path_len; - + char *path_ptr; char *fragment_ptr; @@ -101,57 +99,57 @@ static int _http_client_parse_url(const char *url, char *scheme, uint32_t max_sc host_len = path_ptr - host_ptr; memcpy(host, host_ptr, host_len); host[host_len] = '\0'; - + memcpy(path, "/", 1); path[1] = '\0'; - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } - + if (host_len == 0) { host_len = path_ptr - host_ptr; } - + if (maxhost_len < host_len + 1) { Log_e("Host str is too long (host_len(%d) >= max_len(%d))", host_len + 1, maxhost_len); return QCLOUD_ERR_HTTP_PARSE; } memcpy(host, host_ptr, host_len); host[host_len] = '\0'; - + fragment_ptr = strchr(host_ptr, '#'); if (fragment_ptr != NULL) { path_len = fragment_ptr - path_ptr; } else { path_len = strlen(path_ptr); } - + if (max_path_len < path_len + 1) { Log_e("Path str is too small (%d >= %d)", max_path_len, path_len + 1); return QCLOUD_ERR_HTTP_PARSE; } - + memcpy(path, path_ptr, path_len); - + path[path_len] = '\0'; - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } static int _http_client_parse_host(const char *url, char *host, uint32_t host_max_len) { - const char *host_ptr = (const char *) strstr(url, "://"); - uint32_t host_len = 0; - char *path_ptr; + const char *host_ptr = (const char *)strstr(url, "://"); + uint32_t host_len = 0; + char * path_ptr; if (host_ptr == NULL) { Log_e("Could not find host"); return QCLOUD_ERR_HTTP_PARSE; } host_ptr += 3; - + uint32_t pro_len = 0; - pro_len = host_ptr - url; + pro_len = host_ptr - url; path_ptr = strchr(host_ptr, '/'); if (path_ptr != NULL) @@ -166,22 +164,12 @@ static int _http_client_parse_host(const char *url, char *host, uint32_t host_ma memcpy(host, host_ptr, host_len); host[host_len] = '\0'; - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } -/** - * @brief 拼接发送的数据 - * - * @param client http client - * @param send_buf 发送数据buffer - * @param send_idx 标志send_buf数据结束的位置 - * @param buf 需要被发送的数据,拼接到send_buf中 - * @param len buf的长度 - * @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功 - */ static int _http_client_get_info(HTTPClient *client, unsigned char *send_buf, int *send_idx, char *buf, uint32_t len) { - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; int cp_len; int idx = *send_idx; @@ -202,7 +190,8 @@ static int _http_client_get_info(HTTPClient *client, unsigned char *send_buf, in if (idx == HTTP_CLIENT_SEND_BUF_SIZE) { size_t byte_written_len = 0; - rc = client->network_stack.write(&(client->network_stack), send_buf, HTTP_CLIENT_SEND_BUF_SIZE, 5000, &byte_written_len); + rc = client->network_stack.write(&(client->network_stack), send_buf, HTTP_CLIENT_SEND_BUF_SIZE, 5000, + &byte_written_len); if (byte_written_len) { return (byte_written_len); } @@ -219,88 +208,83 @@ static int _http_client_send_auth(HTTPClient *client, unsigned char *send_buf, i char base64buff[HTTP_CLIENT_AUTHB_SIZE + 3]; _http_client_get_info(client, send_buf, send_idx, "Authorization: Basic ", 0); - HAL_Snprintf(base64buff, sizeof(base64buff), "%s:%s", client->auth_user, client->auth_password); + HAL_Snprintf(base64buff, sizeof(base64buff), "%s:%s", STRING_PTR_PRINT_SANITY_CHECK(client->auth_user), + STRING_PTR_PRINT_SANITY_CHECK(client->auth_password)); _http_client_base64enc(b_auth, base64buff); b_auth[strlen(b_auth) + 1] = '\0'; - b_auth[strlen(b_auth)] = '\n'; + b_auth[strlen(b_auth)] = '\n'; _http_client_get_info(client, send_buf, send_idx, b_auth, 0); - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } - -/** - * @brief 根据请求url和method,拼接请求头 - * - * @param client http client - * @param url 请求url - * @param method 请求方法 - * @param client_data http数据负载 - * @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功 - */ + static int _http_client_send_header(HTTPClient *client, const char *url, HttpMethod method, HTTPClientData *client_data) { - char scheme[8] = { 0 }; - char host[HTTP_CLIENT_MAX_HOST_LEN] = { 0 }; - char path[HTTP_CLIENT_MAX_URL_LEN] = { 0 }; - int len; - unsigned char send_buf[HTTP_CLIENT_SEND_BUF_SIZE] = { 0 }; - char buf[HTTP_CLIENT_SEND_BUF_SIZE] = { 0 }; - char *meth = (method == HTTP_GET) ? "GET" : (method == HTTP_POST) ? "POST" : - (method == HTTP_PUT) ? "PUT" : (method == HTTP_DELETE) ? "DELETE" : - (method == HTTP_HEAD) ? "HEAD" : ""; + char scheme[8] = {0}; + char host[HTTP_CLIENT_MAX_HOST_LEN] = {0}; + char path[HTTP_CLIENT_MAX_URL_LEN] = {0}; + int len; + unsigned char send_buf[HTTP_CLIENT_SEND_BUF_SIZE] = {0}; + char buf[HTTP_CLIENT_SEND_BUF_SIZE] = {0}; + char * meth = (method == HTTP_GET) + ? "GET" + : (method == HTTP_POST) + ? "POST" + : (method == HTTP_PUT) + ? "PUT" + : (method == HTTP_DELETE) ? "DELETE" : (method == HTTP_HEAD) ? "HEAD" : ""; int rc; int port; - + int res = _http_client_parse_url(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); - if (res != QCLOUD_ERR_SUCCESS) { + if (res != QCLOUD_RET_SUCCESS) { Log_e("httpclient_parse_url returned %d", res); return res; } - + if (strcmp(scheme, "http") == 0) { - } else if (strcmp(scheme, "https") == 0) { - } - + memset(send_buf, 0, HTTP_CLIENT_SEND_BUF_SIZE); len = 0; - + HAL_Snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); rc = _http_client_get_info(client, send_buf, &len, buf, strlen(buf)); if (rc) { Log_e("Could not write request"); return QCLOUD_ERR_HTTP_CONN; } - + if (client->auth_user) { _http_client_send_auth(client, send_buf, &len); } - + if (client->header) { - _http_client_get_info(client, send_buf, &len, (char *) client->header, strlen(client->header)); + _http_client_get_info(client, send_buf, &len, (char *)client->header, strlen(client->header)); } - + if (client_data->post_buf != NULL) { HAL_Snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", client_data->post_buf_len); _http_client_get_info(client, send_buf, &len, buf, strlen(buf)); - + if (client_data->post_content_type != NULL) { - HAL_Snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", client_data->post_content_type); + HAL_Snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", + STRING_PTR_PRINT_SANITY_CHECK(client_data->post_content_type)); _http_client_get_info(client, send_buf, &len, buf, strlen(buf)); } } - + _http_client_get_info(client, send_buf, &len, "\r\n", 0); - - //Log_d("REQUEST:\n%s", send_buf); + + // Log_d("REQUEST:\n%s", send_buf); size_t written_len = 0; - rc = client->network_stack.write(&client->network_stack, send_buf, len, 5000, &written_len); + rc = client->network_stack.write(&client->network_stack, send_buf, len, 5000, &written_len); if (written_len > 0) { - //Log_d("Written %lu bytes", written_len); + // Log_d("Written %lu bytes", written_len); } else if (written_len == 0) { Log_e("written_len == 0,Connection was closed by server"); return QCLOUD_ERR_HTTP_CLOSED; /* Connection was closed by server */ @@ -308,26 +292,20 @@ static int _http_client_send_header(HTTPClient *client, const char *url, HttpMet Log_e("Connection error (send returned %d)", rc); return QCLOUD_ERR_HTTP_CONN; } - - return QCLOUD_ERR_SUCCESS; + + return QCLOUD_RET_SUCCESS; } - -/** - * @brief 发送post的请求体数据 - * - * @param client http client - * @param client_data http数据负载 - * @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功 - */ + static int _http_client_send_userdata(HTTPClient *client, HTTPClientData *client_data) -{ +{ if (client_data->post_buf && client_data->post_buf_len) { - //Log_d("client_data->post_buf: %s", client_data->post_buf); + // Log_d("client_data->post_buf: %s", client_data->post_buf); { size_t written_len = 0; - int rc = client->network_stack.write(&client->network_stack, (unsigned char *)client_data->post_buf, client_data->post_buf_len, 5000, &written_len); + int rc = client->network_stack.write(&client->network_stack, (unsigned char *)client_data->post_buf, + client_data->post_buf_len, 5000, &written_len); if (written_len > 0) { - //Log_d("Written %d bytes", written_len); + // Log_d("Written %d bytes", written_len); } else if (written_len == 0) { Log_e("written_len == 0,Connection was closed by server"); return QCLOUD_ERR_HTTP_CLOSED; @@ -337,72 +315,62 @@ static int _http_client_send_userdata(HTTPClient *client, HTTPClientData *client } } } - - return QCLOUD_ERR_SUCCESS; + + return QCLOUD_RET_SUCCESS; } - -/** - * @brief 读取http数据 - * - * @param client http client - * @param buf 数据buffer - * @param min_len 读取数据的最小长度 - * @param max_len 读取数据的最大长度 - * @param p_read_len 成功读取到的数据的长度 - * @param timeout_ms 超时时间 - * @param client_data http数据负载 - * @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功 - */ -static int _http_client_recv(HTTPClient *client, char *buf, int min_len, int max_len, int *p_read_len, uint32_t timeout_ms, HTTPClientData *client_data) + +static int _http_client_recv(HTTPClient *client, char *buf, int min_len, int max_len, int *p_read_len, + uint32_t timeout_ms, HTTPClientData *client_data) { IOT_FUNC_ENTRY; - int rc = 0; - Timer timer; - + int rc = 0; + Timer timer; + size_t recv_size = 0; + InitTimer(&timer); countdown_ms(&timer, (unsigned int)timeout_ms); - + *p_read_len = 0; - rc = client->network_stack.read(&client->network_stack, (unsigned char *)buf, max_len, (uint32_t)left_ms(&timer), (size_t *)p_read_len); - + rc = client->network_stack.read(&client->network_stack, (unsigned char *)buf, max_len, (uint32_t)left_ms(&timer), + &recv_size); + *p_read_len = (int)recv_size; if (rc == QCLOUD_ERR_SSL_NOTHING_TO_READ || rc == QCLOUD_ERR_TCP_NOTHING_TO_READ) { Log_d("HTTP read nothing and timeout"); - rc = QCLOUD_ERR_SUCCESS; - } - else if (rc == QCLOUD_ERR_SSL_READ_TIMEOUT || rc == QCLOUD_ERR_TCP_READ_TIMEOUT) { + rc = QCLOUD_RET_SUCCESS; + } else if (rc == QCLOUD_ERR_SSL_READ_TIMEOUT || rc == QCLOUD_ERR_TCP_READ_TIMEOUT) { if (*p_read_len == client_data->retrieve_len || client_data->retrieve_len == 0) - rc = QCLOUD_ERR_SUCCESS; - } - else if (rc == QCLOUD_ERR_TCP_PEER_SHUTDOWN && *p_read_len > 0) { + rc = QCLOUD_RET_SUCCESS; + else + Log_e("network_stack read timeout"); + } else if (rc == QCLOUD_ERR_TCP_PEER_SHUTDOWN && *p_read_len > 0) { /* HTTP server give response and close this connection */ client->network_stack.disconnect(&client->network_stack); - rc = QCLOUD_ERR_SUCCESS; - } - else if (rc != QCLOUD_ERR_SUCCESS) { // 其他错误 + rc = QCLOUD_RET_SUCCESS; + } else if (rc != QCLOUD_RET_SUCCESS) { Log_e("Connection error rc = %d (recv returned %d)", rc, *p_read_len); IOT_FUNC_EXIT_RC(rc); } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + + IOT_FUNC_EXIT_RC(rc); } - + static int _http_client_retrieve_content(HTTPClient *client, char *data, int len, uint32_t timeout_ms, HTTPClientData *client_data) { IOT_FUNC_ENTRY; - int count = 0; - int templen = 0; - int crlf_pos; + int count = 0; + int templen = 0; + int crlf_pos; Timer timer; - + InitTimer(&timer); countdown_ms(&timer, (unsigned int)timeout_ms); - + client_data->is_more = IOT_TRUE; - + if (client_data->response_content_len == -1 && client_data->is_chunked == IOT_FALSE) { while (1) { int rc, max_len; @@ -415,35 +383,39 @@ static int _http_client_retrieve_content(HTTPClient *client, char *data, int len client_data->response_buf[client_data->response_buf_len - 1] = '\0'; return HTTP_RETRIEVE_MORE_DATA; } - + max_len = HTTP_CLIENT_MIN(HTTP_CLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - count); - rc = _http_client_recv(client, data, 1, max_len, &len, (uint32_t)left_ms(&timer), client_data); - + rc = _http_client_recv(client, data, 1, max_len, &len, (uint32_t)left_ms(&timer), client_data); + /* Receive data */ - //Log_d("data len: %d %d", len, count); - - if (rc != QCLOUD_ERR_SUCCESS) { + // Log_d("data len: %d %d", len, count); + + if (rc != QCLOUD_RET_SUCCESS) { IOT_FUNC_EXIT_RC(rc); } - + if (0 >= left_ms(&timer)) { + Log_e("HTTP read timeout!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_TIMEOUT); + } + if (len == 0) { /* read no more data */ Log_d("no more data, len == 0"); client_data->is_more = IOT_FALSE; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } } } - + while (1) { uint32_t readLen = 0; if (client_data->is_chunked && client_data->retrieve_len <= 0) { /* Read chunk header */ bool foundCrlf; - int n; + int n; do { foundCrlf = IOT_FALSE; - crlf_pos = 0; + crlf_pos = 0; data[len] = 0; if (len >= 2) { for (; crlf_pos < len - 2; crlf_pos++) { @@ -457,15 +429,11 @@ static int _http_client_retrieve_content(HTTPClient *client, char *data, int len /* Try to read more */ if (len < HTTP_CLIENT_CHUNK_SIZE) { int new_trf_len, rc; - rc = _http_client_recv(client, - data + len, - 0, - HTTP_CLIENT_CHUNK_SIZE - len - 1, - &new_trf_len, - left_ms(&timer), - client_data); + rc = _http_client_recv(client, data + len, 0, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len, + left_ms(&timer), client_data); len += new_trf_len; - if (rc != QCLOUD_ERR_SUCCESS) { + if ((rc != QCLOUD_RET_SUCCESS) || (0 >= left_ms(&timer))) { + Log_w("_http_client_recv ret: %d, left_time: %d", rc, left_ms(&timer)); IOT_FUNC_EXIT_RC(rc); } else { continue; @@ -478,8 +446,8 @@ static int _http_client_retrieve_content(HTTPClient *client, char *data, int len data[crlf_pos] = '\0'; // n = sscanf(data, "%x", &readLen);/* chunk length */ - readLen = strtoul(data, NULL, 16); - n = (0 == readLen) ? 0 : 1; + readLen = strtoul(data, NULL, 16); + n = (0 == readLen) ? 0 : 1; client_data->retrieve_len = readLen; client_data->response_content_len += client_data->retrieve_len; if (readLen == 0) { @@ -491,14 +459,14 @@ static int _http_client_retrieve_content(HTTPClient *client, char *data, int len Log_e("Could not read chunk length"); return QCLOUD_ERR_HTTP_UNRESOLVED_DNS; } - + memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2)); len -= (crlf_pos + 2); - + } else { readLen = client_data->retrieve_len; } - + do { templen = HTTP_CLIENT_MIN(len, readLen); if (count + templen < client_data->response_buf_len - 1) { @@ -512,40 +480,46 @@ static int _http_client_retrieve_content(HTTPClient *client, char *data, int len client_data->retrieve_len -= (client_data->response_buf_len - 1 - count); IOT_FUNC_EXIT_RC(HTTP_RETRIEVE_MORE_DATA); } - + if (len > readLen) { Log_d("memmove %d %d %d\n", readLen, len, client_data->retrieve_len); memmove(data, &data[readLen], len - readLen); /* chunk case, read between two chunks */ len -= readLen; - readLen = 0; + readLen = 0; client_data->retrieve_len = 0; } else { readLen -= len; } - + if (readLen) { int rc; int max_len = HTTP_CLIENT_MIN(HTTP_CLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - count); - max_len = HTTP_CLIENT_MIN(max_len, readLen); - rc = _http_client_recv(client, data, 1, max_len, &len, left_ms(&timer), client_data); - if (rc != QCLOUD_ERR_SUCCESS) { + max_len = HTTP_CLIENT_MIN(max_len, readLen); + rc = _http_client_recv(client, data, 1, max_len, &len, left_ms(&timer), client_data); + if (rc != QCLOUD_RET_SUCCESS) { + Log_w("_http_client_recv ret: %d, left_time: %d", rc, left_ms(&timer)); IOT_FUNC_EXIT_RC(rc); } + if (left_ms(&timer) <= 0) { + Log_e("HTTP read timeout!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_TIMEOUT); + } } } while (readLen); - + if (client_data->is_chunked) { if (len < 2) { int new_trf_len, rc; /* Read missing chars to find end of chunk */ rc = _http_client_recv(client, data + len, 2 - len, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len, - left_ms(&timer), client_data); - if (rc != QCLOUD_ERR_SUCCESS) { + left_ms(&timer), client_data); + if ((rc != QCLOUD_RET_SUCCESS) || (0 >= left_ms(&timer))) { + Log_w("_http_client_recv ret: %d, left_time: %d", rc, left_ms(&timer)); IOT_FUNC_EXIT_RC(rc); } len += new_trf_len; } - + if ((data[0] != '\r') || (data[1] != '\n')) { Log_e("Format error, %s", data); /* after memmove, the beginning of next chunk */ IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_UNRESOLVED_DNS); @@ -553,49 +527,38 @@ static int _http_client_retrieve_content(HTTPClient *client, char *data, int len memmove(data, &data[2], len - 2); /* remove the \r\n */ len -= 2; } else { - //Log_d("no more (content-length)"); + // Log_d("no more (content-length)"); client_data->is_more = IOT_FALSE; break; } - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } - -/** - * @brief 解析response body数据 - * - * @param client HTTPClient数据 - * @param data 读取到的数据 - * @param len 读取到的数据的长度 - * @param timeout_ms 读取数据的超时时间 - * @param client_data http数据负载 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -static int _http_client_response_parse(HTTPClient *client, char *data, int len, uint32_t timeout_ms, + +static int _http_client_response_parse(HTTPClient *client, char *data, int len, uint32_t timeout_ms, HTTPClientData *client_data) { IOT_FUNC_ENTRY; - - int crlf_pos; + + int crlf_pos; Timer timer; char *tmp_ptr, *ptr_body_end; - + InitTimer(&timer); countdown_ms(&timer, timeout_ms); - + client_data->response_content_len = -1; - + char *crlf_ptr = strstr(data, "\r\n"); if (crlf_ptr == NULL) { Log_e("\\r\\n not found"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_UNRESOLVED_DNS); } - - crlf_pos = crlf_ptr - data; + + crlf_pos = crlf_ptr - data; data[crlf_pos] = '\0'; - + #if 0 if (sscanf(data, "HTTP/%*d.%*d %d %*[^\r\n]", &(client->response_code)) != 1) { Log_e("Not a correct HTTP answer : %s\n", data); @@ -604,29 +567,30 @@ static int _http_client_response_parse(HTTPClient *client, char *data, int len, #endif client->response_code = atoi(data + 9); - + if ((client->response_code < 200) || (client->response_code >= 400)) { Log_w("Response code %d", client->response_code); - + if (client->response_code == 403) IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_AUTH); - + if (client->response_code == 404) IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_NOT_FOUND); } - //Log_d("Reading headers : %s", data); - - // 移除null终止字符 + // Log_d("Reading headers : %s", data); + + // remove null character memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2) + 1); len -= (crlf_pos + 2); - + client_data->is_chunked = IOT_FALSE; if (NULL == (ptr_body_end = strstr(data, "\r\n\r\n"))) { int new_trf_len, rc; - rc = _http_client_recv(client, data + len, 1, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len, left_ms(&timer), client_data); - if (rc != QCLOUD_ERR_SUCCESS) { + rc = _http_client_recv(client, data + len, 1, HTTP_CLIENT_CHUNK_SIZE - len - 1, &new_trf_len, left_ms(&timer), + client_data); + if (rc != QCLOUD_RET_SUCCESS) { IOT_FUNC_EXIT_RC(rc); } len += new_trf_len; @@ -639,22 +603,21 @@ static int _http_client_response_parse(HTTPClient *client, char *data, int len, if (NULL != (tmp_ptr = strstr(data, "Content-Length"))) { client_data->response_content_len = atoi(tmp_ptr + strlen("Content-Length: ")); - client_data->retrieve_len = client_data->response_content_len; + client_data->retrieve_len = client_data->response_content_len; } else if (NULL != (tmp_ptr = strstr(data, "Transfer-Encoding"))) { - int len_chunk = strlen("Chunked"); + int len_chunk = strlen("Chunked"); char *chunk_value = data + strlen("Transfer-Encoding: "); - if ((! memcmp(chunk_value, "Chunked", len_chunk)) - || (! memcmp(chunk_value, "chunked", len_chunk))) { - client_data->is_chunked = IOT_TRUE; + if ((!memcmp(chunk_value, "Chunked", len_chunk)) || (!memcmp(chunk_value, "chunked", len_chunk))) { + client_data->is_chunked = IOT_TRUE; client_data->response_content_len = 0; - client_data->retrieve_len = 0; + client_data->retrieve_len = 0; } } else { Log_e("Could not parse header"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP); } - + len = len - (ptr_body_end + 4 - data); memmove(data, ptr_body_end + 4, len + 1); int rc = _http_client_retrieve_content(client, data, len, left_ms(&timer), client_data); @@ -663,15 +626,16 @@ static int _http_client_response_parse(HTTPClient *client, char *data, int len, static int _http_client_connect(HTTPClient *client) { - if (QCLOUD_ERR_SUCCESS != client->network_stack.connect(&client->network_stack)) { + if (QCLOUD_RET_SUCCESS != client->network_stack.connect(&client->network_stack)) { return QCLOUD_ERR_HTTP_CONN; } - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } -static int _http_client_send_request(HTTPClient *client, const char *url, HttpMethod method, HTTPClientData *client_data) -{ +static int _http_client_send_request(HTTPClient *client, const char *url, HttpMethod method, + HTTPClientData *client_data) +{ int rc; rc = _http_client_send_header(client, url, method, client_data); @@ -686,71 +650,68 @@ static int _http_client_send_request(HTTPClient *client, const char *url, HttpMe return rc; } - -/** - * @brief 接收http返回的数据 - * - * @param client http client - * @param timeout_ms 读取数据的超时时间 - * @param client_data http数据负载 - * @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功 - */ + static int _http_client_recv_response(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data) { IOT_FUNC_ENTRY; - int reclen = 0, rc = QCLOUD_ERR_HTTP_CONN; - char buf[HTTP_CLIENT_CHUNK_SIZE] = { 0 }; + int reclen = 0, rc = QCLOUD_ERR_HTTP_CONN; + char buf[HTTP_CLIENT_CHUNK_SIZE] = {0}; Timer timer; - + InitTimer(&timer); countdown_ms(&timer, timeout_ms); - + if (0 == client->network_stack.handle) { Log_e("Connection has not been established"); IOT_FUNC_EXIT_RC(rc); } - + if (client_data->is_more) { client_data->response_buf[0] = '\0'; - rc = _http_client_retrieve_content(client, buf, reclen, left_ms(&timer), client_data); + rc = _http_client_retrieve_content(client, buf, reclen, left_ms(&timer), client_data); } else { client_data->is_more = IOT_TRUE; - rc = _http_client_recv(client, buf, 1, HTTP_CLIENT_CHUNK_SIZE - 1, &reclen, left_ms(&timer), client_data); - - if (rc != QCLOUD_ERR_SUCCESS) { + rc = _http_client_recv(client, buf, 1, HTTP_CLIENT_CHUNK_SIZE - 1, &reclen, left_ms(&timer), client_data); + + if (rc != QCLOUD_RET_SUCCESS) { IOT_FUNC_EXIT_RC(rc); } - + // else if(0 == left_ms(&timer)){ + // IOT_FUNC_EXIT_RC(QCLOUD_ERR_HTTP_TIMEOUT); + //} + buf[reclen] = '\0'; - + if (reclen) { - //HAL_Printf("RESPONSE:\n%s", buf); + // HAL_Printf("RESPONSE:\n%s", buf); rc = _http_client_response_parse(client, buf, reclen, left_ms(&timer), client_data); } } - + IOT_FUNC_EXIT_RC(rc); } static int _http_network_init(Network *pNetwork, const char *host, int port, const char *ca_crt_dir) { - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; if (pNetwork == NULL) { return QCLOUD_ERR_INVAL; } + pNetwork->type = NETWORK_TCP; #ifndef AUTH_WITH_NOTLS if (ca_crt_dir != NULL) { - pNetwork->ssl_connect_params.ca_crt = ca_crt_dir; + pNetwork->ssl_connect_params.ca_crt = ca_crt_dir; pNetwork->ssl_connect_params.ca_crt_len = strlen(pNetwork->ssl_connect_params.ca_crt); pNetwork->ssl_connect_params.timeout_ms = 10000; + pNetwork->type = NETWORK_TLS; } #endif pNetwork->host = host; pNetwork->port = port; - rc = utils_net_init(pNetwork); - + rc = network_init(pNetwork); + return rc; } @@ -761,22 +722,23 @@ int qcloud_http_client_connect(HTTPClient *client, const char *url, int port, co return QCLOUD_ERR_HTTP_CONN; } - int rc; + int rc; char host[HTTP_CLIENT_MAX_HOST_LEN] = {0}; - rc = _http_client_parse_host(url, host, sizeof(host)); - if (rc != QCLOUD_ERR_SUCCESS) return rc; + rc = _http_client_parse_host(url, host, sizeof(host)); + if (rc != QCLOUD_RET_SUCCESS) + return rc; rc = _http_network_init(&client->network_stack, host, port, ca_crt); - if (rc != QCLOUD_ERR_SUCCESS) + if (rc != QCLOUD_RET_SUCCESS) return rc; rc = _http_client_connect(client); - if (rc != QCLOUD_ERR_SUCCESS) { + if (rc != QCLOUD_RET_SUCCESS) { Log_e("http_client_connect is error,rc = %d", rc); qcloud_http_client_close(client); } else { /* reduce log print due to frequent log server connect/disconnect */ - if (port == LOG_UPLOAD_SERVER_PORT) + if (0 == strcmp(url, LOG_UPLOAD_SERVER_URL)) UPLOAD_DBG("http client connect success"); else Log_d("http client connect success"); @@ -791,37 +753,38 @@ void qcloud_http_client_close(HTTPClient *client) } } -int qcloud_http_client_common(HTTPClient *client, const char *url, int port, const char *ca_crt, HttpMethod method, HTTPClientData *client_data) +int qcloud_http_client_common(HTTPClient *client, const char *url, int port, const char *ca_crt, HttpMethod method, + HTTPClientData *client_data) { int rc; if (client->network_stack.handle == 0) { rc = qcloud_http_client_connect(client, url, port, ca_crt); - if (rc != QCLOUD_ERR_SUCCESS) return rc; - } + if (rc != QCLOUD_RET_SUCCESS) + return rc; + } rc = _http_client_send_request(client, url, method, client_data); - if (rc != QCLOUD_ERR_SUCCESS) { + if (rc != QCLOUD_RET_SUCCESS) { Log_e("http_client_send_request is error,rc = %d", rc); qcloud_http_client_close(client); return rc; } - - return QCLOUD_ERR_SUCCESS; + + return QCLOUD_RET_SUCCESS; } int qcloud_http_recv_data(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data) { IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; Timer timer; InitTimer(&timer); - countdown_ms(&timer, (unsigned int) timeout_ms); - - if ((NULL != client_data->response_buf) - && (0 != client_data->response_buf_len)) { + countdown_ms(&timer, (unsigned int)timeout_ms); + + if ((NULL != client_data->response_buf) && (0 != client_data->response_buf_len)) { rc = _http_client_recv_response(client, left_ms(&timer), client_data); if (rc < 0) { Log_e("http_client_recv_response is error,rc = %d", rc); @@ -829,11 +792,9 @@ int qcloud_http_recv_data(HTTPClient *client, uint32_t timeout_ms, HTTPClientDat IOT_FUNC_EXIT_RC(rc); } } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } - - #ifdef __cplusplus } #endif diff --git a/sdk_src/protocol/mqtt/mqtt_client.c b/sdk_src/protocol/mqtt/mqtt_client.c new file mode 100644 index 00000000..ac2603f2 --- /dev/null +++ b/sdk_src/protocol/mqtt/mqtt_client.c @@ -0,0 +1,595 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lite-utils.h" +#include "log_upload.h" +#include "mqtt_client.h" +#include "qcloud_iot_ca.h" +#include "qcloud_iot_common.h" +#include "qcloud_iot_device.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_base64.h" +#include "utils_list.h" + +static uint16_t _get_random_start_packet_id(void) +{ + srand((unsigned)HAL_GetTimeMs()); + return rand() % 65536 + 1; +} + +DeviceInfo *IOT_MQTT_GetDeviceInfo(void *pClient) +{ + POINTER_SANITY_CHECK(pClient, NULL); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + return &mqtt_client->device_info; +} + +// currently return a constant value +int IOT_MQTT_GetErrCode(void) +{ + return QCLOUD_ERR_FAILURE; +} + +void *IOT_MQTT_Construct(MQTTInitParams *pParams) +{ + POINTER_SANITY_CHECK(pParams, NULL); + STRING_PTR_SANITY_CHECK(pParams->product_id, NULL); + STRING_PTR_SANITY_CHECK(pParams->device_name, NULL); + + Qcloud_IoT_Client *mqtt_client = NULL; + + // create and init MQTTClient + if ((mqtt_client = (Qcloud_IoT_Client *)HAL_Malloc(sizeof(Qcloud_IoT_Client))) == NULL) { + Log_e("malloc MQTTClient failed"); + pParams->err_code = QCLOUD_ERR_MALLOC; + return NULL; + } + + int rc = qcloud_iot_mqtt_init(mqtt_client, pParams); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("mqtt init failed: %d", rc); + HAL_Free(mqtt_client); + pParams->err_code = rc; + return NULL; + } + + MQTTConnectParams connect_params = DEFAULT_MQTTCONNECT_PARAMS; + connect_params.client_id = mqtt_client->device_info.client_id; + // Upper limit of keep alive interval is (11.5 * 60) seconds + connect_params.keep_alive_interval = Min(pParams->keep_alive_interval_ms / 1000, 690); + connect_params.clean_session = pParams->clean_session; + connect_params.auto_connect_enable = pParams->auto_connect_enable; +#if defined(AUTH_WITH_NOTLS) && defined(AUTH_MODE_KEY) + if (pParams->device_secret == NULL) { + Log_e("Device secret is null!"); + qcloud_iot_mqtt_fini(mqtt_client); + HAL_Free(mqtt_client); + pParams->err_code = QCLOUD_ERR_INVAL; + return NULL; + } + size_t src_len = strlen(pParams->device_secret); + size_t len; + memset(mqtt_client->psk_decode, 0x00, DECODE_PSK_LENGTH); + rc = qcloud_iot_utils_base64decode(mqtt_client->psk_decode, DECODE_PSK_LENGTH, &len, + (unsigned char *)pParams->device_secret, src_len); + connect_params.device_secret = (char *)mqtt_client->psk_decode; + connect_params.device_secret_len = len; + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("Device secret decode err, secret:%s", STRING_PTR_PRINT_SANITY_CHECK(pParams->device_secret)); + qcloud_iot_mqtt_fini(mqtt_client); + HAL_Free(mqtt_client); + pParams->err_code = QCLOUD_ERR_INVAL; + return NULL; + } +#endif + + rc = qcloud_iot_mqtt_connect(mqtt_client, &connect_params); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("mqtt connect with id: %s failed: %d", STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->options.conn_id), rc); + qcloud_iot_mqtt_fini(mqtt_client); + HAL_Free(mqtt_client); + pParams->err_code = rc; + return NULL; + } else { + Log_i("mqtt connect with id: %s success", mqtt_client->options.conn_id); + } + +#ifdef LOG_UPLOAD + // log subscribe topics + if (is_log_uploader_init()) { + int log_level; + rc = qcloud_get_log_level(mqtt_client, &log_level); + // rc = qcloud_log_topic_subscribe(mqtt_client); + if (rc < 0) { + Log_e("client get log topic failed: %d", rc); + } + set_log_mqtt_client((void *)mqtt_client); + + IOT_Log_Upload(true); + } +#endif + return mqtt_client; +} + +int IOT_MQTT_Destroy(void **pClient) +{ + POINTER_SANITY_CHECK(*pClient, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)(*pClient); + + int rc = qcloud_iot_mqtt_disconnect(mqtt_client); + // disconnect network stack by force + if (rc != QCLOUD_RET_SUCCESS) { + mqtt_client->network_stack.disconnect(&(mqtt_client->network_stack)); + set_client_conn_state(mqtt_client, NOTCONNECTED); + } + + int i = 0; + for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { + /* notify this event to topic subscriber */ + if (NULL != mqtt_client->sub_handles[i].topic_filter && NULL != mqtt_client->sub_handles[i].sub_event_handler) + mqtt_client->sub_handles[i].sub_event_handler(mqtt_client, MQTT_EVENT_CLIENT_DESTROY, + mqtt_client->sub_handles[i].handler_user_data); + + if (NULL != mqtt_client->sub_handles[i].topic_filter) { + HAL_Free((void *)mqtt_client->sub_handles[i].topic_filter); + mqtt_client->sub_handles[i].topic_filter = NULL; + } + } + +#ifdef MQTT_RMDUP_MSG_ENABLED + reset_repeat_packet_id_buffer(mqtt_client); +#endif + + HAL_MutexDestroy(mqtt_client->lock_generic); + HAL_MutexDestroy(mqtt_client->lock_write_buf); + + HAL_MutexDestroy(mqtt_client->lock_list_sub); + HAL_MutexDestroy(mqtt_client->lock_list_pub); + + list_destroy(mqtt_client->list_pub_wait_ack); + list_destroy(mqtt_client->list_sub_wait_ack); + + HAL_Free(*pClient); + *pClient = NULL; +#ifdef LOG_UPLOAD + set_log_mqtt_client(NULL); +#endif + Log_i("mqtt release!"); + + return rc; +} + +int IOT_MQTT_Yield(void *pClient, uint32_t timeout_ms) +{ + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + +#ifdef MULTITHREAD_ENABLED + /* only one instance of yield is allowed in running state*/ + if (mqtt_client->thread_running) { + HAL_SleepMs(timeout_ms); + return QCLOUD_RET_SUCCESS; + } +#endif + + int rc = qcloud_iot_mqtt_yield(mqtt_client, timeout_ms); + +#ifdef LOG_UPLOAD + /* do instant log uploading if MQTT communication error */ + if (rc == QCLOUD_RET_SUCCESS) + IOT_Log_Upload(false); + else + IOT_Log_Upload(true); +#endif + + return rc; +} + +int IOT_MQTT_Publish(void *pClient, char *topicName, PublishParams *pParams) +{ + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + return qcloud_iot_mqtt_publish(mqtt_client, topicName, pParams); +} + +int IOT_MQTT_Subscribe(void *pClient, char *topicFilter, SubscribeParams *pParams) +{ + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + return qcloud_iot_mqtt_subscribe(mqtt_client, topicFilter, pParams); +} + +int IOT_MQTT_Unsubscribe(void *pClient, char *topicFilter) +{ + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + return qcloud_iot_mqtt_unsubscribe(mqtt_client, topicFilter); +} + +bool IOT_MQTT_IsSubReady(void *pClient, char *topicFilter) +{ + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + return qcloud_iot_mqtt_is_sub_ready(mqtt_client, topicFilter); +} + +bool IOT_MQTT_IsConnected(void *pClient) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + IOT_FUNC_EXIT_RC(get_client_conn_state(mqtt_client) == 1) +} + +#ifdef MULTITHREAD_ENABLED + +static void _mqtt_yield_thread(void *ptr) +{ + int rc = QCLOUD_RET_SUCCESS; + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)ptr; + + Log_i("MQTT client %s start loop", STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.client_id)); + while (mqtt_client->thread_running) { + int rc = qcloud_iot_mqtt_yield(mqtt_client, 500); + +#ifdef LOG_UPLOAD + /* do instant log uploading if MQTT communication error */ + if (rc == QCLOUD_RET_SUCCESS) + IOT_Log_Upload(false); + else + IOT_Log_Upload(true); +#endif + + if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) { + HAL_SleepMs(500); + continue; + } else if (rc == QCLOUD_RET_MQTT_MANUALLY_DISCONNECTED || rc == QCLOUD_ERR_MQTT_RECONNECT_TIMEOUT) { + Log_e("MQTT Yield thread exit with error: %d", rc); + break; + } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) { + Log_e("MQTT Yield thread error: %d", rc); + } + + HAL_SleepMs(200); + } + + mqtt_client->thread_running = false; + mqtt_client->thread_exit_code = rc; + +#ifdef LOG_UPLOAD + IOT_Log_Upload(true); +#endif + + Log_i("MQTT client %s stop loop", STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.client_id)); +} + +int IOT_MQTT_StartLoop(void *pClient) +{ + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + ThreadParams thread_params = {0}; + thread_params.thread_func = _mqtt_yield_thread; + thread_params.thread_name = "MQTT_yield_thread"; + thread_params.user_arg = pClient; + thread_params.stack_size = 4096; + thread_params.priority = 1; + mqtt_client->thread_running = true; + + int rc = HAL_ThreadCreate(&thread_params); + if (rc) { + Log_e("create mqtt yield thread fail: %d", rc); + return QCLOUD_ERR_FAILURE; + } + + HAL_SleepMs(500); + return QCLOUD_RET_SUCCESS; +} + +void IOT_MQTT_StopLoop(void *pClient) +{ + POINTER_SANITY_CHECK_RTN(pClient); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + mqtt_client->thread_running = false; + HAL_SleepMs(1000); + return; +} + +bool IOT_MQTT_GetLoopStatus(void *pClient, int *exit_code) +{ + POINTER_SANITY_CHECK(pClient, false); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + *exit_code = mqtt_client->thread_exit_code; + return mqtt_client->thread_running; +} + +void IOT_MQTT_SetLoopStatus(void *pClient, bool loop_status) +{ + POINTER_SANITY_CHECK_RTN(pClient); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + mqtt_client->thread_running = loop_status; +} + +#endif + +#if 0 +static inline void _strlowr(char *str) +{ + while (*str != '\0') { + *str = tolower(*str); + str++; + } +} +#endif + +int qcloud_iot_mqtt_init(Qcloud_IoT_Client *pClient, MQTTInitParams *pParams) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pParams, QCLOUD_ERR_INVAL); + + memset(pClient, 0x0, sizeof(Qcloud_IoT_Client)); + + int rc = iot_device_info_set(&(pClient->device_info), pParams->product_id, pParams->device_name); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("failed to set device info: %d", rc); + return rc; + } + + int size = + HAL_Snprintf(pClient->host_addr, HOST_STR_LENGTH, "%s.%s", pParams->product_id, QCLOUD_IOT_MQTT_DIRECT_DOMAIN); + if (size < 0 || size > HOST_STR_LENGTH - 1) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + // enable below code for some special platform + //_strlowr(s_qcloud_iot_host); + + int i = 0; + for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { + pClient->sub_handles[i].topic_filter = NULL; + pClient->sub_handles[i].message_handler = NULL; + pClient->sub_handles[i].sub_event_handler = NULL; + pClient->sub_handles[i].qos = QOS0; + pClient->sub_handles[i].handler_user_data = NULL; + } + + if (pParams->command_timeout < MIN_COMMAND_TIMEOUT) + pParams->command_timeout = MIN_COMMAND_TIMEOUT; + if (pParams->command_timeout > MAX_COMMAND_TIMEOUT) + pParams->command_timeout = MAX_COMMAND_TIMEOUT; + pClient->command_timeout_ms = pParams->command_timeout; + + // packet id, random from [1 - 65536] + pClient->next_packet_id = _get_random_start_packet_id(); + pClient->write_buf_size = QCLOUD_IOT_MQTT_TX_BUF_LEN; + pClient->read_buf_size = QCLOUD_IOT_MQTT_RX_BUF_LEN; + pClient->is_ping_outstanding = 0; + pClient->was_manually_disconnected = 0; + pClient->counter_network_disconnected = 0; + + pClient->event_handle = pParams->event_handle; + + pClient->lock_generic = HAL_MutexCreate(); + if (NULL == pClient->lock_generic) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + set_client_conn_state(pClient, NOTCONNECTED); + + if ((pClient->lock_write_buf = HAL_MutexCreate()) == NULL) { + Log_e("create write buf lock failed."); + goto error; + } + if ((pClient->lock_list_sub = HAL_MutexCreate()) == NULL) { + Log_e("create sub list lock failed."); + goto error; + } + if ((pClient->lock_list_pub = HAL_MutexCreate()) == NULL) { + Log_e("create pub list lock failed."); + goto error; + } + + if ((pClient->list_pub_wait_ack = list_new()) == NULL) { + Log_e("create pub wait list failed."); + goto error; + } + pClient->list_pub_wait_ack->free = HAL_Free; + + if ((pClient->list_sub_wait_ack = list_new()) == NULL) { + Log_e("create sub wait list failed."); + goto error; + } + pClient->list_sub_wait_ack->free = HAL_Free; + +#ifndef AUTH_WITH_NOTLS + // device param for TLS connection +#ifdef AUTH_MODE_CERT + Log_d("cert file: %s", STRING_PTR_PRINT_SANITY_CHECK(pParams->cert_file)); + Log_d("key file: %s", STRING_PTR_PRINT_SANITY_CHECK(pParams->key_file)); + + strncpy(pClient->cert_file_path, pParams->cert_file, FILE_PATH_MAX_LEN - 1); + strncpy(pClient->key_file_path, pParams->key_file, FILE_PATH_MAX_LEN - 1); + + pClient->network_stack.ssl_connect_params.cert_file = pClient->cert_file_path; + pClient->network_stack.ssl_connect_params.key_file = pClient->key_file_path; + pClient->network_stack.ssl_connect_params.ca_crt = iot_ca_get(); + pClient->network_stack.ssl_connect_params.ca_crt_len = strlen(pClient->network_stack.ssl_connect_params.ca_crt); +#else + if (pParams->device_secret != NULL) { + size_t src_len = strlen(pParams->device_secret); + size_t len; + memset(pClient->psk_decode, 0x00, DECODE_PSK_LENGTH); + qcloud_iot_utils_base64decode(pClient->psk_decode, DECODE_PSK_LENGTH, &len, + (unsigned char *)pParams->device_secret, src_len); + pClient->network_stack.ssl_connect_params.psk = (char *)pClient->psk_decode; + pClient->network_stack.ssl_connect_params.psk_length = len; + } else { + Log_e("psk is empty!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); + } + if (strnlen(pClient->device_info.client_id, MAX_SIZE_OF_CLIENT_ID) == 0) { + Log_e("psk id is empty!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); + } + pClient->network_stack.ssl_connect_params.psk_id = pClient->device_info.client_id; + pClient->network_stack.ssl_connect_params.ca_crt = NULL; + pClient->network_stack.ssl_connect_params.ca_crt_len = 0; +#endif + + pClient->network_stack.host = pClient->host_addr; + pClient->network_stack.port = MQTT_SERVER_PORT_TLS; + pClient->network_stack.ssl_connect_params.timeout_ms = + pClient->command_timeout_ms > QCLOUD_IOT_TLS_HANDSHAKE_TIMEOUT ? pClient->command_timeout_ms + : QCLOUD_IOT_TLS_HANDSHAKE_TIMEOUT; + +#else + pClient->network_stack.host = pClient->host_addr; + pClient->network_stack.port = MQTT_SERVER_PORT_NOTLS; +#endif + + // init network stack + qcloud_iot_mqtt_network_init(&(pClient->network_stack)); + + // ping timer and reconnect delay timer + InitTimer(&(pClient->ping_timer)); + InitTimer(&(pClient->reconnect_delay_timer)); + +#ifdef SYSTEM_COMM + pClient->sys_state.result_recv_ok = false; + pClient->sys_state.topic_sub_ok = false; + pClient->sys_state.time = 0; +#endif + +#ifdef MULTITHREAD_ENABLED + pClient->thread_running = false; +#endif + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); + +error: + if (pClient->list_pub_wait_ack) { + pClient->list_pub_wait_ack->free(pClient->list_pub_wait_ack); + pClient->list_pub_wait_ack = NULL; + } + if (pClient->list_sub_wait_ack) { + pClient->list_sub_wait_ack->free(pClient->list_sub_wait_ack); + pClient->list_sub_wait_ack = NULL; + } + if (pClient->lock_generic) { + HAL_MutexDestroy(pClient->lock_generic); + pClient->lock_generic = NULL; + } + if (pClient->lock_list_sub) { + HAL_MutexDestroy(pClient->lock_list_sub); + pClient->lock_list_sub = NULL; + } + if (pClient->lock_list_pub) { + HAL_MutexDestroy(pClient->lock_list_pub); + pClient->lock_list_pub = NULL; + } + if (pClient->lock_write_buf) { + HAL_MutexDestroy(pClient->lock_write_buf); + pClient->lock_write_buf = NULL; + } + + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) +} + +int qcloud_iot_mqtt_fini(Qcloud_IoT_Client *mqtt_client) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(mqtt_client, QCLOUD_ERR_INVAL); + + HAL_MutexDestroy(mqtt_client->lock_generic); + HAL_MutexDestroy(mqtt_client->lock_write_buf); + + HAL_MutexDestroy(mqtt_client->lock_list_sub); + HAL_MutexDestroy(mqtt_client->lock_list_pub); + + list_destroy(mqtt_client->list_pub_wait_ack); + list_destroy(mqtt_client->list_sub_wait_ack); + + Log_i("release mqtt client resources"); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +int qcloud_iot_mqtt_set_autoreconnect(Qcloud_IoT_Client *pClient, bool value) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + pClient->options.auto_connect_enable = (uint8_t)value; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +bool qcloud_iot_mqtt_is_autoreconnect_enabled(Qcloud_IoT_Client *pClient) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + bool is_enabled = false; + if (pClient->options.auto_connect_enable == 1) { + is_enabled = true; + } + + IOT_FUNC_EXIT_RC(is_enabled); +} + +int qcloud_iot_mqtt_get_network_disconnected_count(Qcloud_IoT_Client *pClient) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + IOT_FUNC_EXIT_RC(pClient->counter_network_disconnected); +} + +int qcloud_iot_mqtt_reset_network_disconnected_count(Qcloud_IoT_Client *pClient) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + pClient->counter_network_disconnected = 0; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +#ifdef __cplusplus +} +#endif diff --git a/src/mqtt/src/mqtt_client_common.c b/sdk_src/protocol/mqtt/mqtt_client_common.c old mode 100755 new mode 100644 similarity index 60% rename from src/mqtt/src/mqtt_client_common.c rename to sdk_src/protocol/mqtt/mqtt_client_common.c index e5c4c719..fed4bd3c --- a/src/mqtt/src/mqtt_client_common.c +++ b/sdk_src/protocol/mqtt/mqtt_client_common.c @@ -23,9 +23,10 @@ extern "C" { #include #include "mqtt_client.h" - #include "utils_list.h" +/* remain waiting time after MQTT header is received (unit: ms) */ +#define QCLOUD_IOT_MQTT_MAX_REMAIN_WAIT_MS (2000) #define MAX_NO_OF_REMAINING_LENGTH_BYTES 4 @@ -50,40 +51,47 @@ static int _check_handle_is_identical(SubTopicHandle *sub_handle1, SubTopicHandl return 1; } + if (sub_handle1->sub_event_handler != sub_handle2->sub_event_handler) { + return 1; + } + return 0; } -uint16_t get_next_packet_id(Qcloud_IoT_Client *pClient) { +uint16_t get_next_packet_id(Qcloud_IoT_Client *pClient) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); HAL_MutexLock(pClient->lock_generic); - pClient->next_packet_id = (uint16_t) ((MAX_PACKET_ID == pClient->next_packet_id) ? 1 : (pClient->next_packet_id + 1)); + pClient->next_packet_id = + (uint16_t)((MAX_PACKET_ID == pClient->next_packet_id) ? 1 : (pClient->next_packet_id + 1)); HAL_MutexUnlock(pClient->lock_generic); IOT_FUNC_EXIT_RC(pClient->next_packet_id); } -void get_next_conn_id(char *conn_id) { - int i; - srand((unsigned)time(0)); - for (i = 0; i < MAX_CONN_ID_LEN - 1; i++) { - int flag = rand() % 3; - switch(flag) { - case 0: - conn_id[i] = (rand() % 26) + 'a'; - break; - case 1: - conn_id[i] = (rand() % 26) + 'A'; - break; - case 2: - conn_id[i] = (rand() % 10) + '0'; - break; - } - } - - conn_id[MAX_CONN_ID_LEN - 1] = '\0'; +void get_next_conn_id(char *conn_id) +{ + int i; + srand((unsigned)HAL_GetTimeMs()); + for (i = 0; i < MAX_CONN_ID_LEN - 1; i++) { + int flag = rand() % 3; + switch (flag) { + case 0: + conn_id[i] = (rand() % 26) + 'a'; + break; + case 1: + conn_id[i] = (rand() % 26) + 'A'; + break; + case 2: + conn_id[i] = (rand() % 10) + '0'; + break; + } + } + + conn_id[MAX_CONN_ID_LEN - 1] = '\0'; } /** @@ -92,14 +100,15 @@ void get_next_conn_id(char *conn_id) { * @param length the length to be encoded * @return the number of bytes written to buffer */ -size_t mqtt_write_packet_rem_len(unsigned char *buf, uint32_t length) { +size_t mqtt_write_packet_rem_len(unsigned char *buf, uint32_t length) +{ IOT_FUNC_ENTRY; size_t outLen = 0; do { unsigned char encodeByte; - encodeByte = (unsigned char) (length % 128); + encodeByte = (unsigned char)(length % 128); length /= 128; /* if there are more digits to encode, set the top bit of this digit */ if (length > 0) { @@ -111,7 +120,8 @@ size_t mqtt_write_packet_rem_len(unsigned char *buf, uint32_t length) { IOT_FUNC_EXIT_RC((int)outLen); } -size_t get_mqtt_packet_len(size_t rem_len) { +size_t get_mqtt_packet_len(size_t rem_len) +{ rem_len += 1; /* header byte */ /* now remaining_length field */ @@ -134,47 +144,32 @@ size_t get_mqtt_packet_len(size_t rem_len) { * @param value the decoded length returned * @return the number of bytes read from the socket */ -static int _decode_packet_rem_len_from_buf_read(uint32_t (*getcharfn)(unsigned char *, uint32_t), uint32_t *value, - uint32_t *readBytesLen) { +static int _decode_packet_rem_len_from_buf_read(unsigned char *bufptr, uint32_t *value, uint32_t *readBytesLen) +{ IOT_FUNC_ENTRY; unsigned char c; - uint32_t multiplier = 1; - uint32_t len = 0; - *value = 0; + uint32_t multiplier = 1; + uint32_t len = 0; + *value = 0; do { if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) { /* bad data */ IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_PACKET_READ); } - uint32_t getLen = 0; - getLen = (*getcharfn)(&c, 1); - if (1 != getLen) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } + c = *bufptr++; *value += (c & 127) * multiplier; multiplier *= 128; } while ((c & 128) != 0); *readBytesLen = len; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -static unsigned char *bufptr; -uint32_t bufchar(unsigned char *c, uint32_t count) { - uint32_t i; - - for (i = 0; i < count; ++i) { - *c = *bufptr++; - } - - return count; -} - -int mqtt_read_packet_rem_len_form_buf(unsigned char *buf, uint32_t *value, uint32_t *readBytesLen) { - bufptr = buf; - return _decode_packet_rem_len_from_buf_read(bufchar, value, readBytesLen); +int mqtt_read_packet_rem_len_form_buf(unsigned char *buf, uint32_t *value, uint32_t *readBytesLen) +{ + return _decode_packet_rem_len_from_buf_read(buf, value, readBytesLen); } /** @@ -182,11 +177,12 @@ int mqtt_read_packet_rem_len_form_buf(unsigned char *buf, uint32_t *value, uint3 * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned * @return the value calculated */ -uint16_t mqtt_read_uint16_t(unsigned char **pptr) { - unsigned char *ptr = *pptr; - uint8_t firstByte = (uint8_t) (*ptr); - uint8_t secondByte = (uint8_t) (*(ptr + 1)); - uint16_t len = (uint16_t) (secondByte + (256 * firstByte)); +uint16_t mqtt_read_uint16_t(unsigned char **pptr) +{ + unsigned char *ptr = *pptr; + uint8_t firstByte = (uint8_t)(*ptr); + uint8_t secondByte = (uint8_t)(*(ptr + 1)); + uint16_t len = (uint16_t)(secondByte + (256 * firstByte)); *pptr += 2; return len; } @@ -196,7 +192,8 @@ uint16_t mqtt_read_uint16_t(unsigned char **pptr) { * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned * @return the character read */ -unsigned char mqtt_read_char(unsigned char **pptr) { +unsigned char mqtt_read_char(unsigned char **pptr) +{ unsigned char c = **pptr; (*pptr)++; return c; @@ -207,7 +204,8 @@ unsigned char mqtt_read_char(unsigned char **pptr) { * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned * @param c the character to write */ -void mqtt_write_char(unsigned char **pptr, unsigned char c) { +void mqtt_write_char(unsigned char **pptr, unsigned char c) +{ **pptr = c; (*pptr)++; } @@ -217,10 +215,11 @@ void mqtt_write_char(unsigned char **pptr, unsigned char c) { * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned * @param anInt the integer to write */ -void mqtt_write_uint_16(unsigned char **pptr, uint16_t anInt) { - **pptr = (unsigned char) (anInt / 256); +void mqtt_write_uint_16(unsigned char **pptr, uint16_t anInt) +{ + **pptr = (unsigned char)(anInt / 256); (*pptr)++; - **pptr = (unsigned char) (anInt % 256); + **pptr = (unsigned char)(anInt % 256); (*pptr)++; } @@ -229,9 +228,10 @@ void mqtt_write_uint_16(unsigned char **pptr, uint16_t anInt) { * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned * @param string the C string to write */ -void mqtt_write_utf8_string(unsigned char **pptr, const char *string) { +void mqtt_write_utf8_string(unsigned char **pptr, const char *string) +{ size_t len = strlen(string); - mqtt_write_uint_16(pptr, (uint16_t) len); + mqtt_write_uint_16(pptr, (uint16_t)len); memcpy(*pptr, string, len); *pptr += len; } @@ -239,8 +239,7 @@ void mqtt_write_utf8_string(unsigned char **pptr, const char *string) { /** * Initialize the MQTT Header fixed byte. Used to ensure that Header bits are */ -int mqtt_init_packet_header(unsigned char *header, MessageTypes message_type, - QoS Qos, uint8_t dup, uint8_t retained) +int mqtt_init_packet_header(unsigned char *header, MessageTypes message_type, QoS Qos, uint8_t dup, uint8_t retained) { POINTER_SANITY_CHECK(header, QCLOUD_ERR_INVAL); unsigned char type, qos; @@ -313,24 +312,24 @@ int mqtt_init_packet_header(unsigned char *header, MessageTypes message_type, } /* Generate the final protocol header by using bitwise operator */ - *header = ((type< buf_len) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); } - header = mqtt_read_char(&curdata); - *packet_type = ((header&MQTT_HEADER_TYPE_MASK)>>MQTT_HEADER_TYPE_SHIFT); - *dup = ((header&MQTT_HEADER_DUP_MASK)>>MQTT_HEADER_DUP_SHIFT); + header = mqtt_read_char(&curdata); + *packet_type = ((header & MQTT_HEADER_TYPE_MASK) >> MQTT_HEADER_TYPE_SHIFT); + *dup = ((header & MQTT_HEADER_DUP_MASK) >> MQTT_HEADER_DUP_SHIFT); /* read remaining length */ rc = mqtt_read_packet_rem_len_form_buf(curdata, &decodedLen, &readBytesLen); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } curdata += (readBytesLen); @@ -366,8 +365,7 @@ int deserialize_ack_packet(uint8_t *packet_type, uint8_t *dup, uint16_t *packet_ } *packet_id = mqtt_read_uint16_t(&curdata); - - // 返回错误码处理 + if (enddata - curdata >= 1) { unsigned char ack_code = mqtt_read_char(&curdata); if (ack_code != 0) { @@ -376,21 +374,21 @@ int deserialize_ack_packet(uint8_t *packet_type, uint8_t *dup, uint16_t *packet_ } } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * Deserializes the supplied (wire) buffer into suback data - * @param packet_id returned integer - the MQTT packet identifier - * @param max_count - the maximum number of members allowed in the grantedQoSs array - * @param count returned integer - number of members in the grantedQoSs array - * @param grantedQoSs returned array of integers - the granted qualities of service - * @param buf the raw buffer data, of the correct length determined by the remaining length field - * @param buf_len the length in bytes of the data in the supplied buffer - * @return error code. 1 is success, 0 is failure - */ -int deserialize_suback_packet(uint16_t *packet_id, uint32_t max_count, uint32_t *count, - QoS *grantedQoSs, unsigned char *buf, size_t buf_len) + * Deserializes the supplied (wire) buffer into suback data + * @param packet_id returned integer - the MQTT packet identifier + * @param max_count - the maximum number of members allowed in the grantedQoSs array + * @param count returned integer - number of members in the grantedQoSs array + * @param grantedQoSs returned array of integers - the granted qualities of service + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param buf_len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int deserialize_suback_packet(uint16_t *packet_id, uint32_t max_count, uint32_t *count, QoS *grantedQoSs, + unsigned char *buf, size_t buf_len) { IOT_FUNC_ENTRY; @@ -398,27 +396,27 @@ int deserialize_suback_packet(uint16_t *packet_id, uint32_t max_count, uint32_t POINTER_SANITY_CHECK(count, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(grantedQoSs, QCLOUD_ERR_INVAL); - unsigned char header, type = 0; + unsigned char header, type = 0; unsigned char *curdata = buf; unsigned char *enddata = NULL; - int decodeRc; - uint32_t decodedLen = 0; - uint32_t readBytesLen = 0; + int decodeRc; + uint32_t decodedLen = 0; + uint32_t readBytesLen = 0; - // SUBACK头部大小为4字节, 负载部分至少为1字节QOS返回码 + // 4 bytes of SUBACK header size and at least 1 byte(QoS) in payload if (5 > buf_len) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); } - // 读取报文固定头部的第一个字节 + // read 1st byte in fixed header header = mqtt_read_char(&curdata); - type = (header&MQTT_HEADER_TYPE_MASK)>>MQTT_HEADER_TYPE_SHIFT; + type = (header & MQTT_HEADER_TYPE_MASK) >> MQTT_HEADER_TYPE_SHIFT; if (type != SUBACK) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - // 读取报文固定头部的剩余长度 + // read remain part in fixed header decodeRc = mqtt_read_packet_rem_len_form_buf(curdata, &decodedLen, &readBytesLen); - if (decodeRc != QCLOUD_ERR_SUCCESS) { + if (decodeRc != QCLOUD_RET_SUCCESS) { IOT_FUNC_EXIT_RC(decodeRc); } @@ -428,29 +426,29 @@ int deserialize_suback_packet(uint16_t *packet_id, uint32_t max_count, uint32_t IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - // 读取报文可变头部的报文标识符 + // read packet id from variable header *packet_id = mqtt_read_uint16_t(&curdata); - // 读取报文的负载部分 + // read payload *count = 0; while (curdata < enddata) { if (*count > max_count) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - grantedQoSs[(*count)++] = (QoS) mqtt_read_char(&curdata); + grantedQoSs[(*count)++] = (QoS)mqtt_read_char(&curdata); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * Deserializes the supplied (wire) buffer into unsuback data - * @param packet_id returned integer - the MQTT packet identifier - * @param buf the raw buffer data, of the correct length determined by the remaining length field - * @param buf_len the length in bytes of the data in the supplied buffer - * @return int indicating function execution status - */ -int deserialize_unsuback_packet(uint16_t *packet_id, unsigned char *buf, size_t buf_len) + * Deserializes the supplied (wire) buffer into unsuback data + * @param packet_id returned integer - the MQTT packet identifier + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param buf_len the length in bytes of the data in the supplied buffer + * @return int indicating function execution status + */ +int deserialize_unsuback_packet(uint16_t *packet_id, unsigned char *buf, size_t buf_len) { IOT_FUNC_ENTRY; @@ -458,11 +456,11 @@ int deserialize_unsuback_packet(uint16_t *packet_id, unsigned char *buf, size_t POINTER_SANITY_CHECK(packet_id, QCLOUD_ERR_INVAL); unsigned char type = 0; - unsigned char dup = 0; - int rc; + unsigned char dup = 0; + int rc; rc = deserialize_ack_packet(&type, &dup, packet_id, buf, buf_len); - if (QCLOUD_ERR_SUCCESS == rc && UNSUBACK != type) { + if (QCLOUD_RET_SUCCESS == rc && UNSUBACK != type) { rc = QCLOUD_ERR_FAILURE; } @@ -470,22 +468,24 @@ int deserialize_unsuback_packet(uint16_t *packet_id, unsigned char *buf, size_t } /** - * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket - * @param buf the buffer into which the packet will be serialized - * @param buf_len the length in bytes of the supplied buffer, to avoid overruns - * @param packettype the message type - * @param serialized length - * @return int indicating function execution status - */ -int serialize_packet_with_zero_payload(unsigned char *buf, size_t buf_len, MessageTypes packetType, uint32_t *serialized_len) { + * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket + * @param buf the buffer into which the packet will be serialized + * @param buf_len the length in bytes of the supplied buffer, to avoid overruns + * @param packettype the message type + * @param serialized length + * @return int indicating function execution status + */ +int serialize_packet_with_zero_payload(unsigned char *buf, size_t buf_len, MessageTypes packetType, + uint32_t *serialized_len) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL); - unsigned char header = 0; - unsigned char *ptr = buf; - int rc; + unsigned char header = 0; + unsigned char *ptr = buf; + int rc; /* Buffer should have at least 2 bytes for the header */ if (4 > buf_len) { @@ -493,7 +493,7 @@ int serialize_packet_with_zero_payload(unsigned char *buf, size_t buf_len, Messa } rc = mqtt_init_packet_header(&header, packetType, QOS0, 0, 0); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } @@ -502,18 +502,19 @@ int serialize_packet_with_zero_payload(unsigned char *buf, size_t buf_len, Messa /* write remaining length */ ptr += mqtt_write_packet_rem_len(ptr, 0); - *serialized_len = (uint32_t) (ptr - buf); + *serialized_len = (uint32_t)(ptr - buf); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -int send_mqtt_packet(Qcloud_IoT_Client *pClient, size_t length, Timer *timer) { +int send_mqtt_packet(Qcloud_IoT_Client *pClient, size_t length, Timer *timer) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(timer, QCLOUD_ERR_INVAL); - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; size_t sentLen = 0, sent = 0; if (length >= pClient->write_buf_size) { @@ -521,8 +522,9 @@ int send_mqtt_packet(Qcloud_IoT_Client *pClient, size_t length, Timer *timer) { } while (sent < length && !expired(timer)) { - rc = pClient->network_stack.write(&(pClient->network_stack), &pClient->write_buf[sent], length, left_ms(timer), &sentLen); - if (rc != QCLOUD_ERR_SUCCESS) { + rc = pClient->network_stack.write(&(pClient->network_stack), &pClient->write_buf[sent], length, left_ms(timer), + &sentLen); + if (rc != QCLOUD_RET_SUCCESS) { /* there was an error writing the data */ break; } @@ -531,33 +533,24 @@ int send_mqtt_packet(Qcloud_IoT_Client *pClient, size_t length, Timer *timer) { if (sent == length) { /* record the fact that we have successfully sent the packet */ - //countdown(&c->ping_timer, c->keep_alive_interval); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + // countdown(&c->ping_timer, c->keep_alive_interval); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } IOT_FUNC_EXIT_RC(rc); } -/** - * @brief 解析报文的剩余长度字段 - * - * 每从网络中读取一个字节, 按照MQTT协议算法计算剩余长度 - * - * @param pClient Client结构体 - * @param value 剩余长度 - * @param timeout 超时时间 - * @return - */ -static int _decode_packet_rem_len_with_net_read(Qcloud_IoT_Client *pClient, uint32_t *value, uint32_t timeout) { +static int _decode_packet_rem_len_with_net_read(Qcloud_IoT_Client *pClient, uint32_t *value, uint32_t timeout) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(value, QCLOUD_ERR_INVAL); unsigned char i; - uint32_t multiplier = 1; - uint32_t len = 0; - size_t read_len = 0; + uint32_t multiplier = 1; + uint32_t len = 0; + size_t read_len = 0; *value = 0; @@ -567,8 +560,7 @@ static int _decode_packet_rem_len_with_net_read(Qcloud_IoT_Client *pClient, uint IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_PACKET_READ) } - if ((pClient->network_stack.read(&(pClient->network_stack), &i, 1, timeout, &read_len)) != - QCLOUD_ERR_SUCCESS) { + if ((pClient->network_stack.read(&(pClient->network_stack), &i, 1, timeout, &read_len)) != QCLOUD_RET_SUCCESS) { /* The value argument is the important value. len is just used temporarily * and never used by the calling function for anything else */ IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); @@ -580,66 +572,67 @@ static int _decode_packet_rem_len_with_net_read(Qcloud_IoT_Client *pClient, uint /* The value argument is the important value. len is just used temporarily * and never used by the calling function for anything else */ - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * @brief 从底层SSL/TCP层读取报文数据 + * @brief Read MQTT packet from network stack * - * 1. 读取第一个字节确定报文的类型; - * 2. 读取剩余长度字段, 最大为四个字节; 剩余长度表示可变包头和有效负载的长度 - * 3. 根据剩余长度, 读取剩下的数据, 包括可变包头和有效负荷 + * 1. read 1st byte in fixed header and check if valid + * 2. read the remaining length + * 3. read payload according to remaining length * - * @param pClient Client结构体 - * @param timer 定时器 - * @param packet_type 报文类型 - * @return + * @param pClient MQTT Client + * @param timer timeout timer + * @param packet_type MQTT packet type + * @return QCLOUD_RET_SUCCESS for success, or err code for failure */ -static int _read_mqtt_packet(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_type) { +static int _read_mqtt_packet(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_type) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(timer, QCLOUD_ERR_INVAL); - uint32_t len = 0; - uint32_t rem_len = 0; - size_t read_len = 0; - int rc; - int timer_left_ms = left_ms(timer); - - if (timer_left_ms <= 0) { + uint32_t len = 0; + uint32_t rem_len = 0; + size_t read_len = 0; + int rc; + int timer_left_ms = left_ms(timer); + + if (timer_left_ms <= 0) { timer_left_ms = 1; } - // 1. 读取报文固定头部的第一个字节 + // 1. read 1st byte in fixed header and check if valid rc = pClient->network_stack.read(&(pClient->network_stack), pClient->read_buf, 1, timer_left_ms, &read_len); if (rc == QCLOUD_ERR_SSL_NOTHING_TO_READ || rc == QCLOUD_ERR_TCP_NOTHING_TO_READ) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NOTHING_TO_READ); - } else if (rc != QCLOUD_ERR_SUCCESS) { + } else if (rc != QCLOUD_RET_SUCCESS) { IOT_FUNC_EXIT_RC(rc); } len = 1; - // 2. 读取报文固定头部剩余长度部分 - timer_left_ms = left_ms(timer); + // 2. read the remaining length + timer_left_ms = left_ms(timer); if (timer_left_ms <= 0) { timer_left_ms = 1; } - timer_left_ms += QCLOUD_IOT_MQTT_MAX_REMAIN_WAIT_MS; //确保一包MQTT报文接收完 - + timer_left_ms += QCLOUD_IOT_MQTT_MAX_REMAIN_WAIT_MS; + rc = _decode_packet_rem_len_with_net_read(pClient, &rem_len, timer_left_ms); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } - // 如果读缓冲区的大小小于报文的剩余长度, 报文会被丢弃 + // if read buffer is not enough to read the remaining length, discard the packet if (rem_len >= pClient->read_buf_size) { - size_t total_bytes_read = 0; - size_t bytes_to_be_read; + size_t total_bytes_read = 0; + size_t bytes_to_be_read; int32_t ret_val = 0; - timer_left_ms = left_ms(timer); + timer_left_ms = left_ms(timer); if (timer_left_ms <= 0) { timer_left_ms = 1; } @@ -647,9 +640,9 @@ static int _read_mqtt_packet(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t * bytes_to_be_read = pClient->read_buf_size; do { - ret_val = pClient->network_stack.read(&(pClient->network_stack), pClient->read_buf, bytes_to_be_read, timer_left_ms, - &read_len); - if (ret_val == QCLOUD_ERR_SUCCESS) { + ret_val = pClient->network_stack.read(&(pClient->network_stack), pClient->read_buf, bytes_to_be_read, + timer_left_ms, &read_len); + if (ret_val == QCLOUD_RET_SUCCESS) { total_bytes_read += read_len; if ((rem_len - total_bytes_read) >= pClient->read_buf_size) { bytes_to_be_read = pClient->read_buf_size; @@ -657,81 +650,79 @@ static int _read_mqtt_packet(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t * bytes_to_be_read = rem_len - total_bytes_read; } } - } while (total_bytes_read < rem_len && ret_val == QCLOUD_ERR_SUCCESS); + } while (total_bytes_read < rem_len && ret_val == QCLOUD_RET_SUCCESS); Log_e("MQTT Recv buffer not enough: %d < %d", pClient->read_buf_size, rem_len); IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); } - // 将剩余长度写入读缓冲区 len += mqtt_write_packet_rem_len(pClient->read_buf + 1, rem_len); - // 3. 读取报文的剩余部分数据 + // 3. read payload according to remaining length if (rem_len > 0 && ((len + rem_len) > pClient->read_buf_size)) { - - timer_left_ms = left_ms(timer); + timer_left_ms = left_ms(timer); if (timer_left_ms <= 0) { timer_left_ms = 1; } timer_left_ms += QCLOUD_IOT_MQTT_MAX_REMAIN_WAIT_MS; - - pClient->network_stack.read(&(pClient->network_stack), pClient->read_buf, rem_len, timer_left_ms, &read_len); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); - } - else { - if (rem_len > 0) { - timer_left_ms = left_ms(timer); - if (timer_left_ms <= 0) { - timer_left_ms = 1; - } - timer_left_ms += QCLOUD_IOT_MQTT_MAX_REMAIN_WAIT_MS; - rc = pClient->network_stack.read(&(pClient->network_stack), pClient->read_buf + len, rem_len, timer_left_ms, &read_len); - if (rc != QCLOUD_ERR_SUCCESS) { - IOT_FUNC_EXIT_RC(rc); - } + pClient->network_stack.read(&(pClient->network_stack), pClient->read_buf, rem_len, timer_left_ms, &read_len); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); + } else { + if (rem_len > 0) { + timer_left_ms = left_ms(timer); + if (timer_left_ms <= 0) { + timer_left_ms = 1; + } + timer_left_ms += QCLOUD_IOT_MQTT_MAX_REMAIN_WAIT_MS; + rc = pClient->network_stack.read(&(pClient->network_stack), pClient->read_buf + len, rem_len, timer_left_ms, + &read_len); + if (rc != QCLOUD_RET_SUCCESS) { + IOT_FUNC_EXIT_RC(rc); + } } } - *packet_type = (pClient->read_buf[0]&MQTT_HEADER_TYPE_MASK)>>MQTT_HEADER_TYPE_SHIFT; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + *packet_type = (pClient->read_buf[0] & MQTT_HEADER_TYPE_MASK) >> MQTT_HEADER_TYPE_SHIFT; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * @brief 消息主题是否相同 + * @brief Check if two topic equals * * @param topic_filter * @param topicName * @return */ -static uint8_t _is_topic_equals(char *topic_filter, char *topicName) { - return (uint8_t) (strlen(topic_filter) == strlen(topicName) && !strcmp(topic_filter, topicName)); +static uint8_t _is_topic_equals(char *topic_filter, char *topicName) +{ + return (uint8_t)(strlen(topic_filter) == strlen(topicName) && !strcmp(topic_filter, topicName)); } /** - * @brief 消息主题匹配 + * @brief Check if topic match * * assume topic filter and name is in correct format * # can only be at end * + and # can only be next to separator * - * @param topic_filter 订阅消息的主题名 - * @param topicName 收到消息的主题名, 不能包含通配符 - * @param topicNameLen 主题名的长度 + * @param topic_filter topic name filter, wildcard is supported + * @param topicName topic name, no wildcard + * @param topicNameLen length of topic name * @return */ -static uint8_t _is_topic_matched(char *topic_filter, char *topicName, uint16_t topicNameLen) { +static uint8_t _is_topic_matched(char *topic_filter, char *topicName, uint16_t topicNameLen) +{ char *curf; char *curn; char *curn_end; - curf = topic_filter; - curn = topicName; + curf = topic_filter; + curn = topicName; curn_end = curn + topicNameLen; while (*curf && (curn < curn_end)) { - if (*curf == '+' && *curn == '/') { curf++; continue; @@ -748,8 +739,7 @@ static uint8_t _is_topic_matched(char *topic_filter, char *topicName, uint16_t t if (*curf == '+') { /* skip until we meet the next separator, or end of string */ char *nextpos = curn + 1; - while (nextpos < curn_end && *nextpos != '/') - nextpos = ++curn + 1; + while (nextpos < curn_end && *nextpos != '/') nextpos = ++curn + 1; } else if (*curf == '#') { /* skip until end of string */ curn = curn_end - 1; @@ -757,47 +747,44 @@ static uint8_t _is_topic_matched(char *topic_filter, char *topicName, uint16_t t curf++; curn++; - }; + } if (*curf == '\0') { - return (uint8_t) (curn == curn_end); + return (uint8_t)(curn == curn_end); } else { - return (uint8_t) ((*curf == '#') || *(curf + 1) == '#' || (*curf == '+' && *(curn - 1) == '/')); + return (uint8_t)((*curf == '#') || *(curf + 1) == '#' || (*curf == '+' && *(curn - 1) == '/')); } } /** - * @brief 终端收到服务器的的PUBLISH消息之后, 传递消息给消息回调处理函数 + * @brief deliver the message to user callback * * @param pClient * @param topicName * @param message * @return */ -static int _deliver_message(Qcloud_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, MQTTMessage *message) { +static int _deliver_message(Qcloud_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, MQTTMessage *message) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(topicName, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(message, QCLOUD_ERR_INVAL); - message->ptopic = topicName; + message->ptopic = topicName; message->topic_len = (size_t)topicNameLen; uint32_t i; - int flag_matched = 0; - HAL_MutexLock(pClient->lock_generic); for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { - if ((pClient->sub_handles[i].topic_filter != NULL) - && (_is_topic_equals(topicName, (char *) pClient->sub_handles[i].topic_filter) || - _is_topic_matched((char *) pClient->sub_handles[i].topic_filter, topicName, topicNameLen))) - { + if ((pClient->sub_handles[i].topic_filter != NULL) && + (_is_topic_equals(topicName, (char *)pClient->sub_handles[i].topic_filter) || + _is_topic_matched((char *)pClient->sub_handles[i].topic_filter, topicName, topicNameLen))) { HAL_MutexUnlock(pClient->lock_generic); if (pClient->sub_handles[i].message_handler != NULL) { - pClient->sub_handles[i].message_handler(pClient, message, pClient->sub_handles[i].message_handler_data); - flag_matched = 1; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + pClient->sub_handles[i].message_handler(pClient, message, pClient->sub_handles[i].handler_user_data); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } HAL_MutexLock(pClient->lock_generic); } @@ -807,25 +794,20 @@ static int _deliver_message(Qcloud_IoT_Client *pClient, char *topicName, uint16_ /* May be we do not care change FAILURE use SUCCESS*/ HAL_MutexUnlock(pClient->lock_generic); - if (0 == flag_matched) { - Log_d("no matching any topic, call default handle function"); + Log_d("no matching any topic, call default handle function"); - if (NULL != pClient->event_handle.h_fp) { - MQTTEventMsg msg; - msg.event_type = MQTT_EVENT_PUBLISH_RECVEIVED; - msg.msg = message; - pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); - } + if (NULL != pClient->event_handle.h_fp) { + MQTTEventMsg msg; + msg.event_type = MQTT_EVENT_PUBLISH_RECVEIVED; + msg.msg = message; + pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * @brief 从等待 publish ACK 的列表中,移除由 msdId 标记的元素 - * - * @param c - * @param msgId + * @brief remove node signed with msgId from publish ACK wait list * * @return 0, success; NOT 0, fail; */ @@ -839,13 +821,13 @@ static int _mask_pubInfo_from(Qcloud_IoT_Client *c, uint16_t msgId) HAL_MutexLock(c->lock_list_pub); if (c->list_pub_wait_ack->len) { - ListIterator *iter; - ListNode *node = NULL; + ListIterator * iter; + ListNode * node = NULL; QcloudIotPubInfo *repubInfo = NULL; if (NULL == (iter = list_iterator_new(c->list_pub_wait_ack, LIST_TAIL))) { HAL_MutexUnlock(c->lock_list_pub); - return QCLOUD_ERR_SUCCESS; + return QCLOUD_RET_SUCCESS; } for (;;) { @@ -855,14 +837,14 @@ static int _mask_pubInfo_from(Qcloud_IoT_Client *c, uint16_t msgId) break; } - repubInfo = (QcloudIotPubInfo *) node->val; + repubInfo = (QcloudIotPubInfo *)node->val; if (NULL == repubInfo) { Log_e("node's value is invalid!"); continue; } if (repubInfo->msg_id == msgId) { - repubInfo->node_state = MQTT_NODE_STATE_INVALID; /* 标记为无效节点 */ + repubInfo->node_state = MQTT_NODE_STATE_INVALID; /* set as invalid node */ } } @@ -870,12 +852,14 @@ static int _mask_pubInfo_from(Qcloud_IoT_Client *c, uint16_t msgId) } HAL_MutexUnlock(c->lock_list_pub); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -/* 从等待 subscribe(unsubscribe) ACK 的列表中,移除由 msdId 标记的元素 */ -/* 同时返回消息处理数据 messageHandler */ -/* return: 0, success; NOT 0, fail; */ +/** + * @brief remove node signed with msgId from subscribe ACK wait list, and return the msg handler + * + * @return 0, success; NOT 0, fail; + */ static int _mask_sub_info_from(Qcloud_IoT_Client *c, unsigned int msgId, SubTopicHandle *messageHandler) { IOT_FUNC_ENTRY; @@ -886,13 +870,13 @@ static int _mask_sub_info_from(Qcloud_IoT_Client *c, unsigned int msgId, SubTopi HAL_MutexLock(c->lock_list_sub); if (c->list_sub_wait_ack->len) { - ListIterator *iter; - ListNode *node = NULL; + ListIterator * iter; + ListNode * node = NULL; QcloudIotSubInfo *sub_info = NULL; if (NULL == (iter = list_iterator_new(c->list_sub_wait_ack, LIST_TAIL))) { HAL_MutexUnlock(c->lock_list_sub); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } for (;;) { @@ -901,28 +885,25 @@ static int _mask_sub_info_from(Qcloud_IoT_Client *c, unsigned int msgId, SubTopi break; } - sub_info = (QcloudIotSubInfo *) node->val; + sub_info = (QcloudIotSubInfo *)node->val; if (NULL == sub_info) { Log_e("node's value is invalid!"); continue; } if (sub_info->msg_id == msgId) { - *messageHandler = sub_info->handler; /* return handle */ + *messageHandler = sub_info->handler; /* return handle */ sub_info->node_state = MQTT_NODE_STATE_INVALID; /* mark as invalid node */ - } + } } list_iterator_destroy(iter); } HAL_MutexUnlock(c->lock_list_sub); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -/** - * @brief 终端收到服务器的的PUBACK消息之后, 处理收到的PUBACK报文 - */ static int _handle_puback_packet(Qcloud_IoT_Client *pClient, Timer *timer) { IOT_FUNC_ENTRY; @@ -930,30 +911,27 @@ static int _handle_puback_packet(Qcloud_IoT_Client *pClient, Timer *timer) POINTER_SANITY_CHECK(timer, QCLOUD_ERR_INVAL); uint16_t packet_id; - uint8_t dup, type; - int rc; + uint8_t dup, type; + int rc; rc = deserialize_ack_packet(&type, &dup, &packet_id, pClient->read_buf, pClient->read_buf_size); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } (void)_mask_pubInfo_from(pClient, packet_id); - /* 调用回调函数,通知外部PUBLISH成功. */ + /* notify this event to user callback */ if (NULL != pClient->event_handle.h_fp) { MQTTEventMsg msg; msg.event_type = MQTT_EVENT_PUBLISH_SUCCESS; - msg.msg = (void *)(uintptr_t)packet_id; + msg.msg = (void *)(uintptr_t)packet_id; pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -/** - * @brief 终端收到服务器的的 SUBACK 消息之后, 处理收到的 SUBACK 报文 - */ static int _handle_suback_packet(Qcloud_IoT_Client *pClient, Timer *timer, QoS qos) { IOT_FUNC_ENTRY; @@ -961,47 +939,50 @@ static int _handle_suback_packet(Qcloud_IoT_Client *pClient, Timer *timer, QoS q POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(timer, QCLOUD_ERR_INVAL); - uint32_t count = 0; - uint16_t packet_id = 0; - QoS grantedQoS[3] = {QOS0, QOS0, QOS0}; - int rc; - bool sub_nack = false; - - // 反序列化SUBACK报文 + uint32_t count = 0; + uint16_t packet_id = 0; + QoS grantedQoS[3] = {QOS0, QOS0, QOS0}; + int rc; + bool sub_nack = false; + rc = deserialize_suback_packet(&packet_id, 1, &count, grantedQoS, pClient->read_buf, pClient->read_buf_size); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } int flag_dup = 0, i_free = -1; - // 检查SUBACK报文中的返回码:0x00(QOS0, SUCCESS),0x01(QOS1, SUCCESS),0x02(QOS2, SUCCESS),0x80(Failure) + // check return code in SUBACK packet: 0x00(QOS0, SUCCESS),0x01(QOS1, SUCCESS),0x02(QOS2, SUCCESS),0x80(Failure) if (grantedQoS[0] == 0x80) { - MQTTEventMsg msg; + MQTTEventMsg msg; msg.event_type = MQTT_EVENT_SUBCRIBE_NACK; - msg.msg = (void *)(uintptr_t)packet_id; + msg.msg = (void *)(uintptr_t)packet_id; pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); sub_nack = true; } HAL_MutexLock(pClient->lock_generic); - + SubTopicHandle sub_handle; memset(&sub_handle, 0, sizeof(SubTopicHandle)); (void)_mask_sub_info_from(pClient, (unsigned int)packet_id, &sub_handle); - if (/*(NULL == sub_handle.message_handler) || */(NULL == sub_handle.topic_filter)) { + if (/*(NULL == sub_handle.message_handler) || */ (NULL == sub_handle.topic_filter)) { Log_e("sub_handle is illegal, topic is null"); HAL_MutexUnlock(pClient->lock_generic); IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_SUB); } if (sub_nack) { + HAL_MutexUnlock(pClient->lock_generic); Log_e("MQTT SUBSCRIBE failed, packet_id: %u topic: %s", packet_id, sub_handle.topic_filter); + /* notify this event to topic subscriber */ + if (NULL != sub_handle.sub_event_handler) + sub_handle.sub_event_handler(pClient, MQTT_EVENT_SUBCRIBE_NACK, sub_handle.handler_user_data); + HAL_Free((void *)sub_handle.topic_filter); sub_handle.topic_filter = NULL; - HAL_MutexUnlock(pClient->lock_generic); IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_SUB); } @@ -1009,9 +990,13 @@ static int _handle_suback_packet(Qcloud_IoT_Client *pClient, Timer *timer, QoS q for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { if ((NULL != pClient->sub_handles[i].topic_filter)) { if (0 == _check_handle_is_identical(&pClient->sub_handles[i], &sub_handle)) { - flag_dup = 1; - Log_w("There is a identical topic and related handle in list!"); + Log_w("Identical topic found: %s", sub_handle.topic_filter); + if (pClient->sub_handles[i].handler_user_data != sub_handle.handler_user_data) { + Log_w("Update handler_user_data %p -> %p!", pClient->sub_handles[i].handler_user_data, + sub_handle.handler_user_data); + pClient->sub_handles[i].handler_user_data = sub_handle.handler_user_data; + } HAL_Free((void *)sub_handle.topic_filter); sub_handle.topic_filter = NULL; break; @@ -1029,30 +1014,32 @@ static int _handle_suback_packet(Qcloud_IoT_Client *pClient, Timer *timer, QoS q HAL_MutexUnlock(pClient->lock_generic); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } else { - pClient->sub_handles[i_free].topic_filter = sub_handle.topic_filter; - pClient->sub_handles[i_free].message_handler = sub_handle.message_handler; - pClient->sub_handles[i_free].qos = sub_handle.qos; - pClient->sub_handles[i_free].message_handler_data = sub_handle.message_handler_data; + pClient->sub_handles[i_free].topic_filter = sub_handle.topic_filter; + pClient->sub_handles[i_free].message_handler = sub_handle.message_handler; + pClient->sub_handles[i_free].sub_event_handler = sub_handle.sub_event_handler; + pClient->sub_handles[i_free].qos = sub_handle.qos; + pClient->sub_handles[i_free].handler_user_data = sub_handle.handler_user_data; } } - + HAL_MutexUnlock(pClient->lock_generic); - /* 调用回调函数,通知外部 SUBSCRIBE 成功. */ + /* notify this event to user callback */ if (NULL != pClient->event_handle.h_fp) { MQTTEventMsg msg; msg.event_type = MQTT_EVENT_SUBCRIBE_SUCCESS; - msg.msg = (void *)(uintptr_t)packet_id; + msg.msg = (void *)(uintptr_t)packet_id; if (pClient->event_handle.h_fp != NULL) pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + /* notify this event to topic subscriber */ + if (NULL != sub_handle.sub_event_handler) + sub_handle.sub_event_handler(pClient, MQTT_EVENT_SUBCRIBE_SUCCESS, sub_handle.handler_user_data); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -/** - * @brief 终端收到服务器的的 USUBACK 消息之后, 处理收到的 USUBACK 报文 - */ static int _handle_unsuback_packet(Qcloud_IoT_Client *pClient, Timer *timer) { IOT_FUNC_ENTRY; @@ -1062,8 +1049,8 @@ static int _handle_unsuback_packet(Qcloud_IoT_Client *pClient, Timer *timer) uint16_t packet_id = 0; - int rc = deserialize_unsuback_packet(&packet_id, pClient->read_buf, pClient->read_buf_size); - if (rc != QCLOUD_ERR_SUCCESS) { + int rc = deserialize_unsuback_packet(&packet_id, pClient->read_buf, pClient->read_buf_size); + if (rc != QCLOUD_RET_SUCCESS) { IOT_FUNC_EXIT_RC(rc); } @@ -1073,20 +1060,6 @@ static int _handle_unsuback_packet(Qcloud_IoT_Client *pClient, Timer *timer) /* Remove from message handler array */ HAL_MutexLock(pClient->lock_generic); - /* actually below code is nonsense as unsub handle is different with sub handle even the same topic_filter*/ - #if 0 - int i; - for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { - if ((pClient->sub_handles[i].topic_filter != NULL) - && (0 == _check_handle_is_identical(&pClient->sub_handles[i], &messageHandler))) { - memset(&pClient->sub_handles[i], 0, sizeof(SubTopicHandle)); - - /* NOTE: in case of more than one register(subscribe) with different callback function, - * so we must keep continuously searching related message handle. */ - } - } - #endif - /* Free the topic filter malloced in qcloud_iot_mqtt_unsubscribe */ if (messageHandler.topic_filter) { HAL_Free((void *)messageHandler.topic_filter); @@ -1096,90 +1069,79 @@ static int _handle_unsuback_packet(Qcloud_IoT_Client *pClient, Timer *timer) if (NULL != pClient->event_handle.h_fp) { MQTTEventMsg msg; msg.event_type = MQTT_EVENT_UNSUBCRIBE_SUCCESS; - msg.msg = (void *)(uintptr_t)packet_id; + msg.msg = (void *)(uintptr_t)packet_id; pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); } HAL_MutexUnlock(pClient->lock_generic); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } #ifdef MQTT_RMDUP_MSG_ENABLED -#define MQTT_MAX_REPEAT_BUF_LEN 50 -static uint16_t sg_repeat_packet_id_buf[MQTT_MAX_REPEAT_BUF_LEN]; - -/** - * @brief 判断packet_id缓存中是否已经存有传入的packet_id; - */ -static int _get_packet_id_in_repeat_buf(uint16_t packet_id) +static int _get_packet_id_in_repeat_buf(Qcloud_IoT_Client *pClient, uint16_t packet_id) { int i; - for (i = 0; i < MQTT_MAX_REPEAT_BUF_LEN; ++i) - { - if (packet_id == sg_repeat_packet_id_buf[i]) - { + for (i = 0; i < MQTT_MAX_REPEAT_BUF_LEN; ++i) { + if (packet_id == pClient->repeat_packet_id_buf[i]) { return packet_id; } } return -1; } -static void _add_packet_id_to_repeat_buf(uint16_t packet_id) +static void _add_packet_id_to_repeat_buf(Qcloud_IoT_Client *pClient, uint16_t packet_id) { - static unsigned int current_packet_id_cnt = 0; - if (_get_packet_id_in_repeat_buf(packet_id) < 0) + if (_get_packet_id_in_repeat_buf(pClient, packet_id) > 0) return; - sg_repeat_packet_id_buf[current_packet_id_cnt++] = packet_id; + pClient->repeat_packet_id_buf[pClient->current_packet_id_cnt++] = packet_id; - if (current_packet_id_cnt >= MQTT_MAX_REPEAT_BUF_LEN) - current_packet_id_cnt = current_packet_id_cnt % 50; + if (pClient->current_packet_id_cnt >= MQTT_MAX_REPEAT_BUF_LEN) + pClient->current_packet_id_cnt %= MQTT_MAX_REPEAT_BUF_LEN; } -void reset_repeat_packet_id_buffer(void) +void reset_repeat_packet_id_buffer(Qcloud_IoT_Client *pClient) { int i; - for (i = 0; i < MQTT_MAX_REPEAT_BUF_LEN; ++i) - { - sg_repeat_packet_id_buf[i] = 0; + for (i = 0; i < MQTT_MAX_REPEAT_BUF_LEN; ++i) { + pClient->repeat_packet_id_buf[i] = 0; } + pClient->current_packet_id_cnt = 0; } #endif -/** - * @brief 终端收到服务器的的PUBLISH消息之后, 处理收到的PUBLISH报文 - */ -static int _handle_publish_packet(Qcloud_IoT_Client *pClient, Timer *timer) { +static int _handle_publish_packet(Qcloud_IoT_Client *pClient, Timer *timer) +{ IOT_FUNC_ENTRY; - char *topic_name; - uint16_t topic_len; + char * topic_name; + uint16_t topic_len; MQTTMessage msg; - int rc; - uint32_t len = 0; + int rc; + uint32_t len = 0; - rc = deserialize_publish_packet(&msg.dup, &msg.qos, &msg.retained, &msg.id, &topic_name, &topic_len, (unsigned char **) &msg.payload, - &msg.payload_len, pClient->read_buf, pClient->read_buf_size); - if (QCLOUD_ERR_SUCCESS != rc) { + rc = deserialize_publish_packet(&msg.dup, &msg.qos, &msg.retained, &msg.id, &topic_name, &topic_len, + (unsigned char **)&msg.payload, &msg.payload_len, pClient->read_buf, + pClient->read_buf_size); + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } - - // 传过来的topicName没有截断,会把payload也带过来 + + // topicName from packet is NOT null terminated char fix_topic[MAX_SIZE_OF_CLOUD_TOPIC] = {0}; - - if(topic_len > MAX_SIZE_OF_CLOUD_TOPIC){ - topic_len = MAX_SIZE_OF_CLOUD_TOPIC - 1; - Log_e("topic len exceed buffer len"); - } + + if (topic_len > MAX_SIZE_OF_CLOUD_TOPIC) { + topic_len = MAX_SIZE_OF_CLOUD_TOPIC - 1; + Log_e("topic len exceed buffer len"); + } memcpy(fix_topic, topic_name, topic_len); - if (QOS0 == msg.qos) - { + if (QOS0 == msg.qos) { rc = _deliver_message(pClient, fix_topic, topic_len, &msg); - if (QCLOUD_ERR_SUCCESS != rc) + if (QCLOUD_RET_SUCCESS != rc) IOT_FUNC_EXIT_RC(rc); /* No further processing required for QOS0 */ @@ -1187,88 +1149,77 @@ static int _handle_publish_packet(Qcloud_IoT_Client *pClient, Timer *timer) { } else { #ifdef MQTT_RMDUP_MSG_ENABLED - // 判断packet_id之前是否已经收到过 - int repeat_id = _get_packet_id_in_repeat_buf(msg.id); + // check if packet_id has been received before + int repeat_id = _get_packet_id_in_repeat_buf(pClient, msg.id); - // 执行订阅消息的回调函数 - if (repeat_id < 0) - { + // deliver to msg callback + if (repeat_id < 0) { #endif rc = _deliver_message(pClient, fix_topic, topic_len, &msg); - if (QCLOUD_ERR_SUCCESS != rc) + if (QCLOUD_RET_SUCCESS != rc) IOT_FUNC_EXIT_RC(rc); #ifdef MQTT_RMDUP_MSG_ENABLED } - _add_packet_id_to_repeat_buf(msg.id); + _add_packet_id_to_repeat_buf(pClient, msg.id); #endif } - + HAL_MutexLock(pClient->lock_write_buf); if (QOS1 == msg.qos) { rc = serialize_pub_ack_packet(pClient->write_buf, pClient->write_buf_size, PUBACK, 0, msg.id, &len); - } else { /* Message is not QOS0 or 1 means only option left is QOS2 */ + } else { /* Message is not QOS0 or QOS1 means only option left is QOS2 */ rc = serialize_pub_ack_packet(pClient->write_buf, pClient->write_buf_size, PUBREC, 0, msg.id, &len); } - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } rc = send_mqtt_packet(pClient, len, timer); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } HAL_MutexUnlock(pClient->lock_write_buf); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -/** - * @brief 处理PUBREC报文, 并发送PUBREL报文, PUBLISH报文为QOS2时 - * - * @param pClient - * @param timer - * @return - */ -static int _handle_pubrec_packet(Qcloud_IoT_Client *pClient, Timer *timer) { +static int _handle_pubrec_packet(Qcloud_IoT_Client *pClient, Timer *timer) +{ IOT_FUNC_ENTRY; - uint16_t packet_id; + uint16_t packet_id; unsigned char dup, type; - int rc; - uint32_t len; + int rc; + uint32_t len; rc = deserialize_ack_packet(&type, &dup, &packet_id, pClient->read_buf, pClient->read_buf_size); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } HAL_MutexLock(pClient->lock_write_buf); rc = serialize_pub_ack_packet(pClient->write_buf, pClient->write_buf_size, PUBREL, 0, packet_id, &len); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } /* send the PUBREL packet */ rc = send_mqtt_packet(pClient, len, timer); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { HAL_MutexUnlock(pClient->lock_write_buf); /* there was a problem */ IOT_FUNC_EXIT_RC(rc); } HAL_MutexUnlock(pClient->lock_write_buf); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -/** - * @brief 处理服务器的心跳包回包 - * - * @param pClient - */ -static void _handle_pingresp_packet(Qcloud_IoT_Client *pClient) { +static void _handle_pingresp_packet(Qcloud_IoT_Client *pClient) +{ IOT_FUNC_ENTRY; HAL_MutexLock(pClient->lock_generic); @@ -1279,7 +1230,8 @@ static void _handle_pingresp_packet(Qcloud_IoT_Client *pClient) { IOT_FUNC_EXIT; } -int cycle_for_read(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_type, QoS qos) { +int cycle_for_read(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_type, QoS qos) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); @@ -1290,10 +1242,10 @@ int cycle_for_read(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_typ rc = _read_mqtt_packet(pClient, timer, packet_type); if (QCLOUD_ERR_MQTT_NOTHING_TO_READ == rc) { /* Nothing to read, not a cycle failure */ - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } @@ -1323,29 +1275,29 @@ int cycle_for_read(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_typ } case PUBCOMP: break; - case PINGRESP: + case PINGRESP: break; default: { /* Either unknown packet type or Failure occurred * Should not happen */ - + IOT_FUNC_EXIT_RC(QCLOUD_ERR_RX_MESSAGE_INVAL); break; } } - switch (*packet_type) { + switch (*packet_type) { /* Recv below msgs are all considered as PING OK */ case PUBACK: case SUBACK: - case UNSUBACK: + case UNSUBACK: case PINGRESP: { _handle_pingresp_packet(pClient); break; } /* Recv downlink pub means link is OK but we still need to send PING request */ case PUBLISH: { - HAL_MutexLock(pClient->lock_generic); + HAL_MutexLock(pClient->lock_generic); pClient->is_ping_outstanding = 0; HAL_MutexUnlock(pClient->lock_generic); break; @@ -1355,55 +1307,56 @@ int cycle_for_read(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_typ IOT_FUNC_EXIT_RC(rc); } -int wait_for_read(Qcloud_IoT_Client *pClient, uint8_t packet_type, Timer *timer, QoS qos) { - IOT_FUNC_ENTRY; - int rc; - uint8_t read_packet_type = 0; +int wait_for_read(Qcloud_IoT_Client *pClient, uint8_t packet_type, Timer *timer, QoS qos) +{ + IOT_FUNC_ENTRY; + int rc; + uint8_t read_packet_type = 0; - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(timer, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(timer, QCLOUD_ERR_INVAL); - do { - if (expired(timer)) { - rc = QCLOUD_ERR_MQTT_REQUEST_TIMEOUT; - break; - } - rc = cycle_for_read(pClient, timer, &read_packet_type, qos); - } while (QCLOUD_ERR_SUCCESS == rc && read_packet_type != packet_type ); + do { + if (expired(timer)) { + rc = QCLOUD_ERR_MQTT_REQUEST_TIMEOUT; + break; + } + rc = cycle_for_read(pClient, timer, &read_packet_type, qos); + } while (QCLOUD_RET_SUCCESS == rc && read_packet_type != packet_type); - IOT_FUNC_EXIT_RC(rc); + IOT_FUNC_EXIT_RC(rc); } -void set_client_conn_state(Qcloud_IoT_Client *pClient, uint8_t connected) { +void set_client_conn_state(Qcloud_IoT_Client *pClient, uint8_t connected) +{ HAL_MutexLock(pClient->lock_generic); pClient->is_connected = connected; HAL_MutexUnlock(pClient->lock_generic); } -uint8_t get_client_conn_state(Qcloud_IoT_Client *pClient) { +uint8_t get_client_conn_state(Qcloud_IoT_Client *pClient) +{ IOT_FUNC_ENTRY; - uint8_t is_connected = 0; - HAL_MutexLock(pClient->lock_generic); - is_connected = pClient->is_connected; - HAL_MutexUnlock(pClient->lock_generic); + uint8_t is_connected = 0; + HAL_MutexLock(pClient->lock_generic); + is_connected = pClient->is_connected; + HAL_MutexUnlock(pClient->lock_generic); IOT_FUNC_EXIT_RC(is_connected); } /* - * @brief 向 subscribe(unsubscribe) ACK 等待列表中添加元素 - * + * @brief push node to subscribe(unsubscribe) ACK wait list * * return: 0, success; NOT 0, fail; */ -int push_sub_info_to(Qcloud_IoT_Client *c, int len, unsigned short msgId, MessageTypes type, - SubTopicHandle *handler, ListNode **node) +int push_sub_info_to(Qcloud_IoT_Client *c, int len, unsigned short msgId, MessageTypes type, SubTopicHandle *handler, + ListNode **node) { IOT_FUNC_ENTRY; if (!c || !handler || !node) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); } - HAL_MutexLock(c->lock_list_sub); if (c->list_sub_wait_ack->len >= MAX_MESSAGE_HANDLERS) { @@ -1412,30 +1365,30 @@ int push_sub_info_to(Qcloud_IoT_Client *c, int len, unsigned short msgId, Messag IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_MAX_SUBSCRIPTIONS); } - QcloudIotSubInfo *sub_info = (QcloudIotSubInfo *)HAL_Malloc(sizeof( - QcloudIotSubInfo) + len); + QcloudIotSubInfo *sub_info = (QcloudIotSubInfo *)HAL_Malloc(sizeof(QcloudIotSubInfo) + len); if (NULL == sub_info) { HAL_MutexUnlock(c->lock_list_sub); Log_e("malloc failed!"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - + sub_info->node_state = MQTT_NODE_STATE_NORMANL; - sub_info->msg_id = msgId; - sub_info->len = len; + sub_info->msg_id = msgId; + sub_info->len = len; InitTimer(&sub_info->sub_start_time); countdown_ms(&sub_info->sub_start_time, c->command_timeout_ms); - sub_info->type = type; + sub_info->type = type; sub_info->handler = *handler; - sub_info->buf = (unsigned char *)sub_info + sizeof(QcloudIotSubInfo); + sub_info->buf = (unsigned char *)sub_info + sizeof(QcloudIotSubInfo); memcpy(sub_info->buf, c->write_buf, len); *node = list_node_new(sub_info); if (NULL == *node) { HAL_MutexUnlock(c->lock_list_sub); + HAL_Free(sub_info); Log_e("list_node_new failed!"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } @@ -1444,7 +1397,7 @@ int push_sub_info_to(Qcloud_IoT_Client *c, int len, unsigned short msgId, Messag HAL_MutexUnlock(c->lock_list_sub); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } #ifdef __cplusplus diff --git a/src/mqtt/src/mqtt_client_connect.c b/sdk_src/protocol/mqtt/mqtt_client_connect.c similarity index 53% rename from src/mqtt/src/mqtt_client_connect.c rename to sdk_src/protocol/mqtt/mqtt_client_connect.c index 09a78183..935e717f 100644 --- a/src/mqtt/src/mqtt_client_connect.c +++ b/sdk_src/protocol/mqtt/mqtt_client_connect.c @@ -18,43 +18,44 @@ extern "C" { #endif -#include #include +#include #include "mqtt_client.h" +#include "qcloud_iot_common.h" #include "utils_hmac.h" +#define MQTT_CONNECT_FLAG_USERNAME 0x80 +#define MQTT_CONNECT_FLAG_PASSWORD 0x40 +#define MQTT_CONNECT_FLAG_WILL_RETAIN 0x20 +#define MQTT_CONNECT_FLAG_WILL_QOS2 0x18 +#define MQTT_CONNECT_FLAG_WILL_QOS1 0x08 +#define MQTT_CONNECT_FLAG_WILL_QOS0 0x00 +#define MQTT_CONNECT_FLAG_WILL_FLAG 0x04 +#define MQTT_CONNECT_FLAG_CLEAN_SES 0x02 -#define MQTT_CONNECT_FLAG_USERNAME 0x80 -#define MQTT_CONNECT_FLAG_PASSWORD 0x40 -#define MQTT_CONNECT_FLAG_WILL_RETAIN 0x20 -#define MQTT_CONNECT_FLAG_WILL_QOS2 0x18 -#define MQTT_CONNECT_FLAG_WILL_QOS1 0x08 -#define MQTT_CONNECT_FLAG_WILL_QOS0 0x00 -#define MQTT_CONNECT_FLAG_WILL_FLAG 0x04 -#define MQTT_CONNECT_FLAG_CLEAN_SES 0x02 - -#define MQTT_CONNACK_FLAG_SES_PRE 0x01 +#define MQTT_CONNACK_FLAG_SES_PRE 0x01 /** * Connect return code */ typedef enum { - CONNACK_CONNECTION_ACCEPTED = 0, // connection accepted - CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1, // connection refused: unaccpeted protocol verison - CONNACK_IDENTIFIER_REJECTED_ERROR = 2, // connection refused: identifier rejected - CONNACK_SERVER_UNAVAILABLE_ERROR = 3, // connection refused: server unavailable - CONNACK_BAD_USERDATA_ERROR = 4, // connection refused: bad user name or password - CONNACK_NOT_AUTHORIZED_ERROR = 5 // connection refused: not authorized + CONNACK_CONNECTION_ACCEPTED = 0, // connection accepted + CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1, // connection refused: unaccpeted protocol verison + CONNACK_IDENTIFIER_REJECTED_ERROR = 2, // connection refused: identifier rejected + CONNACK_SERVER_UNAVAILABLE_ERROR = 3, // connection refused: server unavailable + CONNACK_BAD_USERDATA_ERROR = 4, // connection refused: bad user name or password + CONNACK_NOT_AUTHORIZED_ERROR = 5 // connection refused: not authorized } MQTTConnackReturnCodes; /** - * Determines the length of the MQTT connect packet that would be produced using the supplied connect options. - * @param options the options to be used to build the connect packet - * @param the length of buffer needed to contain the serialized version of the packet - * @return int indicating function execution status - */ -static uint32_t _get_packet_connect_rem_len(MQTTConnectParams *options) { + * Determines the length of the MQTT connect packet that would be produced using the supplied connect options. + * @param options the options to be used to build the connect packet + * @param the length of buffer needed to contain the serialized version of the packet + * @return int indicating function execution status + */ +static uint32_t _get_packet_connect_rem_len(MQTTConnectParams *options) +{ size_t len = 0; /* variable depending on MQTT or MQIsdp */ if (3 == options->mqtt_version) { @@ -73,35 +74,42 @@ static uint32_t _get_packet_connect_rem_len(MQTTConnectParams *options) { len += strlen(options->password) + 2; } - return (uint32_t) len; + return (uint32_t)len; } -static void _copy_connect_params(MQTTConnectParams *destination, MQTTConnectParams *source) { +static void _copy_connect_params(MQTTConnectParams *destination, MQTTConnectParams *source) +{ + POINTER_SANITY_CHECK_RTN(destination); + POINTER_SANITY_CHECK_RTN(source); - POINTER_SANITY_CHECK_RTN(destination); - POINTER_SANITY_CHECK_RTN(source); + /* In case of reconnecting, source == destination */ + if (source == destination) { + return; + } - destination->mqtt_version = source->mqtt_version; - destination->client_id = source->client_id; - destination->username = source->username; + destination->mqtt_version = source->mqtt_version; + destination->client_id = source->client_id; + destination->username = source->username; destination->keep_alive_interval = source->keep_alive_interval; - destination->clean_session = source->clean_session; + destination->clean_session = source->clean_session; destination->auto_connect_enable = source->auto_connect_enable; #ifdef AUTH_WITH_NOTLS - destination->device_secret = source->device_secret; + destination->device_secret = source->device_secret; destination->device_secret_len = source->device_secret_len; #endif } /** - * Serializes the connect options into the buffer. - * @param buf the buffer into which the packet will be serialized - * @param len the length in bytes of the supplied buffer - * @param options the options to be used to build the connect packet - * @param serialized length - * @return int indicating function execution status - */ -static int _serialize_connect_packet(unsigned char *buf, size_t buf_len, MQTTConnectParams *options, uint32_t *serialized_len) { + * Serializes the connect options into the buffer. + * @param buf the buffer into which the packet will be serialized + * @param len the length in bytes of the supplied buffer + * @param options the options to be used to build the connect packet + * @param serialized length + * @return int indicating function execution status + */ +static int _serialize_connect_packet(unsigned char *buf, size_t buf_len, MQTTConnectParams *options, + uint32_t *serialized_len) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); @@ -109,134 +117,158 @@ static int _serialize_connect_packet(unsigned char *buf, size_t buf_len, MQTTCon STRING_PTR_SANITY_CHECK(options->client_id, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL); - unsigned char *ptr = buf; - unsigned char header = 0; - unsigned char flags = 0; - uint32_t rem_len = 0; - int rc; + unsigned char *ptr = buf; + unsigned char header = 0; + unsigned char flags = 0; + uint32_t rem_len = 0; + int rc; long cur_timesec = HAL_Timer_current_sec() + MAX_ACCESS_EXPIRE_TIMEOUT / 1000; if (cur_timesec <= 0 || MAX_ACCESS_EXPIRE_TIMEOUT <= 0) { - cur_timesec = LONG_MAX; + cur_timesec = LONG_MAX; } long cur_timesec_bak = cur_timesec; - int cur_timesec_len = 0; - while(cur_timesec_bak != 0) { - cur_timesec_bak /= 10; - ++cur_timesec_len; - } - - int username_len = strlen(options->client_id) + strlen(QCLOUD_IOT_DEVICE_SDK_APPID) + MAX_CONN_ID_LEN + cur_timesec_len + 4; - options->username = (char*)HAL_Malloc(username_len); + int cur_timesec_len = 0; + while (cur_timesec_bak != 0) { + cur_timesec_bak /= 10; + ++cur_timesec_len; + } + + int username_len = + strlen(options->client_id) + strlen(QCLOUD_IOT_DEVICE_SDK_APPID) + MAX_CONN_ID_LEN + cur_timesec_len + 4; + options->username = (char *)HAL_Malloc(username_len); + if (options->username == NULL) { + Log_e("malloc username failed!"); + rc = QCLOUD_ERR_MALLOC; + goto err_exit; + } + get_next_conn_id(options->conn_id); - HAL_Snprintf(options->username, username_len, "%s;%s;%s;%ld", options->client_id, QCLOUD_IOT_DEVICE_SDK_APPID, options->conn_id, cur_timesec); + HAL_Snprintf(options->username, username_len, "%s;%s;%s;%ld", options->client_id, QCLOUD_IOT_DEVICE_SDK_APPID, + options->conn_id, cur_timesec); #if defined(AUTH_WITH_NOTLS) && defined(AUTH_MODE_KEY) - if (options->device_secret != NULL && options->username != NULL) { - char sign[41] = {0}; - utils_hmac_sha1(options->username, strlen(options->username), sign, options->device_secret, options->device_secret_len); - options->password = (char*) HAL_Malloc (51); - if (options->password == NULL) IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - HAL_Snprintf(options->password, 51, "%s;hmacsha1", sign); - } + if (options->device_secret != NULL && options->username != NULL) { + char sign[41] = {0}; + utils_hmac_sha1(options->username, strlen(options->username), sign, options->device_secret, + options->device_secret_len); + options->password = (char *)HAL_Malloc(51); + if (options->password == NULL) { + Log_e("malloc password failed!"); + rc = QCLOUD_ERR_MALLOC; + goto err_exit; + } + HAL_Snprintf(options->password, 51, "%s;hmacsha1", sign); + } #endif rem_len = _get_packet_connect_rem_len(options); if (get_mqtt_packet_len(rem_len) > buf_len) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); + Log_e("get_mqtt_packet_len failed!"); + rc = QCLOUD_ERR_BUF_TOO_SHORT; + goto err_exit; } rc = mqtt_init_packet_header(&header, CONNECT, QOS0, 0, 0); - if (QCLOUD_ERR_SUCCESS != rc) { - IOT_FUNC_EXIT_RC(rc); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("mqtt_init_packet_header failed!"); + goto err_exit; } - // 报文固定头部第一个字节 + // 1st byte in fixed header mqtt_write_char(&ptr, header); - // 报文固定头部剩余长度字段 + // remaining length ptr += mqtt_write_packet_rem_len(ptr, rem_len); - // 报文可变头部协议名 + 协议版本号 + // MQTT protocol name and version in variable header if (4 == options->mqtt_version) { mqtt_write_utf8_string(&ptr, "MQTT"); - mqtt_write_char(&ptr, (unsigned char) 4); + mqtt_write_char(&ptr, (unsigned char)4); } else { mqtt_write_utf8_string(&ptr, "MQIsdp"); - mqtt_write_char(&ptr, (unsigned char) 3); + mqtt_write_char(&ptr, (unsigned char)3); } - // 报文可变头部连接标识位 - + // flags in variable header flags |= (options->clean_session) ? MQTT_CONNECT_FLAG_CLEAN_SES : 0; flags |= (options->username != NULL) ? MQTT_CONNECT_FLAG_USERNAME : 0; #if defined(AUTH_WITH_NOTLS) && defined(AUTH_MODE_KEY) - flags |= MQTT_CONNECT_FLAG_PASSWORD; + flags |= MQTT_CONNECT_FLAG_PASSWORD; #endif - + mqtt_write_char(&ptr, flags); - // 报文可变头部心跳周期/保持连接, 一个以秒为单位的时间间隔, 表示为一个16位的字 + // keep alive interval (unit:ms) in variable header mqtt_write_uint_16(&ptr, options->keep_alive_interval); - // 有效负载部分: 客户端标识符 + // client id mqtt_write_utf8_string(&ptr, options->client_id); - // 用户名 if ((flags & MQTT_CONNECT_FLAG_USERNAME) && options->username != NULL) { mqtt_write_utf8_string(&ptr, options->username); HAL_Free(options->username); + options->username = NULL; } if ((flags & MQTT_CONNECT_FLAG_PASSWORD) && options->password != NULL) { - mqtt_write_utf8_string(&ptr, options->password); - HAL_Free(options->password); + mqtt_write_utf8_string(&ptr, options->password); + HAL_Free(options->password); + options->password = NULL; } - *serialized_len = (uint32_t) (ptr - buf); + *serialized_len = (uint32_t)(ptr - buf); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); + +err_exit: + HAL_Free(options->username); + options->username = NULL; + + HAL_Free(options->password); + options->password = NULL; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(rc); } /** - * Deserializes the supplied (wire) buffer into connack data - return code - * @param sessionPresent the session present flag returned (only for MQTT 3.1.1) - * @param connack_rc returned integer value of the connack return code - * @param buf the raw buffer data, of the correct length determined by the remaining length field - * @param buflen the length in bytes of the data in the supplied buffer - * @return int indicating function execution status - */ -static int _deserialize_connack_packet(uint8_t *sessionPresent, int *connack_rc, unsigned char *buf, size_t buflen) { + * Deserializes the supplied (wire) buffer into connack data - return code + * @param sessionPresent the session present flag returned (only for MQTT 3.1.1) + * @param connack_rc returned integer value of the connack return code + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param buflen the length in bytes of the data in the supplied buffer + * @return int indicating function execution status + */ +static int _deserialize_connack_packet(uint8_t *sessionPresent, int *connack_rc, unsigned char *buf, size_t buflen) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(sessionPresent, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(connack_rc, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); - unsigned char header, type = 0; + unsigned char header, type = 0; unsigned char *curdata = buf; unsigned char *enddata = NULL; - int rc; - uint32_t decodedLen = 0, readBytesLen = 0; - unsigned char flags = 0; - unsigned char connack_rc_char; + int rc; + uint32_t decodedLen = 0, readBytesLen = 0; + unsigned char flags = 0; + unsigned char connack_rc_char; - // CONNACK 头部大小是固定的2字节长度, 可变头部也是两个字节的长度, 无有效负载 + // CONNACK: 2 bytes in fixed header and 2 bytes in variable header, no payload if (4 > buflen) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); } - // 读取固定头部第一个字节 header = mqtt_read_char(&curdata); - type = (header&MQTT_HEADER_TYPE_MASK)>>MQTT_HEADER_TYPE_SHIFT; + type = (header & MQTT_HEADER_TYPE_MASK) >> MQTT_HEADER_TYPE_SHIFT; if (CONNACK != type) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - // 读取固定头部剩余长度字段 rc = mqtt_read_packet_rem_len_form_buf(curdata, &decodedLen, &readBytesLen); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } curdata += (readBytesLen); @@ -245,18 +277,18 @@ static int _deserialize_connack_packet(uint8_t *sessionPresent, int *connack_rc, IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - // 读取可变头部-连接确认标志 参考MQTT协议说明文档3.2.2.1小结 - flags = mqtt_read_char(&curdata); + // variable header - connack flag, refer to MQTT spec 3.2.2.1 + flags = mqtt_read_char(&curdata); *sessionPresent = flags & MQTT_CONNACK_FLAG_SES_PRE; - // 读取可变头部-连接返回码 参考MQTT协议说明文档3.2.2.3小结 + // variable header - return code, refer to MQTT spec 3.2.2.3 connack_rc_char = mqtt_read_char(&curdata); switch (connack_rc_char) { case CONNACK_CONNECTION_ACCEPTED: - *connack_rc = QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED; + *connack_rc = QCLOUD_RET_MQTT_CONNACK_CONNECTION_ACCEPTED; break; case CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR: - *connack_rc = QCLOUD_ERR_MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION; + *connack_rc = QCLOUD_ERR_MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION; break; case CONNACK_IDENTIFIER_REJECTED_ERROR: *connack_rc = QCLOUD_ERR_MQTT_CONNACK_IDENTIFIER_REJECTED; @@ -275,24 +307,24 @@ static int _deserialize_connack_packet(uint8_t *sessionPresent, int *connack_rc, break; } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * @brief 与服务器建立MQTT连接 + * @brief Setup connection with MQTT server * * @param pClient * @param options * @return */ -static int _mqtt_connect(Qcloud_IoT_Client *pClient, MQTTConnectParams *options) { - +static int _mqtt_connect(Qcloud_IoT_Client *pClient, MQTTConnectParams *options) +{ IOT_FUNC_ENTRY; - Timer connect_timer; - int connack_rc = QCLOUD_ERR_FAILURE, rc = QCLOUD_ERR_FAILURE; - uint8_t sessionPresent = 0; - uint32_t len = 0; + Timer connect_timer; + int connack_rc = QCLOUD_ERR_FAILURE, rc = QCLOUD_ERR_FAILURE; + uint8_t sessionPresent = 0; + uint32_t len = 0; InitTimer(&connect_timer); countdown_ms(&connect_timer, pClient->command_timeout_ms); @@ -301,78 +333,78 @@ static int _mqtt_connect(Qcloud_IoT_Client *pClient, MQTTConnectParams *options) _copy_connect_params(&(pClient->options), options); } - // 建立TLS连接 + // TCP or TLS network connect rc = pClient->network_stack.connect(&(pClient->network_stack)); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } HAL_MutexLock(pClient->lock_write_buf); - // 序列化CONNECT报文 + // serialize CONNECT packet rc = _serialize_connect_packet(pClient->write_buf, pClient->write_buf_size, &(pClient->options), &len); - if (QCLOUD_ERR_SUCCESS != rc || 0 == len) { - HAL_MutexUnlock(pClient->lock_write_buf); + if (QCLOUD_RET_SUCCESS != rc || 0 == len) { + HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } - // 发送CONNECT报文 + // send CONNECT packet rc = send_mqtt_packet(pClient, len, &connect_timer); - if (QCLOUD_ERR_SUCCESS != rc) { - HAL_MutexUnlock(pClient->lock_write_buf); + if (QCLOUD_RET_SUCCESS != rc) { + HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } HAL_MutexUnlock(pClient->lock_write_buf); - // 阻塞等待CONNACK的报文, - rc = wait_for_read(pClient, CONNACK, &connect_timer, 0); - if (QCLOUD_ERR_SUCCESS != rc) { + // wait for CONNACK + rc = wait_for_read(pClient, CONNACK, &connect_timer, QOS0); + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } - // 反序列化CONNACK包, 检查返回码 + // deserialize CONNACK and check reture code rc = _deserialize_connack_packet(&sessionPresent, &connack_rc, pClient->read_buf, pClient->read_buf_size); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } - if (QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED != connack_rc) { + if (QCLOUD_RET_MQTT_CONNACK_CONNECTION_ACCEPTED != connack_rc) { IOT_FUNC_EXIT_RC(connack_rc); } set_client_conn_state(pClient, CONNECTED); HAL_MutexLock(pClient->lock_generic); pClient->was_manually_disconnected = 0; - pClient->is_ping_outstanding = 0; + pClient->is_ping_outstanding = 0; countdown(&pClient->ping_timer, pClient->options.keep_alive_interval); HAL_MutexUnlock(pClient->lock_generic); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -int qcloud_iot_mqtt_connect(Qcloud_IoT_Client *pClient, MQTTConnectParams *pParams) { - +int qcloud_iot_mqtt_connect(Qcloud_IoT_Client *pClient, MQTTConnectParams *pParams) +{ IOT_FUNC_ENTRY; int rc; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(pParams, QCLOUD_ERR_INVAL); - // 如果MQTT连接已经建立, 不要重复发送CONNECT报文 + // check connection state first if (get_client_conn_state(pClient)) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_ALREADY_CONNECTED); + IOT_FUNC_EXIT_RC(QCLOUD_RET_MQTT_ALREADY_CONNECTED); } rc = _mqtt_connect(pClient, pParams); - // 如果MQTT连接建立失败, 则断开底层的TLS连接 - if (rc != QCLOUD_ERR_SUCCESS) { + // disconnect network if connect fail + if (rc != QCLOUD_RET_SUCCESS) { pClient->network_stack.disconnect(&(pClient->network_stack)); } IOT_FUNC_EXIT_RC(rc); } -int qcloud_iot_mqtt_attempt_reconnect(Qcloud_IoT_Client *pClient) { - +int qcloud_iot_mqtt_attempt_reconnect(Qcloud_IoT_Client *pClient) +{ IOT_FUNC_ENTRY; int rc; @@ -381,7 +413,7 @@ int qcloud_iot_mqtt_attempt_reconnect(Qcloud_IoT_Client *pClient) { Log_i("attempt to reconnect..."); if (get_client_conn_state(pClient)) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_ALREADY_CONNECTED); + IOT_FUNC_EXIT_RC(QCLOUD_RET_MQTT_ALREADY_CONNECTED); } rc = qcloud_iot_mqtt_connect(pClient, &pClient->options); @@ -391,31 +423,30 @@ int qcloud_iot_mqtt_attempt_reconnect(Qcloud_IoT_Client *pClient) { } rc = qcloud_iot_mqtt_resubscribe(pClient); - if (rc != QCLOUD_ERR_SUCCESS) { + if (rc != QCLOUD_RET_SUCCESS) { IOT_FUNC_EXIT_RC(rc); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_RECONNECTED); + IOT_FUNC_EXIT_RC(QCLOUD_RET_MQTT_RECONNECTED); } -int qcloud_iot_mqtt_disconnect(Qcloud_IoT_Client *pClient) { - +int qcloud_iot_mqtt_disconnect(Qcloud_IoT_Client *pClient) +{ IOT_FUNC_ENTRY; int rc; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - Timer timer; + Timer timer; uint32_t serialized_len = 0; if (get_client_conn_state(pClient) == 0) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); } - // 1. 组disconnect包 HAL_MutexLock(pClient->lock_write_buf); rc = serialize_packet_with_zero_payload(pClient->write_buf, pClient->write_buf_size, DISCONNECT, &serialized_len); - if (rc != QCLOUD_ERR_SUCCESS) { + if (rc != QCLOUD_RET_SUCCESS) { HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } @@ -423,28 +454,24 @@ int qcloud_iot_mqtt_disconnect(Qcloud_IoT_Client *pClient) { InitTimer(&timer); countdown_ms(&timer, pClient->command_timeout_ms); - // 2. 发送disconnect包 if (serialized_len > 0) { rc = send_mqtt_packet(pClient, serialized_len, &timer); - if (rc != QCLOUD_ERR_SUCCESS) { + if (rc != QCLOUD_RET_SUCCESS) { HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } } HAL_MutexUnlock(pClient->lock_write_buf); - // 3. 断开底层TCP连接, 并修改相关标识位 pClient->network_stack.disconnect(&(pClient->network_stack)); set_client_conn_state(pClient, NOTCONNECTED); pClient->was_manually_disconnected = 1; Log_i("mqtt disconnect!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } #ifdef __cplusplus } #endif - - diff --git a/src/mqtt/src/mqtt_client_net.c b/sdk_src/protocol/mqtt/mqtt_client_net.c old mode 100644 new mode 100755 similarity index 66% rename from src/mqtt/src/mqtt_client_net.c rename to sdk_src/protocol/mqtt/mqtt_client_net.c index ffcbd9d3..c57520a7 --- a/src/mqtt/src/mqtt_client_net.c +++ b/sdk_src/protocol/mqtt/mqtt_client_net.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -19,29 +19,37 @@ extern "C" { #include "mqtt_client_net.h" - +// TODO: how to implement /** - * TODO: 需要看下怎么去实现 - * - * @brief 用于检查TLS层连接是否还存在 + * @brief Check if TLS connection is valid * * @param pNetwork * @return */ -int qcloud_iot_mqtt_tls_is_connected(Network *pNetwork) { +int qcloud_iot_mqtt_tls_is_connected(Network *pNetwork) +{ return 1; } /** - * @brief 初始化Network结构体 + * @brief Init network stack * * @param pNetwork * @param pConnectParams * @return */ -int qcloud_iot_mqtt_network_init(Network *pNetwork) { +int qcloud_iot_mqtt_network_init(Network *pNetwork) +{ int rc; - rc = utils_net_init(pNetwork); + + /* first choice: TLS */ + pNetwork->type = NETWORK_TLS; + +#ifdef AUTH_WITH_NOTLS + pNetwork->type = NETWORK_TCP; +#endif + + rc = network_init(pNetwork); pNetwork->is_connected = qcloud_iot_mqtt_tls_is_connected; return rc; diff --git a/src/mqtt/src/mqtt_client_publish.c b/sdk_src/protocol/mqtt/mqtt_client_publish.c similarity index 55% rename from src/mqtt/src/mqtt_client_publish.c rename to sdk_src/protocol/mqtt/mqtt_client_publish.c index 8f3da138..33bba90a 100644 --- a/src/mqtt/src/mqtt_client_publish.c +++ b/sdk_src/protocol/mqtt/mqtt_client_publish.c @@ -22,7 +22,6 @@ extern "C" { #include #include "mqtt_client.h" - #include "utils_list.h" /** @@ -31,23 +30,24 @@ extern "C" { * @param enddata pointer to the end of the data: do not read beyond * @return SUCCESS if successful, FAILURE if not */ -static int _read_string_with_len(char **string, uint16_t *stringLen, unsigned char **pptr, unsigned char *enddata) { +static int _read_string_with_len(char **string, uint16_t *stringLen, unsigned char **pptr, unsigned char *enddata) +{ int rc = QCLOUD_ERR_FAILURE; /* the first two bytes are the length of the string */ /* enough length to read the integer? */ if (enddata - (*pptr) > 1) { *stringLen = mqtt_read_uint16_t(pptr); /* increments pptr to point past length */ - - if(*stringLen > QCLOUD_IOT_MQTT_RX_BUF_LEN){ - Log_e("stringLen exceed QCLOUD_IOT_MQTT_RX_BUF_LEN"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - + + if (*stringLen > QCLOUD_IOT_MQTT_RX_BUF_LEN) { + Log_e("stringLen exceed QCLOUD_IOT_MQTT_RX_BUF_LEN"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + if (&(*pptr)[*stringLen] <= enddata) { - *string = (char *) *pptr; + *string = (char *)*pptr; *pptr += *stringLen; - rc = QCLOUD_ERR_SUCCESS; + rc = QCLOUD_RET_SUCCESS; } } @@ -55,20 +55,21 @@ static int _read_string_with_len(char **string, uint16_t *stringLen, unsigned ch } /** - * Determines the length of the MQTT publish packet that would be produced using the supplied parameters - * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0) - * @param topicName the topic name to be used in the publish - * @param payload_len the length of the payload to be sent - * @return the length of buffer needed to contain the serialized version of the packet - */ -static uint32_t _get_publish_packet_len(uint8_t qos, char *topicName, size_t payload_len) { + * Determines the length of the MQTT publish packet that would be produced using the supplied parameters + * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0) + * @param topicName the topic name to be used in the publish + * @param payload_len the length of the payload to be sent + * @return the length of buffer needed to contain the serialized version of the packet + */ +static uint32_t _get_publish_packet_len(uint8_t qos, char *topicName, size_t payload_len) +{ size_t len = 0; len += 2 + strlen(topicName) + payload_len; if (qos > 0) { len += 2; /* packetid */ } - return (uint32_t) len; + return (uint32_t)len; } static int _mask_push_pubInfo_to(Qcloud_IoT_Client *c, int len, unsigned short msgId, ListNode **node) @@ -101,8 +102,8 @@ static int _mask_push_pubInfo_to(Qcloud_IoT_Client *c, int len, unsigned short m } repubInfo->node_state = MQTT_NODE_STATE_NORMANL; - repubInfo->msg_id = msgId; - repubInfo->len = len; + repubInfo->msg_id = msgId; + repubInfo->len = len; InitTimer(&repubInfo->pub_start_time); countdown_ms(&repubInfo->pub_start_time, c->command_timeout_ms); @@ -113,6 +114,7 @@ static int _mask_push_pubInfo_to(Qcloud_IoT_Client *c, int len, unsigned short m *node = list_node_new(repubInfo); if (NULL == *node) { HAL_MutexUnlock(c->lock_list_pub); + HAL_Free(repubInfo); Log_e("list_node_new failed!"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } @@ -121,24 +123,25 @@ static int _mask_push_pubInfo_to(Qcloud_IoT_Client *c, int len, unsigned short m HAL_MutexUnlock(c->lock_list_pub); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * Deserializes the supplied (wire) buffer into publish data - * @param dup returned integer - the MQTT dup flag - * @param qos returned integer - the MQTT QoS value - * @param retained returned integer - the MQTT retained flag - * @param packet_id returned integer - the MQTT packet identifier - * @param topicName returned MQTTString - the MQTT topic in the publish - * @param payload returned byte buffer - the MQTT publish payload - * @param payload_len returned integer - the length of the MQTT payload - * @param buf the raw buffer data, of the correct length determined by the remaining length field - * @param buf_len the length in bytes of the data in the supplied buffer - * @return error code. 1 is success - */ + * Deserializes the supplied (wire) buffer into publish data + * @param dup returned integer - the MQTT dup flag + * @param qos returned integer - the MQTT QoS value + * @param retained returned integer - the MQTT retained flag + * @param packet_id returned integer - the MQTT packet identifier + * @param topicName returned MQTTString - the MQTT topic in the publish + * @param payload returned byte buffer - the MQTT publish payload + * @param payload_len returned integer - the length of the MQTT payload + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param buf_len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success + */ int deserialize_publish_packet(uint8_t *dup, QoS *qos, uint8_t *retained, uint16_t *packet_id, char **topicName, - uint16_t *topicNameLen,unsigned char **payload, size_t *payload_len, unsigned char *buf, size_t buf_len) + uint16_t *topicNameLen, unsigned char **payload, size_t *payload_len, unsigned char *buf, + size_t buf_len) { IOT_FUNC_ENTRY; @@ -147,12 +150,12 @@ int deserialize_publish_packet(uint8_t *dup, QoS *qos, uint8_t *retained, uint16 POINTER_SANITY_CHECK(retained, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(packet_id, QCLOUD_ERR_INVAL); - unsigned char header, type = 0; + unsigned char header, type = 0; unsigned char *curdata = buf; unsigned char *enddata = NULL; - int rc; - uint32_t decodedLen = 0; - uint32_t readBytesLen = 0; + int rc; + uint32_t decodedLen = 0; + uint32_t readBytesLen = 0; /* Publish header size is at least four bytes. * Fixed header is two bytes. @@ -164,26 +167,27 @@ int deserialize_publish_packet(uint8_t *dup, QoS *qos, uint8_t *retained, uint16 IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); } - header = mqtt_read_char(&curdata); - type = (header&MQTT_HEADER_TYPE_MASK)>>MQTT_HEADER_TYPE_SHIFT; - *dup = (header&MQTT_HEADER_DUP_MASK)>>MQTT_HEADER_DUP_SHIFT; - *qos = (QoS)((header&MQTT_HEADER_QOS_MASK)>>MQTT_HEADER_QOS_SHIFT); - *retained = header&MQTT_HEADER_RETAIN_MASK; - + header = mqtt_read_char(&curdata); + type = (header & MQTT_HEADER_TYPE_MASK) >> MQTT_HEADER_TYPE_SHIFT; + *dup = (header & MQTT_HEADER_DUP_MASK) >> MQTT_HEADER_DUP_SHIFT; + *qos = (QoS)((header & MQTT_HEADER_QOS_MASK) >> MQTT_HEADER_QOS_SHIFT); + *retained = header & MQTT_HEADER_RETAIN_MASK; + if (PUBLISH != type) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } /* read remaining length */ rc = mqtt_read_packet_rem_len_form_buf(curdata, &decodedLen, &readBytesLen); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } curdata += (readBytesLen); enddata = curdata + decodedLen; /* do we have enough data to read the protocol version byte? */ - if (QCLOUD_ERR_SUCCESS != _read_string_with_len(topicName, topicNameLen, &curdata, enddata) || (0 > (enddata - curdata))) { + if (QCLOUD_RET_SUCCESS != _read_string_with_len(topicName, topicNameLen, &curdata, enddata) || + (0 > (enddata - curdata))) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } @@ -191,32 +195,32 @@ int deserialize_publish_packet(uint8_t *dup, QoS *qos, uint8_t *retained, uint16 *packet_id = mqtt_read_uint16_t(&curdata); } - *payload_len = (size_t) (enddata - curdata); - *payload = curdata; + *payload_len = (size_t)(enddata - curdata); + *payload = curdata; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * Serializes the ack packet into the supplied buffer. - * @param buf the buffer into which the packet will be serialized - * @param buf_len the length in bytes of the supplied buffer - * @param packet_type the MQTT packet type: 1.PUBACK; 2.PUBREL; 3.PUBCOMP - * @param dup the MQTT dup flag - * @param packet_id the MQTT packet identifier - * @return serialized length, or error if 0 - */ + * Serializes the ack packet into the supplied buffer. + * @param buf the buffer into which the packet will be serialized + * @param buf_len the length in bytes of the supplied buffer + * @param packet_type the MQTT packet type: 1.PUBACK; 2.PUBREL; 3.PUBCOMP + * @param dup the MQTT dup flag + * @param packet_id the MQTT packet identifier + * @return serialized length, or error if 0 + */ int serialize_pub_ack_packet(unsigned char *buf, size_t buf_len, MessageTypes packet_type, uint8_t dup, - uint16_t packet_id, - uint32_t *serialized_len) { + uint16_t packet_id, uint32_t *serialized_len) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL); - unsigned char header = 0; - unsigned char *ptr = buf; - QoS requestQoS = (PUBREL == packet_type) ? QOS1 : QOS0; // 详见 MQTT协议说明 3.6.1小结 - int rc = mqtt_init_packet_header(&header, packet_type, requestQoS, dup, 0); + unsigned char header = 0; + unsigned char *ptr = buf; + QoS requestQoS = (PUBREL == packet_type) ? QOS1 : QOS0; // refer to MQTT spec 3.6.1 + int rc = mqtt_init_packet_header(&header, packet_type, requestQoS, dup, 0); /* Minimum byte length required by ACK headers is * 2 for fixed and 2 for variable part */ @@ -224,45 +228,44 @@ int serialize_pub_ack_packet(unsigned char *buf, size_t buf_len, MessageTypes pa IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); } - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } mqtt_write_char(&ptr, header); /* write header */ ptr += mqtt_write_packet_rem_len(ptr, 2); /* write remaining length */ mqtt_write_uint_16(&ptr, packet_id); - *serialized_len = (uint32_t) (ptr - buf); + *serialized_len = (uint32_t)(ptr - buf); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } - /** - * Serializes the supplied publish data into the supplied buffer, ready for sending - * @param buf the buffer into which the packet will be serialized - * @param buf_len the length in bytes of the supplied buffer - * @param dup integer - the MQTT dup flag - * @param qos integer - the MQTT QoS value - * @param retained integer - the MQTT retained flag - * @param packet_id integer - the MQTT packet identifier - * @param topicName MQTTString - the MQTT topic in the publish - * @param payload byte buffer - the MQTT publish payload - * @param payload_len integer - the length of the MQTT payload - * @return the length of the serialized data. <= 0 indicates error - */ + * Serializes the supplied publish data into the supplied buffer, ready for sending + * @param buf the buffer into which the packet will be serialized + * @param buf_len the length in bytes of the supplied buffer + * @param dup integer - the MQTT dup flag + * @param qos integer - the MQTT QoS value + * @param retained integer - the MQTT retained flag + * @param packet_id integer - the MQTT packet identifier + * @param topicName MQTTString - the MQTT topic in the publish + * @param payload byte buffer - the MQTT publish payload + * @param payload_len integer - the length of the MQTT payload + * @return the length of the serialized data. <= 0 indicates error + */ static int _serialize_publish_packet(unsigned char *buf, size_t buf_len, uint8_t dup, QoS qos, uint8_t retained, - uint16_t packet_id, - char *topicName, unsigned char *payload, size_t payload_len, - uint32_t *serialized_len) { + uint16_t packet_id, char *topicName, unsigned char *payload, size_t payload_len, + uint32_t *serialized_len) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(payload, QCLOUD_ERR_INVAL); - unsigned char *ptr = buf; - unsigned char header = 0; - uint32_t rem_len = 0; - int rc; + unsigned char *ptr = buf; + unsigned char header = 0; + uint32_t rem_len = 0; + int rc; rem_len = _get_publish_packet_len(qos, topicName, payload_len); if (get_mqtt_packet_len(rem_len) > buf_len) { @@ -270,41 +273,43 @@ static int _serialize_publish_packet(unsigned char *buf, size_t buf_len, uint8_t } rc = mqtt_init_packet_header(&header, PUBLISH, qos, dup, retained); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } mqtt_write_char(&ptr, header); /* write header */ - ptr += mqtt_write_packet_rem_len(ptr, rem_len); /* write remaining length */; + ptr += mqtt_write_packet_rem_len(ptr, rem_len); /* write remaining length */ + ; - mqtt_write_utf8_string(&ptr, topicName); /* Variable Header: Topic Name */ + mqtt_write_utf8_string(&ptr, topicName); /* Variable Header: Topic Name */ if (qos > 0) { - mqtt_write_uint_16(&ptr, packet_id); /* Variable Header: Topic Name */ + mqtt_write_uint_16(&ptr, packet_id); /* Variable Header: Topic Name */ } memcpy(ptr, payload, payload_len); ptr += payload_len; - *serialized_len = (uint32_t) (ptr - buf); + *serialized_len = (uint32_t)(ptr - buf); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -int qcloud_iot_mqtt_publish(Qcloud_IoT_Client *pClient, char *topicName, PublishParams *pParams) { +int qcloud_iot_mqtt_publish(Qcloud_IoT_Client *pClient, char *topicName, PublishParams *pParams) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(pParams, QCLOUD_ERR_INVAL); STRING_PTR_SANITY_CHECK(topicName, QCLOUD_ERR_INVAL); - Timer timer; + Timer timer; uint32_t len = 0; - int rc; + int rc; ListNode *node = NULL; - + size_t topicLen = strlen(topicName); if (topicLen > MAX_SIZE_OF_CLOUD_TOPIC) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH); @@ -325,32 +330,32 @@ int qcloud_iot_mqtt_publish(Qcloud_IoT_Client *pClient, char *topicName, Publish HAL_MutexLock(pClient->lock_write_buf); if (pParams->qos == QOS1) { pParams->id = get_next_packet_id(pClient); - if (IOT_Log_Get_Level() <= DEBUG) { - Log_d("publish topic seq=%d|topicName=%s|payload=%s", pParams->id, topicName, (char *)pParams->payload); + if (IOT_Log_Get_Level() <= eLOG_DEBUG) { + Log_d("publish topic seq=%d|topicName=%s|payload=%s", pParams->id, topicName, + STRING_PTR_PRINT_SANITY_CHECK((char *)pParams->payload)); + } else { + Log_i("publish topic seq=%d|topicName=%s", pParams->id, topicName); } - else { - Log_i("publish topic seq=%d|topicName=%s", pParams->id, topicName); + } else { + if (IOT_Log_Get_Level() <= eLOG_DEBUG) { + Log_d("publish packetID=%d|topicName=%s|payload=%s", pParams->id, topicName, + STRING_PTR_PRINT_SANITY_CHECK((char *)pParams->payload)); + } else { + Log_i("publish packetID=%d|topicName=%s", pParams->id, topicName); } } - else { - if (IOT_Log_Get_Level() <= DEBUG) { - Log_d("publish packetID=%d|topicName=%s|payload=%s", pParams->id, topicName, (char *)pParams->payload); - } - else { - Log_i("publish packetID=%d|topicName=%s", pParams->id, topicName); - } - } - rc = _serialize_publish_packet(pClient->write_buf, pClient->write_buf_size, 0, pParams->qos, pParams->retained, pParams->id, - topicName, (unsigned char *) pParams->payload, pParams->payload_len, &len); - if (QCLOUD_ERR_SUCCESS != rc) { - HAL_MutexUnlock(pClient->lock_write_buf); + rc = _serialize_publish_packet(pClient->write_buf, pClient->write_buf_size, 0, pParams->qos, pParams->retained, + pParams->id, topicName, (unsigned char *)pParams->payload, pParams->payload_len, + &len); + if (QCLOUD_RET_SUCCESS != rc) { + HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } if (pParams->qos > QOS0) { rc = _mask_push_pubInfo_to(pClient, len, pParams->id, &node); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { Log_e("push publish into to pubInfolist failed!"); HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); @@ -359,20 +364,20 @@ int qcloud_iot_mqtt_publish(Qcloud_IoT_Client *pClient, char *topicName, Publish /* send the publish packet */ rc = send_mqtt_packet(pClient, len, &timer); - if (QCLOUD_ERR_SUCCESS != rc) { - if (pParams->qos > QOS0) { - HAL_MutexLock(pClient->lock_list_pub); - list_remove(pClient->list_pub_wait_ack, node); - HAL_MutexUnlock(pClient->lock_list_pub); - } + if (QCLOUD_RET_SUCCESS != rc) { + if (pParams->qos > QOS0) { + HAL_MutexLock(pClient->lock_list_pub); + list_remove(pClient->list_pub_wait_ack, node); + HAL_MutexUnlock(pClient->lock_list_pub); + } - HAL_MutexUnlock(pClient->lock_write_buf); - IOT_FUNC_EXIT_RC(rc); - } + HAL_MutexUnlock(pClient->lock_write_buf); + IOT_FUNC_EXIT_RC(rc); + } - HAL_MutexUnlock(pClient->lock_write_buf); + HAL_MutexUnlock(pClient->lock_write_buf); - IOT_FUNC_EXIT_RC(pParams->id); + IOT_FUNC_EXIT_RC(pParams->id); } #ifdef __cplusplus diff --git a/src/mqtt/src/mqtt_client_subscribe.c b/sdk_src/protocol/mqtt/mqtt_client_subscribe.c old mode 100755 new mode 100644 similarity index 52% rename from src/mqtt/src/mqtt_client_subscribe.c rename to sdk_src/protocol/mqtt/mqtt_client_subscribe.c index 578215e9..4b579aeb --- a/src/mqtt/src/mqtt_client_subscribe.c +++ b/sdk_src/protocol/mqtt/mqtt_client_subscribe.c @@ -23,12 +23,13 @@ extern "C" { #include "mqtt_client.h" /** - * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters - * @param count the number of topic filter strings in topicFilters - * @param topicFilters the array of topic filter strings to be used in the publish - * @return the length of buffer needed to contain the serialized version of the packet - */ -static uint32_t _get_subscribe_packet_rem_len(uint32_t count, char **topicFilters) { + * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters + * @param count the number of topic filter strings in topicFilters + * @param topicFilters the array of topic filter strings to be used in the publish + * @return the length of buffer needed to contain the serialized version of the packet + */ +static uint32_t _get_subscribe_packet_rem_len(uint32_t count, char **topicFilters) +{ size_t i; size_t len = 2; /* packetid */ @@ -36,62 +37,65 @@ static uint32_t _get_subscribe_packet_rem_len(uint32_t count, char **topicFilter len += 2 + strlen(*topicFilters + i) + 1; /* length + topic + req_qos */ } - return (uint32_t) len; + return (uint32_t)len; } /** - * Serializes the supplied subscribe data into the supplied buffer, ready for sending - * @param buf the buffer into which the packet will be serialized - * @param buf_len the length in bytes of the supplied bufferr - * @param dup integer - the MQTT dup flag - * @param packet_id integer - the MQTT packet identifier - * @param count - number of members in the topicFilters and reqQos arrays - * @param topicFilters - array of topic filter names - * @param requestedQoSs - array of requested QoS - * @return the length of the serialized data. <= 0 indicates error - */ -static int _serialize_subscribe_packet(unsigned char *buf, size_t buf_len, uint8_t dup, uint16_t packet_id, uint32_t count, - char **topicFilters, QoS *requestedQoSs, uint32_t *serialized_len) { + * Serializes the supplied subscribe data into the supplied buffer, ready for sending + * @param buf the buffer into which the packet will be serialized + * @param buf_len the length in bytes of the supplied bufferr + * @param dup integer - the MQTT dup flag + * @param packet_id integer - the MQTT packet identifier + * @param count - number of members in the topicFilters and reqQos arrays + * @param topicFilters - array of topic filter names + * @param requestedQoSs - array of requested QoS + * @return the length of the serialized data. <= 0 indicates error + */ +static int _serialize_subscribe_packet(unsigned char *buf, size_t buf_len, uint8_t dup, uint16_t packet_id, + uint32_t count, char **topicFilters, QoS *requestedQoSs, + uint32_t *serialized_len) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL); - unsigned char *ptr = buf; - unsigned char header = 0; - uint32_t rem_len = 0; - uint32_t i = 0; - int rc; + unsigned char *ptr = buf; + unsigned char header = 0; + uint32_t rem_len = 0; + uint32_t i = 0; + int rc; - // SUBSCRIBE报文的剩余长度 = 报文标识符(2 byte) + count * (长度字段(2 byte) + topicLen + qos(1 byte)) + // remaining length of SUBSCRIBE packet = packet type(2 byte) + count * (remaining length(2 byte) + topicLen + qos(1 + // byte)) rem_len = _get_subscribe_packet_rem_len(count, topicFilters); if (get_mqtt_packet_len(rem_len) > buf_len) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_BUF_TOO_SHORT); } - // 初始化报文头部 + // init header rc = mqtt_init_packet_header(&header, SUBSCRIBE, QOS1, dup, 0); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } - // 写报文固定头部第一个字节 + // 1st byte in fixed header mqtt_write_char(&ptr, header); - // 写报文固定头部剩余长度字段 + // remaining length ptr += mqtt_write_packet_rem_len(ptr, rem_len); - // 写可变头部: 报文标识符 + // variable header mqtt_write_uint_16(&ptr, packet_id); - // 写报文的负载部分数据 + // payload for (i = 0; i < count; ++i) { mqtt_write_utf8_string(&ptr, *topicFilters + i); - mqtt_write_char(&ptr, (unsigned char) requestedQoSs[i]); + mqtt_write_char(&ptr, (unsigned char)requestedQoSs[i]); } - *serialized_len = (uint32_t) (ptr - buf); + *serialized_len = (uint32_t)(ptr - buf); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -int qcloud_iot_mqtt_subscribe(Qcloud_IoT_Client *pClient, char *topicFilter, SubscribeParams *pParams) { - +int qcloud_iot_mqtt_subscribe(Qcloud_IoT_Client *pClient, char *topicFilter, SubscribeParams *pParams) +{ IOT_FUNC_ENTRY; int rc; @@ -100,12 +104,12 @@ int qcloud_iot_mqtt_subscribe(Qcloud_IoT_Client *pClient, char *topicFilter, Sub // POINTER_SANITY_CHECK(pParams->on_message_handler, QCLOUD_ERR_INVAL); STRING_PTR_SANITY_CHECK(topicFilter, QCLOUD_ERR_INVAL); - Timer timer; - uint32_t len = 0; + Timer timer; + uint32_t len = 0; uint16_t packet_id = 0; ListNode *node = NULL; - + size_t topicLen = strlen(topicFilter); if (topicLen > MAX_SIZE_OF_CLOUD_TOPIC) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH); @@ -115,7 +119,7 @@ int qcloud_iot_mqtt_subscribe(Qcloud_IoT_Client *pClient, char *topicFilter, Sub Log_e("QoS2 is not supported currently"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_QOS_NOT_SUPPORT); } - + if (!get_client_conn_state(pClient)) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN) } @@ -126,50 +130,50 @@ int qcloud_iot_mqtt_subscribe(Qcloud_IoT_Client *pClient, char *topicFilter, Sub Log_e("malloc failed"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - + strcpy(topic_filter_stored, topicFilter); topic_filter_stored[topicLen] = 0; - + InitTimer(&timer); countdown_ms(&timer, pClient->command_timeout_ms); HAL_MutexLock(pClient->lock_write_buf); - // 序列化SUBSCRIBE报文 packet_id = get_next_packet_id(pClient); - Log_d("topicName=%s|packet_id=%d|pUserdata=%s", topic_filter_stored, packet_id, (char *)pParams->user_data); + Log_d("topicName=%s|packet_id=%d", topic_filter_stored, packet_id); rc = _serialize_subscribe_packet(pClient->write_buf, pClient->write_buf_size, 0, packet_id, 1, &topic_filter_stored, &pParams->qos, &len); - if (QCLOUD_ERR_SUCCESS != rc) { - HAL_MutexUnlock(pClient->lock_write_buf); - HAL_Free(topic_filter_stored); + if (QCLOUD_RET_SUCCESS != rc) { + HAL_MutexUnlock(pClient->lock_write_buf); + HAL_Free(topic_filter_stored); IOT_FUNC_EXIT_RC(rc); } - /* 等待 sub ack 列表中添加元素 */ + /* add node into sub ack wait list */ SubTopicHandle sub_handle; - sub_handle.topic_filter = topic_filter_stored; - sub_handle.message_handler = pParams->on_message_handler; - sub_handle.qos = pParams->qos; - sub_handle.message_handler_data = pParams->user_data; + sub_handle.topic_filter = topic_filter_stored; + sub_handle.message_handler = pParams->on_message_handler; + sub_handle.sub_event_handler = pParams->on_sub_event_handler; + sub_handle.qos = pParams->qos; + sub_handle.handler_user_data = pParams->user_data; rc = push_sub_info_to(pClient, len, (unsigned int)packet_id, SUBSCRIBE, &sub_handle, &node); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { Log_e("push publish into to pubInfolist failed!"); HAL_MutexUnlock(pClient->lock_write_buf); HAL_Free(topic_filter_stored); IOT_FUNC_EXIT_RC(rc); } - - // 发送SUBSCRIBE报文 + + // send SUBSCRIBE packet rc = send_mqtt_packet(pClient, len, &timer); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { HAL_MutexLock(pClient->lock_list_sub); list_remove(pClient->list_sub_wait_ack, node); HAL_MutexUnlock(pClient->lock_list_sub); - HAL_MutexUnlock(pClient->lock_write_buf); - HAL_Free(topic_filter_stored); + HAL_MutexUnlock(pClient->lock_write_buf); + HAL_Free(topic_filter_stored); IOT_FUNC_EXIT_RC(rc); } @@ -178,14 +182,15 @@ int qcloud_iot_mqtt_subscribe(Qcloud_IoT_Client *pClient, char *topicFilter, Sub IOT_FUNC_EXIT_RC(packet_id); } -int qcloud_iot_mqtt_resubscribe(Qcloud_IoT_Client *pClient) { +int qcloud_iot_mqtt_resubscribe(Qcloud_IoT_Client *pClient) +{ IOT_FUNC_ENTRY; int rc; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - uint32_t itr = 0; - char *topic = NULL; + uint32_t itr = 0; + char * topic = NULL; SubscribeParams temp_param; if (NULL == pClient) { @@ -197,22 +202,48 @@ int qcloud_iot_mqtt_resubscribe(Qcloud_IoT_Client *pClient) { } for (itr = 0; itr < MAX_MESSAGE_HANDLERS; itr++) { - topic = (char *) pClient->sub_handles[itr].topic_filter; + topic = (char *)pClient->sub_handles[itr].topic_filter; if (topic == NULL) { continue; } - temp_param.on_message_handler = pClient->sub_handles[itr].message_handler; - temp_param.qos = pClient->sub_handles[itr].qos; - temp_param.user_data = pClient->sub_handles[itr].message_handler_data; + temp_param.on_message_handler = pClient->sub_handles[itr].message_handler; + temp_param.on_sub_event_handler = pClient->sub_handles[itr].sub_event_handler; + temp_param.qos = pClient->sub_handles[itr].qos; + temp_param.user_data = pClient->sub_handles[itr].handler_user_data; rc = qcloud_iot_mqtt_subscribe(pClient, topic, &temp_param); if (rc < 0) { - Log_e("resubscribe failed %d, topic: %s", rc, topic); + Log_e("resubscribe failed %d, topic: %s", rc, topic); IOT_FUNC_EXIT_RC(rc); } } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +bool qcloud_iot_mqtt_is_sub_ready(Qcloud_IoT_Client *pClient, char *topicFilter) +{ + IOT_FUNC_ENTRY; + POINTER_SANITY_CHECK(pClient, false); + STRING_PTR_SANITY_CHECK(topicFilter, false); + + size_t topicLen = strlen(topicFilter); + if (topicLen > MAX_SIZE_OF_CLOUD_TOPIC) { + return false; + } + + int i = 0; + HAL_MutexLock(pClient->lock_generic); + for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { + if ((pClient->sub_handles[i].topic_filter != NULL && + !strcmp(pClient->sub_handles[i].topic_filter, topicFilter)) || + strstr(topicFilter, "/#") != NULL || strstr(topicFilter, "/+") != NULL) { + HAL_MutexUnlock(pClient->lock_generic); + return true; + } + } + HAL_MutexUnlock(pClient->lock_generic); + return false; } #ifdef __cplusplus diff --git a/src/mqtt/src/mqtt_client_unsubscribe.c b/sdk_src/protocol/mqtt/mqtt_client_unsubscribe.c old mode 100755 new mode 100644 similarity index 60% rename from src/mqtt/src/mqtt_client_unsubscribe.c rename to sdk_src/protocol/mqtt/mqtt_client_unsubscribe.c index fcee1079..d327c31d --- a/src/mqtt/src/mqtt_client_unsubscribe.c +++ b/sdk_src/protocol/mqtt/mqtt_client_unsubscribe.c @@ -23,12 +23,13 @@ extern "C" { #include "mqtt_client.h" /** - * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters - * @param count the number of topic filter strings in topicFilters - * @param topicFilters the array of topic filter strings to be used in the publish - * @return the length of buffer needed to contain the serialized version of the packet - */ -static uint32_t _get_unsubscribe_packet_rem_len(uint32_t count, char **topicFilters) { + * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters + * @param count the number of topic filter strings in topicFilters + * @param topicFilters the array of topic filter strings to be used in the publish + * @return the length of buffer needed to contain the serialized version of the packet + */ +static uint32_t _get_unsubscribe_packet_rem_len(uint32_t count, char **topicFilters) +{ size_t i; size_t len = 2; /* packetid */ @@ -36,34 +37,33 @@ static uint32_t _get_unsubscribe_packet_rem_len(uint32_t count, char **topicFilt len += 2 + strlen(*topicFilters + i); /* length + topic*/ } - return (uint32_t) len; + return (uint32_t)len; } /** - * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending - * @param buf the raw buffer data, of the correct length determined by the remaining length field - * @param buf_len the length in bytes of the data in the supplied buffer - * @param dup integer - the MQTT dup flag - * @param packet_id integer - the MQTT packet identifier - * @param count - number of members in the topicFilters array - * @param topicFilters - array of topic filter names - * @param serialized_len - the length of the serialized data - * @return int indicating function execution status - */ -static int _serialize_unsubscribe_packet(unsigned char *buf, size_t buf_len, - uint8_t dup, uint16_t packet_id, - uint32_t count, char **topicFilters, - uint32_t *serialized_len) { + * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param buf_len the length in bytes of the data in the supplied buffer + * @param dup integer - the MQTT dup flag + * @param packet_id integer - the MQTT packet identifier + * @param count - number of members in the topicFilters array + * @param topicFilters - array of topic filter names + * @param serialized_len - the length of the serialized data + * @return int indicating function execution status + */ +static int _serialize_unsubscribe_packet(unsigned char *buf, size_t buf_len, uint8_t dup, uint16_t packet_id, + uint32_t count, char **topicFilters, uint32_t *serialized_len) +{ IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(serialized_len, QCLOUD_ERR_INVAL); - unsigned char *ptr = buf; - unsigned char header = 0; - uint32_t rem_len = 0; - uint32_t i = 0; - int rc; + unsigned char *ptr = buf; + unsigned char header = 0; + uint32_t rem_len = 0; + uint32_t i = 0; + int rc; rem_len = _get_unsubscribe_packet_rem_len(count, topicFilters); if (get_mqtt_packet_len(rem_len) > buf_len) { @@ -71,7 +71,7 @@ static int _serialize_unsubscribe_packet(unsigned char *buf, size_t buf_len, } rc = mqtt_init_packet_header(&header, UNSUBSCRIBE, QOS1, dup, 0); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { IOT_FUNC_EXIT_RC(rc); } mqtt_write_char(&ptr, header); /* write header */ @@ -84,23 +84,24 @@ static int _serialize_unsubscribe_packet(unsigned char *buf, size_t buf_len, mqtt_write_utf8_string(&ptr, *topicFilters + i); } - *serialized_len = (uint32_t) (ptr - buf); + *serialized_len = (uint32_t)(ptr - buf); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -int qcloud_iot_mqtt_unsubscribe(Qcloud_IoT_Client *pClient, char *topicFilter) { +int qcloud_iot_mqtt_unsubscribe(Qcloud_IoT_Client *pClient, char *topicFilter) +{ IOT_FUNC_ENTRY; int rc; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); STRING_PTR_SANITY_CHECK(topicFilter, QCLOUD_ERR_INVAL); - int i = 0; - Timer timer; - uint32_t len = 0; - uint16_t packet_id = 0; - bool suber_exists = false; + int i = 0; + Timer timer; + uint32_t len = 0; + uint16_t packet_id = 0; + bool suber_exists = false; ListNode *node = NULL; @@ -108,15 +109,22 @@ int qcloud_iot_mqtt_unsubscribe(Qcloud_IoT_Client *pClient, char *topicFilter) { if (topicLen > MAX_SIZE_OF_CLOUD_TOPIC) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH); } - + /* Remove from message handler array */ HAL_MutexLock(pClient->lock_generic); - for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { - if ((pClient->sub_handles[i].topic_filter != NULL && !strcmp(pClient->sub_handles[i].topic_filter, topicFilter)) - || strstr(topicFilter,"/#") != NULL || strstr(topicFilter,"/+") != NULL) { + for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { + if ((pClient->sub_handles[i].topic_filter != NULL && + !strcmp(pClient->sub_handles[i].topic_filter, topicFilter)) || + strstr(topicFilter, "/#") != NULL || strstr(topicFilter, "/+") != NULL) { + /* notify this event to topic subscriber */ + if (NULL != pClient->sub_handles[i].sub_event_handler) + pClient->sub_handles[i].sub_event_handler(pClient, MQTT_EVENT_UNSUBSCRIBE, + pClient->sub_handles[i].handler_user_data); + /* Free the topic filter malloced in qcloud_iot_mqtt_subscribe */ HAL_Free((void *)pClient->sub_handles[i].topic_filter); pClient->sub_handles[i].topic_filter = NULL; + /* We don't want to break here, if the same topic is registered * with 2 callbacks. Unlikely scenario */ suber_exists = true; @@ -147,21 +155,22 @@ int qcloud_iot_mqtt_unsubscribe(Qcloud_IoT_Client *pClient, char *topicFilter) { HAL_MutexLock(pClient->lock_write_buf); packet_id = get_next_packet_id(pClient); - rc = _serialize_unsubscribe_packet(pClient->write_buf, pClient->write_buf_size, 0, packet_id, 1, &topic_filter_stored, - &len); - if (QCLOUD_ERR_SUCCESS != rc) { - HAL_MutexUnlock(pClient->lock_write_buf); - HAL_Free(topic_filter_stored); + rc = _serialize_unsubscribe_packet(pClient->write_buf, pClient->write_buf_size, 0, packet_id, 1, + &topic_filter_stored, &len); + if (QCLOUD_RET_SUCCESS != rc) { + HAL_MutexUnlock(pClient->lock_write_buf); + HAL_Free(topic_filter_stored); IOT_FUNC_EXIT_RC(rc); } SubTopicHandle sub_handle; - sub_handle.topic_filter = topic_filter_stored; - sub_handle.message_handler = NULL; - sub_handle.message_handler_data = NULL; + sub_handle.topic_filter = topic_filter_stored; + sub_handle.sub_event_handler = NULL; + sub_handle.message_handler = NULL; + sub_handle.handler_user_data = NULL; rc = push_sub_info_to(pClient, len, (unsigned int)packet_id, UNSUBSCRIBE, &sub_handle, &node); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { Log_e("push publish into to pubInfolist failed: %d", rc); HAL_MutexUnlock(pClient->lock_write_buf); HAL_Free(topic_filter_stored); @@ -170,13 +179,13 @@ int qcloud_iot_mqtt_unsubscribe(Qcloud_IoT_Client *pClient, char *topicFilter) { /* send the unsubscribe packet */ rc = send_mqtt_packet(pClient, len, &timer); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { HAL_MutexLock(pClient->lock_list_sub); list_remove(pClient->list_sub_wait_ack, node); HAL_MutexUnlock(pClient->lock_list_sub); - HAL_MutexUnlock(pClient->lock_write_buf); - HAL_Free(topic_filter_stored); + HAL_MutexUnlock(pClient->lock_write_buf); + HAL_Free(topic_filter_stored); IOT_FUNC_EXIT_RC(rc); } diff --git a/src/mqtt/src/mqtt_client_yield.c b/sdk_src/protocol/mqtt/mqtt_client_yield.c similarity index 66% rename from src/mqtt/src/mqtt_client_yield.c rename to sdk_src/protocol/mqtt/mqtt_client_yield.c index 9a45a4a0..e29763ea 100644 --- a/src/mqtt/src/mqtt_client_yield.c +++ b/sdk_src/protocol/mqtt/mqtt_client_yield.c @@ -18,97 +18,108 @@ extern "C" { #endif -#include "mqtt_client.h" #include "log_upload.h" +#include "mqtt_client.h" +#include "qcloud_iot_import.h" -static void _iot_disconnect_callback(Qcloud_IoT_Client *pClient) +static uint32_t _get_random_interval(void) { + srand((unsigned)HAL_GetTimeMs()); + /* range: 1000 - 2000 ms, in 10ms unit */ + return (rand() % 100 + 100) * 10; +} +static void _iot_disconnect_callback(Qcloud_IoT_Client *pClient) +{ if (NULL != pClient->event_handle.h_fp) { MQTTEventMsg msg; msg.event_type = MQTT_EVENT_DISCONNECT; - msg.msg = NULL; + msg.msg = NULL; pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); } } -static void _reconnect_callback(Qcloud_IoT_Client* pClient) +static void _reconnect_callback(Qcloud_IoT_Client *pClient) { if (NULL != pClient->event_handle.h_fp) { MQTTEventMsg msg; msg.event_type = MQTT_EVENT_RECONNECT; - msg.msg = NULL; + msg.msg = NULL; pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); } } /** - * @brief 处理非手动断开连接的情况 + * @brief handle exceptional disconnection * * @param pClient * @return */ -static int _handle_disconnect(Qcloud_IoT_Client *pClient) { +static int _handle_disconnect(Qcloud_IoT_Client *pClient) +{ IOT_FUNC_ENTRY; int rc; - + if (0 == get_client_conn_state(pClient)) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); } rc = qcloud_iot_mqtt_disconnect(pClient); - // 若断开连接失败, 强制断开底层TLS层连接 - if (rc != QCLOUD_ERR_SUCCESS) { + // disconnect network stack by force + if (rc != QCLOUD_RET_SUCCESS) { pClient->network_stack.disconnect(&(pClient->network_stack)); set_client_conn_state(pClient, NOTCONNECTED); } Log_e("disconnect MQTT for some reasons.."); - + _iot_disconnect_callback(pClient); - // 非手动断开连接 + // exceptional disconnection pClient->was_manually_disconnected = 0; IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); } /** - * @brief 处理自动重连的相关逻辑 + * @brief handle reconnect * * @param pClient * @return */ -static int _handle_reconnect(Qcloud_IoT_Client *pClient) { +static int _handle_reconnect(Qcloud_IoT_Client *pClient) +{ IOT_FUNC_ENTRY; int8_t isPhysicalLayerConnected = 1; - int rc = QCLOUD_ERR_MQTT_RECONNECTED; + int rc = QCLOUD_RET_MQTT_RECONNECTED; - // 自动重连等待时间还未过期, 还未到重连的时候, 返回正在进行重连 + // reconnect control by delay timer (increase interval exponentially ) if (!expired(&(pClient->reconnect_delay_timer))) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT); } if (NULL != pClient->network_stack.is_connected) { - isPhysicalLayerConnected = (int8_t) pClient->network_stack.is_connected(&(pClient->network_stack)); // always return 1 + isPhysicalLayerConnected = + (int8_t)pClient->network_stack.is_connected(&(pClient->network_stack)); // always return 1 } if (isPhysicalLayerConnected) { rc = qcloud_iot_mqtt_attempt_reconnect(pClient); - if (rc == QCLOUD_ERR_MQTT_RECONNECTED) { + if (rc == QCLOUD_RET_MQTT_RECONNECTED) { Log_e("attempt to reconnect success."); _reconnect_callback(pClient); -#ifdef LOG_UPLOAD - int log_level; - if (qcloud_get_log_level(pClient, &log_level) < 0) { - Log_e("client get log topic failed: %d", rc); +#ifdef LOG_UPLOAD + if (is_log_uploader_init()) { + int log_level; + if (qcloud_get_log_level(pClient, &log_level) < 0) { + Log_e("client get log topic failed: %d", rc); + } } -#endif +#endif IOT_FUNC_EXIT_RC(rc); - } - else { + } else { Log_e("attempt to reconnect failed, errCode: %d", rc); rc = QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT; } @@ -125,87 +136,98 @@ static int _handle_reconnect(Qcloud_IoT_Client *pClient) { } /** - * @brief 处理与服务器维持心跳的相关逻辑 + * @brief handle MQTT keep alive (hearbeat with server) * * @param pClient * @return */ static int _mqtt_keep_alive(Qcloud_IoT_Client *pClient) { -#define MQTT_PING_RETRY_TIMES 2 +#define MQTT_PING_RETRY_TIMES 2 IOT_FUNC_ENTRY; - int rc; - Timer timer; + int rc; + Timer timer; uint32_t serialized_len = 0; if (0 == pClient->options.keep_alive_interval) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } if (!expired(&pClient->ping_timer)) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } if (pClient->is_ping_outstanding >= MQTT_PING_RETRY_TIMES) { - //Reaching here means we haven't received any MQTT packet for a long time (keep_alive_interval) + // Reaching here means we haven't received any MQTT packet for a long time (keep_alive_interval) Log_e("Fail to recv MQTT msg. Something wrong with the connection."); rc = _handle_disconnect(pClient); IOT_FUNC_EXIT_RC(rc); } - /* there is no ping outstanding - send one */ + /* there is no ping outstanding - send one */ HAL_MutexLock(pClient->lock_write_buf); rc = serialize_packet_with_zero_payload(pClient->write_buf, pClient->write_buf_size, PINGREQ, &serialized_len); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { HAL_MutexUnlock(pClient->lock_write_buf); IOT_FUNC_EXIT_RC(rc); } /* send the ping packet */ int i = 0; - InitTimer(&timer); + InitTimer(&timer); do { countdown_ms(&timer, pClient->command_timeout_ms); rc = send_mqtt_packet(pClient, serialized_len, &timer); - } while (QCLOUD_ERR_SUCCESS != rc && (i++ < 3)); - - if (QCLOUD_ERR_SUCCESS != rc) { - HAL_MutexUnlock(pClient->lock_write_buf); - //If sending a PING fails, propably the connection is not OK and we decide to disconnect and begin reconnection attempts + } while (QCLOUD_RET_SUCCESS != rc && (i++ < 3)); + + if (QCLOUD_RET_SUCCESS != rc) { + HAL_MutexUnlock(pClient->lock_write_buf); + // If sending a PING fails, propably the connection is not OK and we decide to disconnect and begin reconnection + // attempts Log_e("Fail to send PING request. Something wrong with the connection."); rc = _handle_disconnect(pClient); IOT_FUNC_EXIT_RC(rc); } HAL_MutexUnlock(pClient->lock_write_buf); - + HAL_MutexLock(pClient->lock_generic); pClient->is_ping_outstanding++; /* start a timer to wait for PINGRESP from server */ - countdown(&pClient->ping_timer, Min(5, pClient->options.keep_alive_interval/2)); + countdown(&pClient->ping_timer, Min(5, pClient->options.keep_alive_interval / 2)); HAL_MutexUnlock(pClient->lock_generic); Log_d("PING request %u has been sent...", pClient->is_ping_outstanding); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -int qcloud_iot_mqtt_yield(Qcloud_IoT_Client *pClient, uint32_t timeout_ms) { +/** + * @brief Check connection and keep alive state, read/handle MQTT message in synchronized way + * + * @param pClient handle to MQTT client + * @param timeout_ms timeout value (unit: ms) for this operation + * + * @return QCLOUD_RET_SUCCESS when success, QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT when try reconnecing, or err code for + * failure + */ +int qcloud_iot_mqtt_yield(Qcloud_IoT_Client *pClient, uint32_t timeout_ms) +{ IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; - Timer timer; + int rc = QCLOUD_RET_SUCCESS; + Timer timer; uint8_t packet_type; POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); - // 1. 检查连接是否已经手动断开 + // 1. check if manually disconnect if (!get_client_conn_state(pClient) && pClient->was_manually_disconnected == 1) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED); + IOT_FUNC_EXIT_RC(QCLOUD_RET_MQTT_MANUALLY_DISCONNECTED); } - // 2. 检查连接是否断开, 自动连接是否开启 + // 2. check connection state and if auto reconnect is enabled if (!get_client_conn_state(pClient) && pClient->options.auto_connect_enable == 0) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); } @@ -213,9 +235,8 @@ int qcloud_iot_mqtt_yield(Qcloud_IoT_Client *pClient, uint32_t timeout_ms) { InitTimer(&timer); countdown_ms(&timer, timeout_ms); - // 3. 循环读取消息以及心跳包管理 - while (!expired(&timer)) { - + // 3. main loop for packet reading/handling and keep alive maintainance + while (!expired(&timer)) { if (!get_client_conn_state(pClient)) { if (pClient->current_reconnect_wait_interval > MAX_RECONNECT_WAIT_INTERVAL) { rc = QCLOUD_ERR_MQTT_RECONNECT_TIMEOUT; @@ -224,11 +245,11 @@ int qcloud_iot_mqtt_yield(Qcloud_IoT_Client *pClient, uint32_t timeout_ms) { rc = _handle_reconnect(pClient); continue; - } + } - rc = cycle_for_read(pClient, &timer, &packet_type, 0); + rc = cycle_for_read(pClient, &timer, &packet_type, QOS0); - if (rc == QCLOUD_ERR_SUCCESS) { + if (rc == QCLOUD_RET_SUCCESS) { /* check list of wait publish ACK to remove node that is ACKED or timeout */ qcloud_iot_mqtt_pub_info_proc(pClient); @@ -236,26 +257,25 @@ int qcloud_iot_mqtt_yield(Qcloud_IoT_Client *pClient, uint32_t timeout_ms) { qcloud_iot_mqtt_sub_info_proc(pClient); rc = _mqtt_keep_alive(pClient); - } - else if (rc == QCLOUD_ERR_SSL_READ_TIMEOUT || rc == QCLOUD_ERR_SSL_READ || - rc == QCLOUD_ERR_TCP_PEER_SHUTDOWN || rc == QCLOUD_ERR_TCP_READ_FAIL){ - Log_e("network read failed, rc: %d. MQTT Disconnect.", rc); - rc = _handle_disconnect(pClient); + } else if (rc == QCLOUD_ERR_SSL_READ_TIMEOUT || rc == QCLOUD_ERR_SSL_READ || + rc == QCLOUD_ERR_TCP_PEER_SHUTDOWN || rc == QCLOUD_ERR_TCP_READ_FAIL) { + Log_e("network read failed, rc: %d. MQTT Disconnect.", rc); + rc = _handle_disconnect(pClient); } if (rc == QCLOUD_ERR_MQTT_NO_CONN) { pClient->counter_network_disconnected++; if (pClient->options.auto_connect_enable == 1) { - pClient->current_reconnect_wait_interval = MIN_RECONNECT_WAIT_INTERVAL; + pClient->current_reconnect_wait_interval = _get_random_interval(); countdown_ms(&(pClient->reconnect_delay_timer), pClient->current_reconnect_wait_interval); - // 如果超时时间到了,则会直接返回 + // reconnect timeout rc = QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT; } else { break; } - } else if (rc != QCLOUD_ERR_SUCCESS) { + } else if (rc != QCLOUD_RET_SUCCESS) { break; } } @@ -263,10 +283,27 @@ int qcloud_iot_mqtt_yield(Qcloud_IoT_Client *pClient, uint32_t timeout_ms) { IOT_FUNC_EXIT_RC(rc); } +// workaround wrapper for qcloud_iot_mqtt_yield for multi-thread mode +int qcloud_iot_mqtt_yield_mt(Qcloud_IoT_Client *mqtt_client, uint32_t timeout_ms) +{ + POINTER_SANITY_CHECK(mqtt_client, QCLOUD_ERR_INVAL); + NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); + +#ifdef MULTITHREAD_ENABLED + /* only one instance of yield is allowed in running state*/ + if (mqtt_client->thread_running) { + HAL_SleepMs(timeout_ms); + return QCLOUD_RET_SUCCESS; + } +#endif + + return qcloud_iot_mqtt_yield(mqtt_client, timeout_ms); +} + /** - * @brief puback等待超时检测 + * @brief puback waiting timeout process * - * @param pClient MQTTClient对象 + * @param pClient reference to MQTTClient * */ int qcloud_iot_mqtt_pub_info_proc(Qcloud_IoT_Client *pClient) @@ -275,7 +312,6 @@ int qcloud_iot_mqtt_pub_info_proc(Qcloud_IoT_Client *pClient) POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - HAL_MutexLock(pClient->lock_list_pub); do { if (0 == pClient->list_pub_wait_ack->len) { @@ -283,8 +319,8 @@ int qcloud_iot_mqtt_pub_info_proc(Qcloud_IoT_Client *pClient) } ListIterator *iter; - ListNode *node = NULL; - ListNode *temp_node = NULL; + ListNode * node = NULL; + ListNode * temp_node = NULL; if (NULL == (iter = list_iterator_new(pClient->list_pub_wait_ack, LIST_TAIL))) { Log_e("new list failed"); @@ -303,7 +339,7 @@ int qcloud_iot_mqtt_pub_info_proc(Qcloud_IoT_Client *pClient) break; /* end of list */ } - QcloudIotPubInfo *repubInfo = (QcloudIotPubInfo *) node->val; + QcloudIotPubInfo *repubInfo = (QcloudIotPubInfo *)node->val; if (NULL == repubInfo) { Log_e("node's value is invalid!"); temp_node = node; @@ -325,19 +361,19 @@ int qcloud_iot_mqtt_pub_info_proc(Qcloud_IoT_Client *pClient) continue; } - /* If wait ACK timeout, republish */ HAL_MutexUnlock(pClient->lock_list_pub); - /* 重发机制交给上层用户二次开发, 这里先把超时的节点从列表中移除 */ + /* If wait ACK timeout, remove the node from list */ + /* It is up to user to do republishing or not */ temp_node = node; countdown_ms(&repubInfo->pub_start_time, pClient->command_timeout_ms); HAL_MutexLock(pClient->lock_list_pub); - /* 通知外部网络已经断开 */ + /* notify timeout event */ if (NULL != pClient->event_handle.h_fp) { MQTTEventMsg msg; msg.event_type = MQTT_EVENT_PUBLISH_TIMEOUT; - msg.msg = (void *)(uintptr_t)repubInfo->msg_id; + msg.msg = (void *)(uintptr_t)repubInfo->msg_id; pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); } } @@ -348,19 +384,19 @@ int qcloud_iot_mqtt_pub_info_proc(Qcloud_IoT_Client *pClient) HAL_MutexUnlock(pClient->lock_list_pub); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * @brief suback等待超时检测 + * @brief suback waiting timeout process * - * @param pClient MQTTClient对象 + * @param pClient reference to MQTTClient * */ int qcloud_iot_mqtt_sub_info_proc(Qcloud_IoT_Client *pClient) { IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; if (!pClient) { IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); @@ -373,15 +409,15 @@ int qcloud_iot_mqtt_sub_info_proc(Qcloud_IoT_Client *pClient) } ListIterator *iter; - ListNode *node = NULL; - ListNode *temp_node = NULL; - uint16_t packet_id = 0; - MessageTypes msg_type; + ListNode * node = NULL; + ListNode * temp_node = NULL; + uint16_t packet_id = 0; + MessageTypes msg_type; if (NULL == (iter = list_iterator_new(pClient->list_sub_wait_ack, LIST_TAIL))) { Log_e("new list failed"); HAL_MutexUnlock(pClient->lock_list_sub); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } for (;;) { @@ -396,7 +432,7 @@ int qcloud_iot_mqtt_sub_info_proc(Qcloud_IoT_Client *pClient) break; /* end of list */ } - QcloudIotSubInfo *sub_info = (QcloudIotSubInfo *) node->val; + QcloudIotSubInfo *sub_info = (QcloudIotSubInfo *)node->val; if (NULL == sub_info) { Log_e("node's value is invalid!"); temp_node = node; @@ -420,7 +456,7 @@ int qcloud_iot_mqtt_sub_info_proc(Qcloud_IoT_Client *pClient) /* When arrive here, it means timeout to wait ACK */ packet_id = sub_info->msg_id; - msg_type = sub_info->type; + msg_type = sub_info->type; /* Wait MQTT SUBSCRIBE ACK timeout */ if (NULL != pClient->event_handle.h_fp) { @@ -429,11 +465,17 @@ int qcloud_iot_mqtt_sub_info_proc(Qcloud_IoT_Client *pClient) if (SUBSCRIBE == msg_type) { /* subscribe timeout */ msg.event_type = MQTT_EVENT_SUBCRIBE_TIMEOUT; - msg.msg = (void *)(uintptr_t)packet_id; - } else { + msg.msg = (void *)(uintptr_t)packet_id; + + /* notify this event to topic subscriber */ + if (NULL != sub_info->handler.sub_event_handler) + sub_info->handler.sub_event_handler(pClient, MQTT_EVENT_SUBCRIBE_TIMEOUT, + sub_info->handler.handler_user_data); + + } else { /* unsubscribe timeout */ msg.event_type = MQTT_EVENT_UNSUBCRIBE_TIMEOUT; - msg.msg = (void *)(uintptr_t)packet_id; + msg.msg = (void *)(uintptr_t)packet_id; } pClient->event_handle.h_fp(pClient, pClient->event_handle.context, &msg); @@ -441,7 +483,7 @@ int qcloud_iot_mqtt_sub_info_proc(Qcloud_IoT_Client *pClient) if (NULL != sub_info->handler.topic_filter) HAL_Free((void *)(sub_info->handler.topic_filter)); - + temp_node = node; } diff --git a/sdk_src/services/broadcast/broadcast.c b/sdk_src/services/broadcast/broadcast.c new file mode 100755 index 00000000..1a033a54 --- /dev/null +++ b/sdk_src/services/broadcast/broadcast.c @@ -0,0 +1,103 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "mqtt_client.h" +#include "qcloud_iot_export_broadcast.h" +#include "utils_param_check.h" + +#ifdef BROADCAST_ENABLED + +static void _broadcast_message_cb(void *pClient, MQTTMessage *message, void *pContext) +{ + OnBroadcastMessageCallback callback = (OnBroadcastMessageCallback)pContext; + Log_d("topic=%.*s", message->topic_len, STRING_PTR_PRINT_SANITY_CHECK(message->ptopic)); + Log_i("len=%u, topic_msg=%.*s", message->payload_len, message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); + if (callback) { + callback(pClient, message->payload, message->payload_len); + } +} + +static void _broadcast_event_callback(void *pClient, MQTTEventType event_type, void *user_data) +{ + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + switch (event_type) { + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_d("broadcast topic subscribe success"); + mqtt_client->broadcast_state = true; + break; + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("broadcast topic subscribe timeout"); + mqtt_client->broadcast_state = false; + break; + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("broadcast topic subscribe NACK"); + mqtt_client->broadcast_state = false; + break; + case MQTT_EVENT_UNSUBSCRIBE: + Log_i("broadcast topic has been unsubscribed"); + mqtt_client->broadcast_state = false; + break; + case MQTT_EVENT_CLIENT_DESTROY: + Log_i("mqtt client has been destroyed"); + mqtt_client->broadcast_state = false; + break; + default: + return; + } +} + +int IOT_Broadcast_Subscribe(void *pClient, OnBroadcastMessageCallback callback) +{ + int ret; + char broadcast_topic[MAX_SIZE_OF_CLOUD_TOPIC + 1]; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.on_message_handler = _broadcast_message_cb; + sub_params.on_sub_event_handler = _broadcast_event_callback; + sub_params.qos = QOS1; + sub_params.user_data = callback; + + HAL_Snprintf(broadcast_topic, MAX_SIZE_OF_CLOUD_TOPIC, "$broadcast/rxd/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.device_name)); + + if (!mqtt_client->broadcast_state) { + for (int cntSub = 0; cntSub < 3; cntSub++) { + ret = IOT_MQTT_Subscribe(mqtt_client, broadcast_topic, &sub_params); + if (ret < 0) { + Log_e("broadcast topic subscribe failed: %d, cnt: %d", ret, cntSub); + continue; + } + + /* wait for sub ack */ + ret = qcloud_iot_mqtt_yield_mt(mqtt_client, 500); + if (ret || mqtt_client->broadcast_state) { + break; + } + } + } + + if (!mqtt_client->broadcast_state) { + Log_e("Subscribe broadcast topic failed!"); + return QCLOUD_ERR_FAILURE; + } + return QCLOUD_RET_SUCCESS; +} + +#endif diff --git a/sdk_src/services/config/remote_config_mqtt.c b/sdk_src/services/config/remote_config_mqtt.c new file mode 100644 index 00000000..99def30e --- /dev/null +++ b/sdk_src/services/config/remote_config_mqtt.c @@ -0,0 +1,327 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifdef REMOTE_CONFIG_MQTT +#include +#include "lite-utils.h" +#include "mqtt_client.h" +#include "qcloud_iot_device.h" +#include "qcloud_iot_export_remote_config.h" + +#define JSON_TYPE_STRING_PUSH "push" +#define JSON_TYPE_STRING_REPLY "reply" +#define JSON_TYPE_STRING_GET "get" + +#define CONFIG_PUBLISH_TOPIC_FORMAT "$config/operation/%s/%s" +#define CONFIG_SUBSCRIBE_TOPIC_FORMAT "$config/operation/result/%s/%s" + +static int _check_snprintf_return(int32_t return_code, size_t max_size_of_write) +{ + if (return_code >= max_size_of_write) { + return QCLOUD_ERR_JSON_BUFFER_TRUNCATED; + } else if (return_code < 0) { // err + return QCLOUD_ERR_JSON; + } + + return QCLOUD_RET_SUCCESS; +} + +/**************************** +{ + "type":"push", + "payload": {} +} + +{ + "type":"reply", + "result":0/1001, + "payload": {} +} + +****************************/ +static void _config_mqtt_message_callback(void *client, MQTTMessage *message, void *user_data) +{ + POINTER_SANITY_CHECK_RTN(message); + POINTER_SANITY_CHECK_RTN(client); + + ConfigSubscirbeUserData *config_sub_userdata = (ConfigSubscirbeUserData *)user_data; + POINTER_SANITY_CHECK_RTN(config_sub_userdata); + POINTER_SANITY_CHECK_RTN(config_sub_userdata->on_config_proc); + POINTER_SANITY_CHECK_RTN(config_sub_userdata->json_buffer); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)client; + ConfigMQTTState * config_state = &mqtt_client->config_state; + char * payload = config_sub_userdata->json_buffer; + char * type = NULL; + char * result = NULL; + char * config_payload = NULL; + + // proc recv buff, copy recv data to config_sub_userdata json buffer, need 1B to save '\0' + if (message->payload_len > (config_sub_userdata->json_buffer_len - 1)) { + Log_e("topic message arrived, config user data json buffer len :%d < recv buff len :%d", + config_sub_userdata->json_buffer_len - 1, message->payload_len); + return; + } else { + memcpy(payload, message->payload, message->payload_len); + payload[message->payload_len] = '\0'; + } + + Log_d("Recv Msg Topic:%s, buff data:%s", STRING_PTR_PRINT_SANITY_CHECK(message->ptopic), payload); + + type = LITE_json_value_of("type", payload); + if (NULL == type) { + Log_e("topic message arrived, data error,no type key"); + goto exit; + } + // reply data ? + if (0 == strcmp(type, JSON_TYPE_STRING_REPLY)) { + config_state->get_reply_ok = true; + + result = LITE_json_value_of("result", payload); + if (NULL == result) { + Log_e("topic message arrived, data error,no result key"); + goto exit; + } + } else if (0 != strcmp(type, JSON_TYPE_STRING_PUSH)) { + Log_e("topic message arrived, data error, type: %s is unknow", type); + goto exit; + } + + if ((result != NULL) && (REMOTE_CONFIG_ERRCODE_DISABLE == atoi(result))) { + Log_i("topic message arrived, get config failed cloud platform config disable"); + } + + config_payload = LITE_json_value_of("payload", payload); + // copy config data to user_data json buffer + if (NULL == config_payload) { + config_sub_userdata->json_buffer[0] = '\0'; + } else { + memcpy(config_sub_userdata->json_buffer, config_payload, strlen(config_payload)); + config_sub_userdata->json_buffer[strlen(config_payload)] = '\0'; + } + + if (NULL == result) { + config_sub_userdata->on_config_proc(client, REMOTE_CONFIG_ERRCODE_SUCCESS, config_sub_userdata->json_buffer, + strlen(config_sub_userdata->json_buffer)); + } else { + config_sub_userdata->on_config_proc(client, atoi(result), config_sub_userdata->json_buffer, + strlen(config_sub_userdata->json_buffer)); + } + +exit: + HAL_Free(type); + HAL_Free(result); + HAL_Free(config_payload); + + return; +} + +static void _config_mqtt_sub_event_handler(void *client, MQTTEventType event_type, void *user_data) +{ + POINTER_SANITY_CHECK_RTN(client); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)client; + ConfigMQTTState * config_state = &(mqtt_client->config_state); + + switch (event_type) { + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_d("mqtt config topic subscribe success"); + + config_state->topic_sub_ok = true; + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("mqtt config topic subscribe timeout"); + + config_state->topic_sub_ok = false; + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("mqtt config topic subscribe NACK"); + + config_state->topic_sub_ok = false; + break; + case MQTT_EVENT_UNSUBSCRIBE: + Log_i("mqtt config topic has been unsubscribed"); + + config_state->topic_sub_ok = false; + break; + case MQTT_EVENT_CLIENT_DESTROY: + Log_i("mqtt config has been destroyed"); + + config_state->topic_sub_ok = false; + break; + default: + return; + } + + config_state->get_reply_ok = true; +} + +static int _iot_config_mqtt_subscribe(void *client, ConfigSubscirbeUserData *config_sub_userdata) +{ + POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(config_sub_userdata, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(config_sub_userdata->on_config_proc, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(config_sub_userdata->json_buffer, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)client; + DeviceInfo * dev_info = &mqtt_client->device_info; + + char topic_name[128] = {0}; + + int size = HAL_Snprintf(topic_name, sizeof(topic_name), CONFIG_SUBSCRIBE_TOPIC_FORMAT, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name)); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.on_message_handler = _config_mqtt_message_callback; + sub_params.on_sub_event_handler = _config_mqtt_sub_event_handler; + sub_params.user_data = (void *)config_sub_userdata; + sub_params.qos = QOS0; + + return IOT_MQTT_Subscribe(client, topic_name, &sub_params); +} + +int IOT_Subscribe_Config(void *client, ConfigSubscirbeUserData *config_sub_userdata, int subscribe_timeout) +{ + int ret = QCLOUD_RET_SUCCESS; + + POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)client; + ConfigMQTTState * config_state = &mqtt_client->config_state; + Timer timer; + int packet_id = 0; + + config_state->topic_sub_ok = false; + config_state->get_reply_ok = false; + + ret = _iot_config_mqtt_subscribe(client, config_sub_userdata); + + if (0 > ret) { + Log_e("config topic subscribe failed, ret:%d", ret); + + return ret; + } + packet_id = ret; + // wait for sub ack + InitTimer(&timer); + countdown_ms(&timer, subscribe_timeout); + while (false == config_state->get_reply_ok) { + if (expired(&timer)) { + ret = QCLOUD_ERR_MQTT_REQUEST_TIMEOUT; + break; + } + ret = qcloud_iot_mqtt_yield_mt(mqtt_client, 100); + if (QCLOUD_RET_SUCCESS != ret) { + break; + } + } + if (true == config_state->topic_sub_ok) { + ret = packet_id; + } else if (QCLOUD_RET_SUCCESS == ret) { // multi thread nack + ret = QCLOUD_ERR_MQTT_SUB; + } + + return ret; +} + +static int _iot_config_report_mqtt_publish(void *client, void *json_buffer) +{ + POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)client; + DeviceInfo * dev_info = &mqtt_client->device_info; + POINTER_SANITY_CHECK(dev_info, QCLOUD_ERR_INVAL); + + char topic_name[128] = {0}; + + HAL_Snprintf(topic_name, sizeof(topic_name), CONFIG_PUBLISH_TOPIC_FORMAT, + STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name)); + + PublishParams pub_params = DEFAULT_PUB_PARAMS; + pub_params.qos = QOS0; + pub_params.payload = json_buffer; + pub_params.payload_len = strlen(json_buffer); + + return IOT_MQTT_Publish(mqtt_client, topic_name, &pub_params); +} + +int IOT_Get_Config(void *client, char *json_buffer, int buffer_size, int reply_timeout) +{ + POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); + int ret = 0; + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)client; + Timer timer; + ConfigMQTTState * config_state = &mqtt_client->config_state; + int32_t rc_of_snprintf = 0; + + // return failure if subscribe failed + if (false == config_state->topic_sub_ok) { + Log_e("Subscribe config topic failed!"); + return QCLOUD_ERR_FAILURE; + } + + // create get json string + rc_of_snprintf = HAL_Snprintf(json_buffer, buffer_size, "{\"type\":\"%s\"}", JSON_TYPE_STRING_GET); + ret = _check_snprintf_return(rc_of_snprintf, buffer_size); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("Construct Report Info failed, ret:%d!", ret); + return ret; + } + + config_state->get_reply_ok = false; + + // publish msg to get config + ret = _iot_config_report_mqtt_publish(mqtt_client, json_buffer); + if (ret < 0) { + Log_e("client publish config topic failed :%d.", ret); + return ret; + } + + // wait for reply + InitTimer(&timer); + countdown_ms(&timer, reply_timeout); + while (false == config_state->get_reply_ok) { + if (expired(&timer)) { + ret = QCLOUD_ERR_MQTT_REQUEST_TIMEOUT; + Log_e("get config wait reply timeout"); + break; + } + ret = qcloud_iot_mqtt_yield_mt(mqtt_client, 100); + + if (QCLOUD_RET_SUCCESS != ret) { + break; + } + } + return ret; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk_src/services/dynreg/dynreg.c b/sdk_src/services/dynreg/dynreg.c new file mode 100755 index 00000000..72d05638 --- /dev/null +++ b/sdk_src/services/dynreg/dynreg.c @@ -0,0 +1,496 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lite-utils.h" +#include "qcloud_iot_ca.h" +#include "qcloud_iot_common.h" +#include "qcloud_iot_device.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" +#include "utils_aes.h" +#include "utils_base64.h" +#include "utils_hmac.h" +#include "utils_httpc.h" + +#define REG_URL_MAX_LEN (128) +#define DYN_REG_SIGN_LEN (64) +#define DYN_BUFF_DATA_MORE (10) +#define BASE64_ENCODE_OUT_LEN(x) (((x + 3) * 4) / 3) +#define DYN_REG_RES_HTTP_TIMEOUT_MS (2000) + +#ifdef AUTH_MODE_CERT +#define DYN_RESPONSE_BUFF_LEN (5 * 1024) +#define DECODE_BUFF_LEN (5 * 1024) +#else +#define DYN_RESPONSE_BUFF_LEN (256) +#define DECODE_BUFF_LEN (256) +#endif + +/* Knuth's TAOCP section 3.6 */ +#define M ((1U << 31) - 1) +#define A 48271 +#define Q 44488 // M/A +#define R 3399 // M%A; R < Q !!! + +#define CODE_RESAULT "code" +#define ENCRYPT_TYPE "encryptionType" +#define PSK_DATA "psk" +#define CERT_DATA "clientCert" +#define KEY_DATA "clientKey" + +typedef enum { + eCERT_TYPE = 1, + ePSK_TYPE = 2, +} eAuthType; + +/*Global value*/ +static unsigned int _seed = 1; + +int rand_r(unsigned int *seed) +{ + int32_t X; + + X = *seed; + X = A * (X % Q) - R * (int32_t)(X / Q); + if (X < 0) + X += M; + + *seed = X; + return X; +} + +int rand_d(void) +{ + return rand_r(&_seed); +} + +void srand_d(unsigned int i) +{ + _seed = i; +} + +static int _get_json_resault_code(char *json) +{ + int resault = -1; + char *v = LITE_json_value_of(CODE_RESAULT, json); + + if (v == NULL) { + Log_e("Invalid json content: %s", STRING_PTR_PRINT_SANITY_CHECK(json)); + return -1; + } + + if (LITE_get_int32(&resault, v) != QCLOUD_RET_SUCCESS) { + Log_e("Invalid json content: %s", json); + HAL_Free(v); + return -1; + } + + HAL_Free(v); + + return resault; +} + +static int _get_json_encry_type(char *json) +{ + int type = -1; + char *v = LITE_json_value_of(ENCRYPT_TYPE, json); + + if (v == NULL) { + Log_e("Get encry type fail, %s", STRING_PTR_PRINT_SANITY_CHECK(json)); + return -1; + } + + if (LITE_get_int32(&type, v) != QCLOUD_RET_SUCCESS) { + Log_e("Invalid json content: %s", json); + HAL_Free(v); + return -1; + } + + HAL_Free(v); + + return type; +} + +#ifndef AUTH_MODE_CERT + +static char *_get_json_psk(char *json) +{ + char *psk = LITE_json_value_of(PSK_DATA, json); + + if (psk == NULL) { + Log_e("Get psk fail: %s", STRING_PTR_PRINT_SANITY_CHECK(json)); + } + + return psk; +} + +#else +static char *_get_json_cert_data(char *json) +{ + char *cert = LITE_json_value_of(CERT_DATA, json); + + if (cert == NULL) { + Log_e("Get clientCert fail: %s", STRING_PTR_PRINT_SANITY_CHECK(json)); + } + + return cert; +} + +static char *_get_json_key_data(char *json) +{ + char *key = LITE_json_value_of(KEY_DATA, json); + + if (key == NULL) { + Log_e("Get clientCert fail: %s", STRING_PTR_PRINT_SANITY_CHECK(json)); + } + + return key; +} + +/*\\n in data change to '\n'*/ +static void _deal_transfer(char *data, uint32_t dataLen) +{ + int i; + + for (i = 0; i < dataLen; i++) { + if ((data[i] == '\\') && (data[i + 1] == 'n')) { + data[i] = ' '; + data[i + 1] = '\n'; + } + } +} + +static int _cert_file_save(const char *fileName, char *data, uint32_t dataLen) +{ + FILE * fp; + char filePath[FILE_PATH_MAX_LEN]; + uint32_t len; + int Ret = QCLOUD_ERR_FAILURE; + + memset(filePath, 0, FILE_PATH_MAX_LEN); + HAL_Snprintf(filePath, FILE_PATH_MAX_LEN, "./certs/%s", STRING_PTR_PRINT_SANITY_CHECK(fileName)); + + if ((fp = fopen(filePath, "w+")) == NULL) { + Log_e("fail to open file %s", STRING_PTR_PRINT_SANITY_CHECK(fileName)); + goto exit; + } + + _deal_transfer(data, dataLen); + len = fprintf(fp, "%s", data); + fclose(fp); + + if (len == dataLen) { + Log_d("save %s file succes", fileName); + Ret = QCLOUD_RET_SUCCESS; + } + +exit: + return Ret; +} + +#endif + +static int _parse_devinfo(char *jdoc, DeviceInfo *pDevInfo) +{ + int ret = 0; + size_t len; + int datalen; + int enType; + unsigned int keybits; + char key[UTILS_AES_BLOCK_LEN + 1]; + char decodeBuff[DECODE_BUFF_LEN] = {0}; + unsigned char iv[16]; + char * payload = NULL; + +#ifdef AUTH_MODE_CERT + char *clientCert; + char *clientKey; +#else + char *psk; +#endif + + Log_d("recv: %s", STRING_PTR_PRINT_SANITY_CHECK(jdoc)); + + ret = _get_json_resault_code(jdoc); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("response err, ret:%d", ret); + goto exit; + } + + payload = LITE_json_value_of("payload", jdoc); + if (payload == NULL) { + Log_e("Invalid json content: %s", jdoc); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } else { + Log_d("payload:%s", payload); + } + + ret = qcloud_iot_utils_base64decode((uint8_t *)decodeBuff, sizeof(decodeBuff), &len, (uint8_t *)payload, + strlen(payload)); + if (ret != QCLOUD_RET_SUCCESS) { + Log_e("Response decode err, response:%s", payload); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + datalen = len + (UTILS_AES_BLOCK_LEN - len % UTILS_AES_BLOCK_LEN); + keybits = AES_KEY_BITS_128; + memset(key, 0, UTILS_AES_BLOCK_LEN); + strncpy(key, pDevInfo->product_secret, UTILS_AES_BLOCK_LEN); + memset(iv, '0', UTILS_AES_BLOCK_LEN); + ret = utils_aes_cbc((uint8_t *)decodeBuff, datalen, (uint8_t *)decodeBuff, DECODE_BUFF_LEN, UTILS_AES_DECRYPT, + (uint8_t *)key, keybits, iv); + if (QCLOUD_RET_SUCCESS == ret) { + // Log_d("The decrypted data is:%s", decodeBuff); + + } else { + Log_e("data decry err,ret:%d", ret); + goto exit; + } + + enType = _get_json_encry_type(decodeBuff); + if (enType < 0) { + Log_e("invlid encryt type, decrypt maybe faild"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + +#ifdef AUTH_MODE_CERT + if (eCERT_TYPE != enType) { + Log_e("encryt type should be cert type"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + clientCert = _get_json_cert_data(decodeBuff); + if (NULL != clientCert) { + memset(pDevInfo->dev_cert_file_name, 0, MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); + HAL_Snprintf(pDevInfo->dev_cert_file_name, MAX_SIZE_OF_DEVICE_CERT_FILE_NAME, "%s_cert.crt", + STRING_PTR_PRINT_SANITY_CHECK(pDevInfo->device_name)); + if (QCLOUD_RET_SUCCESS != _cert_file_save(pDevInfo->dev_cert_file_name, clientCert, strlen(clientCert))) { + Log_e("save %s file fail", pDevInfo->dev_cert_file_name); + ret = QCLOUD_ERR_FAILURE; + } + + HAL_Free(clientCert); + + } else { + Log_e("Get clientCert data fail"); + ret = QCLOUD_ERR_FAILURE; + } + + clientKey = _get_json_key_data(decodeBuff); + if (NULL != clientKey) { + memset(pDevInfo->dev_key_file_name, 0, MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); + HAL_Snprintf(pDevInfo->dev_key_file_name, MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME, "%s_private.key", + pDevInfo->device_name); + if (QCLOUD_RET_SUCCESS != _cert_file_save(pDevInfo->dev_key_file_name, clientKey, strlen(clientKey))) { + Log_e("save %s file fail", pDevInfo->dev_key_file_name); + ret = QCLOUD_ERR_FAILURE; + } + + HAL_Free(clientKey); + + } else { + Log_e("Get clientCert data fail"); + ret = QCLOUD_ERR_FAILURE; + } + +#else + if (ePSK_TYPE != enType) { + Log_e("encryt type should be psk type"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + psk = _get_json_psk(decodeBuff); + if (NULL != psk) { + if (strlen(psk) > MAX_SIZE_OF_DEVICE_SECRET) { + Log_e("psk exceed max len,%s", psk); + strcpy(pDevInfo->device_secret, psk); + } else { + strncpy(pDevInfo->device_secret, psk, MAX_SIZE_OF_DEVICE_SECRET); + pDevInfo->device_secret[MAX_SIZE_OF_DEVICE_SECRET] = '\0'; + } + HAL_Free(psk); + } else { + Log_e("Get psk data fail"); + } +#endif +exit: + + if (payload) { + HAL_Free(payload); + } + + return ret; +} + +static int _post_reg_request_by_http(char *request_buf, DeviceInfo *pDevInfo) +{ + int Ret = 0; + HTTPClient http_client; /* http client */ + HTTPClientData http_data; /* http client data */ + + const char *url_format = "%s://%s/register/dev"; + char url[REG_URL_MAX_LEN] = {0}; + int port; + const char *ca_crt = NULL; + char respbuff[DYN_RESPONSE_BUFF_LEN]; + + /*format URL*/ +#ifndef AUTH_WITH_NOTLS + HAL_Snprintf(url, REG_URL_MAX_LEN, url_format, "https", DYN_REG_SERVER_URL); + port = DYN_REG_SERVER_PORT_TLS; + ca_crt = iot_ca_get(); +#else + HAL_Snprintf(url, REG_URL_MAX_LEN, url_format, "http", DYN_REG_SERVER_URL); + port = DYN_REG_SERVER_PORT; +#endif + + memset((char *)&http_client, 0, sizeof(HTTPClient)); + memset((char *)&http_data, 0, sizeof(HTTPClientData)); + + http_client.header = "Accept: text/xml,application/json;*/*\r\n"; + + http_data.post_content_type = "application/x-www-form-urlencoded"; + http_data.post_buf = request_buf; + http_data.post_buf_len = strlen(request_buf); + + Ret = qcloud_http_client_common(&http_client, url, port, ca_crt, HTTP_POST, &http_data); + if (QCLOUD_RET_SUCCESS != Ret) { + Log_e("qcloud_http_client_common failed, Ret = %d", Ret); + return Ret; + } + + memset(respbuff, 0, DYN_RESPONSE_BUFF_LEN); + http_data.response_buf_len = DYN_RESPONSE_BUFF_LEN; + http_data.response_buf = respbuff; + + Ret = qcloud_http_recv_data(&http_client, DYN_REG_RES_HTTP_TIMEOUT_MS, &http_data); + if (QCLOUD_RET_SUCCESS != Ret) { + Log_e("dynamic register response fail, Ret = %d", Ret); + } else { + /*Parse dev info*/ + Ret = _parse_devinfo(http_data.response_buf, pDevInfo); + if (QCLOUD_RET_SUCCESS != Ret) { + Log_e("parse device info err"); + } + } + + qcloud_http_client_close(&http_client); + + return Ret; +} + +static int _cal_dynreg_sign(DeviceInfo *pDevInfo, char *signout, int max_signlen, int nonce, uint32_t timestamp) +{ + int sign_len; + size_t olen = 0; + char * pSignSource = NULL; + const char *sign_fmt = "deviceName=%s&nonce=%d&productId=%s×tamp=%d"; + char sign[DYN_REG_SIGN_LEN] = {0}; + + /*format sign data*/ + sign_len = strlen(sign_fmt) + strlen(pDevInfo->device_name) + strlen(pDevInfo->product_id) + sizeof(int) + + sizeof(uint32_t) + DYN_BUFF_DATA_MORE; + pSignSource = HAL_Malloc(sign_len); + if (pSignSource == NULL) { + Log_e("malloc sign source buff fail"); + return QCLOUD_ERR_FAILURE; + } + memset(pSignSource, 0, sign_len); + HAL_Snprintf((char *)pSignSource, sign_len, sign_fmt, pDevInfo->device_name, nonce, pDevInfo->product_id, + timestamp); + + /*cal hmac sha1*/ + utils_hmac_sha1(pSignSource, strlen(pSignSource), sign, pDevInfo->product_secret, strlen(pDevInfo->product_secret)); + + /*base64 encode*/ + qcloud_iot_utils_base64encode((uint8_t *)signout, max_signlen, &olen, (const uint8_t *)sign, strlen(sign)); + + HAL_Free(pSignSource); + + return (olen > max_signlen) ? QCLOUD_ERR_FAILURE : QCLOUD_RET_SUCCESS; +} + +int IOT_DynReg_Device(DeviceInfo *pDevInfo) +{ + const char *para_format = + "{\"deviceName\":\"%s\",\"nonce\":%d,\"productId\":\"%s\",\"timestamp\":%d,\"signature\":\"%s\"}"; + int nonce; + int Ret; + uint32_t timestamp; + int len; + char sign[DYN_REG_SIGN_LEN] = {0}; + char * pRequest = NULL; + + if (strlen(pDevInfo->product_secret) < UTILS_AES_BLOCK_LEN) { + Log_e("product key inllegal"); + return QCLOUD_ERR_FAILURE; + } + + srand_d(HAL_GetTimeMs()); + nonce = rand_d(); + timestamp = time(0); + + /*cal sign*/ + if (QCLOUD_RET_SUCCESS == _cal_dynreg_sign(pDevInfo, sign, DYN_REG_SIGN_LEN, nonce, timestamp)) { + Log_d("sign:%s", sign); + } else { + Log_e("cal sign fail"); + return QCLOUD_ERR_FAILURE; + } + + /*format http request*/ + len = strlen(para_format) + strlen(pDevInfo->product_id) + strlen(pDevInfo->device_name) + sizeof(int) + + sizeof(uint32_t) + strlen(sign) + DYN_BUFF_DATA_MORE; + pRequest = HAL_Malloc(len); + if (!pRequest) { + Log_e("malloc request memory fail"); + return QCLOUD_ERR_FAILURE; + } + memset(pRequest, 0, len); + HAL_Snprintf(pRequest, len, para_format, pDevInfo->device_name, nonce, pDevInfo->product_id, timestamp, sign); + Log_d("request:%s", pRequest); + + Log_d("resbuff len:%d", DYN_RESPONSE_BUFF_LEN); + /*post request*/ + Ret = _post_reg_request_by_http(pRequest, pDevInfo); + if (QCLOUD_RET_SUCCESS == Ret) { + Log_d("request dev info success"); + } else { + Log_e("request dev info fail"); + } + + HAL_Free(pRequest); + + return Ret; +} + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/services/gateway/gateway_api.c b/sdk_src/services/gateway/gateway_api.c new file mode 100644 index 00000000..1c0b248f --- /dev/null +++ b/sdk_src/services/gateway/gateway_api.c @@ -0,0 +1,492 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "gateway_common.h" +#include "mqtt_client.h" +#include "utils_param_check.h" + +void _gateway_event_handler(void *client, void *context, MQTTEventMsg *msg) +{ + uintptr_t packet_id = (uintptr_t)msg->msg; + Gateway * gateway = (Gateway *)context; + + POINTER_SANITY_CHECK_RTN(context); + POINTER_SANITY_CHECK_RTN(msg); + MQTTMessage *topic_info = (MQTTMessage *)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_SUBCRIBE_SUCCESS: + case MQTT_EVENT_UNSUBCRIBE_SUCCESS: + Log_d("gateway sub|unsub(%d) success, packet-id=%u", msg->event_type, (unsigned int)packet_id); + if (gateway->gateway_data.sync_status == packet_id) { + gateway->gateway_data.sync_status = 0; + return; + } + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: + case MQTT_EVENT_SUBCRIBE_NACK: + case MQTT_EVENT_UNSUBCRIBE_NACK: + Log_d("gateway timeout|nack(%d) event, packet-id=%u", msg->event_type, (unsigned int)packet_id); + if (gateway->gateway_data.sync_status == packet_id) { + gateway->gateway_data.sync_status = -1; + return; + } + break; + + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_d("gateway topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + topic_info->topic_len, STRING_PTR_PRINT_SANITY_CHECK(topic_info->ptopic), topic_info->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(topic_info->payload)); + break; + + default: + break; + } + + if (gateway->event_handle.h_fp != NULL) { + gateway->event_handle.h_fp(client, gateway->event_handle.context, msg); + } + + return; +} + +void *IOT_Gateway_Construct(GatewayInitParam *init_param) +{ + int rc = 0; + GatewayParam param = DEFAULT_GATEWAY_PARAMS; + POINTER_SANITY_CHECK(init_param, NULL); + + Gateway *gateway = (Gateway *)HAL_Malloc(sizeof(Gateway)); + if (gateway == NULL) { + Log_e("gateway malloc failed"); + IOT_FUNC_EXIT_RC(NULL); + } + + memset(gateway, 0, sizeof(Gateway)); + + /* replace user event handle */ + gateway->event_handle.h_fp = init_param->init_param.event_handle.h_fp; + gateway->event_handle.context = init_param->init_param.event_handle.context; + + /* set _gateway_event_handler as mqtt event handle */ + init_param->init_param.event_handle.h_fp = _gateway_event_handler; + init_param->init_param.event_handle.context = gateway; + + /* construct MQTT client */ + gateway->mqtt = IOT_MQTT_Construct(&init_param->init_param); + if (NULL == gateway->mqtt) { + Log_e("construct MQTT failed"); + HAL_Free(gateway); + IOT_FUNC_EXIT_RC(NULL); + } + + /* subscribe default topic */ + param.product_id = init_param->init_param.product_id; + param.device_name = init_param->init_param.device_name; + rc = gateway_subscribe_unsubscribe_default(gateway, ¶m); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("subscribe default topic failed"); + IOT_Gateway_Destroy((void *)gateway); + IOT_FUNC_EXIT_RC(NULL); + } + + return (void *)gateway; +} + +int IOT_Gateway_Subdev_Online(void *client, GatewayParam *param) +{ + int rc = 0; + char topic[MAX_SIZE_OF_CLOUD_TOPIC + 1] = {0}; + char payload[GATEWAY_PAYLOAD_BUFFER_LEN + 1] = {0}; + int size = 0; + SubdevSession *session = NULL; + PublishParams params = DEFAULT_PUB_PARAMS; + Gateway * gateway = (Gateway *)client; + + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(param, QCLOUD_ERR_INVAL); + + STRING_PTR_SANITY_CHECK(param->product_id, QCLOUD_ERR_INVAL); + STRING_PTR_SANITY_CHECK(param->device_name, QCLOUD_ERR_INVAL); + STRING_PTR_SANITY_CHECK(param->subdev_product_id, QCLOUD_ERR_INVAL); + STRING_PTR_SANITY_CHECK(param->subdev_device_name, QCLOUD_ERR_INVAL); + + session = subdev_find_session(gateway, param->subdev_product_id, param->subdev_device_name); + if (NULL == session) { + Log_d("there is no session, create a new session"); + + /* create subdev session */ + session = subdev_add_session(gateway, param->subdev_product_id, param->subdev_device_name); + if (NULL == session) { + Log_e("create session error!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_CREATE_SESSION_FAIL); + } + } else { + if (SUBDEV_SEESION_STATUS_ONLINE == session->session_status) { + Log_i("device have online"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_SUBDEV_ONLINE); + } + } + + size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC + 1, GATEWAY_TOPIC_OPERATION_FMT, param->product_id, + param->device_name); + if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) { + Log_e("buf size < topic length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + size = HAL_Snprintf(payload, GATEWAY_PAYLOAD_BUFFER_LEN + 1, GATEWAY_PAYLOAD_STATUS_FMT, "online", + param->subdev_product_id, param->subdev_device_name); + if (size < 0 || size > GATEWAY_PAYLOAD_BUFFER_LEN) { + Log_e("buf size < payload length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + size = HAL_Snprintf(gateway->gateway_data.online.client_id, MAX_SIZE_OF_CLIENT_ID, GATEWAY_CLIENT_ID_FMT, + param->subdev_product_id, param->subdev_device_name); + if (size < 0 || size > MAX_SIZE_OF_CLIENT_ID) { + Log_e("buf size < client_id length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + gateway->gateway_data.online.result = -1001; + + params.qos = QOS0; + params.payload_len = strlen(payload); + params.payload = (char *)payload; + + /* publish packet */ + rc = gateway_publish_sync(gateway, topic, ¶ms, &gateway->gateway_data.online.result); + if (QCLOUD_RET_SUCCESS != rc) { + subdev_remove_session(gateway, param->subdev_product_id, param->subdev_device_name); + IOT_FUNC_EXIT_RC(gateway->gateway_data.online.result); + } + + session->session_status = SUBDEV_SEESION_STATUS_ONLINE; + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +int IOT_Gateway_Subdev_Offline(void *client, GatewayParam *param) +{ + int rc = 0; + char topic[MAX_SIZE_OF_CLOUD_TOPIC + 1] = {0}; + char payload[GATEWAY_PAYLOAD_BUFFER_LEN + 1] = {0}; + int size = 0; + SubdevSession *session = NULL; + Gateway * gateway = (Gateway *)client; + + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(param, QCLOUD_ERR_INVAL); + + STRING_PTR_SANITY_CHECK(param->product_id, QCLOUD_ERR_INVAL); + STRING_PTR_SANITY_CHECK(param->device_name, QCLOUD_ERR_INVAL); + STRING_PTR_SANITY_CHECK(param->subdev_product_id, QCLOUD_ERR_INVAL); + STRING_PTR_SANITY_CHECK(param->subdev_device_name, QCLOUD_ERR_INVAL); + + session = subdev_find_session(gateway, param->subdev_product_id, param->subdev_device_name); + if (NULL == session) { + Log_d("no session, can not offline"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_SESSION_NO_EXIST); + } + if (SUBDEV_SEESION_STATUS_OFFLINE == session->session_status) { + Log_i("device have offline"); + /* free session */ + subdev_remove_session(gateway, param->subdev_product_id, param->subdev_device_name); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_SUBDEV_OFFLINE); + } + + size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC + 1, GATEWAY_TOPIC_OPERATION_FMT, param->product_id, + param->device_name); + if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) { + Log_e("buf size < topic length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + size = HAL_Snprintf(payload, GATEWAY_PAYLOAD_BUFFER_LEN + 1, GATEWAY_PAYLOAD_STATUS_FMT, "offline", + param->subdev_product_id, param->subdev_device_name); + if (size < 0 || size > GATEWAY_PAYLOAD_BUFFER_LEN) { + Log_e("buf size < payload length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + size = HAL_Snprintf(gateway->gateway_data.offline.client_id, MAX_SIZE_OF_CLIENT_ID, GATEWAY_CLIENT_ID_FMT, + param->subdev_product_id, param->subdev_device_name); + if (size < 0 || size > MAX_SIZE_OF_CLIENT_ID) { + Log_e("buf size < client_id length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + gateway->gateway_data.offline.result = -1001; + + PublishParams params = DEFAULT_PUB_PARAMS; + params.qos = QOS0; + params.payload_len = strlen(payload); + params.payload = (char *)payload; + + /* publish packet */ + rc = gateway_publish_sync(gateway, topic, ¶ms, &gateway->gateway_data.offline.result); + if (QCLOUD_RET_SUCCESS != rc) { + IOT_FUNC_EXIT_RC(gateway->gateway_data.offline.result); + } + + session->session_status = SUBDEV_SEESION_STATUS_OFFLINE; + + /* free session */ + subdev_remove_session(gateway, param->subdev_product_id, param->subdev_device_name); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +int IOT_Gateway_Subdev_GetBindList(void *client, GatewayParam *param, SubdevBindList *subdev_bindlist) +{ + POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(param, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(subdev_bindlist, QCLOUD_ERR_INVAL); + + char topic[MAX_SIZE_OF_CLOUD_TOPIC + 1]; + char payload[GATEWAY_PAYLOAD_BUFFER_LEN + 1]; + int size = 0; + Gateway *gateway = (Gateway *)client; + + gateway->bind_list.bindlist_head = NULL; + gateway->bind_list.bind_num = 0; + + memset(topic, 0, MAX_SIZE_OF_CLOUD_TOPIC); + size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC + 1, GATEWAY_TOPIC_OPERATION_FMT, param->product_id, + param->device_name); + if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) { + Log_e("buf size < topic length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + size = HAL_Snprintf(payload, GATEWAY_PAYLOAD_BUFFER_LEN, "{\"type\":\"%s\"}", GATEWAY_DESCRIBE_SUBDEVIES_OP_STR); + if (size < 0 || size > GATEWAY_PAYLOAD_BUFFER_LEN) { + Log_e("buf size < payload length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + PublishParams params = DEFAULT_PUB_PARAMS; + params.qos = QOS0; + params.payload_len = strlen(payload); + params.payload = (char *)payload; + + /* publish packet */ + gateway->gateway_data.get_bindlist.result = -1001; + int rc = gateway_publish_sync(gateway, topic, ¶ms, &gateway->gateway_data.get_bindlist.result); + if (QCLOUD_RET_SUCCESS != rc) { + Log_e("get bind list failed :%d!", rc); + IOT_FUNC_EXIT_RC(gateway->gateway_data.get_bindlist.result); + } + + subdev_bindlist->bindlist_head = gateway->bind_list.bindlist_head; + subdev_bindlist->bind_num = gateway->bind_list.bind_num; + + gateway->bind_list.bindlist_head = NULL; + gateway->bind_list.bind_num = 0; + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +void IOT_Gateway_Subdev_DestoryBindList(SubdevBindList *subdev_bindlist) +{ + POINTER_SANITY_CHECK_RTN(subdev_bindlist); + + SubdevBindInfo *cur_bindinfo = subdev_bindlist->bindlist_head; + while (cur_bindinfo) { + SubdevBindInfo *bindinfo = cur_bindinfo; + cur_bindinfo = cur_bindinfo->next; + HAL_Free(bindinfo); + } + + subdev_bindlist->bindlist_head = NULL; + subdev_bindlist->bind_num = 0; +} + +int IOT_Gateway_Subdev_Bind(void *client, GatewayParam *param, DeviceInfo *pBindSubDevInfo) +{ + char topic[MAX_SIZE_OF_CLOUD_TOPIC + 1]; + char payload[GATEWAY_PAYLOAD_BUFFER_LEN + 1]; + int size = 0; + Gateway *gateway = (Gateway *)client; + + memset(topic, 0, MAX_SIZE_OF_CLOUD_TOPIC); + size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC + 1, GATEWAY_TOPIC_OPERATION_FMT, param->product_id, + param->device_name); + if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) { + Log_e("buf size < topic length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + srand((unsigned)HAL_GetTimeMs()); + int nonce = rand(); + long timestamp = HAL_Timer_current_sec(); + + /*cal sign*/ + char sign[SUBDEV_BIND_SIGN_LEN]; + memset(sign, 0, SUBDEV_BIND_SIGN_LEN); + if (QCLOUD_RET_SUCCESS != + subdev_bind_hmac_sha1_cal(pBindSubDevInfo, sign, SUBDEV_BIND_SIGN_LEN, nonce, timestamp)) { + Log_e("cal sign fail"); + return QCLOUD_ERR_FAILURE; + } + memset(payload, 0, GATEWAY_PAYLOAD_BUFFER_LEN); +#ifdef AUTH_MODE_CERT + size = HAL_Snprintf(payload, GATEWAY_PAYLOAD_BUFFER_LEN + 1, GATEWAY_PAYLOAD_OP_FMT, GATEWAY_BIND_OP_STR, + pBindSubDevInfo->product_id, pBindSubDevInfo->device_name, sign, nonce, timestamp, "hmacsha1", + "certificate"); +#else + size = HAL_Snprintf(payload, GATEWAY_PAYLOAD_BUFFER_LEN + 1, GATEWAY_PAYLOAD_OP_FMT, GATEWAY_BIND_OP_STR, + pBindSubDevInfo->product_id, pBindSubDevInfo->device_name, sign, nonce, timestamp, "hmacsha1", + "psk"); +#endif + + if (size < 0 || size > GATEWAY_PAYLOAD_BUFFER_LEN) { + Log_e("buf size < payload length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + size = HAL_Snprintf(gateway->gateway_data.bind.client_id, MAX_SIZE_OF_CLIENT_ID, GATEWAY_CLIENT_ID_FMT, + pBindSubDevInfo->product_id, pBindSubDevInfo->device_name); + if (size < 0 || size > MAX_SIZE_OF_CLIENT_ID) { + Log_e("buf size < client_id length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + PublishParams params = DEFAULT_PUB_PARAMS; + params.qos = QOS0; + params.payload_len = strlen(payload); + params.payload = (char *)payload; + + /* publish packet */ + gateway->gateway_data.bind.result = -1001; + int rc = gateway_publish_sync(gateway, topic, ¶ms, &gateway->gateway_data.bind.result); + if (QCLOUD_RET_SUCCESS != rc) { + IOT_FUNC_EXIT_RC(gateway->gateway_data.bind.result); + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +int IOT_Gateway_Subdev_Unbind(void *client, GatewayParam *param, DeviceInfo *pSubDevInfo) +{ + char topic[MAX_SIZE_OF_CLOUD_TOPIC + 1]; + char payload[GATEWAY_PAYLOAD_BUFFER_LEN + 1]; + int size = 0; + Gateway *gateway = (Gateway *)client; + + memset(topic, 0, MAX_SIZE_OF_CLOUD_TOPIC); + size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC + 1, GATEWAY_TOPIC_OPERATION_FMT, param->product_id, + param->device_name); + if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) { + Log_e("buf size < topic length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + memset(payload, 0, GATEWAY_PAYLOAD_BUFFER_LEN); + size = HAL_Snprintf(payload, GATEWAY_PAYLOAD_BUFFER_LEN + 1, GATEWAY_PAYLOAD_STATUS_FMT, GATEWAY_UNBIND_OP_STR, + pSubDevInfo->product_id, pSubDevInfo->device_name); + if (size < 0 || size > GATEWAY_PAYLOAD_BUFFER_LEN) { + Log_e("buf size < payload length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + size = HAL_Snprintf(gateway->gateway_data.unbind.client_id, MAX_SIZE_OF_CLIENT_ID, GATEWAY_CLIENT_ID_FMT, + pSubDevInfo->product_id, pSubDevInfo->device_name); + if (size < 0 || size > MAX_SIZE_OF_CLIENT_ID) { + Log_e("buf size < client_id length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + PublishParams params = DEFAULT_PUB_PARAMS; + params.qos = QOS0; + params.payload_len = strlen(payload); + params.payload = (char *)payload; + + /* publish packet */ + gateway->gateway_data.unbind.result = -1001; + int rc = gateway_publish_sync(gateway, topic, ¶ms, &gateway->gateway_data.unbind.result); + if (QCLOUD_RET_SUCCESS != rc) { + IOT_FUNC_EXIT_RC(gateway->gateway_data.unbind.result); + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +void *IOT_Gateway_Get_Mqtt_Client(void *client) +{ + POINTER_SANITY_CHECK(client, NULL); + Gateway *gateway = (Gateway *)client; + + return gateway->mqtt; +} + +int IOT_Gateway_Destroy(void *client) +{ + Gateway *gateway = (Gateway *)client; + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + + SubdevSession *cur_session = gateway->session_list; + while (cur_session) { + SubdevSession *session = cur_session; + cur_session = cur_session->next; + HAL_Free(session); + } + + IOT_MQTT_Destroy(&gateway->mqtt); + HAL_Free(client); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int IOT_Gateway_Yield(void *client, uint32_t timeout_ms) +{ + Gateway *gateway = (Gateway *)client; + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + + return IOT_MQTT_Yield(gateway->mqtt, timeout_ms); +} + +int IOT_Gateway_Subscribe(void *client, char *topic_filter, SubscribeParams *params) +{ + Gateway *gateway = (Gateway *)client; + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + + return IOT_MQTT_Subscribe(gateway->mqtt, topic_filter, params); +} + +int IOT_Gateway_Unsubscribe(void *client, char *topic_filter) +{ + Gateway *gateway = (Gateway *)client; + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + + return IOT_MQTT_Unsubscribe(gateway->mqtt, topic_filter); +} + +int IOT_Gateway_IsSubReady(void *client, char *topic_filter) +{ + Gateway *gateway = (Gateway *)client; + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + + return IOT_MQTT_IsSubReady(gateway->mqtt, topic_filter); +} + +int IOT_Gateway_Publish(void *client, char *topic_name, PublishParams *params) +{ + Gateway *gateway = (Gateway *)client; + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + + return IOT_MQTT_Publish(gateway->mqtt, topic_name, params); +} diff --git a/sdk_src/services/gateway/gateway_common.c b/sdk_src/services/gateway/gateway_common.c new file mode 100644 index 00000000..eb1e7480 --- /dev/null +++ b/sdk_src/services/gateway/gateway_common.c @@ -0,0 +1,522 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "gateway_common.h" + +#include "lite-utils.h" +#include "mqtt_client.h" +#include "utils_base64.h" +#include "utils_md5.h" +#include "utils_hmac.h" +#include "json_parser.h" + +static bool get_json_type(char *json, char **v) +{ + *v = LITE_json_value_of("type", json); + return *v == NULL ? false : true; +} + +static bool get_json_devices(char *json, char **v) +{ + *v = LITE_json_value_of("payload.devices", json); + return *v == NULL ? false : true; +} + +static bool get_json_result(char *json, int32_t *res) +{ + char *v = LITE_json_value_of("result", json); + if (v == NULL) { + return false; + } + if (LITE_get_int32(res, v) != QCLOUD_RET_SUCCESS) { + HAL_Free(v); + return false; + } + HAL_Free(v); + return true; +} + +static bool get_json_product_id(char *json, char **v) +{ + *v = LITE_json_value_of("product_id", json); + return *v == NULL ? false : true; +} + +static bool get_json_device_name(char *json, char **v) +{ + *v = LITE_json_value_of("device_name", json); + return *v == NULL ? false : true; +} + +#define MIN(a, b) ((a > b) ? b : a) +static SubdevBindInfo *_subdev_add_bindinfo(Gateway *gateway, char *subdev_product_id, char *subdev_device_name) +{ + SubdevBindInfo *bindinfo = NULL; + + POINTER_SANITY_CHECK(gateway, NULL); + STRING_PTR_SANITY_CHECK(subdev_product_id, NULL); + STRING_PTR_SANITY_CHECK(subdev_device_name, NULL); + + bindinfo = HAL_Malloc(sizeof(SubdevBindInfo)); + if (bindinfo == NULL) { + Log_e("add bindinfo not enough memory"); + IOT_FUNC_EXIT_RC(NULL); + } + + memset(bindinfo, 0, sizeof(SubdevBindInfo)); + /* add subdev bind info to list */ + bindinfo->next = gateway->bind_list.bindlist_head; + gateway->bind_list.bindlist_head = bindinfo; + + strncpy(bindinfo->product_id, subdev_product_id, MAX_SIZE_OF_PRODUCT_ID); + bindinfo->product_id[MAX_SIZE_OF_PRODUCT_ID] = '\0'; + int size = strlen(subdev_device_name); + strncpy(bindinfo->device_name, subdev_device_name, MIN(size, MAX_SIZE_OF_DEVICE_NAME)); + bindinfo->device_name[MIN(size, MAX_SIZE_OF_DEVICE_NAME)] = '\0'; + + gateway->bind_list.bind_num += 1; + + IOT_FUNC_EXIT_RC(bindinfo); +} +#undef MIN + +static void _subdev_proc_get_bindlist(Gateway *gateway, char *devices) +{ + char *subdev_product_id = NULL; + char *subdev_device_name = NULL; + char *pos = NULL; + char *entry = NULL; + int entry_len = 0; + int entry_type = 0; + char old_ch = 0; + + // parser json array + json_array_for_each_entry(devices, pos, entry, entry_len, entry_type) + { + if (entry != NULL) { + backup_json_str_last_char(entry, entry_len, old_ch); + if (false == get_json_product_id(entry, &subdev_product_id)) { + continue; + } + if (false == get_json_device_name(entry, &subdev_device_name)) { + continue; + } + if (NULL == _subdev_add_bindinfo(gateway, subdev_product_id, subdev_device_name)) { + break; + } + restore_json_str_last_char(entry, entry_len, old_ch); + } + } + + return; +} + +static void _gateway_message_handler(void *client, MQTTMessage *message, void *user_data) +{ + Qcloud_IoT_Client *mqtt = NULL; + Gateway * gateway = NULL; + char * topic = NULL; + size_t topic_len = 0; + int cloud_rcv_len = 0; + char * type = NULL; + char * devices = NULL, *devices_strip = NULL; + char * product_id = NULL; + char * device_name = NULL; + int32_t result = 0; + char client_id[MAX_SIZE_OF_CLIENT_ID + 1] = {0}; + int size = 0; + + POINTER_SANITY_CHECK_RTN(client); + POINTER_SANITY_CHECK_RTN(message); + + mqtt = (Qcloud_IoT_Client *)client; + gateway = (Gateway *)mqtt->event_handle.context; + POINTER_SANITY_CHECK_RTN(gateway); + + topic = (char *)message->ptopic; + topic_len = message->topic_len; + if (NULL == topic || topic_len == 0) { + Log_e("topic == NULL or topic_len == 0."); + return; + } + + if (message->payload_len > GATEWAY_RECEIVE_BUFFER_LEN) { + Log_e("message->payload_len > GATEWAY_RECEIVE_BUFFER_LEN."); + return; + } + + cloud_rcv_len = Min(GATEWAY_RECEIVE_BUFFER_LEN - 1, message->payload_len); + char *json_buf = gateway->recv_buf; + memcpy(gateway->recv_buf, message->payload, cloud_rcv_len); + json_buf[cloud_rcv_len] = '\0'; // jsmn_parse relies on a string + + Log_d("msg payload: %s", json_buf); + + if (!get_json_type(json_buf, &type)) { + Log_e("Fail to parse type from msg: %s", json_buf); + return; + } + + if (!get_json_devices(json_buf, &devices)) { + Log_e("Fail to parse devices from msg: %s", json_buf); + HAL_Free(type); + return; + } + + if (strncmp(type, GATEWAY_DESCRIBE_SUBDEVIES_OP_STR, sizeof(GATEWAY_DESCRIBE_SUBDEVIES_OP_STR) - 1) == 0) { + _subdev_proc_get_bindlist(gateway, devices); + gateway->gateway_data.get_bindlist.result = 0; + HAL_Free(type); + HAL_Free(devices); + return; + } + + if (devices[0] == '[') { + devices_strip = devices + 1; + } else { + devices_strip = devices; + } + + if (!get_json_result(devices_strip, &result)) { + Log_e("Fail to parse result from msg: %s", json_buf); + HAL_Free(type); + HAL_Free(devices); + return; + } + if (!get_json_product_id(devices_strip, &product_id)) { + Log_e("Fail to parse product_id from msg: %s", json_buf); + HAL_Free(type); + HAL_Free(devices); + return; + } + if (!get_json_device_name(devices_strip, &device_name)) { + Log_e("Fail to parse device_name from msg: %s", json_buf); + HAL_Free(type); + HAL_Free(devices); + HAL_Free(product_id); + return; + } + + size = HAL_Snprintf(client_id, MAX_SIZE_OF_CLIENT_ID + 1, GATEWAY_CLIENT_ID_FMT, product_id, device_name); + if (size < 0 || size > MAX_SIZE_OF_CLIENT_ID) { + Log_e("generate client_id fail."); + HAL_Free(type); + HAL_Free(devices); + HAL_Free(product_id); + HAL_Free(device_name); + return; + } + + if (strncmp(type, GATEWAY_ONLINE_OP_STR, sizeof(GATEWAY_ONLINE_OP_STR) - 1) == 0) { + if (strncmp(client_id, gateway->gateway_data.online.client_id, size) == 0) { + Log_i("client_id(%s), online result %d", client_id, result); + gateway->gateway_data.online.result = result; + } + } else if (strncmp(type, GATEWAY_OFFLIN_OP_STR, sizeof(GATEWAY_OFFLIN_OP_STR) - 1) == 0) { + if (strncmp(client_id, gateway->gateway_data.offline.client_id, size) == 0) { + Log_i("client_id(%s), offline result %d", client_id, result); + gateway->gateway_data.offline.result = result; + } + } else if (strncmp(type, GATEWAY_BIND_OP_STR, sizeof(GATEWAY_BIND_OP_STR) - 1) == 0) { + if (strncmp(client_id, gateway->gateway_data.bind.client_id, size) == 0) { + gateway->gateway_data.bind.result = result; + Log_i("client_id(%s), bind result %d", client_id, gateway->gateway_data.bind.result); + } + } else if (strncmp(type, GATEWAY_UNBIND_OP_STR, sizeof(GATEWAY_UNBIND_OP_STR) - 1) == 0) { + if (strncmp(client_id, gateway->gateway_data.unbind.client_id, size) == 0) { + gateway->gateway_data.unbind.result = result; + Log_i("client_id(%s), unbind result %d", client_id, gateway->gateway_data.unbind.result); + } + } + + HAL_Free(type); + HAL_Free(devices); + HAL_Free(product_id); + HAL_Free(device_name); + return; +} + +int gateway_subscribe_unsubscribe_topic(Gateway *gateway, char *topic_filter, SubscribeParams *params, int is_subscribe) +{ + int rc = 0; + int loop_count = 0; + uint32_t status = -1; + + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(params, QCLOUD_ERR_INVAL); + + STRING_PTR_SANITY_CHECK(topic_filter, QCLOUD_ERR_INVAL); + + params->qos = QOS1; + gateway->gateway_data.sync_status = status; + + if (is_subscribe) { + /* subscribe */ + rc = IOT_MQTT_Subscribe(gateway->mqtt, topic_filter, params); + } else { + /* unsubscribe */ + rc = IOT_MQTT_Unsubscribe(gateway->mqtt, topic_filter); + } + + if (rc < 0) { + Log_e("subscribe or un(%d), result(%d)", is_subscribe, rc); + IOT_FUNC_EXIT_RC(rc); + } + + gateway->gateway_data.sync_status = status = rc; + while (status == gateway->gateway_data.sync_status) { + if (loop_count > GATEWAY_LOOP_MAX_COUNT) { + Log_i("loop max count, time out"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + IOT_Gateway_Yield(gateway, 200); + loop_count++; + } + + if (gateway->gateway_data.sync_status != 0) { + Log_e("gateway->gateway_data.sync_status(%u) != 0", gateway->gateway_data.sync_status); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +int gateway_subscribe_unsubscribe_default(Gateway *gateway, GatewayParam *param) +{ + int rc = 0; + int size = 0; + char topic_filter[MAX_SIZE_OF_CLOUD_TOPIC + 1] = {0}; + SubscribeParams subscribe_params = DEFAULT_SUB_PARAMS; + + POINTER_SANITY_CHECK(param, QCLOUD_ERR_INVAL); + + STRING_PTR_SANITY_CHECK(param->product_id, QCLOUD_ERR_INVAL); + STRING_PTR_SANITY_CHECK(param->device_name, QCLOUD_ERR_INVAL); + + // subscribe online/offline operation reslut + size = HAL_Snprintf(topic_filter, MAX_SIZE_OF_CLOUD_TOPIC + 1, GATEWAY_TOPIC_OPERATION_RESULT_FMT, + param->product_id, param->device_name); + if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) { + Log_e("buf size < topic length!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + subscribe_params.on_message_handler = _gateway_message_handler; + rc = gateway_subscribe_unsubscribe_topic(gateway, topic_filter, &subscribe_params, IOT_TRUE); + if (QCLOUD_RET_SUCCESS != rc) { + IOT_FUNC_EXIT_RC(rc); + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +SubdevSession *subdev_find_session(Gateway *gateway, char *product_id, char *device_name) +{ + SubdevSession *session = NULL; + + POINTER_SANITY_CHECK(gateway, NULL); + STRING_PTR_SANITY_CHECK(product_id, NULL); + STRING_PTR_SANITY_CHECK(device_name, NULL); + + session = gateway->session_list; + + /* session is exist */ + while (session) { + if (0 == strncmp(session->product_id, product_id, strlen(product_id)) && + 0 == strncmp(session->device_name, device_name, strlen(device_name))) { + IOT_FUNC_EXIT_RC(session); + } + session = session->next; + } + + IOT_FUNC_EXIT_RC(NULL); +} + +SubdevSession *subdev_add_session(Gateway *gateway, char *product_id, char *device_name) +{ + SubdevSession *session = NULL; + + POINTER_SANITY_CHECK(gateway, NULL); + STRING_PTR_SANITY_CHECK(product_id, NULL); + STRING_PTR_SANITY_CHECK(device_name, NULL); + + session = HAL_Malloc(sizeof(SubdevSession)); + if (session == NULL) { + Log_e("Not enough memory"); + IOT_FUNC_EXIT_RC(NULL); + } + + memset(session, 0, sizeof(SubdevSession)); + /* add session to list */ + session->next = gateway->session_list; + gateway->session_list = session; + + int size = strlen(product_id); + strncpy(session->product_id, product_id, size); + session->product_id[size] = '\0'; + size = strlen(device_name); + strncpy(session->device_name, device_name, size); + session->device_name[size] = '\0'; + session->session_status = SUBDEV_SEESION_STATUS_INIT; + + IOT_FUNC_EXIT_RC(session); +} + +int subdev_remove_session(Gateway *gateway, char *product_id, char *device_name) +{ + SubdevSession *cur_session = NULL; + SubdevSession *pre_session = NULL; + + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_FAILURE); + STRING_PTR_SANITY_CHECK(product_id, QCLOUD_ERR_FAILURE); + STRING_PTR_SANITY_CHECK(device_name, QCLOUD_ERR_FAILURE); + + pre_session = cur_session = gateway->session_list; + + if (NULL == cur_session) { + Log_e("session list is empty"); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); + } + + /* session is exist */ + while (cur_session) { + if (0 == strncmp(cur_session->product_id, product_id, strlen(product_id)) && + 0 == strncmp(cur_session->device_name, device_name, strlen(device_name))) { + if (cur_session == gateway->session_list) { + gateway->session_list = cur_session->next; + } else { + pre_session->next = cur_session->next; + } + HAL_Free(cur_session); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); + } + pre_session = cur_session; + cur_session = cur_session->next; + } + + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); +} + +int gateway_publish_sync(Gateway *gateway, char *topic, PublishParams *params, int32_t *result) +{ + int rc = 0; + int loop_count = 0; + int32_t res = *result; + + POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); + + rc = IOT_Gateway_Publish(gateway, topic, params); + if (rc < 0) { + Log_e("publish fail."); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + /* wait for response */ + while (res == *result) { + if (loop_count > GATEWAY_LOOP_MAX_COUNT) { + Log_i("loop max count, time out."); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_SESSION_TIMEOUT); + } + + IOT_Gateway_Yield(gateway, 200); + loop_count++; + } + + if (*result != 0) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +#ifdef AUTH_MODE_CERT +static int gen_key_from_cert_file(const char *file_path, char *keybuff, int buff_len) +{ + FILE * fp; + uint32_t length; + int ret = QCLOUD_RET_SUCCESS; + + if ((fp = fopen(file_path, "r")) == NULL) { + Log_e("fail to open cert file %s", file_path); + return QCLOUD_ERR_FAILURE; + } + + fseek(fp, 0L, SEEK_END); + length = ftell(fp); + uint8_t *data = HAL_Malloc(length + 1); + if (!data) { + Log_e("malloc mem err"); + return QCLOUD_ERR_MALLOC; + } + + fseek(fp, 0, SEEK_SET); + if (length != fread(data, 1, length, fp)) { + Log_e("read data len fail"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + utils_md5_str(data, length, (uint8_t *)keybuff); + Log_d("sign key: %s", STRING_PTR_PRINT_SANITY_CHECK(keybuff)); + +exit: + + HAL_Free(data); + fclose(fp); + + return ret; +} + +#endif + +int subdev_bind_hmac_sha1_cal(DeviceInfo *pDevInfo, char *signout, int max_signlen, int nonce, long timestamp) +{ + int text_len, ret; + size_t olen = 0; + char * pSignText = NULL; + const char *sign_fmt = "%s%s;%d;%d"; //${product_id}${device_name};${random};${expiration_time} + + /*format sign data*/ + text_len = strlen(sign_fmt) + strlen(pDevInfo->device_name) + strlen(pDevInfo->product_id) + sizeof(int) + + sizeof(long) + 10; + pSignText = HAL_Malloc(text_len); + if (pSignText == NULL) { + Log_e("malloc sign source buff fail"); + return QCLOUD_ERR_FAILURE; + } + memset(pSignText, 0, text_len); + HAL_Snprintf((char *)pSignText, text_len, sign_fmt, pDevInfo->product_id, pDevInfo->device_name, nonce, timestamp); + + // gen digest key + char key[BIND_SIGN_KEY_SIZE + 1] = {0}; +#ifdef AUTH_MODE_CERT + ret = gen_key_from_cert_file(pDevInfo->dev_cert_file_name, key, BIND_SIGN_KEY_SIZE); + if (QCLOUD_RET_SUCCESS != ret) { + Log_e("gen key from cert file fail, ret:%d", ret); + HAL_Free(pSignText); + return ret; + } +#else + strncpy(key, pDevInfo->device_secret, strlen(pDevInfo->device_secret)); +#endif + + /*cal hmac sha1*/ + char sign[SUBDEV_BIND_SIGN_LEN] = {0}; + int sign_len = utils_hmac_sha1_hex(pSignText, strlen(pSignText), sign, key, strlen(key)); + + /*base64 encode*/ + ret = qcloud_iot_utils_base64encode((uint8_t *)signout, max_signlen, &olen, (const uint8_t *)sign, sign_len); + HAL_Free(pSignText); + + return (olen > max_signlen) ? QCLOUD_ERR_FAILURE : ret; +} diff --git a/sdk_src/services/log/log_mqtt.c b/sdk_src/services/log/log_mqtt.c new file mode 100755 index 00000000..ed7396c3 --- /dev/null +++ b/sdk_src/services/log/log_mqtt.c @@ -0,0 +1,243 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" +#ifdef LOG_UPLOAD + +#include + +#include "lite-utils.h" +#include "log_upload.h" +#include "mqtt_client.h" +#include "qcloud_iot_device.h" + +typedef struct _log_mqtt_state { + bool topic_sub_ok; + bool result_recv_ok; + int log_level; +} LogMQTTState; + +static LogMQTTState sg_state = {.topic_sub_ok = false, .result_recv_ok = false, .log_level = eLOG_ERROR}; + +static bool _get_json_log_level(char *json, int32_t *res) +{ + char *v = LITE_json_value_of("log_level", json); + if (v == NULL) { + Log_e("Invalid log level from JSON: %s", STRING_PTR_PRINT_SANITY_CHECK(json)); + return false; + } + if (LITE_get_int32(res, v) != QCLOUD_RET_SUCCESS) { + Log_e("Invalid log level from JSON: %s", json); + HAL_Free(v); + return false; + } + HAL_Free(v); + return true; +} + +static void _log_level_sub_cb(void *pClient, MQTTMessage *message, void *pUserData) +{ +#define LOG_JSON_LENGTH 128 + char json_buf[LOG_JSON_LENGTH] = {0}; + int32_t json_buf_len = 0; + if (message == NULL) { + return; + } + LogMQTTState *state = (LogMQTTState *)pUserData; + + json_buf_len = Min(LOG_JSON_LENGTH - 1, message->payload_len); + memcpy(json_buf, message->payload, json_buf_len); + json_buf[json_buf_len] = '\0'; // json_parse relies on a string + + Log_d("Recv Msg Topic:%s, payload:%s", STRING_PTR_PRINT_SANITY_CHECK(message->ptopic), json_buf); + int log_level; + if (!_get_json_log_level(json_buf, &log_level)) { + return; + } + + switch (log_level) { + case eLOG_DISABLE: + Log_w("Upload log level change to: %d", log_level); + clear_upload_buffer(); + set_log_upload_in_comm_err(true); + IOT_Log_Set_Upload_Level(eLOG_ERROR); + break; + case eLOG_ERROR: + case eLOG_WARN: + case eLOG_INFO: + case eLOG_DEBUG: + if (log_level < IOT_Log_Get_Upload_Level()) + clear_upload_buffer(); + IOT_Log_Set_Upload_Level((LOG_LEVEL)log_level); + Log_w("Upload log level change to: %d", log_level); + set_log_upload_in_comm_err(false); + break; + default: + Log_e("Invalid log level: %d", log_level); + break; + } + + state->log_level = log_level; + state->result_recv_ok = true; +} + +static void _log_mqtt_sub_event_handler(void *pclient, MQTTEventType event_type, void *pUserData) +{ + LogMQTTState *state = (LogMQTTState *)pUserData; + + switch (event_type) { + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_d("mqtt log topic subscribe success"); + state->topic_sub_ok = true; + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("mqtt log topic subscribe timeout"); + state->topic_sub_ok = false; + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("mqtt log topic subscribe NACK"); + state->topic_sub_ok = false; + break; + case MQTT_EVENT_UNSUBSCRIBE: + Log_i("mqtt log topic has been unsubscribed"); + state->topic_sub_ok = false; + ; + break; + case MQTT_EVENT_CLIENT_DESTROY: + Log_i("mqtt client has been destroyed"); + state->topic_sub_ok = false; + ; + break; + default: + return; + } +} + +static int _iot_log_level_get_publish(void *pClient) +{ + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + static unsigned int sg_client_token = 1; + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + DeviceInfo * dev_info = &mqtt_client->device_info; + + char topic_name[128] = {0}; + char payload_content[128] = {0}; + + HAL_Snprintf(topic_name, sizeof(topic_name), "$log/operation/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name)); + HAL_Snprintf(payload_content, sizeof(payload_content), + "{\"type\": \"get_log_level\", " + "\"clientToken\": \"%s-%u\"}", + STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), sg_client_token++); + + PublishParams pub_params = DEFAULT_PUB_PARAMS; + pub_params.qos = QOS0; + pub_params.payload = payload_content; + pub_params.payload_len = strlen(payload_content); + + return IOT_MQTT_Publish(mqtt_client, topic_name, &pub_params); +} + +int qcloud_log_topic_subscribe(void *client) +{ + /* subscribe the log topic: "$log/operation/result/${productId}/${deviceName}" */ + char topic_name[128] = {0}; + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)client; + DeviceInfo * dev_info = &mqtt_client->device_info; + int size = HAL_Snprintf(topic_name, sizeof(topic_name), "$log/operation/result/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name)); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content buf not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.on_message_handler = _log_level_sub_cb; + sub_params.on_sub_event_handler = _log_mqtt_sub_event_handler; + sub_params.user_data = (void *)&sg_state; + sub_params.qos = QOS0; + + return IOT_MQTT_Subscribe(client, topic_name, &sub_params); +} + +int qcloud_get_log_level(void *pClient, int *log_level) +{ + int ret = 0; + int cntSub = 0; + int cntRev = 0; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + // subscribe log topic: $log/operation/get/${productid}/${devicename} + // skip this if the subscription is done and valid + if (!sg_state.topic_sub_ok) { + for (cntSub = 0; cntSub < 3; cntSub++) { + ret = qcloud_log_topic_subscribe(mqtt_client); + if (ret < 0) { + Log_w("qcloud_log_topic_subscribe failed: %d, cnt: %d", ret, cntSub); + continue; + } + + /* wait for sub ack */ + ret = qcloud_iot_mqtt_yield_mt((Qcloud_IoT_Client *)pClient, 100); + if (sg_state.topic_sub_ok) { + break; + } + } + } + + // return failure if subscribe failed + if (!sg_state.topic_sub_ok) { + Log_e("Subscribe log topic failed!"); + return QCLOUD_ERR_FAILURE; + } + + sg_state.result_recv_ok = false; + // publish msg to get log level + ret = _iot_log_level_get_publish(mqtt_client); + if (ret < 0) { + Log_e("client publish log topic failed :%d", ret); + return ret; + } + + do { + ret = qcloud_iot_mqtt_yield_mt((Qcloud_IoT_Client *)pClient, 100); + cntRev++; + } while (!ret && !sg_state.result_recv_ok && cntRev < 20); + + *log_level = sg_state.log_level; + if (sg_state.result_recv_ok) + ret = QCLOUD_RET_SUCCESS; + else + ret = QCLOUD_ERR_FAILURE; + + return ret; +} + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/services/log/log_upload.c b/sdk_src/services/log/log_upload.c new file mode 100755 index 00000000..a87e27a3 --- /dev/null +++ b/sdk_src/services/log/log_upload.c @@ -0,0 +1,702 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifdef LOG_UPLOAD + +#include +#include +#include +#include +#include + +#include "lite-utils.h" +#include "log_upload.h" +#include "qcloud_iot_common.h" +#include "utils_hmac.h" +#include "utils_httpc.h" +#include "utils_timer.h" + +/* log post header format */ +#define TIMESTAMP_SIZE 10 +#define SIGNATURE_SIZE 40 +#define CTRL_BYTES_SIZE 4 +// LOG_BUF_FIXED_HEADER_SIZE = 112 +#define LOG_BUF_FIXED_HEADER_SIZE \ + (SIGNATURE_SIZE + CTRL_BYTES_SIZE + MAX_SIZE_OF_PRODUCT_ID + MAX_SIZE_OF_DEVICE_NAME + TIMESTAMP_SIZE) + +/* do immediate log update if buffer is lower than this threshold (about two max log item) */ +#define LOG_LOW_BUFFER_THRESHOLD (LOG_UPLOAD_BUFFER_SIZE / 4) + +/* log upload buffer */ +static char * sg_log_buffer = NULL; +static uint32_t sg_write_index = LOG_BUF_FIXED_HEADER_SIZE; + +#define SIGN_KEY_SIZE 24 +static char sg_sign_key[SIGN_KEY_SIZE + 1] = {0}; + +/* Log upload feature switch */ +/* To check log http server return msg or not */ +#define LOG_CHECK_HTTP_RET_CODE + +typedef struct { + const char * url; + const char * ca_crt; + int port; + HTTPClient http; /* http client */ + HTTPClientData http_data; /* http client data */ + +} LogHTTPStruct; + +static LogHTTPStruct *sg_http_c = NULL; + +typedef struct { + const char *product_id; + const char *device_name; + void * mqtt_client; + bool upload_only_in_comm_err; + + void *lock_buf; + Timer upload_timer; +#ifndef LOG_UPDATE_TIME_WHEN_UPLOAD + Timer time_update_timer; +#endif + long system_time; + + LogSaveFunc save_func; + LogReadFunc read_func; + LogDelFunc del_func; + LogGetSizeFunc get_size_func; + bool log_save_enabled; + + bool uploader_init_done; + +} LogUploaderStruct; + +static LogUploaderStruct *sg_uploader = NULL; +static bool sg_log_uploader_init_done = false; + +#ifdef AUTH_MODE_CERT +static int _gen_key_from_file(const char *file_path) +{ + FILE *fp; + int len; + char line_buf[128] = {0}; + + if ((fp = fopen(file_path, "r")) == NULL) { + UPLOAD_ERR("fail to open cert file %s", STRING_PTR_PRINT_SANITY_CHECK(file_path)); + return -1; + } + + /* find the begin line */ + do { + if (NULL == fgets(line_buf, sizeof(line_buf), fp)) { + UPLOAD_ERR("fail to fgets file %s", file_path); + return -1; + } + } while (strstr(line_buf, "-----BEGIN ") == NULL); + + if (feof(fp)) { + UPLOAD_ERR("invalid cert file %s", file_path); + return -1; + } + + if (NULL == fgets(line_buf, sizeof(line_buf), fp)) { + UPLOAD_ERR("fail to fgets file %s", file_path); + return -1; + } + + len = strlen(line_buf); + memcpy(sg_sign_key, line_buf, len > SIGN_KEY_SIZE ? SIGN_KEY_SIZE : len); + UPLOAD_DBG("sign key %s", sg_sign_key); + + fclose(fp); + + return 0; +} +#endif + +static long _get_system_time(void) +{ +#ifdef SYSTEM_COMM + if (sg_uploader->mqtt_client == NULL) + return 0; + + long sys_time = 0; + int rc = IOT_Get_SysTime(sg_uploader->mqtt_client, &sys_time); + if (rc == QCLOUD_RET_SUCCESS) + return sys_time; + else + return 0; +#else + return 0; +#endif +} + +static void _update_system_time(void) +{ + /* to avoid frequent get_system_time */ +#define LOG_TIME_UPDATE_INTERVAL 2 + + if (!expired(&sg_uploader->time_update_timer)) + return; + + sg_uploader->system_time = _get_system_time(); + + countdown(&sg_uploader->time_update_timer, LOG_TIME_UPDATE_INTERVAL); +} + +static int _check_server_connection() +{ + int rc; + + rc = qcloud_http_client_connect(&sg_http_c->http, sg_http_c->url, sg_http_c->port, sg_http_c->ca_crt); + if (rc != QCLOUD_RET_SUCCESS) + return rc; + + qcloud_http_client_close(&sg_http_c->http); + + return QCLOUD_RET_SUCCESS; +} + +#ifdef LOG_CHECK_HTTP_RET_CODE +static bool _get_json_ret_code(char *json, int32_t *res) +{ + char *v = LITE_json_value_of("Retcode", json); + if (v == NULL) { + UPLOAD_ERR("Invalid json content: %s", STRING_PTR_PRINT_SANITY_CHECK(json)); + return false; + } + if (LITE_get_int32(res, v) != QCLOUD_RET_SUCCESS) { + UPLOAD_ERR("Invalid json content: %s", json); + HAL_Free(v); + return false; + } + HAL_Free(v); + return true; +} +#endif + +static int _post_one_http_to_server(char *post_buf, size_t post_size) +{ + int rc = 0; + + if (sg_http_c == NULL) + return QCLOUD_ERR_INVAL; + + sg_http_c->http_data.post_content_type = "text/plain;charset=utf-8"; + sg_http_c->http_data.post_buf = post_buf; + sg_http_c->http_data.post_buf_len = post_size; + + rc = qcloud_http_client_common(&sg_http_c->http, sg_http_c->url, sg_http_c->port, sg_http_c->ca_crt, HTTP_POST, + &sg_http_c->http_data); + if (rc != QCLOUD_RET_SUCCESS) { + UPLOAD_ERR("qcloud_http_client_common failed, rc = %d", rc); + return rc; + } + UPLOAD_DBG("Log client POST size: %d", post_size); + +#ifdef LOG_CHECK_HTTP_RET_CODE + /* TODO: handle recv data from log server */ +#define HTTP_RET_JSON_LENGTH 256 +#define HTTP_WAIT_RET_TIMEOUT_MS 1000 + char buf[HTTP_RET_JSON_LENGTH] = {0}; + sg_http_c->http_data.response_buf = buf; + sg_http_c->http_data.response_buf_len = sizeof(buf); + + rc = qcloud_http_recv_data(&sg_http_c->http, HTTP_WAIT_RET_TIMEOUT_MS, &sg_http_c->http_data); + if (QCLOUD_RET_SUCCESS != rc) { + UPLOAD_ERR("qcloud_http_recv_data failed, rc = %d", rc); + } else { + int32_t ret = -1; + + buf[HTTP_RET_JSON_LENGTH - 1] = '\0'; // json_parse relies on a string + if (strlen(buf) > 0 && _get_json_ret_code(buf, &ret) && ret == 0) { + UPLOAD_DBG("Log server return SUCCESS: %s", buf); + } else { + UPLOAD_ERR("Log server return FAIL(%d): %s", ret, buf); + rc = QCLOUD_ERR_HTTP; + } + } +#endif + + qcloud_http_client_close(&sg_http_c->http); + + return rc; +} + +static void _update_time_and_signature(char *log_buf, size_t log_size) +{ + char timestamp[TIMESTAMP_SIZE + 1] = {0}; + char signature[SIGNATURE_SIZE + 1] = {0}; + + /* get system time from IoT hub first */ + _update_system_time(); + + /* record the timestamp for this log uploading */ + HAL_Snprintf(timestamp, TIMESTAMP_SIZE + 1, "%010ld", sg_uploader->system_time); + memcpy(log_buf + LOG_BUF_FIXED_HEADER_SIZE - TIMESTAMP_SIZE, timestamp, strlen(timestamp)); + + /* signature of this log uploading */ + utils_hmac_sha1(log_buf + SIGNATURE_SIZE, log_size - SIGNATURE_SIZE, signature, sg_sign_key, strlen(sg_sign_key)); + memcpy(log_buf, signature, SIGNATURE_SIZE); +} + +static int _post_log_to_server(char *post_buf, size_t post_size, size_t *actual_post_payload) +{ +#define LOG_DELIMITER "\n\f" + int ret = QCLOUD_RET_SUCCESS; + /* one shot upload */ + if (post_size < MAX_HTTP_LOG_POST_SIZE) { + _update_time_and_signature(post_buf, post_size); + ret = _post_one_http_to_server(post_buf, post_size); + if (QCLOUD_RET_SUCCESS == ret) { + *actual_post_payload = post_size - LOG_BUF_FIXED_HEADER_SIZE; + } else { + UPLOAD_ERR("one time log send failed"); + *actual_post_payload = 0; + } + return ret; + } + + /* Log size is larger than one HTTP post size */ + /* Fragment the log and upload multi-times */ + UPLOAD_DBG("to post large log size %d", post_size); + *actual_post_payload = 0; + size_t delimiter_len = strlen(LOG_DELIMITER); + size_t orig_post_size = post_size; + size_t post_payload, upload_size, possible_size; + do { + char *next_log_buf = NULL; + possible_size = 0; + while (possible_size < MAX_HTTP_LOG_POST_SIZE) { + /*remember last valid position */ + upload_size = possible_size; + /* locate the delimiter */ + next_log_buf = strstr(post_buf + upload_size, LOG_DELIMITER); + if (next_log_buf == NULL) { + UPLOAD_ERR("Invalid log delimiter. Total sent: %d. Left: %d", + *actual_post_payload + LOG_BUF_FIXED_HEADER_SIZE, post_size); + return QCLOUD_ERR_INVAL; + } + possible_size = (size_t)(next_log_buf - post_buf + delimiter_len); + /* end of log */ + if (next_log_buf[delimiter_len] == 0 && possible_size < MAX_HTTP_LOG_POST_SIZE) { + upload_size = possible_size; + break; + } + } + + if (upload_size == 0) { + UPLOAD_ERR("Upload size should not be 0! Total sent: %d. Left: %d", + *actual_post_payload + LOG_BUF_FIXED_HEADER_SIZE, post_size); + return QCLOUD_ERR_FAILURE; + } + + _update_time_and_signature(post_buf, upload_size); + ret = _post_one_http_to_server(post_buf, upload_size); + if (QCLOUD_RET_SUCCESS != ret) { + UPLOAD_ERR("Send log failed. Total sent: %d. Left: %d", *actual_post_payload + LOG_BUF_FIXED_HEADER_SIZE, + post_size); + return QCLOUD_ERR_FAILURE; + } + + /* move the left log forward and do next upload */ + memmove(post_buf + LOG_BUF_FIXED_HEADER_SIZE, post_buf + upload_size, post_size - upload_size); + post_payload = upload_size - LOG_BUF_FIXED_HEADER_SIZE; + post_size -= post_payload; + *actual_post_payload += post_payload; + memset(post_buf + post_size, 0, orig_post_size - post_size); + UPLOAD_DBG("post log %d OK. Total sent: %d. Left: %d", upload_size, + *actual_post_payload + LOG_BUF_FIXED_HEADER_SIZE, post_size); + } while (post_size > LOG_BUF_FIXED_HEADER_SIZE); + + return QCLOUD_RET_SUCCESS; +} + +static void _reset_log_buffer(void) +{ + sg_write_index = LOG_BUF_FIXED_HEADER_SIZE; + memset(sg_log_buffer + LOG_BUF_FIXED_HEADER_SIZE, 0, LOG_UPLOAD_BUFFER_SIZE - LOG_BUF_FIXED_HEADER_SIZE); +} + +static int _save_log(char *log_buf, size_t log_size) +{ + int rc = 0; + size_t write_size, current_size = sg_uploader->get_size_func(); + + /* overwrite the previous saved log to avoid too many saved logs */ + if ((current_size + log_size) > MAX_LOG_SAVE_SIZE) { + UPLOAD_ERR("overwrite the previous saved log. %d", current_size); + rc = sg_uploader->del_func(); + if (rc) { + Log_e("fail to delete previous log"); + } + } + + write_size = sg_uploader->save_func(log_buf, log_size); + if (write_size != log_size) { + Log_e("fail to save log. RC %d - log size %d", write_size, log_size); + rc = -1; + } else { + rc = 0; + } + + return rc; +} + +static int _handle_saved_log(void) +{ + int rc = QCLOUD_RET_SUCCESS; + size_t whole_log_size = sg_uploader->get_size_func(); + if (whole_log_size > 0) { + /* only do the job when connection is OK */ + if (_check_server_connection() != QCLOUD_RET_SUCCESS) + return QCLOUD_ERR_FAILURE; + + size_t buf_size = whole_log_size + LOG_BUF_FIXED_HEADER_SIZE + 1; + char * log_buf = HAL_Malloc(buf_size); + if (log_buf != NULL) { + /* read the whole log to buffer */ + size_t read_len = sg_uploader->read_func(log_buf + LOG_BUF_FIXED_HEADER_SIZE, whole_log_size); + if (read_len == whole_log_size) { + size_t upload_size = whole_log_size + LOG_BUF_FIXED_HEADER_SIZE; + + /* copy header from global log buffer */ + memcpy(log_buf, sg_log_buffer, LOG_BUF_FIXED_HEADER_SIZE); + log_buf[buf_size - 1] = 0; + + size_t actual_post_payload; + rc = _post_log_to_server(log_buf, upload_size, &actual_post_payload); + if (rc == QCLOUD_RET_SUCCESS || rc == QCLOUD_ERR_INVAL) { + Log_d("handle saved log done! Size: %d. upload paylod: %d", whole_log_size, actual_post_payload); + sg_uploader->del_func(); + } + HAL_Free(log_buf); + } else { + Log_e("fail to read whole saved log. Size: %u - read: %u", whole_log_size, read_len); + HAL_Free(log_buf); + return QCLOUD_ERR_FAILURE; + } + + } else { + Log_e("Malloc failed, size: %u", buf_size); + return QCLOUD_ERR_FAILURE; + } + } + + return rc; +} + +void set_log_mqtt_client(void *client) +{ + if (!sg_log_uploader_init_done) + return; + + sg_uploader->mqtt_client = client; +} + +void set_log_upload_in_comm_err(bool value) +{ + if (!sg_log_uploader_init_done) + return; + + sg_uploader->upload_only_in_comm_err = value; +} + +int append_to_upload_buffer(const char *log_content, size_t log_size) +{ + if (!sg_log_uploader_init_done) + return -1; + + if (log_content == NULL || log_size == 0) { + UPLOAD_ERR("invalid log content!"); + return -1; + } + + if (HAL_MutexTryLock(sg_uploader->lock_buf) != 0) { + UPLOAD_ERR("trylock buffer failed!"); + return -1; + } + + if ((sg_write_index + log_size + 1) > LOG_UPLOAD_BUFFER_SIZE) { + countdown_ms(&sg_uploader->upload_timer, 0); + HAL_MutexUnlock(sg_uploader->lock_buf); + UPLOAD_ERR("log upload buffer is not enough!"); + return -1; + } + + memcpy(sg_log_buffer + sg_write_index, log_content, log_size); + + sg_write_index += log_size; + + /* replace \r\n to \n\f as delimiter */ + sg_log_buffer[sg_write_index - 1] = '\f'; + sg_log_buffer[sg_write_index - 2] = '\n'; + + HAL_MutexUnlock(sg_uploader->lock_buf); + return 0; +} + +void clear_upload_buffer(void) +{ + if (!sg_log_uploader_init_done) + return; + + HAL_MutexLock(sg_uploader->lock_buf); + _reset_log_buffer(); + HAL_MutexUnlock(sg_uploader->lock_buf); +} + +int init_log_uploader(LogUploadInitParams *init_params) +{ + if (sg_log_uploader_init_done) + return QCLOUD_RET_SUCCESS; + + if (init_params == NULL || init_params->product_id == NULL || init_params->device_name == NULL || + init_params->sign_key == NULL) { + UPLOAD_ERR("invalid init parameters"); + return QCLOUD_ERR_INVAL; + } + + int key_len = strlen(init_params->sign_key); + if (key_len == 0) { + UPLOAD_ERR("invalid key length"); + return QCLOUD_ERR_INVAL; + } + + sg_log_buffer = HAL_Malloc(LOG_UPLOAD_BUFFER_SIZE); + if (sg_log_buffer == NULL) { + UPLOAD_ERR("malloc log buffer failed"); + return QCLOUD_ERR_FAILURE; + } + + int i; + for (i = 0; i < LOG_BUF_FIXED_HEADER_SIZE; i++) sg_log_buffer[i] = '#'; + +#ifdef AUTH_MODE_CERT + if (_gen_key_from_file(init_params->sign_key) != 0) { + UPLOAD_ERR("gen_key_from_file failed"); + goto err_exit; + } + sg_log_buffer[SIGNATURE_SIZE] = 'C'; +#else + memcpy(sg_sign_key, init_params->sign_key, key_len > SIGN_KEY_SIZE ? SIGN_KEY_SIZE : key_len); + sg_log_buffer[SIGNATURE_SIZE] = 'P'; +#endif + + memcpy(sg_log_buffer + SIGNATURE_SIZE + CTRL_BYTES_SIZE, init_params->product_id, MAX_SIZE_OF_PRODUCT_ID); + memcpy(sg_log_buffer + SIGNATURE_SIZE + CTRL_BYTES_SIZE + MAX_SIZE_OF_PRODUCT_ID, init_params->device_name, + strlen(init_params->device_name)); + + if (NULL == (sg_uploader = HAL_Malloc(sizeof(LogUploaderStruct)))) { + UPLOAD_ERR("allocate for LogUploaderStruct failed"); + goto err_exit; + } + memset(sg_uploader, 0, sizeof(LogUploaderStruct)); + + sg_uploader->product_id = init_params->product_id; + sg_uploader->device_name = init_params->device_name; + sg_uploader->mqtt_client = NULL; + sg_uploader->system_time = 0; + sg_uploader->upload_only_in_comm_err = false; + + /* all the call back functions are necessary to handle log save and re-upload */ + if (init_params->save_func != NULL && init_params->read_func != NULL && init_params->del_func != NULL && + init_params->get_size_func) { + sg_uploader->save_func = init_params->save_func; + sg_uploader->read_func = init_params->read_func; + sg_uploader->del_func = init_params->del_func; + sg_uploader->get_size_func = init_params->get_size_func; + sg_uploader->log_save_enabled = true; + } else { + sg_uploader->log_save_enabled = false; + } + + InitTimer(&sg_uploader->upload_timer); + InitTimer(&sg_uploader->time_update_timer); + + if ((sg_uploader->lock_buf = HAL_MutexCreate()) == NULL) { + UPLOAD_ERR("mutex create failed"); + goto err_exit; + } + + if (NULL == (sg_http_c = HAL_Malloc(sizeof(LogHTTPStruct)))) { + UPLOAD_ERR("allocate for LogHTTPStruct failed"); + goto err_exit; + } + memset(sg_http_c, 0, sizeof(LogHTTPStruct)); + + /* set http request-header parameter */ + sg_http_c->http.header = "Accept:application/json;*/*\r\n"; + sg_http_c->url = LOG_UPLOAD_SERVER_URL; + sg_http_c->port = LOG_UPLOAD_SERVER_PORT; + sg_http_c->ca_crt = NULL; + + _reset_log_buffer(); + sg_log_uploader_init_done = true; + + return QCLOUD_RET_SUCCESS; +err_exit: + HAL_Free(sg_log_buffer); + sg_log_buffer = NULL; + + if (sg_uploader && sg_uploader->lock_buf) { + HAL_MutexDestroy(sg_uploader->lock_buf); + sg_uploader->lock_buf = NULL; + } + HAL_Free(sg_uploader); + sg_uploader = NULL; + HAL_Free(sg_http_c); + sg_http_c = NULL; + return QCLOUD_ERR_FAILURE; +} + +void fini_log_uploader(void) +{ + if (!sg_log_uploader_init_done) + return; + + HAL_MutexLock(sg_uploader->lock_buf); + sg_log_uploader_init_done = false; + if (sg_log_buffer) { + _reset_log_buffer(); + HAL_Free(sg_log_buffer); + sg_log_buffer = NULL; + } + HAL_MutexUnlock(sg_uploader->lock_buf); + + HAL_MutexDestroy(sg_uploader->lock_buf); + sg_uploader->lock_buf = NULL; + HAL_Free(sg_uploader); + sg_uploader = NULL; + HAL_Free(sg_http_c); + sg_http_c = NULL; +} + +bool is_log_uploader_init(void) +{ + return sg_log_uploader_init_done; +} + +static bool _check_force_upload(bool force_upload) +{ + if (!force_upload) { + /* Double check if the buffer is low */ + HAL_MutexLock(sg_uploader->lock_buf); + bool is_low_buffer = (LOG_UPLOAD_BUFFER_SIZE - sg_write_index) < LOG_LOW_BUFFER_THRESHOLD ? true : false; + + /* force_upload is false and upload_only_in_comm_err is true */ + if (sg_uploader->upload_only_in_comm_err) { + /* buffer is low but we couldn't upload now, reset buffer */ + if (is_low_buffer) + _reset_log_buffer(); + + HAL_MutexUnlock(sg_uploader->lock_buf); + countdown_ms(&sg_uploader->upload_timer, LOG_UPLOAD_INTERVAL_MS); + return false; + } + HAL_MutexUnlock(sg_uploader->lock_buf); + + if (is_low_buffer) { + /* buffer is low, handle it right now */ + return true; + } else { + return expired(&sg_uploader->upload_timer); + } + + } else { + return true; + } +} + +int do_log_upload(bool force_upload) +{ + int rc; + int upload_log_size = 0; + static bool unhandle_saved_log = true; + + if (!sg_log_uploader_init_done) + return QCLOUD_ERR_FAILURE; + + /* double check force upload */ + if (!_check_force_upload(force_upload)) + return QCLOUD_RET_SUCCESS; + + /* handle previously saved log */ + if (sg_uploader->log_save_enabled && unhandle_saved_log) { + rc = _handle_saved_log(); + if (rc == QCLOUD_RET_SUCCESS) + unhandle_saved_log = false; + } + + /* no more log in buffer */ + if (sg_write_index == LOG_BUF_FIXED_HEADER_SIZE) + return QCLOUD_RET_SUCCESS; + + HAL_MutexLock(sg_uploader->lock_buf); + upload_log_size = sg_write_index; + HAL_MutexUnlock(sg_uploader->lock_buf); + + size_t actual_post_payload; + rc = _post_log_to_server(sg_log_buffer, upload_log_size, &actual_post_payload); + if (rc != QCLOUD_RET_SUCCESS) { + /* save log via user callbacks when log upload fail */ + if (sg_uploader->log_save_enabled) { + /* new error logs should have been added, update log size */ + HAL_MutexLock(sg_uploader->lock_buf); + /* parts of log were uploaded succesfully. Need to move the new logs forward */ + if (actual_post_payload) { + UPLOAD_DBG("move the new log %d forward", actual_post_payload); + memmove(sg_log_buffer + upload_log_size - actual_post_payload, sg_log_buffer + upload_log_size, + sg_write_index - upload_log_size); + sg_write_index = sg_write_index - actual_post_payload; + memset(sg_log_buffer + sg_write_index, 0, LOG_UPLOAD_BUFFER_SIZE - sg_write_index); + } + upload_log_size = sg_write_index; + HAL_MutexUnlock(sg_uploader->lock_buf); + _save_log(sg_log_buffer + LOG_BUF_FIXED_HEADER_SIZE, upload_log_size - LOG_BUF_FIXED_HEADER_SIZE); + unhandle_saved_log = true; + } + } + + /* move the new log during send_log_to_server */ + HAL_MutexLock(sg_uploader->lock_buf); + if (upload_log_size == sg_write_index) { + _reset_log_buffer(); + } else { + memmove(sg_log_buffer + LOG_BUF_FIXED_HEADER_SIZE, sg_log_buffer + upload_log_size, + sg_write_index - upload_log_size); + sg_write_index = sg_write_index - upload_log_size + LOG_BUF_FIXED_HEADER_SIZE; + memset(sg_log_buffer + sg_write_index, 0, LOG_UPLOAD_BUFFER_SIZE - sg_write_index); + } + HAL_MutexUnlock(sg_uploader->lock_buf); + + countdown_ms(&sg_uploader->upload_timer, LOG_UPLOAD_INTERVAL_MS); + + return QCLOUD_RET_SUCCESS; +} + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/src/ota/src/ota_client.c b/sdk_src/services/ota/ota_client.c similarity index 67% rename from src/ota/src/ota_client.c rename to sdk_src/services/ota/ota_client.c index 3cad9077..75873954 100644 --- a/src/ota/src/ota_client.c +++ b/sdk_src/services/ota/ota_client.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -17,112 +17,102 @@ extern "C" { #endif +#include "ota_client.h" + #include #include #include -#include "ota_client.h" - -#include "qcloud_iot_export.h" -#include "qcloud_iot_sdk_impl_internal.h" - -#include "ota_lib.h" #include "ota_fetch.h" - +#include "ota_lib.h" +#include "qcloud_iot_export.h" +#include "utils_param_check.h" #include "utils_timer.h" -#define OTA_VERSION_STR_LEN_MIN (1) -#define OTA_VERSION_STR_LEN_MAX (32) +#define OTA_VERSION_STR_LEN_MIN (1) +#define OTA_VERSION_STR_LEN_MAX (32) -typedef struct { - const char *product_id; /* point to product id */ - const char *device_name; /* point to device name */ +typedef struct { + const char *product_id; /* point to product id */ + const char *device_name; /* point to device name */ - uint32_t id; /* message id */ - IOT_OTA_State_Code state; /* OTA state */ - uint32_t size_last_fetched; /* size of last downloaded */ - uint32_t size_fetched; /* size of already downloaded */ - uint32_t size_file; /* size of file */ + uint32_t id; /* message id */ + IOT_OTA_State_Code state; /* OTA state */ + uint32_t size_last_fetched; /* size of last downloaded */ + uint32_t size_fetched; /* size of already downloaded */ + uint32_t size_file; /* size of file */ - char *purl; /* point to URL */ - char *version; /* point to string */ - char md5sum[33]; /* MD5 string */ + char *purl; /* point to URL */ + char *version; /* point to string */ + char md5sum[33]; /* MD5 string */ - void *md5; /* MD5 handle */ - void *ch_signal; /* channel handle of signal exchanged with OTA server */ - void *ch_fetch; /* channel handle of download */ + void *md5; /* MD5 handle */ + void *ch_signal; /* channel handle of signal exchanged with OTA server */ + void *ch_fetch; /* channel handle of download */ - int err; /* last error code */ + int err; /* last error code */ - short current_signal_type; + short current_signal_type; Timer report_timer; } OTA_Struct_t; - -/* 检查进度状态是否有效 */ +/* check ota progress */ /* return: true, valid progress state; false, invalid progress state. */ static int _ota_check_progress(IOT_OTA_Progress_Code progress) { - return ((progress >= IOT_OTAP_BURN_FAILED) - && (progress <= IOT_OTAP_FETCH_PERCENTAGE_MAX)); + return ((progress >= IOT_OTAP_BURN_FAILED) && (progress <= IOT_OTAP_FETCH_PERCENTAGE_MAX)); } -/* 当收到OTA topic的订阅消息过后,订阅回调函数会执行此函数 */ -static void _ota_callback(void *pcontext, const char *msg, uint32_t msg_len) { +/* callback when OTA topic msg is received */ +static void _ota_callback(void *pcontext, const char *msg, uint32_t msg_len) +{ #define OTA_JSON_TYPE_VALUE_LENGTH 64 char *json_type = NULL; - OTA_Struct_t *h_ota = (OTA_Struct_t *) pcontext; + OTA_Struct_t *h_ota = (OTA_Struct_t *)pcontext; if (h_ota->state >= IOT_OTAS_FETCHING) { Log_i("In downloading or downloaded state"); goto End; } - if (msg == NULL || msg_len <= 0) { - Log_e("OTA response message is NULL"); - return; + if (msg == NULL || msg_len == 0) { + Log_e("OTA response message is NULL"); + return; } - if (qcloud_otalib_get_firmware_type(msg, &json_type) != QCLOUD_ERR_SUCCESS) { + if (qcloud_otalib_get_firmware_type(msg, &json_type) != QCLOUD_RET_SUCCESS) { Log_e("Get firmware type failed!"); goto End; } if (!strcmp(json_type, REPORT_VERSION_RSP)) { - if (qcloud_otalib_get_report_version_result(msg) < QCLOUD_ERR_SUCCESS) { + if (qcloud_otalib_get_report_version_result(msg) < QCLOUD_RET_SUCCESS) { Log_e("Report version failed!"); - h_ota->err = IOT_OTA_ERR_REPORT_VERSION; + h_ota->err = IOT_OTA_ERR_REPORT_VERSION; h_ota->state = IOT_OTAS_FETCHED; - } - else { - Log_i("Report version success!"); - } - goto End; - } - else { - if (strcmp(json_type, UPDATE_FIRMWARE) != 0) { - Log_e("Netheir Report version result nor update firmware! type: %s", json_type); - goto End; + } else { + Log_i("Report version success!"); } - - if (0 != qcloud_otalib_get_params(msg, &json_type, &h_ota->purl, &h_ota->version, - h_ota->md5sum, &h_ota->size_file)) { - Log_e("Get firmware parameter failed"); + goto End; + } else { + if (strcmp(json_type, UPDATE_FIRMWARE) != 0) { + Log_e("Netheir Report version result nor update firmware! type: %s", + STRING_PTR_PRINT_SANITY_CHECK(json_type)); goto End; } - if (NULL == (h_ota->ch_fetch = ofc_Init(h_ota->purl))) { - Log_e("Initialize fetch module failed"); - goto End; + if (NULL != json_type) { + HAL_Free(json_type); + json_type = NULL; } - if (0 != qcloud_ofc_connect(h_ota->ch_fetch)) { - Log_e("Connect fetch module failed"); - h_ota->state = IOT_OTAS_DISCONNECTED; + if (0 != qcloud_otalib_get_params(msg, &json_type, &h_ota->purl, &h_ota->version, h_ota->md5sum, + &h_ota->size_file)) { + Log_e("Get firmware parameter failed"); goto End; } @@ -130,18 +120,37 @@ static void _ota_callback(void *pcontext, const char *msg, uint32_t msg_len) { } End: - if (json_type != NULL) HAL_Free(json_type); + if (json_type != NULL) + HAL_Free(json_type); #undef OTA_JSON_TYPE_VALUE_LENGTH } +static void IOT_OTA_ResetStatus(void *handle) +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + Log_i("reset OTA state!"); + h_ota->state = IOT_OTAS_INITED; + h_ota->err = 0; + + if (NULL != h_ota->purl) { + HAL_Free(h_ota->purl); + h_ota->purl = NULL; + } + + if (NULL != h_ota->version) { + HAL_Free(h_ota->version); + h_ota->version = NULL; + } +} + static int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_Code progress, IOT_OTAReportType reportType) { -#define MSG_REPORT_LEN (256) +#define MSG_REPORT_LEN (256) - int ret = QCLOUD_ERR_FAILURE; - char *msg_reported; - OTA_Struct_t * h_ota = (OTA_Struct_t *) handle; + int ret = QCLOUD_ERR_FAILURE; + char * msg_reported; + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; if (NULL == handle) { Log_e("handle is NULL"); @@ -155,7 +164,7 @@ static int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_Code progress, } if (!_ota_check_progress(progress)) { - Log_e("progress is a invalid parameter"); + Log_e("progress is a invalid parameter: %d", progress); h_ota->err = IOT_OTA_ERR_INVALID_PARAM; return QCLOUD_ERR_FAILURE; } @@ -174,13 +183,13 @@ static int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_Code progress, } ret = qcloud_osc_report_progress(h_ota->ch_signal, msg_reported); - if (QCLOUD_ERR_SUCCESS != ret) { + if (QCLOUD_RET_SUCCESS != ret) { Log_e("Report progress failed"); h_ota->err = ret; goto do_exit; } - ret = QCLOUD_ERR_SUCCESS; + ret = QCLOUD_RET_SUCCESS; do_exit: if (NULL != msg_reported) { @@ -193,13 +202,13 @@ static int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_Code progress, static int IOT_OTA_ReportUpgradeResult(void *handle, const char *version, IOT_OTAReportType reportType) { -#define MSG_UPGPGRADE_LEN (256) +#define MSG_UPGPGRADE_LEN (256) POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM); POINTER_SANITY_CHECK(version, IOT_OTA_ERR_INVALID_PARAM); - - int ret, len; - char *msg_upgrade; + + int ret, len; + char * msg_upgrade; OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; if (IOT_OTAS_UNINITED == h_ota->state) { @@ -208,6 +217,9 @@ static int IOT_OTA_ReportUpgradeResult(void *handle, const char *version, IOT_OT return QCLOUD_ERR_FAILURE; } + if (version == NULL) + version = h_ota->version; + len = strlen(version); if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) { Log_e("version string is invalid: must be [1, 32] chars"); @@ -225,7 +237,7 @@ static int IOT_OTA_ReportUpgradeResult(void *handle, const char *version, IOT_OT if (ret != 0) { Log_e("generate inform message failed"); h_ota->err = ret; - ret = QCLOUD_ERR_FAILURE; + ret = QCLOUD_ERR_FAILURE; goto do_exit; } @@ -233,10 +245,15 @@ static int IOT_OTA_ReportUpgradeResult(void *handle, const char *version, IOT_OT if (0 > ret) { Log_e("Report version failed"); h_ota->err = ret; - ret = QCLOUD_ERR_FAILURE; + ret = QCLOUD_ERR_FAILURE; goto do_exit; } + if ((IOT_OTAR_UPGRADE_FAIL == reportType) || (IOT_OTAR_UPGRADE_SUCCESS == reportType) || + (IOT_OTAR_MD5_NOT_MATCH == reportType)) { + IOT_OTA_ResetStatus(h_ota); + } + do_exit: if (NULL != msg_upgrade) { HAL_Free(msg_upgrade); @@ -246,14 +263,13 @@ static int IOT_OTA_ReportUpgradeResult(void *handle, const char *version, IOT_OT #undef MSG_UPGPGRADE_LEN } - -/* 初始化OTA模块 */ +/* Init OTA handle */ void *IOT_OTA_Init(const char *product_id, const char *device_name, void *ch_signal) { POINTER_SANITY_CHECK(product_id, NULL); POINTER_SANITY_CHECK(device_name, NULL); POINTER_SANITY_CHECK(ch_signal, NULL); - + OTA_Struct_t *h_ota = NULL; if (NULL == (h_ota = HAL_Malloc(sizeof(OTA_Struct_t)))) { @@ -275,9 +291,9 @@ void *IOT_OTA_Init(const char *product_id, const char *device_name, void *ch_sig goto do_exit; } - h_ota->product_id = product_id; + h_ota->product_id = product_id; h_ota->device_name = device_name; - h_ota->state = IOT_OTAS_INITED; + h_ota->state = IOT_OTAS_INITED; #ifdef OTA_MQTT_CHANNEL h_ota->current_signal_type = MQTT_CHANNEL; #else @@ -304,11 +320,10 @@ void *IOT_OTA_Init(const char *product_id, const char *device_name, void *ch_sig #undef AOM_INFO_MSG_LEN } - -/* 释放OTA模块 */ +/* Destroy OTA handle and resource */ int IOT_OTA_Destroy(void *handle) { - OTA_Struct_t *h_ota = (OTA_Struct_t*) handle; + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; if (NULL == h_ota) { Log_e("handle is NULL"); @@ -334,16 +349,73 @@ int IOT_OTA_Destroy(void *handle) } HAL_Free(h_ota); - return 0; + return QCLOUD_RET_SUCCESS; +} + +/*support continuous transmission of breakpoints*/ +int IOT_OTA_StartDownload(void *handle, uint32_t offset, uint32_t size) +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + int Ret; + + Log_d("to download FW from offset: %u, size: %u", offset, size); + h_ota->size_fetched = offset; + + // reset md5 for new download + if (offset == 0) { + Ret = IOT_OTA_ResetClientMD5(h_ota); + if (Ret) { + Log_e("initialize md5 failed"); + return QCLOUD_ERR_FAILURE; + } + } + + // reinit ofc + qcloud_ofc_deinit(h_ota->ch_fetch); + h_ota->ch_fetch = ofc_Init(h_ota->purl, offset, size); + if (NULL == h_ota->ch_fetch) { + Log_e("Initialize fetch module failed"); + return QCLOUD_ERR_FAILURE; + } + + Ret = qcloud_ofc_connect(h_ota->ch_fetch); + if (QCLOUD_RET_SUCCESS != Ret) { + Log_e("Connect fetch module failed"); + h_ota->state = IOT_OTAS_DISCONNECTED; + } + + return Ret; +} + +/*support continuous transmission of breakpoints*/ +void IOT_OTA_UpdateClientMd5(void *handle, char *buff, uint32_t size) +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + + qcloud_otalib_md5_update(h_ota->md5, buff, size); +} + +/*support continuous transmission of breakpoints*/ +int IOT_OTA_ResetClientMD5(void *handle) +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + + qcloud_otalib_md5_deinit(h_ota->md5); + h_ota->md5 = qcloud_otalib_md5_init(); + if (NULL == h_ota->md5) { + return QCLOUD_ERR_FAILURE; + } + + return QCLOUD_RET_SUCCESS; } int IOT_OTA_ReportVersion(void *handle, const char *version) { -#define MSG_INFORM_LEN (128) +#define MSG_INFORM_LEN (128) - int ret, len; - char *msg_informed; - OTA_Struct_t *h_ota = (OTA_Struct_t *) handle; + int ret, len; + char * msg_informed; + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM); POINTER_SANITY_CHECK(version, IOT_OTA_ERR_INVALID_PARAM); @@ -361,6 +433,8 @@ int IOT_OTA_ReportVersion(void *handle, const char *version) return QCLOUD_ERR_FAILURE; } + IOT_OTA_ResetStatus(h_ota); + if (NULL == (msg_informed = HAL_Malloc(MSG_INFORM_LEN))) { Log_e("allocate for msg_informed failed"); h_ota->err = IOT_OTA_ERR_NOMEM; @@ -371,7 +445,7 @@ int IOT_OTA_ReportVersion(void *handle, const char *version) if (ret != 0) { Log_e("generate inform message failed"); h_ota->err = ret; - ret = QCLOUD_ERR_FAILURE; + ret = QCLOUD_ERR_FAILURE; goto do_exit; } @@ -379,7 +453,7 @@ int IOT_OTA_ReportVersion(void *handle, const char *version) if (0 > ret) { Log_e("Report version failed"); h_ota->err = ret; - ret = QCLOUD_ERR_FAILURE; + ret = QCLOUD_ERR_FAILURE; goto do_exit; } @@ -394,20 +468,37 @@ int IOT_OTA_ReportVersion(void *handle, const char *version) int IOT_OTA_ReportUpgradeBegin(void *handle) { - OTA_Struct_t *h_ota = (OTA_Struct_t *) handle; + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; return IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_BEGIN); } int IOT_OTA_ReportUpgradeSuccess(void *handle, const char *version) { - return IOT_OTA_ReportUpgradeResult(handle, version, IOT_OTAR_UPGRADE_SUCCESS); + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + int ret; + + if (NULL == version) { + ret = IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_SUCCESS); + } else { + ret = IOT_OTA_ReportUpgradeResult(handle, version, IOT_OTAR_UPGRADE_SUCCESS); + } + + return ret; } int IOT_OTA_ReportUpgradeFail(void *handle, const char *version) { - return IOT_OTA_ReportUpgradeResult(handle, version, IOT_OTAR_UPGRADE_FAIL); -} + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + int ret; + if (NULL == version) { + ret = IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_FAIL); + } else { + ret = IOT_OTA_ReportUpgradeResult(handle, version, IOT_OTAR_UPGRADE_FAIL); + } + + return ret; +} /* check whether is downloading */ int IOT_OTA_IsFetching(void *handle) @@ -428,11 +519,10 @@ int IOT_OTA_IsFetching(void *handle) return (IOT_OTAS_FETCHING == h_ota->state); } - /* check whether fetch over */ int IOT_OTA_IsFetchFinish(void *handle) { - OTA_Struct_t *h_ota = (OTA_Struct_t *) handle; + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; if (NULL == handle) { Log_e("handle is NULL"); @@ -448,11 +538,10 @@ int IOT_OTA_IsFetchFinish(void *handle) return (IOT_OTAS_FETCHED == h_ota->state); } - -int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_ms) +int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s) { - int ret; - OTA_Struct_t *h_ota = (OTA_Struct_t *) handle; + int ret; + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM); POINTER_SANITY_CHECK(buf, IOT_OTA_ERR_INVALID_PARAM); @@ -463,22 +552,22 @@ int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeo return IOT_OTA_ERR_INVALID_STATE; } - ret = qcloud_ofc_fetch(h_ota->ch_fetch, buf, buf_len, timeout_ms); + ret = qcloud_ofc_fetch(h_ota->ch_fetch, buf, buf_len, timeout_s); if (ret < 0) { h_ota->state = IOT_OTAS_FETCHED; - h_ota->err = IOT_OTA_ERR_FETCH_FAILED; + h_ota->err = IOT_OTA_ERR_FETCH_FAILED; - if (ret == IOT_OTA_ERR_FETCH_AUTH_FAIL) { // 上报签名过期 + if (ret == IOT_OTA_ERR_FETCH_AUTH_FAIL) { // OTA auth failed IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_AUTH_FAIL); h_ota->err = ret; - } else if (ret == IOT_OTA_ERR_FETCH_NOT_EXIST) { // 上报文件不存在 + } else if (ret == IOT_OTA_ERR_FETCH_NOT_EXIST) { // fetch not existed IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_FILE_NOT_EXIST); h_ota->err = ret; - } else if (ret == IOT_OTA_ERR_FETCH_TIMEOUT) { // 上报下载超时 + } else if (ret == IOT_OTA_ERR_FETCH_TIMEOUT) { // fetch timeout IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_DOWNLOAD_TIMEOUT); h_ota->err = ret; - } - + } + return ret; } else if (0 == h_ota->size_fetched) { /* force report status in the first */ @@ -509,10 +598,9 @@ int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeo return ret; } - int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len) { - OTA_Struct_t * h_ota = (OTA_Struct_t *) handle; + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM); POINTER_SANITY_CHECK(buf, IOT_OTA_ERR_INVALID_PARAM); @@ -566,12 +654,12 @@ int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len) } else { char md5_str[33]; qcloud_otalib_md5_finalize(h_ota->md5, md5_str); - Log_d("origin=%s, now=%s", h_ota->md5sum, md5_str); + Log_i("FW MD5 check: origin=%s, now=%s", STRING_PTR_PRINT_SANITY_CHECK(h_ota->md5sum), md5_str); if (0 == strcmp(h_ota->md5sum, md5_str)) { *((uint32_t *)buf) = 1; } else { *((uint32_t *)buf) = 0; - // 上报MD5不匹配 + // report MD5 inconsistent IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_MD5_NOT_MATCH); } return 0; @@ -586,15 +674,14 @@ int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len) return 0; } - /* Get last error code */ int IOT_OTA_GetLastError(void *handle) { - OTA_Struct_t * h_ota = (OTA_Struct_t *) handle; + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; if (NULL == handle) { Log_e("handle is NULL"); - return IOT_OTA_ERR_INVALID_PARAM; + return IOT_OTA_ERR_INVALID_PARAM; } return h_ota->err; diff --git a/sdk_src/services/ota/ota_coap.c b/sdk_src/services/ota/ota_coap.c new file mode 100755 index 00000000..665dc493 --- /dev/null +++ b/sdk_src/services/ota/ota_coap.c @@ -0,0 +1,202 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifndef OTA_MQTT_CHANNEL + +#include + +#include "ota_client.h" + +typedef struct { + void *coap; + + const char *product_id; + const char *device_name; + + char topic_upgrade[OTA_MAX_TOPIC_LEN]; + + OnOTAMessageCallback msg_callback; + + void *context; +} OTA_CoAP_Struct_t; + +static void _otacoap_upgrage_cb(void *coap_message, void *pcontext) +{ + int ret_code = IOT_COAP_GetMessageCode(coap_message); + + switch (ret_code) { + case COAP_EVENT_RECEIVE_ACK: + Log_i("received OTA message ACK, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_RECEIVE_RESPCONTENT: { + Log_i("received OTA message respconetent."); + char *payload = NULL; + int payload_len = 0; + int ret = -1; + ret = IOT_COAP_GetMessagePayload(coap_message, &payload, &payload_len); + if (ret == QCLOUD_RET_SUCCESS) { + OTA_CoAP_Struct_t *handle = (OTA_CoAP_Struct_t *)pcontext; + if (NULL != handle->msg_callback) { + handle->msg_callback(handle->context, payload, payload_len); + } + } else { + Log_e("message received response, content error."); + } + } break; + case COAP_EVENT_UNAUTHORIZED: + Log_e("coap client auth token expired or invalid, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_FORBIDDEN: + Log_e("coap URI is invalid for this device, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_INTERNAL_SERVER_ERROR: + Log_e("coap server internal error, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_ACK_TIMEOUT: + Log_e("message receive ACK timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + case COAP_EVENT_SEPRESP_TIMEOUT: + Log_i("message received ACK but receive response timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); + break; + default: + break; + } +} + +/* Generate topic name according to @OTATopicType, @productId, @deviceName */ +/* and then copy to @buf. */ +/* 0, successful; -1, failed */ +static int _otacoap_gen_topic_name(char *buf, size_t bufLen, const char *OTATopicType, const char *productId, + const char *deviceName) +{ + IOT_FUNC_ENTRY; + + int ret; + + ret = HAL_Snprintf(buf, bufLen, "$ota/%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(OTATopicType), + STRING_PTR_PRINT_SANITY_CHECK(productId), STRING_PTR_PRINT_SANITY_CHECK(deviceName)); + + if (ret >= bufLen) + IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); + + if (ret < 0) { + Log_e("HAL_Snprintf failed"); + IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +/* report progress of OTA */ +static int _otacoap_publish(OTA_CoAP_Struct_t *handle, const char *topicType, const char *msg, bool needResp) +{ + IOT_FUNC_ENTRY; + + int ret; + char topic_name[OTA_MAX_TOPIC_LEN]; + + SendMsgParams send_params = DEFAULT_SENDMSG_PARAMS; + send_params.pay_load = (void *)msg; + send_params.pay_load_len = strlen(msg); + send_params.resp_callback = _otacoap_upgrage_cb; + send_params.need_resp = needResp; + send_params.user_context = handle; + + /* inform OTA to topic: "/ota/device/progress/$(product_id)/$(device_name)" */ + ret = _otacoap_gen_topic_name(topic_name, OTA_MAX_TOPIC_LEN, topicType, handle->product_id, handle->device_name); + if (ret < 0) { + Log_e("generate topic name of info failed"); + IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); + } + + ret = IOT_COAP_SendMessage(handle->coap, topic_name, &send_params); + if (ret < 0) { + Log_e("publish failed"); + IOT_FUNC_EXIT_RC(IOT_OTA_ERR_OSC_FAILED); + } + + IOT_FUNC_EXIT_RC(ret); +} + +void *qcloud_osc_init(const char *productId, const char *deviceName, void *channel, OnOTAMessageCallback callback, + void *context) +{ + OTA_CoAP_Struct_t *h_osc = NULL; + + if (NULL == (h_osc = HAL_Malloc(sizeof(OTA_CoAP_Struct_t)))) { + Log_e("allocate for h_osc failed"); + goto do_exit; + } + + memset(h_osc, 0, sizeof(OTA_CoAP_Struct_t)); + + h_osc->coap = channel; + h_osc->product_id = productId; + h_osc->device_name = deviceName; + h_osc->msg_callback = callback; + h_osc->context = context; + + return h_osc; + +do_exit: + if (NULL != h_osc) { + HAL_Free(h_osc); + } + + return NULL; +} + +int qcloud_osc_deinit(void *handle) +{ + IOT_FUNC_ENTRY; + + if (NULL != handle) { + HAL_Free(handle); + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +/* report progress of OTA */ +int qcloud_osc_report_progress(void *handle, const char *msg) +{ + return _otacoap_publish(handle, "report", msg, false); +} + +/* report version of OTA firmware */ +int qcloud_osc_report_version(void *handle, const char *msg) +{ + return _otacoap_publish(handle, "report", msg, true); +} + +/* report upgrade begin of OTA firmware */ +int qcloud_osc_report_upgrade_result(void *handle, const char *msg) +{ + return _otacoap_publish(handle, "report", msg, false); +} + +/* OSC, OTA signal channel */ +#endif + +#ifdef __cplusplus +} +#endif diff --git a/src/ota/src/ota_fetch.c b/sdk_src/services/ota/ota_fetch.c old mode 100644 new mode 100755 similarity index 55% rename from src/ota/src/ota_fetch.c rename to sdk_src/services/ota/ota_fetch.c index 4dce4162..518f9514 --- a/src/ota/src/ota_fetch.c +++ b/sdk_src/services/ota/ota_fetch.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -20,47 +20,47 @@ extern "C" { #include "ota_fetch.h" #include -#include +#include "qcloud_iot_ca.h" #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" - -#include "ca.h" - #include "utils_httpc.h" +#define OTA_HTTP_HEAD_CONTENT_LEN 256 + /* ofc, OTA fetch channel */ typedef struct { - - const char *url; - HTTPClient http; /* http client */ - HTTPClientData http_data; /* http client data */ + const char * url; + HTTPClient http; /* http client */ + HTTPClientData http_data; /* http client data */ } OTAHTTPStruct; -static int is_begin_with(const char * str1,char *str2) +#ifdef OTA_USE_HTTPS +static int is_begin_with(const char *str1, char *str2) { - if(str1 == NULL || str2 == NULL) + if (str1 == NULL || str2 == NULL) return -1; int len1 = strlen(str1); int len2 = strlen(str2); - if((len1 < len2) || (len1 == 0 || len2 == 0)) + if ((len1 < len2) || (len1 == 0 || len2 == 0)) return -1; char *p = str2; - int i = 0; - while(*p != '\0') - { - if(*p != str1[i]) - return 0; + int i = 0; + while (*p != '\0') { + if (*p != str1[i]) + return 0; p++; i++; } return 1; } +#endif -void *ofc_Init(const char *url) -{ +static char sg_head_content[OTA_HTTP_HEAD_CONTENT_LEN]; +void * ofc_Init(const char *url, uint32_t offset, uint32_t size) +{ OTAHTTPStruct *h_odc; if (NULL == (h_odc = HAL_Malloc(sizeof(OTAHTTPStruct)))) { @@ -69,12 +69,17 @@ void *ofc_Init(const char *url) } memset(h_odc, 0, sizeof(OTAHTTPStruct)); - + memset(sg_head_content, 0, OTA_HTTP_HEAD_CONTENT_LEN); + HAL_Snprintf(sg_head_content, OTA_HTTP_HEAD_CONTENT_LEN, + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + "Accept-Encoding: gzip, deflate\r\n" + "Range: bytes=%d-%d\r\n", + offset, size); + + Log_d("head_content:%s", sg_head_content); /* set http request-header parameter */ - h_odc->http.header = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \ - "Accept-Encoding: gzip, deflate\r\n"; - - h_odc->url = url; + h_odc->http.header = sg_head_content; + h_odc->url = url; return h_odc; } @@ -83,60 +88,62 @@ int32_t qcloud_ofc_connect(void *handle) { IOT_FUNC_ENTRY; - OTAHTTPStruct * h_odc = (OTAHTTPStruct *)handle; + OTAHTTPStruct *h_odc = (OTAHTTPStruct *)handle; - int port = 80; + int port = 80; const char *ca_crt = NULL; - if (is_begin_with(h_odc->url, "https")) - { - port = 443; +#ifdef OTA_USE_HTTPS + if (is_begin_with(h_odc->url, "https")) { + port = 443; ca_crt = iot_https_ca_get(); } +#endif int32_t rc = qcloud_http_client_common(&h_odc->http, h_odc->url, port, ca_crt, HTTP_GET, &h_odc->http_data); IOT_FUNC_EXIT_RC(rc); } - int32_t qcloud_ofc_fetch(void *handle, char *buf, uint32_t bufLen, uint32_t timeout_s) { IOT_FUNC_ENTRY; - int diff; - OTAHTTPStruct * h_odc = (OTAHTTPStruct *)handle; + int diff; + OTAHTTPStruct *h_odc = (OTAHTTPStruct *)handle; - h_odc->http_data.response_buf = buf; + h_odc->http_data.response_buf = buf; h_odc->http_data.response_buf_len = bufLen; - diff = h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len; - + diff = h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len; + int rc = qcloud_http_recv_data(&h_odc->http, timeout_s * 1000, &h_odc->http_data); - if (QCLOUD_ERR_SUCCESS != rc) { + if (QCLOUD_RET_SUCCESS != rc) { if (rc == QCLOUD_ERR_HTTP_NOT_FOUND) IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FETCH_NOT_EXIST); - + if (rc == QCLOUD_ERR_HTTP_AUTH) IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FETCH_AUTH_FAIL); - + if (rc == QCLOUD_ERR_HTTP_TIMEOUT) IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FETCH_TIMEOUT); - + IOT_FUNC_EXIT_RC(rc); } IOT_FUNC_EXIT_RC(h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len - diff); } - int qcloud_ofc_deinit(void *handle) { - IOT_FUNC_ENTRY; - if (NULL != handle) { - HAL_Free(handle); - } + OTAHTTPStruct *h_odc = (OTAHTTPStruct *)handle; + if (NULL == handle) + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); + + if (h_odc->http.network_stack.is_connected(&h_odc->http.network_stack)) + h_odc->http.network_stack.disconnect(&h_odc->http.network_stack); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + HAL_Free(handle); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } #ifdef __cplusplus diff --git a/src/ota/src/ota_lib.c b/sdk_src/services/ota/ota_lib.c old mode 100644 new mode 100755 similarity index 51% rename from src/ota/src/ota_lib.c rename to sdk_src/services/ota/ota_lib.c index 72aefefa..9985e48e --- a/src/ota/src/ota_lib.c +++ b/sdk_src/services/ota/ota_lib.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -19,74 +19,68 @@ extern "C" { #include "ota_lib.h" -#include #include +#include +#include "lite-utils.h" +#include "ota_client.h" #include "qcloud_iot_export.h" #include "qcloud_iot_import.h" - -#include "ota_client.h" - #include "utils_md5.h" -#include "lite-utils.h" /* Get the specific @key value, and copy to @dest */ /* 0, successful; -1, failed */ -static int _qcloud_otalib_get_firmware_fixlen_para(const char *json_doc, const char *key, - char *dest, size_t dest_len) +static int _qcloud_otalib_get_firmware_fixlen_para(const char *json_doc, const char *key, char *dest, size_t dest_len) { IOT_FUNC_ENTRY; - int ret = QCLOUD_ERR_SUCCESS; + int ret = QCLOUD_RET_SUCCESS; - char* key_bak = HAL_Malloc(strlen(key)); + char *key_bak = HAL_Malloc(strlen(key) + 1); if (key_bak == NULL) { - Log_e("not enough memory for malloc key"); - ret = IOT_OTA_ERR_FAIL; - IOT_FUNC_EXIT_RC(ret); + Log_e("not enough memory for malloc key"); + ret = IOT_OTA_ERR_FAIL; + IOT_FUNC_EXIT_RC(ret); } - char* json_doc_bak = HAL_Malloc(strlen(json_doc)); + char *json_doc_bak = HAL_Malloc(strlen(json_doc) + 1); if (json_doc_bak == NULL) { - Log_e("not enough memory for malloc json"); - HAL_Free(key_bak); - ret = IOT_OTA_ERR_FAIL; - IOT_FUNC_EXIT_RC(ret); + Log_e("not enough memory for malloc json"); + HAL_Free(key_bak); + ret = IOT_OTA_ERR_FAIL; + IOT_FUNC_EXIT_RC(ret); } strcpy(key_bak, key); strcpy(json_doc_bak, json_doc); - char* value = LITE_json_value_of(key_bak, json_doc_bak); + char *value = LITE_json_value_of(key_bak, json_doc_bak); if (value == NULL) { - Log_e("Not '%s' key in json doc of OTA", key); - ret = IOT_OTA_ERR_FAIL; - } - else { - uint32_t val_len = strlen(value); - if (val_len > dest_len) { - Log_e("value length of the key is too long"); - ret = IOT_OTA_ERR_FAIL; - } - else { - memcpy(dest, value, val_len); - ret = QCLOUD_ERR_SUCCESS; - } - - HAL_Free(value); + Log_e("Not '%s' key in json doc of OTA", STRING_PTR_PRINT_SANITY_CHECK(key)); + ret = IOT_OTA_ERR_FAIL; + } else { + uint32_t val_len = strlen(value); + if (val_len > dest_len) { + Log_e("value length of the key is too long"); + ret = IOT_OTA_ERR_FAIL; + } else { + memcpy(dest, value, val_len); + ret = QCLOUD_RET_SUCCESS; + } + + HAL_Free(value); } - if (key_bak != NULL) { - HAL_Free(key_bak); - } - if (json_doc_bak != NULL) { - HAL_Free(json_doc_bak); - } + if (key_bak != NULL) { + HAL_Free(key_bak); + } + if (json_doc_bak != NULL) { + HAL_Free(json_doc_bak); + } IOT_FUNC_EXIT_RC(ret); } - /* Get variant length parameter of firmware, and copy to @dest */ /* 0, successful; -1, failed */ static int _qcloud_otalib_get_firmware_varlen_para(const char *json_doc, const char *key, char **dest) @@ -95,21 +89,21 @@ static int _qcloud_otalib_get_firmware_varlen_para(const char *json_doc, const c IOT_FUNC_ENTRY; - int ret = QCLOUD_ERR_SUCCESS; + int ret = QCLOUD_RET_SUCCESS; - char* key_bak = HAL_Malloc(strlen(key)); + char *key_bak = HAL_Malloc(strlen(key) + 1); if (key_bak == NULL) { - Log_e("not enough memory for malloc key"); - ret = IOT_OTA_ERR_FAIL; - IOT_FUNC_EXIT_RC(ret); + Log_e("not enough memory for malloc key"); + ret = IOT_OTA_ERR_FAIL; + IOT_FUNC_EXIT_RC(ret); } - char* json_doc_bak = HAL_Malloc(strlen(json_doc)); + char *json_doc_bak = HAL_Malloc(strlen(json_doc) + 1); if (json_doc_bak == NULL) { - Log_e("not enough memory for malloc json"); - HAL_Free(key_bak); - ret = IOT_OTA_ERR_FAIL; - IOT_FUNC_EXIT_RC(ret); + Log_e("not enough memory for malloc json"); + HAL_Free(key_bak); + ret = IOT_OTA_ERR_FAIL; + IOT_FUNC_EXIT_RC(ret); } strcpy(key_bak, key); @@ -117,16 +111,16 @@ static int _qcloud_otalib_get_firmware_varlen_para(const char *json_doc, const c *dest = LITE_json_value_of(key_bak, json_doc_bak); if (*dest == NULL) { - Log_e("Not '%s' key in json '%s' doc of OTA", key_bak, json_doc_bak); - ret = IOT_OTA_ERR_FAIL; + Log_e("Not '%s' key in json '%s' doc of OTA", key_bak, json_doc_bak); + ret = IOT_OTA_ERR_FAIL; } - if (key_bak != NULL) { - HAL_Free(key_bak); - } - if (json_doc_bak != NULL) { - HAL_Free(json_doc_bak); - } + if (key_bak != NULL) { + HAL_Free(key_bak); + } + if (json_doc_bak != NULL) { + HAL_Free(json_doc_bak); + } IOT_FUNC_EXIT_RC(ret); @@ -153,12 +147,12 @@ void qcloud_otalib_md5_update(void *md5, const char *buf, size_t buf_len) void qcloud_otalib_md5_finalize(void *md5, char *output_str) { - int i; + int i; unsigned char buf_out[16]; utils_md5_finish(md5, buf_out); for (i = 0; i < 16; ++i) { - output_str[i * 2] = utils_hb2hex(buf_out[i] >> 4); + output_str[i * 2] = utils_hb2hex(buf_out[i] >> 4); output_str[i * 2 + 1] = utils_hb2hex(buf_out[i]); } output_str[32] = '\0'; @@ -183,21 +177,24 @@ int qcloud_otalib_get_report_version_result(const char *json) char *result_code = NULL; int rc = _qcloud_otalib_get_firmware_varlen_para(json, RESULT_FIELD, &result_code); - if ( rc != QCLOUD_ERR_SUCCESS || strcmp(result_code, "0") != 0) { + if (rc != QCLOUD_RET_SUCCESS || strcmp(result_code, "0") != 0) { + if (NULL != result_code) + HAL_Free(result_code); IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + if (NULL != result_code) + HAL_Free(result_code); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -int qcloud_otalib_get_params(const char *json, char **type, char **url, char **version, char *md5, - uint32_t *fileSize) +int qcloud_otalib_get_params(const char *json, char **type, char **url, char **version, char *md5, uint32_t *fileSize) { -#define OTA_FILESIZE_STR_LEN (16) +#define OTA_FILESIZE_STR_LEN (16) IOT_FUNC_ENTRY; - char file_size_str[OTA_FILESIZE_STR_LEN + 1]; + char file_size_str[OTA_FILESIZE_STR_LEN + 1] = {0}; /* get type */ if (0 != _qcloud_otalib_get_firmware_varlen_para(json, TYPE_FIELD, type)) { @@ -230,9 +227,9 @@ int qcloud_otalib_get_params(const char *json, char **type, char **url, char **v } file_size_str[OTA_FILESIZE_STR_LEN] = '\0'; - *fileSize = atoi(file_size_str); + *fileSize = atoi(file_size_str); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); #undef OTA_FILESIZE_STR_LEN } @@ -242,70 +239,70 @@ int qcloud_otalib_gen_info_msg(char *buf, size_t bufLen, uint32_t id, const char IOT_FUNC_ENTRY; int ret; - ret = HAL_Snprintf(buf, - bufLen, - "{\"type\": \"report_version\", \"report\":{\"version\":\"%s\"}}", - version); + ret = HAL_Snprintf(buf, bufLen, "{\"type\": \"report_version\", \"report\":{\"version\":\"%s\"}}", + STRING_PTR_PRINT_SANITY_CHECK(version)); if (ret < 0) { Log_e("HAL_Snprintf failed"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -int qcloud_otalib_gen_report_msg(char *buf, size_t bufLen, uint32_t id, const char *version, int progress, IOT_OTAReportType reportType) +int qcloud_otalib_gen_report_msg(char *buf, size_t bufLen, uint32_t id, const char *version, int progress, + IOT_OTAReportType reportType) { IOT_FUNC_ENTRY; int ret; switch (reportType) { - /* 上报开始下载 */ + /* report OTA download begin */ case IOT_OTAR_DOWNLOAD_BEGIN: - ret = HAL_Snprintf(buf, - bufLen, - "{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"downloading\", \"percent\":\"0\", \"result_code\":\"0\", \"result_msg\":\"\"}, \"version\": \"%s\"}}", version); - break; - /* 上报下载进度 */ + ret = HAL_Snprintf(buf, bufLen, + "{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"downloading\", " + "\"percent\":\"0\", \"result_code\":\"0\", \"result_msg\":\"\"}, \"version\": \"%s\"}}", + STRING_PTR_PRINT_SANITY_CHECK(version)); + break; + /* report OTA download progress */ case IOT_OTAR_DOWNLOADING: - ret = HAL_Snprintf(buf, - bufLen, - "{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"downloading\", \"percent\":\"%d\", \"result_code\":\"0\", \"result_msg\":\"\"}, \"version\": \"%s\"}}", - progress, version); - break; + ret = HAL_Snprintf(buf, bufLen, + "{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"downloading\", " + "\"percent\":\"%d\", \"result_code\":\"0\", \"result_msg\":\"\"}, \"version\": \"%s\"}}", + progress, STRING_PTR_PRINT_SANITY_CHECK(version)); + break; case IOT_OTAR_DOWNLOAD_TIMEOUT: case IOT_OTAR_FILE_NOT_EXIST: case IOT_OTAR_MD5_NOT_MATCH: case IOT_OTAR_AUTH_FAIL: case IOT_OTAR_UPGRADE_FAIL: - ret = HAL_Snprintf(buf, - bufLen, - "{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"fail\", \"result_code\":\"%d\", \"result_msg\":\"time_out\"}, \"version\": \"%s\"}}", reportType, version); - break; - /* 上报开始升级 */ + ret = HAL_Snprintf(buf, bufLen, + "{\"type\": \"report_progress\", \"report\": {\"progress\": {\"state\":\"fail\", " + "\"result_code\":\"%d\", \"result_msg\":\"time_out\"}, \"version\": \"%s\"}}", + reportType, STRING_PTR_PRINT_SANITY_CHECK(version)); + break; + /* report OTA upgrade begin */ case IOT_OTAR_UPGRADE_BEGIN: - ret = HAL_Snprintf(buf, - bufLen, - "{\"type\": \"report_progress\", \"report\":{\"progress\":{\"state\":\"burning\", \"result_code\":\"0\", \"result_msg\":\"\"}, \"version\":\"%s\"}}", - version); - break; + ret = HAL_Snprintf(buf, bufLen, + "{\"type\": \"report_progress\", \"report\":{\"progress\":{\"state\":\"burning\", " + "\"result_code\":\"0\", \"result_msg\":\"\"}, \"version\":\"%s\"}}", + STRING_PTR_PRINT_SANITY_CHECK(version)); + break; - /* 上报升级完成 */ + /* report OTA upgrade finish */ case IOT_OTAR_UPGRADE_SUCCESS: - ret = HAL_Snprintf(buf, - bufLen, - "{\"type\": \"report_progress\", \"report\":{\"progress\":{\"state\":\"done\", \"result_code\":\"0\", \"result_msg\":\"\"}, \"version\":\"%s\"}}", - version); - break; - + ret = HAL_Snprintf(buf, bufLen, + "{\"type\": \"report_progress\", \"report\":{\"progress\":{\"state\":\"done\", " + "\"result_code\":\"0\", \"result_msg\":\"\"}, \"version\":\"%s\"}}", + STRING_PTR_PRINT_SANITY_CHECK(version)); + break; + default: - IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); - break; + IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); + break; } - if (ret < 0) { Log_e("HAL_Snprintf failed"); IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); @@ -314,7 +311,7 @@ int qcloud_otalib_gen_report_msg(char *buf, size_t bufLen, uint32_t id, const ch IOT_FUNC_EXIT_RC(IOT_OTA_ERR_STR_TOO_LONG); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } #ifdef __cplusplus diff --git a/src/ota/src/ota_mqtt.c b/sdk_src/services/ota/ota_mqtt.c old mode 100644 new mode 100755 similarity index 53% rename from src/ota/src/ota_mqtt.c rename to sdk_src/services/ota/ota_mqtt.c index 163ac888..c4d26833 --- a/src/ota/src/ota_mqtt.c +++ b/sdk_src/services/ota/ota_mqtt.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -17,45 +17,51 @@ extern "C" { #endif -#include "ota_client.h" +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifdef OTA_MQTT_CHANNEL #include -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" +#include "ota_client.h" /* OSC, OTA signal channel */ -typedef struct { - void *mqtt; //MQTT信令通道 +typedef struct { + void *mqtt; // MQTT cient - const char *product_id; - const char *device_name; + const char *product_id; + const char *device_name; - char topic_upgrade[OTA_MAX_TOPIC_LEN]; //OTA MQTT Topic - OnOTAMessageCallback msg_callback; + char topic_upgrade[OTA_MAX_TOPIC_LEN]; // OTA MQTT Topic + OnOTAMessageCallback msg_callback; void *context; + bool topic_ready; } OTA_MQTT_Struct_t; /* Generate topic name according to @OTATopicType, @productId, @deviceName */ /* and then copy to @buf. */ /* 0, successful; -1, failed */ -static int _otamqtt_gen_topic_name(char *buf, size_t bufLen, const char *OTATopicType, const char *productId, const char *deviceName) +static int _otamqtt_gen_topic_name(char *buf, size_t bufLen, const char *OTATopicType, const char *productId, + const char *deviceName) { IOT_FUNC_ENTRY; int ret; - ret = HAL_Snprintf(buf, bufLen, "$ota/%s/%s/%s", OTATopicType, productId, deviceName); + ret = HAL_Snprintf(buf, bufLen, "$ota/%s/%s/%s", STRING_PTR_PRINT_SANITY_CHECK(OTATopicType), + STRING_PTR_PRINT_SANITY_CHECK(productId), STRING_PTR_PRINT_SANITY_CHECK(deviceName)); - if(ret >= bufLen) IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); + if (ret >= bufLen) + IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); if (ret < 0) { Log_e("HAL_Snprintf failed"); IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /* report progress of OTA */ @@ -63,8 +69,8 @@ static int _otamqtt_publish(OTA_MQTT_Struct_t *handle, const char *topicType, in { IOT_FUNC_ENTRY; - int ret; - char topic_name[OTA_MAX_TOPIC_LEN]; + int ret; + char topic_name[OTA_MAX_TOPIC_LEN]; PublishParams pub_params = DEFAULT_PUB_PARAMS; if (0 == qos) { @@ -72,14 +78,14 @@ static int _otamqtt_publish(OTA_MQTT_Struct_t *handle, const char *topicType, in } else { pub_params.qos = QOS1; } - pub_params.payload = (void *)msg; + pub_params.payload = (void *)msg; pub_params.payload_len = strlen(msg); /* inform OTA to topic: "/ota/device/progress/$(product_id)/$(device_name)" */ ret = _otamqtt_gen_topic_name(topic_name, OTA_MAX_TOPIC_LEN, topicType, handle->product_id, handle->device_name); if (ret < 0) { - Log_e("generate topic name of info failed"); - IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); + Log_e("generate topic name of info failed"); + IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); } ret = IOT_MQTT_Publish(handle->mqtt, topic_name, &pub_params); @@ -91,23 +97,59 @@ static int _otamqtt_publish(OTA_MQTT_Struct_t *handle, const char *topicType, in IOT_FUNC_EXIT_RC(ret); } -/* OTA订阅主题之后收到消息就会执行该回调函数 */ -/* 通过解析JSON字符串获取firmware信息如:版本号、URL、文件大小以及MD5值 */ +/* callback after OTA topic is subscribed */ +/* Parse firmware info (version/URL/file size/MD5) from JSON text */ static void _otamqtt_upgrage_cb(void *pClient, MQTTMessage *message, void *pcontext) { - OTA_MQTT_Struct_t *handle = (OTA_MQTT_Struct_t *) pcontext; + OTA_MQTT_Struct_t *handle = (OTA_MQTT_Struct_t *)pcontext; - Log_d("topic=%.*s", message->topic_len, message->ptopic); - Log_i("len=%u, topic_msg=%.*s", message->payload_len, message->payload_len, (char *)message->payload); + Log_d("topic=%.*s", message->topic_len, STRING_PTR_PRINT_SANITY_CHECK(message->ptopic)); + Log_i("len=%u, topic_msg=%.*s", message->payload_len, message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); if (NULL != handle->msg_callback) { handle->msg_callback(handle->context, message->payload, message->payload_len); } } -void *qcloud_osc_init(const char *productId, const char *deviceName, void *channel, OnOTAMessageCallback callback, void *context) +static void _otamqtt_event_callback(void *pclient, MQTTEventType event_type, void *user_data) { - int ret; + OTA_MQTT_Struct_t *h_osc = (OTA_MQTT_Struct_t *)user_data; + + switch (event_type) { + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_d("OTA topic subscribe success"); + h_osc->topic_ready = true; + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("OTA topic subscribe timeout"); + h_osc->topic_ready = false; + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("OTA topic subscribe NACK"); + h_osc->topic_ready = false; + break; + case MQTT_EVENT_UNSUBSCRIBE: + Log_i("OTA topic has been unsubscribed"); + h_osc->topic_ready = false; + ; + break; + case MQTT_EVENT_CLIENT_DESTROY: + Log_i("mqtt client has been destroyed"); + h_osc->topic_ready = false; + ; + break; + default: + return; + } +} + +void *qcloud_osc_init(const char *productId, const char *deviceName, void *channel, OnOTAMessageCallback callback, + void *context) +{ + int ret; OTA_MQTT_Struct_t *h_osc = NULL; if (NULL == (h_osc = HAL_Malloc(sizeof(OTA_MQTT_Struct_t)))) { @@ -124,10 +166,11 @@ void *qcloud_osc_init(const char *productId, const char *deviceName, void *chann goto do_exit; } - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.on_message_handler = _otamqtt_upgrage_cb; - sub_params.qos = QOS1; - sub_params.user_data = h_osc; + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.on_message_handler = _otamqtt_upgrage_cb; + sub_params.on_sub_event_handler = _otamqtt_event_callback; + sub_params.qos = QOS1; + sub_params.user_data = h_osc; ret = IOT_MQTT_Subscribe(channel, h_osc->topic_upgrade, &sub_params); if (ret < 0) { @@ -135,17 +178,29 @@ void *qcloud_osc_init(const char *productId, const char *deviceName, void *chann goto do_exit; } - h_osc->mqtt = channel; - h_osc->product_id = productId; - h_osc->device_name = deviceName; + int wait_cnt = 10; + while (!h_osc->topic_ready && (wait_cnt > 0)) { + // wait for subscription result + IOT_MQTT_Yield(channel, 200); + wait_cnt--; + } + + if (wait_cnt == 0) { + Log_e("ota mqtt subscribe timeout!"); + goto do_exit; + } + + h_osc->mqtt = channel; + h_osc->product_id = productId; + h_osc->device_name = deviceName; h_osc->msg_callback = callback; - h_osc->context = context; + h_osc->context = context; return h_osc; do_exit: if (NULL != h_osc) { - HAL_Free(h_osc); + HAL_Free(h_osc); } return NULL; @@ -156,10 +211,12 @@ int qcloud_osc_deinit(void *handle) IOT_FUNC_ENTRY; if (NULL != handle) { + OTA_MQTT_Struct_t *h_osc = (OTA_MQTT_Struct_t *)handle; + IOT_MQTT_Unsubscribe(h_osc->mqtt, h_osc->topic_upgrade); HAL_Free(handle); } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /* report progress of OTA */ @@ -180,6 +237,8 @@ int qcloud_osc_report_upgrade_result(void *handle, const char *msg) return _otamqtt_publish(handle, "report", QOS1, msg); } +#endif + #ifdef __cplusplus } #endif diff --git a/sdk_src/services/rrpc/rrpc_client.c b/sdk_src/services/rrpc/rrpc_client.c new file mode 100755 index 00000000..73ee726a --- /dev/null +++ b/sdk_src/services/rrpc/rrpc_client.c @@ -0,0 +1,183 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "mqtt_client.h" +#include "qcloud_iot_export_error.h" +#include "qcloud_iot_export_rrpc.h" +#include "utils_param_check.h" + +#ifdef RRPC_ENABLED + +static char sg_process_id_buffer[MAX_RRPC_PROCESS_ID_LEN + 1] = {0}; // process id buffer + +static int _publish_rrpc_to_cloud(void *client, const char *processId, char *pJsonDoc) +{ + IOT_FUNC_ENTRY; + int rc = QCLOUD_RET_SUCCESS; + char topic[MAX_SIZE_OF_CLOUD_TOPIC] = {0}; + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)client; + + int size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC, "$rrpc/txd/%s/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.device_name), + STRING_PTR_PRINT_SANITY_CHECK(processId)); + if (size < 0 || size > sizeof(topic) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic)); + return QCLOUD_ERR_FAILURE; + } + + PublishParams pubParams = DEFAULT_PUB_PARAMS; + pubParams.qos = QOS0; + pubParams.payload_len = strlen(pJsonDoc); + pubParams.payload = (char *)pJsonDoc; + + rc = IOT_MQTT_Publish(mqtt_client, topic, &pubParams); + + IOT_FUNC_EXIT_RC(rc); +} + +static int _rrpc_get_process_id(char *processIdBuffer, size_t sizeOfBuffer, const char *topic, size_t topic_len) +{ + char *p = NULL; + char ch = '/'; + + p = strrchr(topic, ch); + if (p == NULL) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); + } + + p++; + if ((topic_len - (p - topic)) > sizeOfBuffer) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + + strncpy(processIdBuffer, p, topic_len - (p - topic)); + Log_i("len=%u, process id=%.*s", topic_len - (p - topic), topic_len - (p - topic), processIdBuffer); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +static void _rrpc_message_cb(void *pClient, MQTTMessage *message, void *pContext) +{ + OnRRPCMessageCallback callback = (OnRRPCMessageCallback)pContext; + + Log_d("topic=%.*s", message->topic_len, message->ptopic); + Log_i("len=%u, topic_msg=%.*s", message->payload_len, message->payload_len, + STRING_PTR_PRINT_SANITY_CHECK((char *)message->payload)); + + int rc = _rrpc_get_process_id(sg_process_id_buffer, MAX_RRPC_PROCESS_ID_LEN, message->ptopic, message->topic_len); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("rrpc get process id failed: %d", rc); + return; + } + + if (callback) { + callback(pClient, message->payload, message->payload_len); + } +} + +static void _rrpc_event_callback(void *pClient, MQTTEventType event_type, void *user_data) +{ + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + switch (event_type) { + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_d("rrpc topic subscribe success"); + mqtt_client->rrpc_state = true; + break; + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("rrpc topic subscribe timeout"); + mqtt_client->rrpc_state = false; + break; + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("rrpc topic subscribe NACK"); + mqtt_client->rrpc_state = false; + break; + case MQTT_EVENT_UNSUBSCRIBE: + Log_i("rrpc topic has been unsubscribed"); + mqtt_client->rrpc_state = false; + break; + case MQTT_EVENT_CLIENT_DESTROY: + Log_i("mqtt client has been destroyed"); + mqtt_client->rrpc_state = false; + break; + default: + return; + } +} + +int IOT_RRPC_Init(void *pClient, OnRRPCMessageCallback callback) +{ + int rc = QCLOUD_RET_SUCCESS; + char rrpc_topic[MAX_SIZE_OF_CLOUD_TOPIC + 1] = {0}; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.on_message_handler = _rrpc_message_cb; + sub_params.on_sub_event_handler = _rrpc_event_callback; + sub_params.qos = QOS0; + sub_params.user_data = callback; + + HAL_Snprintf(rrpc_topic, MAX_SIZE_OF_CLOUD_TOPIC, "$rrpc/rxd/%s/%s/+", + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.device_name)); + + if (!mqtt_client->rrpc_state) { + for (int cntSub = 0; cntSub < 3; cntSub++) { + rc = IOT_MQTT_Subscribe(mqtt_client, rrpc_topic, &sub_params); + if (rc < 0) { + Log_e("rrpc topic subscribe failed: %d, cnt: %d", rc, cntSub); + continue; + } + + /* wait for sub ack */ + rc = qcloud_iot_mqtt_yield_mt(mqtt_client, 500); + if ((rc != QCLOUD_RET_SUCCESS) || mqtt_client->rrpc_state) { + break; + } + } + } + + if (!mqtt_client->rrpc_state) { + Log_e("Subscribe rrpc topic failed!"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +int IOT_RRPC_Reply(void *pClient, char *pJsonDoc, size_t sizeOfBuffer, sRRPCReplyPara *replyPara) +{ + int rc = QCLOUD_RET_SUCCESS; + rc = _publish_rrpc_to_cloud(pClient, sg_process_id_buffer, pJsonDoc); + if (rc < 0) { + Log_e("publish rrpc to cloud fail, %d", rc); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_RRPC_REPLY_ERR); + } + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); +} + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/services/shadow/shadow_client.c b/sdk_src/services/shadow/shadow_client.c new file mode 100755 index 00000000..bf3defb9 --- /dev/null +++ b/sdk_src/services/shadow/shadow_client.c @@ -0,0 +1,898 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "shadow_client.h" + +#include +#include +#include + +#include "shadow_client_common.h" +#include "shadow_client_json.h" +#include "utils_param_check.h" + +static void _init_request_params(RequestParams *pParams, Method method, OnRequestCallback callback, void *userContext, + uint8_t timeout_sec) +{ + pParams->method = method; + pParams->user_context = userContext; + pParams->timeout_sec = timeout_sec; + pParams->request_callback = callback; +} + +/** + * @brief check return value of snprintf + * + * @param returnCode return value of snprintf + * @param maxSizeOfWrite max size of write buffer + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +static inline int _check_snprintf_return(int32_t returnCode, size_t maxSizeOfWrite) +{ + if (returnCode >= maxSizeOfWrite) { + return QCLOUD_ERR_JSON_BUFFER_TRUNCATED; + } else if (returnCode < 0) { + return QCLOUD_ERR_JSON; + } + + return QCLOUD_RET_SUCCESS; +} + +static void _shadow_event_handler(void *pclient, void *context, MQTTEventMsg *msg) +{ + uintptr_t packet_id = (uintptr_t)msg->msg; + Qcloud_IoT_Shadow *shadow_client = (Qcloud_IoT_Shadow *)context; + MQTTMessage * topic_info = (MQTTMessage *)msg->msg; + + switch (msg->event_type) { + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_d("shadow subscribe success, packet-id=%u", (unsigned int)packet_id); + if (shadow_client->inner_data.sync_status > 0) + shadow_client->inner_data.sync_status = 0; + break; + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_d("shadow subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); + if (shadow_client->inner_data.sync_status > 0) + shadow_client->inner_data.sync_status = -1; + break; + case MQTT_EVENT_SUBCRIBE_NACK: + Log_d("shadow subscribe nack, packet-id=%u", (unsigned int)packet_id); + if (shadow_client->inner_data.sync_status > 0) + shadow_client->inner_data.sync_status = -1; + break; + case MQTT_EVENT_PUBLISH_RECVEIVED: + Log_d("shadow topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", + topic_info->topic_len, STRING_PTR_PRINT_SANITY_CHECK(topic_info->ptopic), topic_info->payload_len, + STRING_PTR_PRINT_SANITY_CHECK(topic_info->payload)); + break; + default: + /* Log_i("Should NOT arrive here."); */ + break; + } + if (shadow_client->event_handle.h_fp != NULL) { + shadow_client->event_handle.h_fp(shadow_client, shadow_client->event_handle.context, msg); + } +} + +static void _copy_shadow_init_params_to_mqtt(MQTTInitParams *pMqttInitParams, ShadowInitParams *shadowInitParams) +{ + pMqttInitParams->device_name = shadowInitParams->device_name; + pMqttInitParams->product_id = shadowInitParams->product_id; + +#ifdef AUTH_MODE_CERT + memcpy(pMqttInitParams->cert_file, shadowInitParams->cert_file, FILE_PATH_MAX_LEN); + memcpy(pMqttInitParams->key_file, shadowInitParams->key_file, FILE_PATH_MAX_LEN); +#else + pMqttInitParams->device_secret = shadowInitParams->device_secret; +#endif + + pMqttInitParams->command_timeout = shadowInitParams->command_timeout; + pMqttInitParams->keep_alive_interval_ms = shadowInitParams->keep_alive_interval_ms; + pMqttInitParams->clean_session = shadowInitParams->clean_session; + pMqttInitParams->auto_connect_enable = shadowInitParams->auto_connect_enable; +} + +static void _update_ack_cb(void *pClient, Method method, RequestAck requestAck, const char *pReceivedJsonDocument, + void *pUserdata) +{ + Log_d("requestAck=%d", requestAck); + + if (NULL != pReceivedJsonDocument) { + Log_d("Received Json Document=%s", pReceivedJsonDocument); + } else { + Log_d("Received Json Document is NULL"); + } + + *((RequestAck *)pUserdata) = requestAck; +} + +void *IOT_Shadow_Construct(ShadowInitParams *pParams) +{ + POINTER_SANITY_CHECK(pParams, NULL); + + Qcloud_IoT_Shadow *shadow_client = NULL; + if ((shadow_client = (Qcloud_IoT_Shadow *)HAL_Malloc(sizeof(Qcloud_IoT_Shadow))) == NULL) { + Log_e("memory not enough to malloc ShadowClient"); + return NULL; + } + + MQTTInitParams mqtt_init_params; + _copy_shadow_init_params_to_mqtt(&mqtt_init_params, pParams); + + mqtt_init_params.event_handle.h_fp = _shadow_event_handler; + mqtt_init_params.event_handle.context = shadow_client; + + void *mqtt_client = NULL; + if ((mqtt_client = IOT_MQTT_Construct(&mqtt_init_params)) == NULL) { + HAL_Free(shadow_client); + goto End; + } + + memset(shadow_client, 0, sizeof(Qcloud_IoT_Shadow)); + shadow_client->mqtt = mqtt_client; + shadow_client->shadow_type = pParams->shadow_type; + shadow_client->event_handle = pParams->event_handle; + shadow_client->inner_data.result_topic = NULL; + shadow_client->inner_data.token_num = 0; + + int rc; + + rc = qcloud_iot_shadow_init(shadow_client); + if (rc != QCLOUD_RET_SUCCESS) { + IOT_Shadow_Destroy(shadow_client); + goto End; + } + + rc = subscribe_operation_result_to_cloud(shadow_client); + if (rc < 0) { + Log_e("Subcribe $shadow/operation/results fail!"); + } else { + shadow_client->inner_data.sync_status = rc; + while (rc == shadow_client->inner_data.sync_status) { + IOT_Shadow_Yield(shadow_client, 100); + } + if (0 == shadow_client->inner_data.sync_status) { + Log_i("Sync device data successfully"); + } else { + Log_e("Sync device data failed"); + } + } + + return shadow_client; + +End: + return NULL; +} + +void *IOT_Shadow_Get_Mqtt_Client(void *handle) +{ + POINTER_SANITY_CHECK(handle, NULL); + + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + return shadow->mqtt; +} + +int IOT_Shadow_Publish(void *handle, char *topicName, PublishParams *pParams) +{ + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + return qcloud_iot_mqtt_publish(shadow->mqtt, topicName, pParams); +} + +int IOT_Shadow_Subscribe(void *handle, char *topicFilter, SubscribeParams *pParams) +{ + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + return qcloud_iot_mqtt_subscribe(shadow->mqtt, topicFilter, pParams); +} + +int IOT_Shadow_Unsubscribe(void *handle, char *topicFilter) +{ + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + return qcloud_iot_mqtt_unsubscribe(shadow->mqtt, topicFilter); +} + +bool IOT_Shadow_IsConnected(void *handle) +{ + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; + + IOT_FUNC_EXIT_RC(IOT_MQTT_IsConnected(pshadow->mqtt)) +} + +int IOT_Shadow_Destroy(void *handle) +{ + IOT_FUNC_ENTRY; + + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *shadow_client = (Qcloud_IoT_Shadow *)handle; + qcloud_iot_shadow_reset(handle); + + IOT_MQTT_Destroy(&shadow_client->mqtt); + + if (NULL != shadow_client->mutex) { + HAL_MutexDestroy(shadow_client->mutex); + } + + if (NULL != shadow_client->inner_data.result_topic) { + HAL_Free(shadow_client->inner_data.result_topic); + shadow_client->inner_data.result_topic = NULL; + } + + HAL_Free(handle); + + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS) +} + +int IOT_Shadow_Yield(void *handle, uint32_t timeout_ms) +{ + IOT_FUNC_ENTRY; + int rc; + + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; + POINTER_SANITY_CHECK(pshadow, QCLOUD_ERR_INVAL); + + handle_expired_request(pshadow); + + rc = IOT_MQTT_Yield(pshadow->mqtt, timeout_ms); + + IOT_FUNC_EXIT_RC(rc); +} + +int IOT_Shadow_Register_Property(void *handle, DeviceProperty *pProperty, OnPropRegCallback callback) +{ + IOT_FUNC_ENTRY; + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; + int rc; + + if (IOT_MQTT_IsConnected(pshadow->mqtt) == false) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); + } + + if (shadow_common_check_property_existence(pshadow, pProperty)) + IOT_FUNC_EXIT_RC(QCLOUD_ERR_SHADOW_PROPERTY_EXIST); + + rc = shadow_common_register_property_on_delta(pshadow, pProperty, callback); + + IOT_FUNC_EXIT_RC(rc); +} + +int IOT_Shadow_UnRegister_Property(void *handle, DeviceProperty *pProperty) +{ + IOT_FUNC_ENTRY; + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; + + if (IOT_MQTT_IsConnected(pshadow->mqtt) == false) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); + } + + if (!shadow_common_check_property_existence(pshadow, pProperty)) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_SHADOW_NOT_PROPERTY_EXIST); + } + int rc = shadow_common_remove_property(pshadow, pProperty); + IOT_FUNC_EXIT_RC(rc); +} + +int IOT_Shadow_Update(void *handle, char *pJsonDoc, size_t sizeOfBuffer, OnRequestCallback callback, void *userContext, + uint32_t timeout_ms) +{ + IOT_FUNC_ENTRY; + int rc; + + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pJsonDoc, QCLOUD_ERR_INVAL); + NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + if (IOT_MQTT_IsConnected(shadow->mqtt) == false) { + Log_e("shadow is disconnected"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); + } + + // subscribe topic $shadow/operation/result if not subscribed yet + if (shadow->inner_data.sync_status < 0) { + subscribe_operation_result_to_cloud(shadow); + } + + Log_d("UPDATE Request Document: %s", pJsonDoc); + + RequestParams request_params = DEFAULT_REQUEST_PARAMS; + _init_request_params(&request_params, UPDATE, callback, userContext, timeout_ms / 1000); + + rc = do_shadow_request(shadow, &request_params, pJsonDoc, sizeOfBuffer); + IOT_FUNC_EXIT_RC(rc); +} + +int IOT_Shadow_Update_Sync(void *handle, char *pJsonDoc, size_t sizeOfBuffer, uint32_t timeout_ms) +{ + IOT_FUNC_ENTRY; + int rc = QCLOUD_RET_SUCCESS; + + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pJsonDoc, QCLOUD_ERR_INVAL); + NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + if (IOT_MQTT_IsConnected(shadow->mqtt) == false) { + Log_e("shadow is disconnected"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); + } + + RequestAck ack_update = ACK_NONE; + rc = IOT_Shadow_Update(handle, pJsonDoc, sizeOfBuffer, _update_ack_cb, &ack_update, timeout_ms); + if (rc != QCLOUD_RET_SUCCESS) + IOT_FUNC_EXIT_RC(rc); + + while (ACK_NONE == ack_update) { + IOT_Shadow_Yield(handle, 200); + } + + if (ACK_ACCEPTED == ack_update) { + rc = QCLOUD_RET_SUCCESS; + } else if (ACK_TIMEOUT == ack_update) { + rc = QCLOUD_ERR_SHADOW_UPDATE_TIMEOUT; + } else if (ACK_REJECTED == ack_update) { + rc = QCLOUD_ERR_SHADOW_UPDATE_REJECTED; + } + + IOT_FUNC_EXIT_RC(rc); +} + +int IOT_Shadow_Get(void *handle, OnRequestCallback callback, void *userContext, uint32_t timeout_ms) +{ + IOT_FUNC_ENTRY; + int rc; + + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(callback, QCLOUD_ERR_INVAL); + NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + if (IOT_MQTT_IsConnected(shadow->mqtt) == false) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); + } + + // subscribe topic $shadow/operation/result if not subscribed yet + if (shadow->inner_data.sync_status < 0) { + subscribe_operation_result_to_cloud(shadow); + } + + char getRequestJsonDoc[MAX_SIZE_OF_JSON_WITH_CLIENT_TOKEN]; + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)shadow->mqtt; + build_empty_json(&(shadow->inner_data.token_num), getRequestJsonDoc, mqtt_client->device_info.product_id); + Log_d("GET Request Document: %s", getRequestJsonDoc); + + RequestParams request_params = DEFAULT_REQUEST_PARAMS; + _init_request_params(&request_params, GET, callback, userContext, timeout_ms / 1000); + + rc = do_shadow_request(shadow, &request_params, getRequestJsonDoc, MAX_SIZE_OF_JSON_WITH_CLIENT_TOKEN); + IOT_FUNC_EXIT_RC(rc); +} + +int IOT_Shadow_Get_Sync(void *handle, uint32_t timeout_ms) +{ + IOT_FUNC_ENTRY; + int rc = QCLOUD_RET_SUCCESS; + + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + if (IOT_MQTT_IsConnected(shadow->mqtt) == false) { + IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); + } + + RequestAck ack_update = ACK_NONE; + rc = IOT_Shadow_Get(handle, _update_ack_cb, &ack_update, timeout_ms); + if (rc != QCLOUD_RET_SUCCESS) + IOT_FUNC_EXIT_RC(rc); + + while (ACK_NONE == ack_update) { + IOT_Shadow_Yield(handle, 200); + } + + if (ACK_ACCEPTED == ack_update) { + rc = QCLOUD_RET_SUCCESS; + } else if (ACK_TIMEOUT == ack_update) { + rc = QCLOUD_ERR_SHADOW_GET_TIMEOUT; + } else if (ACK_REJECTED == ack_update) { + rc = QCLOUD_ERR_SHADOW_GET_REJECTED; + } + + IOT_FUNC_EXIT_RC(rc); +} + +/** + * @brief Init a shadow JSON string, add the initial field of "{\"state\":{" + * + * @param jsonBuffer JSON string buffer + * @param sizeOfBuffer buffer size + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +static int IOT_Shadow_JSON_Init(Qcloud_IoT_Shadow *pShadow, char *jsonBuffer, size_t sizeOfBuffer, bool overwrite) +{ + if (jsonBuffer == NULL) { + return QCLOUD_ERR_INVAL; + } + + int32_t rc_of_snprintf = 0; + if (overwrite) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer, sizeOfBuffer, "{\"overwriteUpdate\":true, \"state\":{"); + } else { + rc_of_snprintf = HAL_Snprintf(jsonBuffer, sizeOfBuffer, "{\"state\":{"); + } + + return _check_snprintf_return(rc_of_snprintf, sizeOfBuffer); +} + +/** + * @brief Finish a shadow JSON string, append the tail fields of clientToken and version + * + * @param jsonBuffer JSON string buffer + * @param sizeOfBuffer buffer size + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +static int IOT_Shadow_JSON_Finalize(Qcloud_IoT_Shadow *pShadow, char *jsonBuffer, size_t sizeOfBuffer) +{ + int rc; + size_t remain_size = 0; + int32_t rc_of_snprintf = 0; + + if (jsonBuffer == NULL) { + return QCLOUD_ERR_INVAL; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "}, \"%s\":\"", CLIENT_TOKEN_FIELD); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pShadow->mqtt; + rc_of_snprintf = generate_client_token(jsonBuffer + strlen(jsonBuffer), remain_size, + &(pShadow->inner_data.token_num), mqtt_client->device_info.product_id); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"}"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + return rc; +} + +int IOT_Shadow_JSON_ConstructReport(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...) +{ + Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; + POINTER_SANITY_CHECK(pshadow, QCLOUD_ERR_INVAL); + + int rc = IOT_Shadow_JSON_Init(pshadow, jsonBuffer, sizeOfBuffer, false); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json init failed: %d", rc); + return rc; + } + + size_t remain_size = 0; + int32_t rc_of_snprintf = 0; + int8_t i; + + if (jsonBuffer == NULL) { + return QCLOUD_ERR_INVAL; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"reported\":{"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + va_list pArgs; + va_start(pArgs, count); + + for (i = 0; i < count; i++) { + DeviceProperty *pJsonNode; + pJsonNode = va_arg(pArgs, DeviceProperty *); + if (pJsonNode != NULL && pJsonNode->key != NULL) { + rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); + + if (rc != QCLOUD_RET_SUCCESS) { + va_end(pArgs); + return rc; + } + } else { + va_end(pArgs); + return QCLOUD_ERR_INVAL; + } + } + + va_end(pArgs); + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json add report failed: %d", rc); + return rc; + } + + rc = IOT_Shadow_JSON_Finalize(pshadow, jsonBuffer, sizeOfBuffer); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json finalize failed: %d", rc); + } + + return rc; +} + +int IOT_Shadow_JSON_ConstructReportArray(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, + DeviceProperty *pDeviceProperties[]) +{ + Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; + POINTER_SANITY_CHECK(pshadow, QCLOUD_ERR_INVAL); + POINTER_SANITY_CHECK(pDeviceProperties, QCLOUD_ERR_INVAL); + + int rc = IOT_Shadow_JSON_Init(pshadow, jsonBuffer, sizeOfBuffer, false); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json init failed: %d", rc); + return rc; + } + + size_t remain_size = 0; + int32_t rc_of_snprintf = 0; + int8_t i; + + if (jsonBuffer == NULL) { + return QCLOUD_ERR_INVAL; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"reported\":{"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + for (i = 0; i < count; i++) { + DeviceProperty *pJsonNode = pDeviceProperties[i]; + if (pJsonNode != NULL && pJsonNode->key != NULL) { + rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); + + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + } else { + return QCLOUD_ERR_INVAL; + } + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json add report failed: %d", rc); + return rc; + } + + rc = IOT_Shadow_JSON_Finalize(pshadow, jsonBuffer, sizeOfBuffer); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json finalize failed: %d", rc); + } + + return rc; +} + +int IOT_Shadow_JSON_Construct_OverwriteReport(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...) +{ + Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; + POINTER_SANITY_CHECK(pshadow, QCLOUD_ERR_INVAL); + + int rc = IOT_Shadow_JSON_Init(pshadow, jsonBuffer, sizeOfBuffer, true); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json init failed: %d", rc); + return rc; + } + + size_t remain_size = 0; + int32_t rc_of_snprintf = 0; + int8_t i; + + if (jsonBuffer == NULL) { + return QCLOUD_ERR_INVAL; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"reported\":{"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + va_list pArgs; + va_start(pArgs, count); + + for (i = 0; i < count; i++) { + DeviceProperty *pJsonNode; + pJsonNode = va_arg(pArgs, DeviceProperty *); + if (pJsonNode != NULL && pJsonNode->key != NULL) { + rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); + + if (rc != QCLOUD_RET_SUCCESS) { + va_end(pArgs); + return rc; + } + } else { + va_end(pArgs); + return QCLOUD_ERR_INVAL; + } + } + + va_end(pArgs); + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json add report failed: %d", rc); + return rc; + } + + rc = IOT_Shadow_JSON_Finalize(pshadow, jsonBuffer, sizeOfBuffer); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json finalize failed: %d", rc); + } + + return rc; +} + +int IOT_Shadow_JSON_ConstructReportAndDesireAllNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, + ...) +{ + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; + + int rc = IOT_Shadow_JSON_Init(pshadow, jsonBuffer, sizeOfBuffer, false); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json init failed: %d", rc); + return rc; + } + + size_t remain_size = 0; + int32_t rc_of_snprintf = 0; + int8_t i; + + if (jsonBuffer == NULL) { + return QCLOUD_ERR_INVAL; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"reported\":{"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + va_list pArgs; + va_start(pArgs, count); + + for (i = 0; i < count; i++) { + DeviceProperty *pJsonNode; + pJsonNode = va_arg(pArgs, DeviceProperty *); + if (pJsonNode != NULL && pJsonNode->key != NULL) { + rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); + + if (rc != QCLOUD_RET_SUCCESS) { + va_end(pArgs); + return rc; + } + } else { + va_end(pArgs); + return QCLOUD_ERR_INVAL; + } + } + + va_end(pArgs); + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json add report failed: %d", rc); + return rc; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"desired\": null "); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + rc = IOT_Shadow_JSON_Finalize(pshadow, jsonBuffer, sizeOfBuffer); + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json finalize failed: %d", rc); + } + + return rc; +} + +int IOT_Shadow_JSON_ConstructDesireAllNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer) +{ + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + int rc = IOT_Shadow_JSON_Init(shadow, jsonBuffer, sizeOfBuffer, false); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json init failed: %d", rc); + return rc; + } + + size_t remain_size = 0; + int32_t rc_of_snprintf = 0; + + if (jsonBuffer == NULL) { + return QCLOUD_ERR_INVAL; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"desired\": null "); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + rc = IOT_Shadow_JSON_Finalize(shadow, jsonBuffer, sizeOfBuffer); + return rc; +} + +int IOT_Shadow_JSON_ConstructDesirePropNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...) +{ + POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); + Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; + + int rc = IOT_Shadow_JSON_Init(shadow, jsonBuffer, sizeOfBuffer, false); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json init failed: %d", rc); + return rc; + } + + size_t remain_size = 0; + int32_t rc_of_snprintf = 0; + int8_t i; + + if (jsonBuffer == NULL) { + return QCLOUD_ERR_INVAL; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"desired\":{"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + va_list pArgs; + va_start(pArgs, count); + + for (i = 0; i < count; i++) { + DeviceProperty *pJsonNode; + pJsonNode = va_arg(pArgs, DeviceProperty *); + if (pJsonNode != NULL && pJsonNode->key != NULL) { + rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); + if (rc != QCLOUD_RET_SUCCESS) { + va_end(pArgs); + return rc; + } + } else { + va_end(pArgs); + return QCLOUD_ERR_INVAL; + } + } + + va_end(pArgs); + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + // strlen(jsonBuffer) - 1 to remove last comma + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + if (rc != QCLOUD_RET_SUCCESS) { + Log_e("shadow json add desired failed: %d", rc); + return rc; + } + + rc = IOT_Shadow_JSON_Finalize(shadow, jsonBuffer, sizeOfBuffer); + return rc; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/shadow/src/shadow_client_common.c b/sdk_src/services/shadow/shadow_client_common.c old mode 100644 new mode 100755 similarity index 86% rename from src/shadow/src/shadow_client_common.c rename to sdk_src/services/shadow/shadow_client_common.c index 5fc3d27f..3acab0f6 --- a/src/shadow/src/shadow_client_common.c +++ b/sdk_src/services/shadow/shadow_client_common.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -18,18 +18,16 @@ extern "C" { #endif #include "shadow_client_common.h" + #include "qcloud_iot_import.h" -/** - * @brief 将注册属性的回调函数保存到列表之中 - */ -static int _add_property_handle_to_list(Qcloud_IoT_Shadow *pShadow, DeviceProperty *pProperty, OnPropRegCallback callback) +static int _add_property_handle_to_list(Qcloud_IoT_Shadow *pShadow, DeviceProperty *pProperty, + OnPropRegCallback callback) { IOT_FUNC_ENTRY; PropertyHandler *property_handle = (PropertyHandler *)HAL_Malloc(sizeof(PropertyHandler)); - if (NULL == property_handle) - { + if (NULL == property_handle) { Log_e("run memory malloc is error!"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } @@ -40,11 +38,12 @@ static int _add_property_handle_to_list(Qcloud_IoT_Shadow *pShadow, DeviceProper ListNode *node = list_node_new(property_handle); if (NULL == node) { Log_e("run list_node_new is error!"); + HAL_Free(property_handle); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } list_rpush(pShadow->inner_data.property_handle_list, node); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } int shadow_common_check_property_existence(Qcloud_IoT_Shadow *pshadow, DeviceProperty *pProperty) @@ -60,7 +59,7 @@ int shadow_common_check_property_existence(Qcloud_IoT_Shadow *pshadow, DevicePro int shadow_common_remove_property(Qcloud_IoT_Shadow *pshadow, DeviceProperty *pProperty) { - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; ListNode *node; HAL_MutexLock(pshadow->mutex); @@ -72,11 +71,12 @@ int shadow_common_remove_property(Qcloud_IoT_Shadow *pshadow, DeviceProperty *pP list_remove(pshadow->inner_data.property_handle_list, node); } HAL_MutexUnlock(pshadow->mutex); - + return rc; } -int shadow_common_register_property_on_delta(Qcloud_IoT_Shadow *pShadow, DeviceProperty *pProperty, OnPropRegCallback callback) +int shadow_common_register_property_on_delta(Qcloud_IoT_Shadow *pShadow, DeviceProperty *pProperty, + OnPropRegCallback callback) { IOT_FUNC_ENTRY; diff --git a/sdk_src/services/shadow/shadow_client_json.c b/sdk_src/services/shadow/shadow_client_json.c new file mode 100755 index 00000000..394a2058 --- /dev/null +++ b/sdk_src/services/shadow/shadow_client_json.c @@ -0,0 +1,326 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "shadow_client_json.h" + +#include +#include +#include +#include +#include + +#include "lite-utils.h" +#include "qcloud_iot_device.h" +#include "shadow_client.h" + +static int _direct_update_value(char *value, DeviceProperty *pProperty) +{ + int rc = QCLOUD_RET_SUCCESS; + + if (pProperty->type == JBOOL) { + rc = LITE_get_boolean(pProperty->data, value); + } else if (pProperty->type == JINT32) { + rc = LITE_get_int32(pProperty->data, value); + } else if (pProperty->type == JINT16) { + rc = LITE_get_int16(pProperty->data, value); + } else if (pProperty->type == JINT8) { + rc = LITE_get_int8(pProperty->data, value); + } else if (pProperty->type == JUINT32) { + rc = LITE_get_uint32(pProperty->data, value); + } else if (pProperty->type == JUINT16) { + rc = LITE_get_uint16(pProperty->data, value); + } else if (pProperty->type == JUINT8) { + rc = LITE_get_uint8(pProperty->data, value); + } else if (pProperty->type == JFLOAT) { + rc = LITE_get_float(pProperty->data, value); + } else if (pProperty->type == JDOUBLE) { + rc = LITE_get_double(pProperty->data, value); + } else if (pProperty->type == JSTRING) { + // Log_d("string type wait to be deal,%s",value); + } else if (pProperty->type == JOBJECT) { + // Log_d("Json type wait to be deal,%s",value); + } else { + Log_e("pProperty type unknow,%d", pProperty->type); + } + + return rc; +} + +/** + * @brief check return value of snprintf + * + * @param returnCode return value of snprintf + * @param maxSizeOfWrite max size of write buffer + * @return QCLOUD_RET_SUCCESS for success, or err code for failure + */ +static inline int _check_snprintf_return(int32_t returnCode, size_t maxSizeOfWrite) +{ + if (returnCode >= maxSizeOfWrite) { + return QCLOUD_ERR_JSON_BUFFER_TRUNCATED; + } else if (returnCode < 0) { + return QCLOUD_ERR_JSON; + } + + return QCLOUD_RET_SUCCESS; +} + +int put_json_node(char *jsonBuffer, size_t sizeOfBuffer, const char *pKey, void *pData, JsonDataType type) +{ + int rc; + int32_t rc_of_snprintf = 0; + size_t remain_size = 0; + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"%s\":", STRING_PTR_PRINT_SANITY_CHECK(pKey)); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + if (pData == NULL) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "null,"); + } else { + if (type == JINT32) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIi32 ",", *(int32_t *)(pData)); + } else if (type == JINT16) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIi16 ",", *(int16_t *)(pData)); + } else if (type == JINT8) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIi8 ",", *(int8_t *)(pData)); + } else if (type == JUINT32) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIu32 ",", *(uint32_t *)(pData)); + } else if (type == JUINT16) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIu16 ",", *(uint16_t *)(pData)); + } else if (type == JUINT8) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIu8 ",", *(uint8_t *)(pData)); + } else if (type == JDOUBLE) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%f,", *(double *)(pData)); + } else if (type == JFLOAT) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%f,", *(float *)(pData)); + } else if (type == JBOOL) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%s,", *(bool *)(pData) ? "true" : "false"); + } else if (type == JSTRING) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"%s\",", (char *)(pData)); + } else if (type == JOBJECT) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%s,", (char *)(pData)); + } + } + + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + return rc; +} + +int event_put_json_node(char *jsonBuffer, size_t sizeOfBuffer, const char *pKey, void *pData, JsonDataType type) +{ + int rc; + int32_t rc_of_snprintf = 0; + size_t remain_size = 0; + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"%s\":", STRING_PTR_PRINT_SANITY_CHECK(pKey)); + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + if (rc != QCLOUD_RET_SUCCESS) { + return rc; + } + + if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { + return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; + } + + if (pData == NULL) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "null,"); + } else { + if (type == JINT32) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIi32 ",", *(int32_t *)(pData)); + } else if (type == JINT16) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIi16 ",", *(int16_t *)(pData)); + } else if (type == JINT8) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIi8 ",", *(int8_t *)(pData)); + } else if (type == JUINT32) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIu32 ",", *(uint32_t *)(pData)); + } else if (type == JUINT16) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIu16 ",", *(uint16_t *)(pData)); + } else if (type == JUINT8) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" PRIu8 ",", *(uint8_t *)(pData)); + } else if (type == JDOUBLE) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%f,", *(double *)(pData)); + } else if (type == JFLOAT) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%f,", *(float *)(pData)); + } else if (type == JBOOL) { + rc_of_snprintf = + HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%u,", *(bool *)(pData) ? 1 : 0); + } else if (type == JSTRING) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"%s\",", (char *)(pData)); + } else if (type == JOBJECT) { + rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%s,", (char *)(pData)); + } + } + + rc = _check_snprintf_return(rc_of_snprintf, remain_size); + + return rc; +} + +int generate_client_token(char *pStrBuffer, size_t sizeOfBuffer, uint32_t *tokenNumber, char *product_id) +{ + return HAL_Snprintf(pStrBuffer, sizeOfBuffer, "%s-%u", STRING_PTR_PRINT_SANITY_CHECK(product_id), (*tokenNumber)++); +} + +void build_empty_json(uint32_t *tokenNumber, char *pJsonBuffer, char *product_id) +{ + HAL_Snprintf(pJsonBuffer, MAX_SIZE_OF_JSON_WITH_CLIENT_TOKEN, "{\"clientToken\":\"%s-%u\"}", + STRING_PTR_PRINT_SANITY_CHECK(product_id), (*tokenNumber)++); +} + +bool parse_client_token(char *pJsonDoc, char **pClientToken) +{ + *pClientToken = LITE_json_value_of(CLIENT_TOKEN_FIELD, pJsonDoc); + return *pClientToken == NULL ? false : true; +} + +bool parse_version_num(char *pJsonDoc, uint32_t *pVersionNumber) +{ + bool ret = false; + + char *version_num = LITE_json_value_of(PAYLOAD_VERSION, pJsonDoc); + if (version_num == NULL) + return false; + + if (sscanf(version_num, "%" SCNu32, pVersionNumber) != 1) { + Log_e("parse shadow version failed, errCode: %d", QCLOUD_ERR_JSON_PARSE); + } else { + ret = true; + } + + HAL_Free(version_num); + + return ret; +} + +bool parse_shadow_state(char *pJsonDoc, char **pState) +{ + *pState = LITE_json_value_of(PAYLOAD_VERSION, pJsonDoc); + return *pState == NULL ? false : true; +} + +bool parse_code_return(char *pJsonDoc, int32_t *pCode) +{ + bool ret = false; + + char *code = LITE_json_value_of(REPLY_CODE, pJsonDoc); + if (code == NULL) + return false; + + if (sscanf(code, "%" SCNi32, pCode) != 1) { + Log_e("parse code failed, errCode: %d", QCLOUD_ERR_JSON_PARSE); + } else { + ret = true; + } + + HAL_Free(code); + + return ret; +} + +bool parse_status_return(char *pJsonDoc, char **pStatus) +{ + *pStatus = LITE_json_value_of(REPLY_STATUS, pJsonDoc); + return *pStatus == NULL ? false : true; +} + +bool parse_shadow_operation_type(char *pJsonDoc, char **pType) +{ + *pType = LITE_json_value_of(TYPE_FIELD, pJsonDoc); + return *pType == NULL ? false : true; +} + +bool parse_shadow_operation_result_code(char *pJsonDoc, int16_t *pResultCode) +{ + bool ret = false; + + char *result_code = LITE_json_value_of(RESULT_FIELD, pJsonDoc); + if (result_code == NULL) + return false; + + if (sscanf(result_code, "%" SCNi16, pResultCode) != 1) { + Log_e("parse shadow result_code failed, errCode: %d", QCLOUD_ERR_JSON_PARSE); + } else { + ret = true; + } + + HAL_Free(result_code); + + return ret; +} + +bool parse_shadow_operation_delta(char *pJsonDoc, char **pDelta) +{ + *pDelta = LITE_json_value_of(PAYLOAD_STATE, pJsonDoc); + return *pDelta == NULL ? false : true; +} + +bool parse_shadow_operation_get(char *pJsonDoc, char **pDelta) +{ + *pDelta = LITE_json_value_of(PAYLOAD_STATE_DELTA, pJsonDoc); + return *pDelta == NULL ? false : true; +} + +bool update_value_if_key_match(char *pJsonDoc, DeviceProperty *pProperty) +{ + bool ret = false; + + char *property_data = LITE_json_value_of(pProperty->key, pJsonDoc); + if ((property_data == NULL) || !(strncmp(property_data, "null", 4)) || !(strncmp(property_data, "NULL", 4))) { + } else { + _direct_update_value(property_data, pProperty); + ret = true; + HAL_Free(property_data); + } + + return ret; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/shadow/src/shadow_client_manager.c b/sdk_src/services/shadow/shadow_client_manager.c old mode 100644 new mode 100755 similarity index 53% rename from src/shadow/src/shadow_client_manager.c rename to sdk_src/services/shadow/shadow_client_manager.c index 51bf425f..4d3981ae --- a/src/shadow/src/shadow_client_manager.c +++ b/sdk_src/services/shadow/shadow_client_manager.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -17,54 +17,36 @@ extern "C" { #endif -#include -#include #include #include +#include +#include -#include "shadow_client.h" - -#include "qcloud_iot_sdk_impl_internal.h" #include "qcloud_iot_import.h" - +#include "shadow_client.h" #include "shadow_client_json.h" - #include "utils_list.h" - -#define MAX_TOPICS_AT_ANY_GIVEN_TIME 2 * MAX_DEVICE_HANDLED_AT_ANY_GIVEN_TIME -#define SUBSCRIBE_WAITING_TIME 2 - -#define min(a,b) (a) < (b) ? (a) : (b) +#include "utils_param_check.h" /** - * @brief 代表一个文档请求 + * @brief type for document request */ typedef struct { - char client_token[MAX_SIZE_OF_CLIENT_TOKEN]; // 标识该请求的clientToken字段 - Method method; // 文档操作方式 + char client_token[MAX_SIZE_OF_CLIENT_TOKEN]; // clientToken + Method method; // method type - void *user_context; // 用户数据 - Timer timer; // 请求超时定时器 + void *user_context; // user context + Timer timer; // timer for timeout - OnRequestCallback callback; // 文档操作请求返回处理函数 + OnRequestCallback callback; // request response callback } Request; -/** - * @brief 用于生成不同的主题 - */ -typedef enum { - ACCEPTED, REJECTED, METHOD -} RequestType; - -static char cloud_rcv_buf[CLOUD_IOT_JSON_RX_BUF_LEN]; - -bool discard_old_delta_flag = true; - -typedef void (*TraverseHandle)(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, const char *pClientToken, const char *pType); +typedef void (*TraverseHandle)(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, const char *pClientToken, + const char *pType); static void _on_operation_result_handler(void *pClient, MQTTMessage *message, void *pUserdata); -static void _handle_delta(Qcloud_IoT_Shadow *pShadow, char* delta_str); +static void _handle_delta(Qcloud_IoT_Shadow *pShadow, char *delta_str); static int _set_shadow_json_type(char *pJsonDoc, size_t sizeOfBuffer, Method method); @@ -72,48 +54,48 @@ static int _publish_operation_to_cloud(Qcloud_IoT_Shadow *pShadow, Method method static int _add_request_to_list(Qcloud_IoT_Shadow *pShadow, const char *pClientToken, RequestParams *pParams); -static int _unsubscribe_operation_result_to_cloud(void *pClient); +static int _unsubscribe_operation_result_to_cloud(Qcloud_IoT_Shadow *pShadow); -static void _traverse_list(Qcloud_IoT_Shadow *pShadow, List *list, const char *pClientToken, const char *pType, TraverseHandle traverseHandle); +static void _traverse_list(Qcloud_IoT_Shadow *pShadow, List *list, const char *pClientToken, const char *pType, + TraverseHandle traverseHandle); -static void _handle_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, const char *pClientToken, const char *pType); +static void _handle_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, const char *pClientToken, + const char *pType); -static void _handle_expired_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, const char *pClientToken, const char *pType); +static void _handle_expired_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, + const char *pClientToken, const char *pType); -int qcloud_iot_shadow_init(Qcloud_IoT_Shadow *pShadow) { - IOT_FUNC_ENTRY; +int qcloud_iot_shadow_init(Qcloud_IoT_Shadow *pShadow) +{ + IOT_FUNC_ENTRY; POINTER_SANITY_CHECK(pShadow, QCLOUD_ERR_INVAL); - pShadow->inner_data.version = 0; - pShadow->mutex = HAL_MutexCreate(); if (pShadow->mutex == NULL) IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); pShadow->inner_data.property_handle_list = list_new(); - if (pShadow->inner_data.property_handle_list) - { + if (pShadow->inner_data.property_handle_list) { pShadow->inner_data.property_handle_list->free = HAL_Free; - } - else { - Log_e("no memory to allocate property_handle_list"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } else { + Log_e("no memory to allocate property_handle_list"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } - pShadow->inner_data.request_list = list_new(); - if (pShadow->inner_data.request_list) - { - pShadow->inner_data.request_list->free = HAL_Free; - } else { - Log_e("no memory to allocate request_list"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } + pShadow->inner_data.request_list = list_new(); + if (pShadow->inner_data.request_list) { + pShadow->inner_data.request_list->free = HAL_Free; + } else { + Log_e("no memory to allocate request_list"); + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } -void qcloud_iot_shadow_reset(void *pClient) { +void qcloud_iot_shadow_reset(void *pClient) +{ POINTER_SANITY_CHECK_RTN(pClient); Qcloud_IoT_Shadow *shadow_client = (Qcloud_IoT_Shadow *)pClient; @@ -121,15 +103,15 @@ void qcloud_iot_shadow_reset(void *pClient) { list_destroy(shadow_client->inner_data.property_handle_list); } - _unsubscribe_operation_result_to_cloud(shadow_client->mqtt); + _unsubscribe_operation_result_to_cloud(shadow_client); - if (shadow_client->inner_data.request_list) - { + if (shadow_client->inner_data.request_list) { list_destroy(shadow_client->inner_data.request_list); } } -void handle_expired_request(Qcloud_IoT_Shadow *pShadow) { +void handle_expired_request(Qcloud_IoT_Shadow *pShadow) +{ IOT_FUNC_ENTRY; _traverse_list(pShadow, pShadow->inner_data.request_list, NULL, NULL, _handle_expired_request_callback); @@ -140,33 +122,31 @@ void handle_expired_request(Qcloud_IoT_Shadow *pShadow) { int do_shadow_request(Qcloud_IoT_Shadow *pShadow, RequestParams *pParams, char *pJsonDoc, size_t sizeOfBuffer) { IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; POINTER_SANITY_CHECK(pShadow, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(pJsonDoc, QCLOUD_ERR_INVAL); POINTER_SANITY_CHECK(pParams, QCLOUD_ERR_INVAL); - char* client_token = NULL; + char *client_token = NULL; - // 解析文档中的clientToken, 如果解析失败, 直接返回错误 if (!parse_client_token(pJsonDoc, &client_token)) { Log_e("fail to parse client token!"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); } - if (rc != QCLOUD_ERR_SUCCESS) + if (rc != QCLOUD_RET_SUCCESS) IOT_FUNC_EXIT_RC(rc); rc = _set_shadow_json_type(pJsonDoc, sizeOfBuffer, pParams->method); - if (rc != QCLOUD_ERR_SUCCESS) + if (rc != QCLOUD_RET_SUCCESS) IOT_FUNC_EXIT_RC(rc); - // 相应的 operation topic 订阅成功或已经订阅 - if (rc == QCLOUD_ERR_SUCCESS) { + if (rc == QCLOUD_RET_SUCCESS) { rc = _publish_operation_to_cloud(pShadow, pParams->method, pJsonDoc); } - if (rc == QCLOUD_ERR_SUCCESS) { + if (rc >= 0) { rc = _add_request_to_list(pShadow, client_token, pParams); } @@ -180,15 +160,25 @@ int subscribe_operation_result_to_cloud(Qcloud_IoT_Shadow *pShadow) IOT_FUNC_ENTRY; int rc; + int size; if (pShadow->inner_data.result_topic == NULL) { char *operation_result_topic = (char *)HAL_Malloc(MAX_SIZE_OF_CLOUD_TOPIC * sizeof(char)); - if (operation_result_topic == NULL) IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); + if (operation_result_topic == NULL) + IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); memset(operation_result_topic, 0x0, MAX_SIZE_OF_CLOUD_TOPIC); - int size = HAL_Snprintf(operation_result_topic, MAX_SIZE_OF_CLOUD_TOPIC, "$shadow/operation/result/%s/%s", iot_device_info_get()->product_id, iot_device_info_get()->device_name); - if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC - 1) - { + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pShadow->mqtt; + if (eTEMPLATE == pShadow->shadow_type) { + size = HAL_Snprintf(operation_result_topic, MAX_SIZE_OF_CLOUD_TOPIC, "$template/operation/result/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.device_name)); + } else { + size = HAL_Snprintf(operation_result_topic, MAX_SIZE_OF_CLOUD_TOPIC, "$shadow/operation/result/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.device_name)); + } + if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC - 1) { Log_e("buf size < topic length!"); HAL_Free(operation_result_topic); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); @@ -196,43 +186,54 @@ int subscribe_operation_result_to_cloud(Qcloud_IoT_Shadow *pShadow) pShadow->inner_data.result_topic = operation_result_topic; } - SubscribeParams subscribe_params = DEFAULT_SUB_PARAMS; + SubscribeParams subscribe_params = DEFAULT_SUB_PARAMS; subscribe_params.on_message_handler = _on_operation_result_handler; - subscribe_params.qos = QOS0; + subscribe_params.qos = QOS0; rc = IOT_MQTT_Subscribe(pShadow->mqtt, pShadow->inner_data.result_topic, &subscribe_params); if (rc < 0) { - Log_e("subscribe topic: %s failed: %d.", pShadow->inner_data.result_topic, rc); + Log_e("subscribe topic: %s failed: %d.", STRING_PTR_PRINT_SANITY_CHECK(pShadow->inner_data.result_topic), rc); } IOT_FUNC_EXIT_RC(rc); } /** - * @brief 发布文档请求到物联云 + * @brief publish operation to server * - * @param pClient Qcloud_IoT_Client对象 - * @param method 文档操作方式 - * @param pJsonDoc 等待发送的文档 - * @return 返回QCLOUD_ERR_SUCCESS, 表示发布文档请求成功 + * @param pClient Qcloud_IoT_Client + * @param method method type + * @param pJsonDoc JSON to publish + * @return QCLOUD_RET_SUCCESS for success, or err code for failure */ static int _publish_operation_to_cloud(Qcloud_IoT_Shadow *pShadow, Method method, char *pJsonDoc) { IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; char topic[MAX_SIZE_OF_CLOUD_TOPIC] = {0}; - int size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC, "$shadow/operation/%s/%s", iot_device_info_get()->product_id, iot_device_info_get()->device_name); - if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC - 1) - { + int size; + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pShadow->mqtt; + if (eTEMPLATE == pShadow->shadow_type) { + size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC, "$template/operation/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.device_name)); + } else { + size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC, "$shadow/operation/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.product_id), + STRING_PTR_PRINT_SANITY_CHECK(mqtt_client->device_info.device_name)); + } + + if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC - 1) { Log_e("buf size < topic length!"); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } PublishParams pubParams = DEFAULT_PUB_PARAMS; - pubParams.qos = QOS0; - pubParams.payload_len = strlen(pJsonDoc); - pubParams.payload = (char *) pJsonDoc; + pubParams.qos = QOS0; + pubParams.payload_len = strlen(pJsonDoc); + pubParams.payload = (char *)pJsonDoc; rc = IOT_MQTT_Publish(pShadow->mqtt, topic, &pubParams); @@ -240,9 +241,7 @@ static int _publish_operation_to_cloud(Qcloud_IoT_Shadow *pShadow, Method method } /** - * @brief 文档操作请求结果的回调函数 - * 客户端先订阅 $shadow/operation/result/{ProductId}/{DeviceName}, 收到该topic的消息则会调用该回调函数 - * 在这个回调函数中, 解析出各个设备影子文档操作的结果 + * @brief callback when msg of operation result arrives */ static void _on_operation_result_handler(void *pClient, MQTTMessage *message, void *pUserdata) { @@ -251,62 +250,54 @@ static void _on_operation_result_handler(void *pClient, MQTTMessage *message, vo POINTER_SANITY_CHECK_RTN(pClient); POINTER_SANITY_CHECK_RTN(message); - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - Qcloud_IoT_Shadow *shadow_client = (Qcloud_IoT_Shadow*)mqtt_client->event_handle.context; + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + Qcloud_IoT_Shadow *shadow_client = (Qcloud_IoT_Shadow *)mqtt_client->event_handle.context; - const char *topic = message->ptopic; - size_t topic_len = message->topic_len; + const char *topic = message->ptopic; + size_t topic_len = message->topic_len; if (NULL == topic || topic_len <= 0) { IOT_FUNC_EXIT; } char *client_token = NULL; - char *type_str = NULL; + char *type_str = NULL; if (message->payload_len > CLOUD_IOT_JSON_RX_BUF_LEN) { Log_e("The length of the received message exceeds the specified length!"); goto End; } - int cloud_rcv_len = min(CLOUD_IOT_JSON_RX_BUF_LEN - 1, message->payload_len); - memcpy(cloud_rcv_buf, message->payload, cloud_rcv_len + 1); - cloud_rcv_buf[cloud_rcv_len] = '\0'; // jsmn_parse relies on a string - - //解析shadow result topic消息类型 - if (!parse_shadow_operation_type(cloud_rcv_buf, &type_str)) - { + int cloud_rcv_len = Min(CLOUD_IOT_JSON_RX_BUF_LEN - 1, message->payload_len); + memcpy(shadow_client->shadow_recv_buf, message->payload, cloud_rcv_len + 1); + shadow_client->shadow_recv_buf[cloud_rcv_len] = '\0'; // jsmn_parse relies on a string + if (!parse_shadow_operation_type(shadow_client->shadow_recv_buf, &type_str)) { Log_e("Fail to parse type!"); goto End; } - //非delta消息的push,一定由设备端触发,找到设备段对应的client_token - if (strcmp(type_str, OPERATION_DELTA) && !parse_client_token(cloud_rcv_buf, &client_token)) { - Log_e("Fail to parse client token! Json=%s", cloud_rcv_buf); - goto End; - } + Log_d("type: %s", STRING_PTR_PRINT_SANITY_CHECK(type_str)); - //获取shadow push消息version,如果比本地的version则修改本地version,比本地可能是由于服务器回滚或出错 - uint32_t version_num = 0; - if (parse_version_num(cloud_rcv_buf, &version_num)) { - if (version_num > shadow_client->inner_data.version) { - shadow_client->inner_data.version = version_num; - } - } + // non-delta msg push is triggered by device side, parse client token first + if (strcmp(type_str, OPERATION_DELTA) && !parse_client_token(shadow_client->shadow_recv_buf, &client_token)) { + Log_e("Fail to parse client token! Json=%s", STRING_PTR_PRINT_SANITY_CHECK(shadow_client->shadow_recv_buf)); + goto End; + } if (!strcmp(type_str, OPERATION_DELTA)) { HAL_MutexLock(shadow_client->mutex); - - char* delta_str = NULL; - if (parse_shadow_operation_delta(cloud_rcv_buf, &delta_str)) { - _handle_delta(shadow_client, delta_str); - HAL_Free(delta_str); + char *delta_str = NULL; + if (parse_shadow_operation_delta(shadow_client->shadow_recv_buf, &delta_str)) { + Log_d("delta string: %s", STRING_PTR_PRINT_SANITY_CHECK(delta_str)); + _handle_delta(shadow_client, delta_str); + HAL_Free(delta_str); } HAL_MutexUnlock(shadow_client->mutex); goto End; } - + if (shadow_client != NULL) - _traverse_list(shadow_client, shadow_client->inner_data.request_list, client_token, type_str, _handle_request_callback); + _traverse_list(shadow_client, shadow_client->inner_data.request_list, client_token, type_str, + _handle_request_callback); End: HAL_Free(type_str); @@ -315,18 +306,12 @@ static void _on_operation_result_handler(void *pClient, MQTTMessage *message, vo IOT_FUNC_EXIT; } -/** - * @brief 处理注册属性的回调函数 - * 当订阅的$shadow/operation/result/{ProductId}/{DeviceName}返回消息时, - * 若对应的type为delta, 则执行该函数 - * - */ -static void _handle_delta(Qcloud_IoT_Shadow *pShadow, char* delta_str) +static void _handle_delta(Qcloud_IoT_Shadow *pShadow, char *delta_str) { IOT_FUNC_ENTRY; if (pShadow->inner_data.property_handle_list->len) { - ListIterator *iter; - ListNode *node = NULL; + ListIterator * iter; + ListNode * node = NULL; PropertyHandler *property_handle = NULL; if (NULL == (iter = list_iterator_new(pShadow->inner_data.property_handle_list, LIST_TAIL))) { @@ -347,17 +332,13 @@ static void _handle_delta(Qcloud_IoT_Shadow *pShadow, char* delta_str) } if (property_handle->property != NULL) { - - if (update_value_if_key_match(delta_str, property_handle->property)) - { - if (property_handle->callback != NULL) - { + if (update_value_if_key_match(delta_str, property_handle->property)) { + if (property_handle->callback != NULL) { property_handle->callback(pShadow, delta_str, strlen(delta_str), property_handle->property); } node = NULL; } } - } list_iterator_destroy(iter); @@ -366,8 +347,9 @@ static void _handle_delta(Qcloud_IoT_Shadow *pShadow, char* delta_str) IOT_FUNC_EXIT; } -static void _insert(char *str, char *pch, int pos) { - int len = strlen(str); +static void _insert(char *str, char *pch, int pos) +{ + int len = strlen(str); int nlen = strlen(pch); int i; for (i = len - 1; i >= pos; --i) { @@ -375,38 +357,34 @@ static void _insert(char *str, char *pch, int pos) { } int n; - for (n = 0; n < nlen; n++) - *(str + pos + n) = *pch++; + for (n = 0; n < nlen; n++) *(str + pos + n) = *pch++; *(str + len + nlen) = 0; } -/** - * @brief 根据RequestParams、Method来给json填入type字段的值 - */ static int _set_shadow_json_type(char *pJsonDoc, size_t sizeOfBuffer, Method method) { IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; POINTER_SANITY_CHECK(pJsonDoc, QCLOUD_ERR_INVAL); char *type_str = NULL; switch (method) { - case GET: - type_str = OPERATION_GET; - break; - case UPDATE: - type_str = OPERATION_UPDATE; - break; - default: - Log_e("unexpected method!"); - rc = QCLOUD_ERR_INVAL; - break; + case GET: + type_str = OPERATION_GET; + break; + case UPDATE: + type_str = OPERATION_UPDATE; + break; + default: + Log_e("unexpected method!"); + rc = QCLOUD_ERR_INVAL; + break; } - if (rc != QCLOUD_ERR_SUCCESS) + if (rc != QCLOUD_RET_SUCCESS) IOT_FUNC_EXIT_RC(rc); - size_t json_len = strlen(pJsonDoc); + size_t json_len = strlen(pJsonDoc); size_t remain_size = sizeOfBuffer - json_len; char json_node_str[64] = {0}; @@ -423,40 +401,30 @@ static int _set_shadow_json_type(char *pJsonDoc, size_t sizeOfBuffer, Method met } /** - * @brief 取消订阅topic: $shadow/operation/result/{ProductId}/{DeviceName} + * @brief unsubsribe topic: $shadow/operation/result/{ProductId}/{DeviceName} */ -static int _unsubscribe_operation_result_to_cloud(void* pClient) +static int _unsubscribe_operation_result_to_cloud(Qcloud_IoT_Shadow *pShadow) { IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; + int rc = QCLOUD_RET_SUCCESS; - char operation_result_topic[MAX_SIZE_OF_CLOUD_TOPIC] = {0}; - int size = HAL_Snprintf(operation_result_topic, MAX_SIZE_OF_CLOUD_TOPIC, "$shadow/operation/result/%s/%s", iot_device_info_get()->product_id, iot_device_info_get()->device_name); - - if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC - 1) - { - Log_e("buf size < topic length!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } + if (pShadow->inner_data.result_topic == NULL) + IOT_FUNC_EXIT_RC(rc); - IOT_MQTT_Unsubscribe(pClient, operation_result_topic); - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("unsubscribe topic: %s failed: %d.", operation_result_topic, rc); + rc = IOT_MQTT_Unsubscribe(pShadow->mqtt, pShadow->inner_data.result_topic); + if (rc < 0) { + Log_e("unsubscribe topic: %s failed: %d.", pShadow->inner_data.result_topic, rc); } IOT_FUNC_EXIT_RC(rc); } -/** - * @brief 将设备影子文档的操作请求保存在列表中 - */ static int _add_request_to_list(Qcloud_IoT_Shadow *pShadow, const char *pClientToken, RequestParams *pParams) { IOT_FUNC_ENTRY; HAL_MutexLock(pShadow->mutex); - if (pShadow->inner_data.request_list->len >= MAX_APPENDING_REQUEST_AT_ANY_GIVEN_TIME) - { + if (pShadow->inner_data.request_list->len >= MAX_APPENDING_REQUEST_AT_ANY_GIVEN_TIME) { HAL_MutexUnlock(pShadow->mutex); IOT_FUNC_EXIT_RC(QCLOUD_ERR_MAX_APPENDING_REQUEST); } @@ -472,7 +440,7 @@ static int _add_request_to_list(Qcloud_IoT_Shadow *pShadow, const char *pClientT strncpy(request->client_token, pClientToken, MAX_SIZE_OF_CLIENT_TOKEN); request->user_context = pParams->user_context; - request->method = pParams->method; + request->method = pParams->method; InitTimer(&(request->timer)); countdown(&(request->timer), pParams->timeout_sec); @@ -481,6 +449,7 @@ static int _add_request_to_list(Qcloud_IoT_Shadow *pShadow, const char *pClientT if (NULL == node) { HAL_MutexUnlock(pShadow->mutex); Log_e("run list_node_new is error!"); + HAL_Free(request); IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); } @@ -488,13 +457,14 @@ static int _add_request_to_list(Qcloud_IoT_Shadow *pShadow, const char *pClientT HAL_MutexUnlock(pShadow->mutex); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); + IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS); } /** - * @brief 遍历列表, 对列表每个节点都执行一次传入的函数traverseHandle + * @brief iterator list and call traverseHandle for each node */ -static void _traverse_list(Qcloud_IoT_Shadow *pShadow, List *list, const char *pClientToken, const char *pType, TraverseHandle traverseHandle) +static void _traverse_list(Qcloud_IoT_Shadow *pShadow, List *list, const char *pClientToken, const char *pType, + TraverseHandle traverseHandle) { IOT_FUNC_ENTRY; @@ -502,7 +472,7 @@ static void _traverse_list(Qcloud_IoT_Shadow *pShadow, List *list, const char *p if (list->len) { ListIterator *iter; - ListNode *node = NULL; + ListNode * node = NULL; if (NULL == (iter = list_iterator_new(list, LIST_TAIL))) { HAL_MutexUnlock(pShadow->mutex); @@ -530,10 +500,8 @@ static void _traverse_list(Qcloud_IoT_Shadow *pShadow, List *list, const char *p IOT_FUNC_EXIT; } -/** - * @brief 执行设备影子操作的回调函数 - */ -static void _handle_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, const char *pClientToken, const char *pType) +static void _handle_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, const char *pClientToken, + const char *pType) { IOT_FUNC_ENTRY; @@ -541,52 +509,46 @@ static void _handle_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node if (NULL == request) IOT_FUNC_EXIT; - if (strcmp(request->client_token, pClientToken) == 0) - { + if (strcmp(request->client_token, pClientToken) == 0) { RequestAck status = ACK_NONE; - // 通过 payload 包体的 result 来确定对应的操作是否成功 - // 当result=0时,payload不为空,result非0时,代表update失败 + // result field in payload tell us if operation success or not + // result = 0 for success, result != 0 for fail int16_t result_code = 0; - - bool parse_success = parse_shadow_operation_result_code(cloud_rcv_buf, &result_code); + + bool parse_success = parse_shadow_operation_result_code(pShadow->shadow_recv_buf, &result_code); if (parse_success) { - if (result_code == 0) { - status = ACK_ACCEPTED; - } else { - status = ACK_REJECTED; - } - - if ((strcmp(pType, "get") == 0 && status == ACK_ACCEPTED) || - (strcmp(pType, "update") && status == ACK_REJECTED)) - { - char* delta_str = NULL; - if (parse_shadow_operation_get(cloud_rcv_buf, &delta_str)) { - _handle_delta(pShadow, delta_str); - HAL_Free(delta_str); - } - } - - if (request->callback != NULL) { - request->callback(pShadow, request->method, status, cloud_rcv_buf, request->user_context); - } - } - else { - Log_e("parse shadow operation result code failed."); + if (result_code == 0) { + status = ACK_ACCEPTED; + } else { + status = ACK_REJECTED; + } + + if ((strcmp(pType, "get") == 0 && status == ACK_ACCEPTED) || + (strcmp(pType, "update") && status == ACK_REJECTED)) { + char *delta_str = NULL; + if (parse_shadow_operation_get(pShadow->shadow_recv_buf, &delta_str)) { + _handle_delta(pShadow, delta_str); + HAL_Free(delta_str); + } + } + + if (request->callback != NULL) { + request->callback(pShadow, request->method, status, pShadow->shadow_recv_buf, request->user_context); + } + } else { + Log_e("parse shadow operation result code failed."); } - + list_remove(list, *node); *node = NULL; - } IOT_FUNC_EXIT; } -/** - * @brief 执行过期的设备影子操作的回调函数 - */ -static void _handle_expired_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, const char *pClientToken, const char *pType) +static void _handle_expired_request_callback(Qcloud_IoT_Shadow *pShadow, ListNode **node, List *list, + const char *pClientToken, const char *pType) { IOT_FUNC_ENTRY; @@ -594,10 +556,9 @@ static void _handle_expired_request_callback(Qcloud_IoT_Shadow *pShadow, ListNod if (NULL == request) IOT_FUNC_EXIT; - if (expired(&request->timer)) - { + if (expired(&request->timer)) { if (request->callback != NULL) { - request->callback(pShadow, request->method, ACK_TIMEOUT, cloud_rcv_buf, request->user_context); + request->callback(pShadow, request->method, ACK_TIMEOUT, pShadow->shadow_recv_buf, request->user_context); } list_remove(list, *node); diff --git a/sdk_src/services/system/system_mqtt.c b/sdk_src/services/system/system_mqtt.c new file mode 100755 index 00000000..7255fc4a --- /dev/null +++ b/sdk_src/services/system/system_mqtt.c @@ -0,0 +1,311 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#ifdef SYSTEM_COMM +#include + +#include "lite-utils.h" +#include "mqtt_client.h" +#include "qcloud_iot_device.h" +#include "qcloud_iot_export_system.h" + +static void _system_mqtt_message_callback(void *pClient, MQTTMessage *message, void *pUserData) +{ +#define MAX_RECV_LEN (512) + + POINTER_SANITY_CHECK_RTN(message); + + static char rcv_buf[MAX_RECV_LEN + 1]; + size_t len = (message->payload_len > MAX_RECV_LEN) ? MAX_RECV_LEN : (message->payload_len); + + if (message->payload_len > MAX_RECV_LEN) { + Log_e("payload len oversize"); + } + memcpy(rcv_buf, message->payload, len); + rcv_buf[len] = '\0'; // jsmn_parse relies on a string + SysMQTTState *state = (SysMQTTState *)pUserData; + + Log_d("Recv Msg Topic:%s, payload:%s", STRING_PTR_PRINT_SANITY_CHECK(message->ptopic), rcv_buf); + + char *value = LITE_json_value_of("time", rcv_buf); + if (value != NULL) + state->time = atol(value); + + // ntp time 64bit platform parse ntp time + if (4 != sizeof(size_t)) { + char *ntptime1 = LITE_json_value_of("ntptime1", rcv_buf); + if (ntptime1 != NULL) { +#ifdef _WIN64 + state->ntptime1 = _atoi64(ntptime1); +#else + state->ntptime1 = atol(ntptime1); +#endif + } else { + state->ntptime1 = ((size_t)(state->time) * 1000); + } + char *ntptime2 = LITE_json_value_of("ntptime2", rcv_buf); + if (ntptime2 != NULL) { +#ifdef _WIN64 + state->ntptime2 = _atoi64(ntptime2); +#else + state->ntptime2 = atol(ntptime2); +#endif + } else { + state->ntptime2 = ((size_t)(state->time) * 1000); + } + HAL_Free(ntptime1); + HAL_Free(ntptime2); + } + state->result_recv_ok = true; + HAL_Free(value); + return; +} + +static void _system_mqtt_sub_event_handler(void *pclient, MQTTEventType event_type, void *pUserData) +{ + SysMQTTState *state = (SysMQTTState *)pUserData; + + switch (event_type) { + case MQTT_EVENT_SUBCRIBE_SUCCESS: + Log_d("mqtt sys topic subscribe success"); + state->topic_sub_ok = true; + break; + + case MQTT_EVENT_SUBCRIBE_TIMEOUT: + Log_i("mqtt sys topic subscribe timeout"); + state->topic_sub_ok = false; + break; + + case MQTT_EVENT_SUBCRIBE_NACK: + Log_i("mqtt sys topic subscribe NACK"); + state->topic_sub_ok = false; + break; + case MQTT_EVENT_UNSUBSCRIBE: + Log_i("mqtt sys topic has been unsubscribed"); + state->topic_sub_ok = false; + ; + break; + case MQTT_EVENT_CLIENT_DESTROY: + Log_i("mqtt client has been destroyed"); + state->topic_sub_ok = false; + ; + break; + default: + return; + } +} + +static int _iot_system_info_get_publish(void *pClient) +{ + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + DeviceInfo * dev_info = &mqtt_client->device_info; + POINTER_SANITY_CHECK(dev_info, QCLOUD_ERR_INVAL); + + char topic_name[128] = {0}; + char payload_content[128] = {0}; + + HAL_Snprintf(topic_name, sizeof(topic_name), "$sys/operation/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name)); + HAL_Snprintf(payload_content, sizeof(payload_content), "{\"type\": \"get\", \"resource\": [\"time\"]}"); + + PublishParams pub_params = DEFAULT_PUB_PARAMS; + pub_params.qos = QOS0; + pub_params.payload = payload_content; + pub_params.payload_len = strlen(payload_content); + + return IOT_MQTT_Publish(mqtt_client, topic_name, &pub_params); +} + +static int _iot_system_info_result_subscribe(void *pClient) +{ + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + DeviceInfo * dev_info = &mqtt_client->device_info; + SysMQTTState * sys_state = &mqtt_client->sys_state; + + char topic_name[128] = {0}; + int size = HAL_Snprintf(topic_name, sizeof(topic_name), "$sys/operation/result/%s/%s", + STRING_PTR_PRINT_SANITY_CHECK(dev_info->product_id), + STRING_PTR_PRINT_SANITY_CHECK(dev_info->device_name)); + if (size < 0 || size > sizeof(topic_name) - 1) { + Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); + return QCLOUD_ERR_FAILURE; + } + SubscribeParams sub_params = DEFAULT_SUB_PARAMS; + sub_params.on_message_handler = _system_mqtt_message_callback; + sub_params.on_sub_event_handler = _system_mqtt_sub_event_handler; + sub_params.user_data = (void *)sys_state; + sub_params.qos = QOS0; + + return IOT_MQTT_Subscribe(pClient, topic_name, &sub_params); +} + +int IOT_Get_SysTime(void *pClient, long *time) +{ + int ret = 0; + int cntSub = 0; + int cntRev = 0; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + SysMQTTState *sys_state = &mqtt_client->sys_state; + // subscribe sys topic: $sys/operation/get/${productid}/${devicename} + // skip this if the subscription is done and valid + if (!sys_state->topic_sub_ok) { + for (cntSub = 0; cntSub < 3; cntSub++) { + ret = _iot_system_info_result_subscribe(mqtt_client); + if (ret < 0) { + Log_w("_iot_system_info_result_subscribe failed: %d, cnt: %d", ret, cntSub); + continue; + } + + /* wait for sub ack */ + ret = qcloud_iot_mqtt_yield_mt((Qcloud_IoT_Client *)pClient, 100); + if (ret || sys_state->topic_sub_ok) { + break; + } + } + } + + // return failure if subscribe failed + if (!sys_state->topic_sub_ok) { + Log_e("Subscribe sys topic failed!"); + return QCLOUD_ERR_FAILURE; + } + + sys_state->result_recv_ok = false; + // publish msg to get system timestamp + ret = _iot_system_info_get_publish(mqtt_client); + if (ret < 0) { + Log_e("client publish sys topic failed :%d.", ret); + return ret; + } + + do { + ret = qcloud_iot_mqtt_yield_mt((Qcloud_IoT_Client *)pClient, 100); + cntRev++; + } while (!ret && !sys_state->result_recv_ok && cntRev < 20); + + if (sys_state->result_recv_ok) { + *time = sys_state->time; + ret = QCLOUD_RET_SUCCESS; + } else { + *time = 0; + ret = QCLOUD_ERR_FAILURE; + } + + return ret; +} + +int IOT_Sync_NTPTime(void *pClient) +{ + int ret = 0; + int cntSub = 0; + int cntRev = 0; + + POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); + Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; + + SysMQTTState *sys_state = &mqtt_client->sys_state; + // subscribe sys topic: $sys/operation/get/${productid}/${devicename} + // skip this if the subscription is done and valid + if (!sys_state->topic_sub_ok) { + for (cntSub = 0; cntSub < 3; cntSub++) { + ret = _iot_system_info_result_subscribe(mqtt_client); + if (ret < 0) { + Log_w("_iot_system_info_result_subscribe failed: %d, cnt: %d", ret, cntSub); + continue; + } + + /* wait for sub ack */ + ret = qcloud_iot_mqtt_yield_mt((Qcloud_IoT_Client *)pClient, 100); + if (ret || sys_state->topic_sub_ok) { + break; + } + } + } + + // return failure if subscribe failed + if (!sys_state->topic_sub_ok) { + Log_e("Subscribe sys topic failed!"); + return QCLOUD_ERR_FAILURE; + } + + size_t localtime_before_ms = 0; + // 64bit platform + if (4 != sizeof(size_t)) { + localtime_before_ms = HAL_GetTimeMs(); + } + sys_state->result_recv_ok = false; + // publish msg to get system timestamp + ret = _iot_system_info_get_publish(mqtt_client); + if (ret < 0) { + Log_e("client publish sys topic failed :%d.", ret); + return ret; + } + + do { + ret = qcloud_iot_mqtt_yield_mt((Qcloud_IoT_Client *)pClient, 100); + cntRev++; + } while (!ret && !sys_state->result_recv_ok && cntRev < 20); + + if (sys_state->result_recv_ok) { + // 32bit platform + if (4 == sizeof(size_t)) { + ret = HAL_Timer_set_systime_sec(sys_state->time); + if (0 != ret) { + Log_e("set systime sec failed, timestamp %ld sec, please check permission or other ret:%d", + sys_state->time, ret); + } else { + Log_i("set systime sec success, timestamp %ld sec", sys_state->time); + } + } else { + // 64bit platform + size_t localtime_after_ms = HAL_GetTimeMs(); + size_t local_ntptime = + ((sys_state->ntptime2 + sys_state->ntptime1 + localtime_after_ms - localtime_before_ms) / 2); + ret = HAL_Timer_set_systime_ms(local_ntptime); + if (0 != ret) { + Log_e("set systime ms failed, timestamp %lld, please check permission or other ret :%d", local_ntptime, + ret); + } else { + Log_i("set systime ms success, timestamp %lld ms", local_ntptime); + } + } + ret = QCLOUD_RET_SUCCESS; + } else { + ret = QCLOUD_ERR_FAILURE; + } + + return ret; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utils/lite/json_parser.c b/sdk_src/utils/json_parser.c old mode 100644 new mode 100755 similarity index 59% rename from src/utils/lite/json_parser.c rename to sdk_src/utils/json_parser.c index 88393b61..d01b89c9 --- a/src/utils/lite/json_parser.c +++ b/sdk_src/utils/json_parser.c @@ -1,30 +1,24 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. * */ -/** - * Edit by shockcao@tencent.com 2018/3/15 - */ +#include "json_parser.h" + +#include #include #include #include -#include - -#include "json_parser.h" #include "lite-utils.h" #include "qcloud_iot_export_log.h" @@ -32,17 +26,17 @@ #define json_debug Log_d typedef struct JSON_NV { - int nLen; - int vLen; - int vType; - char *pN; - char *pV; + int nLen; + int vLen; + int vType; + char *pN; + char *pV; } JSON_NV; char *json_get_object(int type, char *str) { char *pos = 0; - char ch = (type == JSOBJECT) ? '{' : '['; + char ch = (type == JSOBJECT) ? '{' : '['; while (str != 0 && *str != 0) { if (*str == ' ') { str++; @@ -54,12 +48,12 @@ char *json_get_object(int type, char *str) return pos; } -char *json_get_next_object(int type, char *str, char **key, int *key_len, - char **val, int *val_len, int *val_type) +char *json_get_next_object(int type, char *str, char **key, int *key_len, char **val, int *val_len, int *val_type) { - char JsonMark[JSTYPEMAX][2] = { { '\"', '\"' }, { '{', '}' }, { '[', ']' }, { '0', ' ' } }; - int iMarkDepth = 0, iValueType = JSNONE, iNameLen = 0, iValueLen = 0; - char *p_cName = 0, *p_cValue = 0, *p_cPos = str; + char JsonMark[JSTYPEMAX][2] = {{'\"', '\"'}, {'{', '}'}, {'[', ']'}, {'0', ' '}}; + int iMarkDepth = 0, iValueType = JSNONE, iNameLen = 0, iValueLen = 0; + char *p_cName = 0, *p_cValue = 0, *p_cPos = str; + char lastchr = ' '; if (type == JSOBJECT) { /* Get Key */ @@ -68,7 +62,7 @@ char *json_get_next_object(int type, char *str, char **key, int *key_len, return 0; } p_cName = ++p_cPos; - p_cPos = strchr(p_cPos, '"'); + p_cPos = strchr(p_cPos, '"'); if (!p_cPos) { return 0; } @@ -80,46 +74,59 @@ char *json_get_next_object(int type, char *str, char **key, int *key_len, while (p_cPos && *p_cPos) { if (*p_cPos == '"') { iValueType = JSSTRING; - p_cValue = ++p_cPos; + lastchr = *p_cPos; + p_cValue = ++p_cPos; break; } else if (*p_cPos == '{') { iValueType = JSOBJECT; - p_cValue = p_cPos++; + p_cValue = p_cPos++; break; } else if (*p_cPos == '[') { iValueType = JSARRAY; - p_cValue = p_cPos++; + p_cValue = p_cPos++; break; } else if ((*p_cPos == '-') || (*p_cPos >= '0' && *p_cPos <= '9')) { iValueType = JSNUMBER; - p_cValue = p_cPos++; + p_cValue = p_cPos++; break; } else if (*p_cPos == 't' || *p_cPos == 'T' || *p_cPos == 'f' || *p_cPos == 'F') { iValueType = JSBOOLEAN; - p_cValue = p_cPos; + p_cValue = p_cPos; + break; + } else if (*p_cPos == 'n' || *p_cPos == 'N') { + iValueType = JSNULL; + p_cValue = p_cPos; break; } p_cPos++; } while (p_cPos && *p_cPos && iValueType > JSNONE) { if (iValueType == JSBOOLEAN) { - int len = strlen(p_cValue); + int len = strlen(p_cValue); - if ((*p_cValue == 't' || *p_cValue == 'T') && len >= 4 - && (!strncmp(p_cValue, "true", 4) - || !strncmp(p_cValue, "TRUE", 4))) { + if ((*p_cValue == 't' || *p_cValue == 'T') && len >= 4 && + (!strncmp(p_cValue, "true", 4) || !strncmp(p_cValue, "TRUE", 4))) { iValueLen = 4; - p_cPos = p_cValue + iValueLen; + // p_cPos = p_cValue + iValueLen; break; - } else if ((*p_cValue == 'f' || *p_cValue == 'F') && len >= 5 - && (!strncmp(p_cValue, "false", 5) - || !strncmp(p_cValue, "FALSE", 5))) { + } else if ((*p_cValue == 'f' || *p_cValue == 'F') && len >= 5 && + (!strncmp(p_cValue, "false", 5) || !strncmp(p_cValue, "FALSE", 5))) { iValueLen = 5; - p_cPos = p_cValue + iValueLen; + // p_cPos = p_cValue + iValueLen; + break; + } + } else if (iValueType == JSNULL) { // support null/NULL + int nlen = strlen(p_cValue); + + if ((*p_cValue == 'n' || *p_cValue == 'N') && nlen >= 4 && + (!strncmp(p_cValue, "null", 4) || !strncmp(p_cValue, "NULL", 4))) { + iValueLen = 4; + // p_cPos = p_cValue + iValueLen; break; } } else if (iValueType == JSNUMBER) { - if (*p_cPos < '0' || *p_cPos > '9') { + // if (*p_cPos < '0' || *p_cPos > '9') { + if ((*p_cPos < '0' || *p_cPos > '9') && (*p_cPos != '.')) { // support float iValueLen = p_cPos - p_cValue; break; } @@ -127,23 +134,29 @@ char *json_get_next_object(int type, char *str, char **key, int *key_len, if (iMarkDepth == 0) { iValueLen = p_cPos - p_cValue + (iValueType == JSSTRING ? 0 : 1); p_cPos++; - break; + if ((iValueType == JSSTRING) && (lastchr == '\\')) { + lastchr = *p_cPos; + continue; + } else { + break; + } } else { iMarkDepth--; } } else if (*p_cPos == JsonMark[iValueType][0]) { iMarkDepth++; } + lastchr = *p_cPos; p_cPos++; } if (type == JSOBJECT) { - *key = p_cName; + *key = p_cName; *key_len = iNameLen; } - *val = p_cValue; - *val_len = iValueLen; + *val = p_cValue; + *val_len = iValueLen; *val_type = iValueType; if (iValueType == JSSTRING) { return p_cValue + iValueLen + 1; @@ -154,10 +167,10 @@ char *json_get_next_object(int type, char *str, char **key, int *key_len, int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData) { - char *pos = 0, *key = 0, *val = 0; - int klen = 0, vlen = 0, vtype = 0; - char last_char = 0; - int ret = JSON_RESULT_ERR; + char *pos = 0, *key = 0, *val = 0; + int klen = 0, vlen = 0, vtype = 0; + char last_char = 0; + int ret = JSON_RESULT_ERR; if (p_cJsonStr == NULL || iStrLen == 0 || pfnCB == NULL) { return ret; @@ -168,7 +181,8 @@ int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, vo backup_json_str_last_char(p_cJsonStr, iStrLen, last_char); } - json_object_for_each_kv(p_cJsonStr, pos, key, klen, val, vlen, vtype) { + json_object_for_each_kv(p_cJsonStr, pos, key, klen, val, vlen, vtype) + { if (key && klen && val && vlen) { ret = JSON_RESULT_OK; if (JSON_PARSE_FINISH == pfnCB(key, klen, val, vlen, vtype, p_CBData)) { @@ -187,10 +201,10 @@ int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, vo int json_get_value_by_name_cb(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType, void *p_CBData) { - JSON_NV *p_stNameValue = (JSON_NV *)p_CBData; + JSON_NV *p_stNameValue = (JSON_NV *)p_CBData; #if (JSON_DEBUG == 1) - int i; + int i; if (p_cName) { json_debug("Name:"); @@ -207,9 +221,9 @@ int json_get_value_by_name_cb(char *p_cName, int iNameLen, char *p_cValue, int i } #endif - if (!strncmp(p_cName, p_stNameValue->pN, p_stNameValue->nLen)) { - p_stNameValue->pV = p_cValue; - p_stNameValue->vLen = iValueLen; + if ((iNameLen == p_stNameValue->nLen) && !strncmp(p_cName, p_stNameValue->pN, p_stNameValue->nLen)) { + p_stNameValue->pV = p_cValue; + p_stNameValue->vLen = iValueLen; p_stNameValue->vType = iValueType; return JSON_PARSE_FINISH; } else { @@ -219,10 +233,10 @@ int json_get_value_by_name_cb(char *p_cName, int iNameLen, char *p_cValue, int i char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType) { - JSON_NV stNV; + JSON_NV stNV; memset(&stNV, 0, sizeof(stNV)); - stNV.pN = p_cName; + stNV.pN = p_cName; stNV.nLen = strlen(p_cName); if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) { if (p_iValueLen) { @@ -230,8 +244,10 @@ char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int * } if (p_iValueType) { *p_iValueType = stNV.vType; + if (JSNULL == stNV.vType) { + stNV.pV = NULL; + } } } return stNV.pV; } - diff --git a/sdk_src/utils/json_token.c b/sdk_src/utils/json_token.c new file mode 100755 index 00000000..ad3a7a0e --- /dev/null +++ b/sdk_src/utils/json_token.c @@ -0,0 +1,208 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "json_parser.h" +#include "lite-utils.h" +#include "qcloud_iot_export_error.h" + +#ifndef SCNi8 +#define SCNi8 "hhi" +#endif + +#ifndef SCNu8 +#define SCNu8 "hhu" +#endif + +char *LITE_json_value_of(char *key, char *src) +{ + char *value = NULL; + int value_len = -1; + char *ret = NULL; + + char *delim = NULL; + char *key_iter; + char *key_next; + int key_len; + char *src_iter; + + src_iter = src; + key_iter = key; + + do { + if ((delim = strchr(key_iter, '.')) != NULL) { + key_len = delim - key_iter; + key_next = HAL_Malloc(key_len + 1); + strncpy(key_next, key_iter, key_len); + key_next[key_len] = '\0'; + value = json_get_value_by_name(src_iter, strlen(src_iter), key_next, &value_len, 0); + + if (value == NULL) { + HAL_Free(key_next); + return NULL; + } + + src_iter = value; + key_iter = delim + 1; + HAL_Free(key_next); + } + } while (delim); + + value = json_get_value_by_name(src_iter, strlen(src_iter), key_iter, &value_len, 0); + if (NULL == value) { + return NULL; + } + ret = HAL_Malloc((value_len + 1) * sizeof(char)); + if (NULL == ret) { + return NULL; + } + HAL_Snprintf(ret, value_len + 1, "%s", value); + return ret; +} + +list_head_t *LITE_json_keys_of(char *src, char *prefix) +{ + static LIST_HEAD(keylist); + + char *pos = 0, *key = 0, *val = 0; + int klen = 0, vlen = 0, vtype = 0; + + if (src == NULL || prefix == NULL) { + return NULL; + } + + if (!strcmp("", prefix)) { + INIT_LIST_HEAD(&keylist); + } + + json_object_for_each_kv(src, pos, key, klen, val, vlen, vtype) + { + if (key && klen && val && vlen) { + json_key_t *entry = NULL; + + entry = HAL_Malloc(sizeof(json_key_t)); + memset(entry, 0, sizeof(json_key_t)); + entry->key = LITE_format_string("%s%.*s", prefix, klen, key); + list_add_tail(&entry->list, &keylist); + + if (JSOBJECT == vtype) { + char *iter_val = LITE_format_string("%.*s", vlen, val); + char *iter_pre = LITE_format_string("%s%.*s.", prefix, klen, key); + LITE_json_keys_of(iter_val, iter_pre); + HAL_Free(iter_val); + HAL_Free(iter_pre); + } + } + } + + if (!strcmp("", prefix)) { + json_key_t *entry = NULL; + + entry = HAL_Malloc(sizeof(json_key_t)); + memset(entry, 0, sizeof(json_key_t)); + list_add_tail(&entry->list, &keylist); + + return &keylist; + } + + return NULL; +} + +void LITE_json_keys_release(list_head_t *keylist) +{ + json_key_t *pos, *tmp; + + list_for_each_entry_safe(pos, tmp, keylist, list, json_key_t) + { + if (pos->key) { + HAL_Free(pos->key); + } + list_del(&pos->list); + HAL_Free(pos); + } +} + +static void _strip_transfer(char *src) +{ + char *end = src + strlen(src) + 1; + + while (*src != '\0') { + if (*src == '\\') { + memmove(src, src + 1, end - src); + end--; + } + src++; + } +} + +char *LITE_json_string_value_strip_transfer(char *key, char *src) +{ + char *str = LITE_json_value_of(key, src); + + if (NULL != str) { + _strip_transfer(str); + } + return str; +} + +int LITE_get_int32(int32_t *value, char *src) +{ + return (sscanf(src, "%" SCNi32, value) == 1) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE; +} + +int LITE_get_int16(int16_t *value, char *src) +{ + return (sscanf(src, "%" SCNi16, value) == 1) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE; +} + +int LITE_get_int8(int8_t *value, char *src) +{ + return (sscanf(src, "%" SCNi8, value) == 1) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE; +} + +int LITE_get_uint32(uint32_t *value, char *src) +{ + return (sscanf(src, "%" SCNu32, value) == 1) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE; +} + +int LITE_get_uint16(uint16_t *value, char *src) +{ + return (sscanf(src, "%" SCNu16, value) == 1) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE; +} + +int LITE_get_uint8(uint8_t *value, char *src) +{ + return (sscanf(src, "%" SCNu8, value) == 1) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE; +} + +int LITE_get_float(float *value, char *src) +{ + return (sscanf(src, "%f", value) == 1) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE; +} + +int LITE_get_double(double *value, char *src) +{ + return (sscanf(src, "%lf", value) == 1) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE; +} + +int LITE_get_boolean(bool *value, char *src) +{ + if (!strcmp(src, "false")) { + *value = false; + } else { + *value = true; + } + + return QCLOUD_RET_SUCCESS; +} diff --git a/src/device/src/ca.c b/sdk_src/utils/qcloud_iot_ca.c old mode 100644 new mode 100755 similarity index 86% rename from src/device/src/ca.c rename to sdk_src/utils/qcloud_iot_ca.c index 4910ccb2..076354ac --- a/src/device/src/ca.c +++ b/sdk_src/utils/qcloud_iot_ca.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -17,40 +17,42 @@ extern "C" { #endif -#include "ca.h" +#include "qcloud_iot_ca.h" #include +#include "qcloud_iot_import.h" + #ifndef AUTH_WITH_NOTLS -static const char *iot_ca_crt = \ -{ +#if defined(AUTH_MODE_CERT) || defined(DEV_DYN_REG_ENABLED) +static const char *iot_ca_crt = { "-----BEGIN CERTIFICATE-----\r\n" - "MIIDxTCCAq2gAwIBAgIJALM1winYO2xzMA0GCSqGSIb3DQEBCwUAMHkxCzAJBgNV\r\n" \ - "BAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxETAPBgNVBAcMCFNoZW5aaGVuMRAw\r\n" \ - "DgYDVQQKDAdUZW5jZW50MRcwFQYDVQQLDA5UZW5jZW50IElvdGh1YjEYMBYGA1UE\r\n" \ - "AwwPd3d3LnRlbmNlbnQuY29tMB4XDTE3MTEyNzA0MjA1OVoXDTMyMTEyMzA0MjA1\r\n" \ - "OVoweTELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nRG9uZzERMA8GA1UEBwwI\r\n" \ - "U2hlblpoZW4xEDAOBgNVBAoMB1RlbmNlbnQxFzAVBgNVBAsMDlRlbmNlbnQgSW90\r\n" \ - "aHViMRgwFgYDVQQDDA93d3cudGVuY2VudC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\r\n" \ - "A4IBDwAwggEKAoIBAQDVxwDZRVkU5WexneBEkdaKs4ehgQbzpbufrWo5Lb5gJ3i0\r\n" \ - "eukbOB81yAaavb23oiNta4gmMTq2F6/hAFsRv4J2bdTs5SxwEYbiYU1teGHuUQHO\r\n" \ - "iQsZCdNTJgcikga9JYKWcBjFEnAxKycNsmqsq4AJ0CEyZbo//IYX3czEQtYWHjp7\r\n" \ - "FJOlPPd1idKtFMVNG6LGXEwS/TPElE+grYOxwB7Anx3iC5ZpE5lo5tTioFTHzqbT\r\n" \ - "qTN7rbFZRytAPk/JXMTLgO55fldm4JZTP3GQsPzwIh4wNNKhi4yWG1o2u3hAnZDv\r\n" \ - "UVFV7al2zFdOfuu0KMzuLzrWrK16SPadRDd9eT17AgMBAAGjUDBOMB0GA1UdDgQW\r\n" \ - "BBQrr48jv4FxdKs3r0BkmJO7zH4ALzAfBgNVHSMEGDAWgBQrr48jv4FxdKs3r0Bk\r\n" \ - "mJO7zH4ALzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQDRSjXnBc3T\r\n" \ - "d9VmtTCuALXrQELY8KtM+cXYYNgtodHsxmrRMpJofsPGiqPfb82klvswpXxPK8Xx\r\n" \ - "SuUUo74Fo+AEyJxMrRKlbJvlEtnpSilKmG6rO9+bFq3nbeOAfat4lPl0DIscWUx3\r\n" \ - "ajXtvMCcSwTlF8rPgXbOaSXZidRYNqSyUjC2Q4m93Cv+KlyB+FgOke8x4aKAkf5p\r\n" \ - "XR8i1BN1OiMTIRYhGSfeZbVRq5kTdvtahiWFZu9DGO+hxDZObYGIxGHWPftrhBKz\r\n" \ - "RT16Amn780rQLWojr70q7o7QP5tO0wDPfCdFSc6CQFq/ngOzYag0kJ2F+O5U6+kS\r\n" \ - "QVrcRBDxzx/G\r\n" \ - "-----END CERTIFICATE-----" -}; + "MIIDxTCCAq2gAwIBAgIJALM1winYO2xzMA0GCSqGSIb3DQEBCwUAMHkxCzAJBgNV\r\n" + "BAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxETAPBgNVBAcMCFNoZW5aaGVuMRAw\r\n" + "DgYDVQQKDAdUZW5jZW50MRcwFQYDVQQLDA5UZW5jZW50IElvdGh1YjEYMBYGA1UE\r\n" + "AwwPd3d3LnRlbmNlbnQuY29tMB4XDTE3MTEyNzA0MjA1OVoXDTMyMTEyMzA0MjA1\r\n" + "OVoweTELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nRG9uZzERMA8GA1UEBwwI\r\n" + "U2hlblpoZW4xEDAOBgNVBAoMB1RlbmNlbnQxFzAVBgNVBAsMDlRlbmNlbnQgSW90\r\n" + "aHViMRgwFgYDVQQDDA93d3cudGVuY2VudC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\r\n" + "A4IBDwAwggEKAoIBAQDVxwDZRVkU5WexneBEkdaKs4ehgQbzpbufrWo5Lb5gJ3i0\r\n" + "eukbOB81yAaavb23oiNta4gmMTq2F6/hAFsRv4J2bdTs5SxwEYbiYU1teGHuUQHO\r\n" + "iQsZCdNTJgcikga9JYKWcBjFEnAxKycNsmqsq4AJ0CEyZbo//IYX3czEQtYWHjp7\r\n" + "FJOlPPd1idKtFMVNG6LGXEwS/TPElE+grYOxwB7Anx3iC5ZpE5lo5tTioFTHzqbT\r\n" + "qTN7rbFZRytAPk/JXMTLgO55fldm4JZTP3GQsPzwIh4wNNKhi4yWG1o2u3hAnZDv\r\n" + "UVFV7al2zFdOfuu0KMzuLzrWrK16SPadRDd9eT17AgMBAAGjUDBOMB0GA1UdDgQW\r\n" + "BBQrr48jv4FxdKs3r0BkmJO7zH4ALzAfBgNVHSMEGDAWgBQrr48jv4FxdKs3r0Bk\r\n" + "mJO7zH4ALzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQDRSjXnBc3T\r\n" + "d9VmtTCuALXrQELY8KtM+cXYYNgtodHsxmrRMpJofsPGiqPfb82klvswpXxPK8Xx\r\n" + "SuUUo74Fo+AEyJxMrRKlbJvlEtnpSilKmG6rO9+bFq3nbeOAfat4lPl0DIscWUx3\r\n" + "ajXtvMCcSwTlF8rPgXbOaSXZidRYNqSyUjC2Q4m93Cv+KlyB+FgOke8x4aKAkf5p\r\n" + "XR8i1BN1OiMTIRYhGSfeZbVRq5kTdvtahiWFZu9DGO+hxDZObYGIxGHWPftrhBKz\r\n" + "RT16Amn780rQLWojr70q7o7QP5tO0wDPfCdFSc6CQFq/ngOzYag0kJ2F+O5U6+kS\r\n" + "QVrcRBDxzx/G\r\n" + "-----END CERTIFICATE-----"}; +#endif -static const char *iot_https_ca_crt = \ -{ +#ifdef OTA_USE_HTTPS +static const char *iot_https_ca_crt = { "-----BEGIN CERTIFICATE-----\r\n" "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\r\n" "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n" @@ -97,21 +99,33 @@ static const char *iot_https_ca_crt = \ "30JAZGSGvip2CTFvHST0mdCF/vIhCPnG9vHQWe3WVjwIKANnuvD58ZAWR65n5ryA\r\n" "SOlCdjSXVWkkDoPWoC209fN5ikkodBpBocLTJIg1MGCUF7ThBCIxPTsvFwayuJ2G\r\n" "K1pp74P1S8SqtCr4fKGxhZSM9AyHDPSsQPhZSZg=\r\n" - "-----END CERTIFICATE-----" -}; + "-----END CERTIFICATE-----"}; +#endif #endif -const char *iot_ca_get() { +const char *iot_ca_get() +{ #ifndef AUTH_WITH_NOTLS - return iot_ca_crt; +#if defined(AUTH_MODE_CERT) || defined(DEV_DYN_REG_ENABLED) + return iot_ca_crt; +#else + return NULL; +#endif #else return NULL; #endif } -const char *iot_https_ca_get() { +const char *iot_https_ca_get() +{ #ifndef AUTH_WITH_NOTLS - return iot_https_ca_crt; + +#ifdef OTA_USE_HTTPS + return iot_https_ca_crt; +#else + return NULL; +#endif + #else return NULL; #endif @@ -120,5 +134,3 @@ const char *iot_https_ca_get() { #ifdef __cplusplus } #endif - - diff --git a/sdk_src/utils/qcloud_iot_device.c b/sdk_src/utils/qcloud_iot_device.c new file mode 100755 index 00000000..327ebcac --- /dev/null +++ b/sdk_src/utils/qcloud_iot_device.c @@ -0,0 +1,56 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif +#include "qcloud_iot_device.h" + +#include +#include + +#include "qcloud_iot_export.h" + +int iot_device_info_set(DeviceInfo *device_info, const char *product_id, const char *device_name) +{ + memset(device_info, 0x0, sizeof(DeviceInfo)); + if ((MAX_SIZE_OF_PRODUCT_ID) < strlen(product_id)) { + Log_e("product name(%s) length:(%lu) exceeding limitation", product_id, strlen(product_id)); + return QCLOUD_ERR_FAILURE; + } + if ((MAX_SIZE_OF_DEVICE_NAME) < strlen(device_name)) { + Log_e("device name(%s) length:(%lu) exceeding limitation", device_name, strlen(device_name)); + return QCLOUD_ERR_FAILURE; + } + + strncpy(device_info->product_id, product_id, MAX_SIZE_OF_PRODUCT_ID); + strncpy(device_info->device_name, device_name, MAX_SIZE_OF_DEVICE_NAME); + + /* construct device-id(@product_id+@device_name) */ + memset(device_info->client_id, 0x0, MAX_SIZE_OF_CLIENT_ID); + int ret = HAL_Snprintf(device_info->client_id, MAX_SIZE_OF_CLIENT_ID, "%s%s", product_id, device_name); + if ((ret < 0) || (ret >= MAX_SIZE_OF_CLIENT_ID)) { + Log_e("set device info failed"); + return QCLOUD_ERR_FAILURE; + } + + Log_i("SDK_Ver: %s, Product_ID: %s, Device_Name: %s", QCLOUD_IOT_DEVICE_SDK_VERSION, device_info->product_id, + device_info->device_name); + return QCLOUD_RET_SUCCESS; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/sdk-impl/qcloud_iot_sdk_impl.c b/sdk_src/utils/qcloud_iot_log.c old mode 100644 new mode 100755 similarity index 55% rename from src/sdk-impl/qcloud_iot_sdk_impl.c rename to sdk_src/utils/qcloud_iot_log.c index da630312..6700b387 --- a/src/sdk-impl/qcloud_iot_sdk_impl.c +++ b/sdk_src/utils/qcloud_iot_log.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -17,69 +17,81 @@ extern "C" { #endif -#include "qcloud_iot_export_log.h" - #include -#include "qcloud_iot_import.h" #include "log_upload.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" +static char *level_str[] = {"DIS", "ERR", "WRN", "INF", "DBG"}; -static char *level_str[] = { - "DIS", "ERR", "WRN", "INF", "DBG" -}; - -static LogMessageHandler sg_log_message_handler= NULL; +static LogMessageHandler sg_log_message_handler = NULL; -LOG_LEVEL g_log_print_level = INFO; +LOG_LEVEL g_log_print_level = eLOG_INFO; #ifdef LOG_UPLOAD -LOG_LEVEL g_log_upload_level = ERROR; +LOG_LEVEL g_log_upload_level = eLOG_ERROR; #else -LOG_LEVEL g_log_upload_level = DISABLE; +LOG_LEVEL g_log_upload_level = eLOG_DISABLE; #endif static const char *_get_filename(const char *p) { +#ifdef WIN32 + char ch = '\\'; +#else char ch = '/'; - const char *q = strrchr(p,ch); - if(q == NULL) - { +#endif + const char *q = strrchr(p, ch); + if (q == NULL) { q = p; - } - else - { + } else { q++; } return q; } -void IOT_Log_Set_Level(LOG_LEVEL logLevel) { +void IOT_Log_Set_Level(LOG_LEVEL logLevel) +{ g_log_print_level = logLevel; } -LOG_LEVEL IOT_Log_Get_Level() { +LOG_LEVEL IOT_Log_Get_Level(void) +{ return g_log_print_level; } -void IOT_Log_Set_MessageHandler(LogMessageHandler handler) { - sg_log_message_handler = handler; +void IOT_Log_Set_MessageHandler(LogMessageHandler handler) +{ + sg_log_message_handler = handler; } -void IOT_Log_Set_Upload_Level(LOG_LEVEL logLevel) { +void IOT_Log_Set_Upload_Level(LOG_LEVEL logLevel) +{ g_log_upload_level = logLevel; } -LOG_LEVEL IOT_Log_Get_Upload_Level() { +LOG_LEVEL IOT_Log_Get_Upload_Level(void) +{ return g_log_upload_level; } -void IOT_Log_Init_Uploader(LogUploadInitParams *init_params) +int IOT_Log_Init_Uploader(LogUploadInitParams *init_params) { #ifdef LOG_UPLOAD return init_log_uploader(init_params); #else - return ; + return 0; +#endif +} + +void IOT_Log_Fini_Uploader(void) +{ +#ifdef LOG_UPLOAD + fini_log_uploader(); + return; +#else + return; #endif } @@ -92,25 +104,27 @@ int IOT_Log_Upload(bool force_upload) #endif } -void Log_writter(const char *file, const char *func, const int line, const int level, const char *fmt, ...) +void IOT_Log_Gen(const char *file, const char *func, const int line, const int level, const char *fmt, ...) { - if (level > g_log_print_level && level > g_log_upload_level) { - return; - } + if (level > g_log_print_level && level > g_log_upload_level) { + return; + } /* format log content */ - const char *file_name = _get_filename(file); + const char *file_name = _get_filename(file); - char sg_text_buf[MAX_LOG_MSG_LEN + 1]; - char *tmp_buf = sg_text_buf; - char *o = tmp_buf; + char sg_text_buf[MAX_LOG_MSG_LEN + 1]; + char *tmp_buf = sg_text_buf; + char *o = tmp_buf; memset(tmp_buf, 0, sizeof(sg_text_buf)); + char time_str[TIME_FORMAT_STR_LEN] = {0}; - o += HAL_Snprintf(o, sizeof(sg_text_buf), "%s|%s|%s|%s(%d): ", level_str[level], HAL_Timer_current(), file_name, func, line); + o += HAL_Snprintf(o, sizeof(sg_text_buf), "%s|%s|%s|%s(%d): ", level_str[level], HAL_Timer_current(time_str), + file_name, func, line); - va_list ap; + va_list ap; va_start(ap, fmt); - o += vsnprintf(o, MAX_LOG_MSG_LEN - 2 - strlen(tmp_buf), fmt, ap); + HAL_Vsnprintf(o, MAX_LOG_MSG_LEN - 2 - strlen(tmp_buf), fmt, ap); va_end(ap); strcat(tmp_buf, "\r\n"); @@ -124,9 +138,9 @@ void Log_writter(const char *file, const char *func, const int line, const int l if (level <= g_log_print_level) { /* customer defined log print handler */ - if (sg_log_message_handler != NULL && sg_log_message_handler(tmp_buf)) { - return; - } + if (sg_log_message_handler != NULL && sg_log_message_handler(tmp_buf)) { + return; + } /* default log handler: print to console */ HAL_Printf("%s", tmp_buf); diff --git a/sdk_src/utils/string_utils.c b/sdk_src/utils/string_utils.c new file mode 100644 index 00000000..a85e79c2 --- /dev/null +++ b/sdk_src/utils/string_utils.c @@ -0,0 +1,136 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "lite-utils.h" +#include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" + +char *LITE_format_string(const char *fmt, ...) +{ +#define TEMP_STRING_MAXLEN (512) + + va_list ap; + char * tmp = NULL; + char * dst; + int rc = -1; + + va_start(ap, fmt); + tmp = HAL_Malloc(TEMP_STRING_MAXLEN); + memset(tmp, 0, TEMP_STRING_MAXLEN); + rc = HAL_Vsnprintf(tmp, TEMP_STRING_MAXLEN, fmt, ap); + va_end(ap); + LITE_ASSERT(tmp); + LITE_ASSERT(rc < 1024); + + dst = LITE_strdup(tmp); + HAL_Free(tmp); + + return dst; + +#undef TEMP_STRING_MAXLEN +} + +char *LITE_format_nstring(const int len, const char *fmt, ...) +{ + va_list ap; + char * tmp = NULL; + char * dst; + int rc = -1; + + va_start(ap, fmt); + tmp = HAL_Malloc(len + 2); + memset(tmp, 0, len + 2); + rc = HAL_Vsnprintf(tmp, len + 1, fmt, ap); + va_end(ap); + LITE_ASSERT(tmp); + LITE_ASSERT(rc < 1024); + + dst = HAL_Malloc(len + 1); + HAL_Snprintf(dst, (len + 1), "%s", tmp); + HAL_Free(tmp); + + return dst; +} + +char *LITE_strdup(const char *src) +{ + int len = 0; + char *dst = NULL; + + if (!src) { + return NULL; + } + len = strlen(src) + 1; + if (len > 1024) { + Log_e("Too long string to duplicate, abort! len = %d", len); + return NULL; + } + + dst = (char *)HAL_Malloc(sizeof(char) * len); + if (!dst) { + return NULL; + } + strncpy(dst, src, len); + + return dst; +} + +void LITE_hexbuf_convert(unsigned char *digest, char *out, int in_len, int uppercase) +{ + static char *zEncode[] = {"0123456789abcdef", "0123456789ABCDEF"}; + int j = 0; + int i = 0; + int idx = uppercase ? 1 : 0; + + for (i = 0; i < in_len; i++) { + int a = digest[i]; + + out[j++] = zEncode[idx][(a >> 4) & 0xf]; + out[j++] = zEncode[idx][a & 0xf]; + } +} + +static uint8_t _hexval_of_char(char hex) +{ + if (LITE_isdigit(hex)) { + return (hex - '0'); + } + if (hex >= 'a' && hex <= 'f') { + return (hex - 'a' + 10); + } + if (hex >= 'A' && hex <= 'F') { + return (hex - 'A' + 10); + } + + return 0; +} + +void LITE_hexstr_convert(char *hexstr, uint8_t *out_buf, int in_len) +{ + int i = 0; + uint8_t ch0, ch1; + + if (in_len % 2 != 0) { + Log_e("hexstr length (%d) is not even", in_len); + return; + } + + while (i < (in_len / 2)) { + ch0 = _hexval_of_char((char)hexstr[2 * i]); + ch1 = _hexval_of_char((char)hexstr[2 * i + 1]); + out_buf[i] = (ch0 << 4 | ch1); + i++; + } +} diff --git a/sdk_src/utils/utils_aes.c b/sdk_src/utils/utils_aes.c new file mode 100755 index 00000000..2226b179 --- /dev/null +++ b/sdk_src/utils/utils_aes.c @@ -0,0 +1,1326 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif +#include "utils_aes.h" + +#include +#include + +#include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" + +#if defined(UTILS_AES_C) + +#include + +#if defined(UTILS_SELF_TEST) +#include +#define utils_printf Log_d +#endif /* UTILS_SELF_TEST */ + +//====================================// +#if !defined(UTILS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for utils_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * utils_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option UTILS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * utils_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void *(*const volatile memset_func)(void *, int, size_t) = memset; + +void utils_platform_zeroize(void *buf, size_t len) +{ + memset_func(buf, 0, len); +} +#endif /* UTILS_PLATFORM_ZEROIZE_ALT */ + +//====================================// + +#if !defined(UTILS_AES_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET(cond) UTILS_INTERNAL_VALIDATE_RET(cond, UTILS_ERR_AES_BAD_INPUT_DATA) +#define AES_VALIDATE(cond) UTILS_INTERNAL_VALIDATE(cond) + +/* + * 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(UTILS_PADLOCK_C) && (defined(UTILS_HAVE_X86) || defined(UTILS_PADLOCK_ALIGN16)) +static int aes_padlock_ace = -1; +#endif + +#if defined(UTILS_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 + +#if !defined(UTILS_AES_FEWER_TABLES) + +#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 + +#endif /* !UTILS_AES_FEWER_TABLES */ + +#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 + +#if !defined(UTILS_AES_FEWER_TABLES) + +#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 + +#endif /* !UTILS_AES_FEWER_TABLES */ + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = {0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, + 0x00000020, 0x00000040, 0x00000080, 0x0000001B, 0x00000036}; + +#else /* UTILS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +#if !defined(UTILS_AES_FEWER_TABLES) +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; +#endif /* !UTILS_AES_FEWER_TABLES */ + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +#if !defined(UTILS_AES_FEWER_TABLES) +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; +#endif /* !UTILS_AES_FEWER_TABLES */ + +/* + * 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); + +#if !defined(UTILS_AES_FEWER_TABLES) + FT1[i] = ROTL8(FT0[i]); + FT2[i] = ROTL8(FT1[i]); + FT3[i] = ROTL8(FT2[i]); +#endif /* !UTILS_AES_FEWER_TABLES */ + + 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); + +#if !defined(UTILS_AES_FEWER_TABLES) + RT1[i] = ROTL8(RT0[i]); + RT2[i] = ROTL8(RT1[i]); + RT3[i] = ROTL8(RT2[i]); +#endif /* !UTILS_AES_FEWER_TABLES */ + } +} + +#undef ROTL8 + +#endif /* UTILS_AES_ROM_TABLES */ + +#if defined(UTILS_AES_FEWER_TABLES) + +#define ROTL8(x) ((uint32_t)((x) << 8) + (uint32_t)((x) >> 24)) +#define ROTL16(x) ((uint32_t)((x) << 16) + (uint32_t)((x) >> 16)) +#define ROTL24(x) ((uint32_t)((x) << 24) + (uint32_t)((x) >> 8)) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8(RT0[idx]) +#define AES_RT2(idx) ROTL16(RT0[idx]) +#define AES_RT3(idx) ROTL24(RT0[idx]) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8(FT0[idx]) +#define AES_FT2(idx) ROTL16(FT0[idx]) +#define AES_FT3(idx) ROTL24(FT0[idx]) + +#else /* UTILS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* UTILS_AES_FEWER_TABLES */ + +void utils_aes_init(utils_aes_context *ctx) +{ + AES_VALIDATE(ctx != NULL); + + memset(ctx, 0, sizeof(utils_aes_context)); +} + +void utils_aes_free(utils_aes_context *ctx) +{ + if (ctx == NULL) + return; + + utils_platform_zeroize(ctx, sizeof(utils_aes_context)); +} + +/* + * AES key schedule (encryption) + */ +#if !defined(UTILS_AES_SETKEY_ENC_ALT) +int utils_aes_setkey_enc(utils_aes_context *ctx, const unsigned char *key, unsigned int keybits) +{ + unsigned int i; + uint32_t * RK; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + switch (keybits) { + case 128: + ctx->nr = 10; + break; + case 192: + ctx->nr = 12; + break; + case 256: + ctx->nr = 14; + break; + default: + return (UTILS_ERR_AES_INVALID_KEY_LENGTH); + } + +#if !defined(UTILS_AES_ROM_TABLES) + if (aes_init_done == 0) { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + + ctx->rk = RK = ctx->buf; + + 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 /* !UTILS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(UTILS_AES_SETKEY_DEC_ALT) +int utils_aes_setkey_dec(utils_aes_context *ctx, const unsigned char *key, unsigned int keybits) +{ + int i, j, ret; + utils_aes_context cty; + uint32_t * RK; + uint32_t * SK; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + utils_aes_init(&cty); + + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if ((ret = utils_aes_setkey_enc(&cty, key, keybits)) != 0) + goto exit; + + ctx->nr = cty.nr; + + 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++ = AES_RT0(FSb[(*SK) & 0xFF]) ^ AES_RT1(FSb[(*SK >> 8) & 0xFF]) ^ AES_RT2(FSb[(*SK >> 16) & 0xFF]) ^ + AES_RT3(FSb[(*SK >> 24) & 0xFF]); + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + utils_aes_free(&cty); + + return (ret); +} + +#endif /* !UTILS_AES_SETKEY_DEC_ALT */ + +#define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \ + { \ + X0 = *RK++ ^ AES_FT0((Y0)&0xFF) ^ AES_FT1((Y1 >> 8) & 0xFF) ^ AES_FT2((Y2 >> 16) & 0xFF) ^ \ + AES_FT3((Y3 >> 24) & 0xFF); \ + \ + X1 = *RK++ ^ AES_FT0((Y1)&0xFF) ^ AES_FT1((Y2 >> 8) & 0xFF) ^ AES_FT2((Y3 >> 16) & 0xFF) ^ \ + AES_FT3((Y0 >> 24) & 0xFF); \ + \ + X2 = *RK++ ^ AES_FT0((Y2)&0xFF) ^ AES_FT1((Y3 >> 8) & 0xFF) ^ AES_FT2((Y0 >> 16) & 0xFF) ^ \ + AES_FT3((Y1 >> 24) & 0xFF); \ + \ + X3 = *RK++ ^ AES_FT0((Y3)&0xFF) ^ AES_FT1((Y0 >> 8) & 0xFF) ^ AES_FT2((Y1 >> 16) & 0xFF) ^ \ + AES_FT3((Y2 >> 24) & 0xFF); \ + } + +#define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \ + { \ + X0 = *RK++ ^ AES_RT0((Y0)&0xFF) ^ AES_RT1((Y3 >> 8) & 0xFF) ^ AES_RT2((Y2 >> 16) & 0xFF) ^ \ + AES_RT3((Y1 >> 24) & 0xFF); \ + \ + X1 = *RK++ ^ AES_RT0((Y1)&0xFF) ^ AES_RT1((Y0 >> 8) & 0xFF) ^ AES_RT2((Y3 >> 16) & 0xFF) ^ \ + AES_RT3((Y2 >> 24) & 0xFF); \ + \ + X2 = *RK++ ^ AES_RT0((Y2)&0xFF) ^ AES_RT1((Y1 >> 8) & 0xFF) ^ AES_RT2((Y0 >> 16) & 0xFF) ^ \ + AES_RT3((Y3 >> 24) & 0xFF); \ + \ + X3 = *RK++ ^ AES_RT0((Y3)&0xFF) ^ AES_RT1((Y2 >> 8) & 0xFF) ^ AES_RT2((Y1 >> 16) & 0xFF) ^ \ + AES_RT3((Y0 >> 24) & 0xFF); \ + } + +/* + * AES-ECB block encryption + */ +#if !defined(UTILS_AES_ENCRYPT_ALT) +int utils_internal_aes_encrypt(utils_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 /* !UTILS_AES_ENCRYPT_ALT */ + +#if !defined(UTILS_DEPRECATED_REMOVED) +void utils_aes_encrypt(utils_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) +{ + utils_internal_aes_encrypt(ctx, input, output); +} +#endif /* !UTILS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block decryption + */ +#if !defined(UTILS_AES_DECRYPT_ALT) +int utils_internal_aes_decrypt(utils_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 /* !UTILS_AES_DECRYPT_ALT */ + +#if !defined(UTILS_DEPRECATED_REMOVED) +void utils_aes_decrypt(utils_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) +{ + utils_internal_aes_decrypt(ctx, input, output); +} +#endif /* !UTILS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block encryption/decryption + */ +int utils_aes_crypt_ecb(utils_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) +{ + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + AES_VALIDATE_RET(mode == UTILS_AES_ENCRYPT || mode == UTILS_AES_DECRYPT); + + if (mode == UTILS_AES_ENCRYPT) + return (utils_internal_aes_encrypt(ctx, input, output)); + else + return (utils_internal_aes_decrypt(ctx, input, output)); +} + +#if defined(UTILS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int utils_aes_crypt_cbc(utils_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]; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == UTILS_AES_ENCRYPT || mode == UTILS_AES_DECRYPT); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + if (length % 16) + return (UTILS_ERR_AES_INVALID_INPUT_LENGTH); + + if (mode == UTILS_AES_DECRYPT) { + while (length > 0) { + memcpy(temp, input, 16); + utils_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]); + + utils_aes_crypt_ecb(ctx, mode, output, output); + memcpy(iv, output, 16); + + input += 16; + output += 16; + length -= 16; + } + } + + return (0); +} + +int utils_aes_cbc(uint8_t *pInData, uint32_t datalen, uint8_t *pOutData, uint32_t outBuffLen, uint8_t mode, + uint8_t *pKey, uint16_t keybits, uint8_t *iv) +{ + int ret = QCLOUD_RET_SUCCESS; + int padlen; + utils_aes_context ctx; + + utils_aes_init(&ctx); + + if (UTILS_AES_ENCRYPT == mode) { + ret = utils_aes_setkey_enc(&ctx, pKey, keybits); + if (ret != 0) { + Log_e("Set encry key err,ret:%d", ret); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + + /*zero padding*/ + if (outBuffLen < (datalen + UTILS_AES_BLOCK_LEN)) { + Log_e("Output buffer should not less than datalen+UTILS_AES_BLOCK_LEN for padding"); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + padlen = UTILS_AES_BLOCK_LEN - datalen % UTILS_AES_BLOCK_LEN; + memcpy(pOutData, pInData, datalen); + memset(pOutData + datalen, '\0', padlen); /*zero-padding*/ + datalen += padlen; + } else { + ret = utils_aes_setkey_dec(&ctx, pKey, keybits); + if (ret != 0) { + Log_e("Set dencry key err,ret:%d", ret); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } + } + + ret = utils_aes_crypt_cbc(&ctx, mode, datalen, iv, pInData, pOutData); + if (ret != 0) { + Log_e("encryt err,ret:%d", ret); + ret = QCLOUD_ERR_FAILURE; + goto exit; + } else { + ret = QCLOUD_RET_SUCCESS; + } + +exit: + + return ret; +} +#endif /* UTILS_CIPHER_MODE_CBC */ + +#endif /* !UTILS_AES_ALT */ + +#if defined(UTILS_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(UTILS_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 /* UTILS_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int utils_aes_self_test(int verbose) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#if defined(UTILS_CIPHER_MODE_CBC) || defined(UTILS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(UTILS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(UTILS_CIPHER_MODE_CTR) || defined(UTILS_CIPHER_MODE_CFB) || defined(UTILS_CIPHER_MODE_OFB) + size_t offset; +#endif +#if defined(UTILS_CIPHER_MODE_CTR) || defined(UTILS_CIPHER_MODE_XTS) + int len; +#endif +#if defined(UTILS_CIPHER_MODE_CTR) + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + utils_aes_context ctx; + + memset(key, 0, 32); + utils_aes_init(&ctx); + + /* + * ECB mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if (verbose != 0) + utils_printf(" AES-ECB-%3d (%s): ", keybits, (mode == UTILS_AES_DECRYPT) ? "dec" : "enc"); + + memset(buf, 0, 16); + + if (mode == UTILS_AES_DECRYPT) { + ret = utils_aes_setkey_dec(&ctx, key, keybits); + aes_tests = aes_test_ecb_dec[u]; + } else { + ret = utils_aes_setkey_enc(&ctx, key, keybits); + aes_tests = aes_test_ecb_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * UTILS_AES_ALT is defined. + */ + if (ret == UTILS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + utils_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + for (j = 0; j < 10000; j++) { + ret = utils_aes_crypt_ecb(&ctx, mode, buf, buf); + if (ret != 0) + goto exit; + } + + if (memcmp(buf, aes_tests, 16) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) + utils_printf("passed\n"); + } + + if (verbose != 0) + utils_printf("\n"); + +#if defined(UTILS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if (verbose != 0) + utils_printf(" AES-CBC-%3d (%s): ", keybits, (mode == UTILS_AES_DECRYPT) ? "dec" : "enc"); + + memset(iv, 0, 16); + memset(prv, 0, 16); + memset(buf, 0, 16); + + if (mode == UTILS_AES_DECRYPT) { + ret = utils_aes_setkey_dec(&ctx, key, keybits); + aes_tests = aes_test_cbc_dec[u]; + } else { + ret = utils_aes_setkey_enc(&ctx, key, keybits); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * UTILS_AES_ALT is defined. + */ + if (ret == UTILS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + utils_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + for (j = 0; j < 10000; j++) { + if (mode == UTILS_AES_ENCRYPT) { + unsigned char tmp[16]; + + memcpy(tmp, prv, 16); + memcpy(prv, buf, 16); + memcpy(buf, tmp, 16); + } + + ret = utils_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf); + if (ret != 0) + goto exit; + } + + if (memcmp(buf, aes_tests, 16) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) + utils_printf("passed\n"); + } + + if (verbose != 0) + utils_printf("\n"); +#endif /* UTILS_CIPHER_MODE_CBC */ + +#if defined(UTILS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if (verbose != 0) + utils_printf(" AES-CFB128-%3d (%s): ", keybits, (mode == UTILS_AES_DECRYPT) ? "dec" : "enc"); + + memcpy(iv, aes_test_cfb128_iv, 16); + memcpy(key, aes_test_cfb128_key[u], keybits / 8); + + offset = 0; + ret = utils_aes_setkey_enc(&ctx, key, keybits); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * UTILS_AES_ALT is defined. + */ + if (ret == UTILS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + utils_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + if (mode == UTILS_AES_DECRYPT) { + memcpy(buf, aes_test_cfb128_ct[u], 64); + aes_tests = aes_test_cfb128_pt; + } else { + memcpy(buf, aes_test_cfb128_pt, 64); + aes_tests = aes_test_cfb128_ct[u]; + } + + ret = utils_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf); + if (ret != 0) + goto exit; + + if (memcmp(buf, aes_tests, 64) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) + utils_printf("passed\n"); + } + + if (verbose != 0) + utils_printf("\n"); +#endif /* UTILS_CIPHER_MODE_CFB */ + +#if defined(UTILS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if (verbose != 0) + utils_printf(" AES-OFB-%3d (%s): ", keybits, (mode == UTILS_AES_DECRYPT) ? "dec" : "enc"); + + memcpy(iv, aes_test_ofb_iv, 16); + memcpy(key, aes_test_ofb_key[u], keybits / 8); + + offset = 0; + ret = utils_aes_setkey_enc(&ctx, key, keybits); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * UTILS_AES_ALT is defined. + */ + if (ret == UTILS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + utils_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + if (mode == UTILS_AES_DECRYPT) { + memcpy(buf, aes_test_ofb_ct[u], 64); + aes_tests = aes_test_ofb_pt; + } else { + memcpy(buf, aes_test_ofb_pt, 64); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = utils_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf); + if (ret != 0) + goto exit; + + if (memcmp(buf, aes_tests, 64) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) + utils_printf("passed\n"); + } + + if (verbose != 0) + utils_printf("\n"); +#endif /* UTILS_CIPHER_MODE_OFB */ + +#if defined(UTILS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + mode = i & 1; + + if (verbose != 0) + utils_printf(" AES-CTR-128 (%s): ", (mode == UTILS_AES_DECRYPT) ? "dec" : "enc"); + + memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16); + memcpy(key, aes_test_ctr_key[u], 16); + + offset = 0; + if ((ret = utils_aes_setkey_enc(&ctx, key, 128)) != 0) + goto exit; + + len = aes_test_ctr_len[u]; + + if (mode == UTILS_AES_DECRYPT) { + memcpy(buf, aes_test_ctr_ct[u], len); + aes_tests = aes_test_ctr_pt[u]; + } else { + memcpy(buf, aes_test_ctr_pt[u], len); + aes_tests = aes_test_ctr_ct[u]; + } + + ret = utils_aes_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block, buf, buf); + if (ret != 0) + goto exit; + + if (memcmp(buf, aes_tests, len) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) + utils_printf("passed\n"); + } + + if (verbose != 0) + utils_printf("\n"); +#endif /* UTILS_CIPHER_MODE_CTR */ + +#if defined(UTILS_CIPHER_MODE_XTS) + { + static const int num_tests = sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + utils_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + utils_aes_xts_init(&ctx_xts); + + for (i = 0; i < num_tests << 1; i++) { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if (verbose != 0) + utils_printf(" AES-XTS-128 (%s): ", (mode == UTILS_AES_DECRYPT) ? "dec" : "enc"); + + memset(key, 0, sizeof(key)); + memcpy(key, aes_test_xts_key[u], 32); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof(*aes_test_xts_ct32); + + if (mode == UTILS_AES_DECRYPT) { + ret = utils_aes_xts_setkey_dec(&ctx_xts, key, 256); + if (ret != 0) + goto exit; + memcpy(buf, aes_test_xts_ct32[u], len); + aes_tests = aes_test_xts_pt32[u]; + } else { + ret = utils_aes_xts_setkey_enc(&ctx_xts, key, 256); + if (ret != 0) + goto exit; + memcpy(buf, aes_test_xts_pt32[u], len); + aes_tests = aes_test_xts_ct32[u]; + } + + ret = utils_aes_crypt_xts(&ctx_xts, mode, len, data_unit, buf, buf); + if (ret != 0) + goto exit; + + if (memcmp(buf, aes_tests, len) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) + utils_printf("passed\n"); + } + + if (verbose != 0) + utils_printf("\n"); + + utils_aes_xts_free(&ctx_xts); + } +#endif /* UTILS_CIPHER_MODE_XTS */ + + ret = 0; + +exit: + if (ret != 0 && verbose != 0) + utils_printf("failed\n"); + + utils_aes_free(&ctx); + + return (ret); +} + +/*aes128-cbc*/ +int aes_sample(int verbose) +{ + int ret = 0, i; + unsigned int keybits; + unsigned char key[UTILS_AES_BLOCK_LEN] = "1234567890abcdef"; + char dataIn[1024] = {0}; + unsigned char iv[16]; + int sLen; + int datalen; + + utils_printf("\nAES-CBC-128 enc "); + keybits = AES_KEY_BITS_128; + memset(iv, '0', 16); + + sLen = strlen("{\"code\":0,\"message\":\"success\",\"encryptionType\":1,\"psk\":\"VI04Eh4N8VgM29U/dnu9cQ==\"}"); + strncpy(dataIn, "{\"code\":0,\"message\":\"success\",\"encryptionType\":1,\"psk\":\"VI04Eh4N8VgM29U/dnu9cQ==\"}", + sLen); + + utils_printf("\nthe data to encrypt(%d):\n", sLen); + for (i = 0; i < sLen; i++) { + HAL_Printf("%02x ", (uint8_t)dataIn[i]); + } + + if (QCLOUD_RET_SUCCESS == utils_aes_cbc((uint8_t *)dataIn, sLen, (uint8_t *)dataIn, sLen + UTILS_AES_BLOCK_LEN, + UTILS_AES_ENCRYPT, key, keybits, iv)) { + utils_printf("\nThe encrypted data is:\n"); + for (i = 0; i < sLen; i++) { + HAL_Printf("%02x ", (uint8_t)dataIn[i]); + } + } + + datalen = sLen + (UTILS_AES_BLOCK_LEN - sLen % UTILS_AES_BLOCK_LEN); + keybits = AES_KEY_BITS_128; + memset(iv, '0', UTILS_AES_BLOCK_LEN); + if (QCLOUD_RET_SUCCESS == + utils_aes_cbc((uint8_t *)dataIn, datalen, (uint8_t *)dataIn, datalen, UTILS_AES_DECRYPT, key, keybits, iv)) { + utils_printf("\nThe decrypted data is:\n"); + for (i = 0; i < datalen; i++) { + // HAL_Printf("%02x ", (uint8_t)dataIn[i]); + if (dataIn[i] == '\0') { + Log_d("payload len:%d", i); + break; + } + HAL_Printf("%c", dataIn[i]); + } + } + + if (ret != 0 && verbose != 0) + utils_printf("failed\n"); + + return (ret); +} + +#endif /* UTILS_SELF_TEST */ + +#endif /* UTILS_AES_C */ + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/utils/utils_base64.c b/sdk_src/utils/utils_base64.c new file mode 100755 index 00000000..75a36a4c --- /dev/null +++ b/sdk_src/utils/utils_base64.c @@ -0,0 +1,178 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "utils_base64.h" + +#include +#include + +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 */ + +int qcloud_iot_utils_base64encode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen) +{ + size_t i, n; + 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 (QCLOUD_ERR_FAILURE); + } + + n *= 4; + + if ((dlen < n + 1) || (NULL == dst)) { + *olen = n + 1; + return (QCLOUD_ERR_FAILURE); + } + + n = (slen / 3) * 3; + + int C1, C2, C3; + 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); +} + +int qcloud_iot_utils_base64decode(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 (QCLOUD_ERR_FAILURE); + + if (src[i] == '=' && ++j > 2) + return (QCLOUD_ERR_FAILURE); + + if (src[i] > 127 || base64_dec_map[src[i]] == 127) + return (QCLOUD_ERR_FAILURE); + + if (base64_dec_map[src[i]] < 64 && j != 0) + return (QCLOUD_ERR_FAILURE); + + n++; + } + + if (n == 0) { + *olen = 0; + return (0); + } + + n = ((n * 6) + 7) >> 3; + n -= j; + + if (dst == NULL || dlen < n) { + *olen = n; + return (QCLOUD_ERR_FAILURE); + } + + 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); +} + +#ifdef __cplusplus +} +#endif diff --git a/sdk_src/utils/utils_getopt.c b/sdk_src/utils/utils_getopt.c new file mode 100755 index 00000000..7f575134 --- /dev/null +++ b/sdk_src/utils/utils_getopt.c @@ -0,0 +1,95 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "utils_getopt.h" + +#include +#include + +#include "qcloud_iot_import.h" + +static int utils_opterr = 1; /* if error message should be printed */ +static int utils_optind = 1; /* index into parent argv vector */ +static int utils_optopt; /* character checked for validity */ +static int utils_optreset = 1; /* reset getopt */ + +char* utils_optarg; /* argument associated with option */ + +int utils_getopt(int nargc, char* const* nargv, const char* options) +{ +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + + static char* place = EMSG; /* option letter processing */ + const char* oli; /* option letter list index */ + + if (utils_optreset || !*place) { /* update scanning pointer */ + utils_optreset = 0; + + if (utils_optind >= nargc || *(place = nargv[utils_optind]) != '-') { + utils_optind = 1; + utils_optreset = 1; + place = EMSG; + return (-1); + } + + place++; + } + + /* option letter okay? */ + if ((utils_optopt = (int)*place++) == (int)':' || !(oli = strchr(options, utils_optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (utils_optopt == (int)'-') + return (-1); + + if (!*place) + ++utils_optind; + + if (utils_opterr && *options != ':') + HAL_Printf("illegal option - %c\n", utils_optopt); + + return (BADCH); + } + + if (*++oli != ':') { /* don't need argument */ + utils_optarg = NULL; + if (!*place) + ++utils_optind; + } else { + /* need an argument */ + if (*place) { /* no white space */ + utils_optarg = place; + } else if (nargc <= ++utils_optind) { /* no arg */ + place = EMSG; + if (*options == ':') + return (BADARG); + if (utils_opterr) + HAL_Printf("option requires an argument - %c\n", utils_optopt); + return (BADCH); + } else { /* white space */ + utils_optarg = nargv[utils_optind]; + } + + place = EMSG; + ++utils_optind; + } + + /* dump back option letter */ + return (utils_optopt); +} diff --git a/sdk_src/utils/utils_hmac.c b/sdk_src/utils/utils_hmac.c new file mode 100644 index 00000000..d5a4107f --- /dev/null +++ b/sdk_src/utils/utils_hmac.c @@ -0,0 +1,176 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "utils_hmac.h" + +#include + +#include "qcloud_iot_export_log.h" +#include "utils_md5.h" +#include "utils_sha1.h" + +#define KEY_IOPAD_SIZE 64 + +#define MD5_DIGEST_SIZE 16 +#define SHA1_DIGEST_SIZE 20 + +void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len) +{ + if ((NULL == msg) || (NULL == digest) || (NULL == key)) { + Log_e("parameter is Null,failed!"); + return; + } + + if (key_len > KEY_IOPAD_SIZE) { + Log_e("key_len > size(%d) of array", KEY_IOPAD_SIZE); + return; + } + + iot_md5_context context; + unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ + unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ + unsigned char out[MD5_DIGEST_SIZE]; + int i; + + /* start out by storing key in pads */ + memset(k_ipad, 0, sizeof(k_ipad)); + memset(k_opad, 0, sizeof(k_opad)); + memcpy(k_ipad, key, key_len); + memcpy(k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < KEY_IOPAD_SIZE; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner MD5 */ + utils_md5_init(&context); /* init context for 1st pass */ + utils_md5_starts(&context); /* setup context for 1st pass */ + utils_md5_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */ + utils_md5_update(&context, (unsigned char *)msg, msg_len); /* then text of datagram */ + utils_md5_finish(&context, out); /* finish up 1st pass */ + + /* perform outer MD5 */ + utils_md5_init(&context); /* init context for 2nd pass */ + utils_md5_starts(&context); /* setup context for 2nd pass */ + utils_md5_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */ + utils_md5_update(&context, out, MD5_DIGEST_SIZE); /* then results of 1st hash */ + utils_md5_finish(&context, out); /* finish up 2nd pass */ + + for (i = 0; i < MD5_DIGEST_SIZE; ++i) { + digest[i * 2] = utils_hb2hex(out[i] >> 4); + digest[i * 2 + 1] = utils_hb2hex(out[i]); + } +} + +void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len) +{ + if ((NULL == msg) || (NULL == digest) || (NULL == key)) { + Log_e("parameter is Null,failed!"); + return; + } + + if (key_len > KEY_IOPAD_SIZE) { + Log_e("key_len > size(%d) of array", KEY_IOPAD_SIZE); + return; + } + + iot_sha1_context context; + unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ + unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ + unsigned char out[SHA1_DIGEST_SIZE]; + int i; + + /* start out by storing key in pads */ + memset(k_ipad, 0, sizeof(k_ipad)); + memset(k_opad, 0, sizeof(k_opad)); + memcpy(k_ipad, key, key_len); + memcpy(k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < KEY_IOPAD_SIZE; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner SHA */ + utils_sha1_init(&context); /* init context for 1st pass */ + utils_sha1_starts(&context); /* setup context for 1st pass */ + utils_sha1_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */ + utils_sha1_update(&context, (unsigned char *)msg, msg_len); /* then text of datagram */ + utils_sha1_finish(&context, out); /* finish up 1st pass */ + + /* perform outer SHA */ + utils_sha1_init(&context); /* init context for 2nd pass */ + utils_sha1_starts(&context); /* setup context for 2nd pass */ + utils_sha1_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */ + utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */ + utils_sha1_finish(&context, out); /* finish up 2nd pass */ + + for (i = 0; i < SHA1_DIGEST_SIZE; ++i) { + digest[i * 2] = utils_hb2hex(out[i] >> 4); + digest[i * 2 + 1] = utils_hb2hex(out[i]); + } +} + +int utils_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len) +{ + if ((NULL == msg) || (NULL == digest) || (NULL == key)) { + Log_e("parameter is Null,failed!"); + return 0; + } + + if (key_len > KEY_IOPAD_SIZE) { + Log_e("key_len > size(%d) of array", KEY_IOPAD_SIZE); + return 0; + } + + iot_sha1_context context; + unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ + unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ + unsigned char out[SHA1_DIGEST_SIZE]; + int i; + + /* start out by storing key in pads */ + memset(k_ipad, 0, sizeof(k_ipad)); + memset(k_opad, 0, sizeof(k_opad)); + memcpy(k_ipad, key, key_len); + memcpy(k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < KEY_IOPAD_SIZE; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner SHA */ + utils_sha1_init(&context); /* init context for 1st pass */ + utils_sha1_starts(&context); /* setup context for 1st pass */ + utils_sha1_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */ + utils_sha1_update(&context, (unsigned char *)msg, msg_len); /* then text of datagram */ + utils_sha1_finish(&context, out); /* finish up 1st pass */ + + /* perform outer SHA */ + utils_sha1_init(&context); /* init context for 2nd pass */ + utils_sha1_starts(&context); /* setup context for 2nd pass */ + utils_sha1_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */ + utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */ + utils_sha1_finish(&context, out); /* finish up 2nd pass */ + + memcpy(digest, out, SHA1_DIGEST_SIZE); + + return SHA1_DIGEST_SIZE; +} diff --git a/src/utils/farra/utils_list.c b/sdk_src/utils/utils_list.c old mode 100644 new mode 100755 similarity index 77% rename from src/utils/farra/utils_list.c rename to sdk_src/utils/utils_list.c index 2fbf24c7..0cd0ac1b --- a/src/utils/farra/utils_list.c +++ b/sdk_src/utils/utils_list.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,18 +13,17 @@ * */ - #ifdef __cplusplus extern "C" { #endif #include "utils_list.h" -#include "qcloud_iot_import.h" #include "qcloud_iot_export_log.h" +#include "qcloud_iot_import.h" - /* - * 创建List. 失败则返回NULL. +/* + * create list, return NULL if fail */ List *list_new(void) { @@ -33,22 +32,22 @@ List *list_new(void) if (!self) { return NULL; } - self->head = NULL; - self->tail = NULL; - self->free = NULL; + self->head = NULL; + self->tail = NULL; + self->free = NULL; self->match = NULL; - self->len = 0; + self->len = 0; return self; } /* - * 失败List的内存. + * destroy list */ void list_destroy(List *self) { unsigned int len = self->len; - ListNode *next; - ListNode *curr = self->head; + ListNode * next; + ListNode * curr = self->head; while (len--) { next = curr->next; @@ -63,7 +62,7 @@ void list_destroy(List *self) } /* - * 将给定节点附加到列表并返回该节点,在失败时返回NULL. + * push the node to list tail, return NULL if node invalid */ ListNode *list_rpush(List *self, ListNode *node) { @@ -72,10 +71,10 @@ ListNode *list_rpush(List *self, ListNode *node) } if (self->len) { - node->prev = self->tail; - node->next = NULL; + node->prev = self->tail; + node->next = NULL; self->tail->next = node; - self->tail = node; + self->tail = node; } else { self->head = self->tail = node; node->prev = node->next = NULL; @@ -86,7 +85,7 @@ ListNode *list_rpush(List *self, ListNode *node) } /* - * 弹出列表中的最后一个节点, 失败返回NULL. + * pop the node from list tail, return NULL if list empty */ ListNode *list_rpop(List *self) { @@ -108,7 +107,7 @@ ListNode *list_rpop(List *self) } /* - * 弹出列表中的首个节点, 失败返回NULL. + * pop the node from list headl, return NULL if list empty */ ListNode *list_lpop(List *self) { @@ -130,7 +129,7 @@ ListNode *list_lpop(List *self) } /* - * 预先将给定的节点添加到列表中,并返回该节点,在失败时返回NULL. + * push the node to list head, return NULL if node invalid */ ListNode *list_lpush(List *self, ListNode *node) { @@ -139,10 +138,10 @@ ListNode *list_lpush(List *self, ListNode *node) } if (self->len) { - node->next = self->head; - node->prev = NULL; + node->next = self->head; + node->prev = NULL; self->head->prev = node; - self->head = node; + self->head = node; } else { self->head = self->tail = node; node->prev = node->next = NULL; @@ -153,12 +152,12 @@ ListNode *list_lpush(List *self, ListNode *node) } /* - * 根据val返回对应的节点,没有则返回NULL. + * find the node via node value, return NULL if not found */ ListNode *list_find(List *self, void *val) { ListIterator *it; - ListNode *node; + ListNode * node; if (NULL == (it = list_iterator_new(self, LIST_HEAD))) { return NULL; @@ -184,7 +183,7 @@ ListNode *list_find(List *self, void *val) } /* - * 根据index返回对应的节点,没有则返回NULL. + * find the node via list index, return NULL if not found */ ListNode *list_at(List *self, int index) { @@ -192,12 +191,12 @@ ListNode *list_at(List *self, int index) if (index < 0) { direction = LIST_TAIL; - index = ~index; + index = ~index; } - if ((unsigned) index < self->len) { + if ((unsigned)index < self->len) { ListIterator *it; - ListNode *node; + ListNode * node; if (NULL == (it = list_iterator_new(self, direction))) { return NULL; @@ -215,7 +214,7 @@ ListNode *list_at(List *self, int index) } /* - * 从列表中删除给定的节点,释放它和它的值. + * delete the node in list and release the resource */ void list_remove(List *self, ListNode *node) { @@ -228,11 +227,12 @@ void list_remove(List *self, ListNode *node) } HAL_Free(node); - --self->len; + if (self->len) + --self->len; } /* - * 创建一个新的ListIterator,失败返回NULL, 并且设置其ListDirection. + * create a new ListIterator and set the ListDirection. */ ListIterator *list_iterator_new(List *list, ListDirection direction) { @@ -241,7 +241,7 @@ ListIterator *list_iterator_new(List *list, ListDirection direction) } /* - * 创建一个新的ListIterator, 并设置初始节点. 失败则返回NULL. + * create a new ListIterator and set the ListDirection and node */ ListIterator *list_iterator_new_from_node(ListNode *node, ListDirection direction) { @@ -250,13 +250,13 @@ ListIterator *list_iterator_new_from_node(ListNode *node, ListDirection directio if (!self) { return NULL; } - self->next = node; + self->next = node; self->direction = direction; return self; } /* - * 返回下一个节点, 如果没有更多的节点则返回NULL. + * return next node */ ListNode *list_iterator_next(ListIterator *self) { @@ -268,16 +268,15 @@ ListNode *list_iterator_next(ListIterator *self) } /* - * 释放列表迭代器. + * release the ListIterator */ void list_iterator_destroy(ListIterator *self) { HAL_Free(self); - self = NULL; } /* - * 根据预设值来创建新节点, 失败则返回NULL. + * create a new node and set the value */ ListNode *list_node_new(void *val) { @@ -289,7 +288,7 @@ ListNode *list_node_new(void *val) self->prev = NULL; self->next = NULL; - self->val = val; + self->val = val; return self; } diff --git a/src/utils/digest/utils_md5.c b/sdk_src/utils/utils_md5.c old mode 100644 new mode 100755 similarity index 50% rename from src/utils/digest/utils_md5.c rename to sdk_src/utils/utils_md5.c index e9986ee5..0f763974 --- a/src/utils/digest/utils_md5.c +++ b/sdk_src/utils/utils_md5.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,22 +13,20 @@ * */ - #ifdef __cplusplus extern "C" { #endif - #include "utils_md5.h" #include #include -#include "qcloud_iot_import.h" + #include "qcloud_iot_export.h" +#include "qcloud_iot_import.h" #define MD5_DIGEST_SIZE 16 - /* Implementation that should never be optimized out by the compiler */ static void _utils_md5_zeroize(void *v, size_t n) { @@ -40,22 +38,20 @@ static void _utils_md5_zeroize(void *v, size_t n) * 32-bit integer manipulation macros (little endian) */ #ifndef IOT_MD5_GET_UINT32_LE -#define IOT_MD5_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 ); \ +#define IOT_MD5_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 IOT_MD5_PUT_UINT32_LE -#define IOT_MD5_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 ); \ +#define IOT_MD5_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 @@ -73,8 +69,7 @@ void utils_md5_free(iot_md5_context *ctx) _utils_md5_zeroize(ctx, sizeof(iot_md5_context)); } -void utils_md5_clone(iot_md5_context *dst, - const iot_md5_context *src) +void utils_md5_clone(iot_md5_context *dst, const iot_md5_context *src) { *dst = *src; } @@ -97,16 +92,16 @@ void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]) { uint32_t X[16], A, B, C, D; - IOT_MD5_GET_UINT32_LE(X[ 0], data, 0); - IOT_MD5_GET_UINT32_LE(X[ 1], data, 4); - IOT_MD5_GET_UINT32_LE(X[ 2], data, 8); - IOT_MD5_GET_UINT32_LE(X[ 3], data, 12); - IOT_MD5_GET_UINT32_LE(X[ 4], data, 16); - IOT_MD5_GET_UINT32_LE(X[ 5], data, 20); - IOT_MD5_GET_UINT32_LE(X[ 6], data, 24); - IOT_MD5_GET_UINT32_LE(X[ 7], data, 28); - IOT_MD5_GET_UINT32_LE(X[ 8], data, 32); - IOT_MD5_GET_UINT32_LE(X[ 9], data, 36); + IOT_MD5_GET_UINT32_LE(X[0], data, 0); + IOT_MD5_GET_UINT32_LE(X[1], data, 4); + IOT_MD5_GET_UINT32_LE(X[2], data, 8); + IOT_MD5_GET_UINT32_LE(X[3], data, 12); + IOT_MD5_GET_UINT32_LE(X[4], data, 16); + IOT_MD5_GET_UINT32_LE(X[5], data, 20); + IOT_MD5_GET_UINT32_LE(X[6], data, 24); + IOT_MD5_GET_UINT32_LE(X[7], data, 28); + IOT_MD5_GET_UINT32_LE(X[8], data, 32); + IOT_MD5_GET_UINT32_LE(X[9], data, 36); IOT_MD5_GET_UINT32_LE(X[10], data, 40); IOT_MD5_GET_UINT32_LE(X[11], data, 44); IOT_MD5_GET_UINT32_LE(X[12], data, 48); @@ -114,11 +109,12 @@ void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]) IOT_MD5_GET_UINT32_LE(X[14], data, 56); IOT_MD5_GET_UINT32_LE(X[15], data, 60); -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) +#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) -#define P(a,b,c,d,k,s,t) \ - { \ - a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +#define P(a, b, c, d, k, s, t) \ + { \ + a += F(b, c, d) + X[k] + t; \ + a = S(a, s) + b; \ } A = ctx->state[0]; @@ -126,87 +122,87 @@ void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]) C = ctx->state[2]; D = ctx->state[3]; -#define F(x,y,z) (z ^ (x & (y ^ z))) - - P(A, B, C, D, 0, 7, 0xD76AA478); - P(D, A, B, C, 1, 12, 0xE8C7B756); - P(C, D, A, B, 2, 17, 0x242070DB); - P(B, C, D, A, 3, 22, 0xC1BDCEEE); - P(A, B, C, D, 4, 7, 0xF57C0FAF); - P(D, A, B, C, 5, 12, 0x4787C62A); - P(C, D, A, B, 6, 17, 0xA8304613); - P(B, C, D, A, 7, 22, 0xFD469501); - P(A, B, C, D, 8, 7, 0x698098D8); - P(D, A, B, C, 9, 12, 0x8B44F7AF); +#define F(x, y, z) (z ^ (x & (y ^ z))) + + P(A, B, C, D, 0, 7, 0xD76AA478); + P(D, A, B, C, 1, 12, 0xE8C7B756); + P(C, D, A, B, 2, 17, 0x242070DB); + P(B, C, D, A, 3, 22, 0xC1BDCEEE); + P(A, B, C, D, 4, 7, 0xF57C0FAF); + P(D, A, B, C, 5, 12, 0x4787C62A); + P(C, D, A, B, 6, 17, 0xA8304613); + P(B, C, D, A, 7, 22, 0xFD469501); + P(A, B, C, D, 8, 7, 0x698098D8); + P(D, A, B, C, 9, 12, 0x8B44F7AF); P(C, D, A, B, 10, 17, 0xFFFF5BB1); P(B, C, D, A, 11, 22, 0x895CD7BE); - P(A, B, C, D, 12, 7, 0x6B901122); + P(A, B, C, D, 12, 7, 0x6B901122); P(D, A, B, C, 13, 12, 0xFD987193); P(C, D, A, B, 14, 17, 0xA679438E); P(B, C, D, A, 15, 22, 0x49B40821); #undef F -#define F(x,y,z) (y ^ (z & (x ^ y))) +#define F(x, y, z) (y ^ (z & (x ^ y))) - P(A, B, C, D, 1, 5, 0xF61E2562); - P(D, A, B, C, 6, 9, 0xC040B340); + P(A, B, C, D, 1, 5, 0xF61E2562); + P(D, A, B, C, 6, 9, 0xC040B340); P(C, D, A, B, 11, 14, 0x265E5A51); - P(B, C, D, A, 0, 20, 0xE9B6C7AA); - P(A, B, C, D, 5, 5, 0xD62F105D); - P(D, A, B, C, 10, 9, 0x02441453); + P(B, C, D, A, 0, 20, 0xE9B6C7AA); + P(A, B, C, D, 5, 5, 0xD62F105D); + P(D, A, B, C, 10, 9, 0x02441453); P(C, D, A, B, 15, 14, 0xD8A1E681); - P(B, C, D, A, 4, 20, 0xE7D3FBC8); - P(A, B, C, D, 9, 5, 0x21E1CDE6); - P(D, A, B, C, 14, 9, 0xC33707D6); - P(C, D, A, B, 3, 14, 0xF4D50D87); - P(B, C, D, A, 8, 20, 0x455A14ED); - P(A, B, C, D, 13, 5, 0xA9E3E905); - P(D, A, B, C, 2, 9, 0xFCEFA3F8); - P(C, D, A, B, 7, 14, 0x676F02D9); + P(B, C, D, A, 4, 20, 0xE7D3FBC8); + P(A, B, C, D, 9, 5, 0x21E1CDE6); + P(D, A, B, C, 14, 9, 0xC33707D6); + P(C, D, A, B, 3, 14, 0xF4D50D87); + P(B, C, D, A, 8, 20, 0x455A14ED); + P(A, B, C, D, 13, 5, 0xA9E3E905); + P(D, A, B, C, 2, 9, 0xFCEFA3F8); + P(C, D, A, B, 7, 14, 0x676F02D9); P(B, C, D, A, 12, 20, 0x8D2A4C8A); #undef F -#define F(x,y,z) (x ^ y ^ z) +#define F(x, y, z) (x ^ y ^ z) - P(A, B, C, D, 5, 4, 0xFFFA3942); - P(D, A, B, C, 8, 11, 0x8771F681); + P(A, B, C, D, 5, 4, 0xFFFA3942); + P(D, A, B, C, 8, 11, 0x8771F681); P(C, D, A, B, 11, 16, 0x6D9D6122); P(B, C, D, A, 14, 23, 0xFDE5380C); - P(A, B, C, D, 1, 4, 0xA4BEEA44); - P(D, A, B, C, 4, 11, 0x4BDECFA9); - P(C, D, A, B, 7, 16, 0xF6BB4B60); + P(A, B, C, D, 1, 4, 0xA4BEEA44); + P(D, A, B, C, 4, 11, 0x4BDECFA9); + P(C, D, A, B, 7, 16, 0xF6BB4B60); P(B, C, D, A, 10, 23, 0xBEBFBC70); - P(A, B, C, D, 13, 4, 0x289B7EC6); - P(D, A, B, C, 0, 11, 0xEAA127FA); - P(C, D, A, B, 3, 16, 0xD4EF3085); - P(B, C, D, A, 6, 23, 0x04881D05); - P(A, B, C, D, 9, 4, 0xD9D4D039); + P(A, B, C, D, 13, 4, 0x289B7EC6); + P(D, A, B, C, 0, 11, 0xEAA127FA); + P(C, D, A, B, 3, 16, 0xD4EF3085); + P(B, C, D, A, 6, 23, 0x04881D05); + P(A, B, C, D, 9, 4, 0xD9D4D039); P(D, A, B, C, 12, 11, 0xE6DB99E5); P(C, D, A, B, 15, 16, 0x1FA27CF8); - P(B, C, D, A, 2, 23, 0xC4AC5665); + P(B, C, D, A, 2, 23, 0xC4AC5665); #undef F -#define F(x,y,z) (y ^ (x | ~z)) +#define F(x, y, z) (y ^ (x | ~z)) - P(A, B, C, D, 0, 6, 0xF4292244); - P(D, A, B, C, 7, 10, 0x432AFF97); + P(A, B, C, D, 0, 6, 0xF4292244); + P(D, A, B, C, 7, 10, 0x432AFF97); P(C, D, A, B, 14, 15, 0xAB9423A7); - P(B, C, D, A, 5, 21, 0xFC93A039); - P(A, B, C, D, 12, 6, 0x655B59C3); - P(D, A, B, C, 3, 10, 0x8F0CCC92); + P(B, C, D, A, 5, 21, 0xFC93A039); + P(A, B, C, D, 12, 6, 0x655B59C3); + P(D, A, B, C, 3, 10, 0x8F0CCC92); P(C, D, A, B, 10, 15, 0xFFEFF47D); - P(B, C, D, A, 1, 21, 0x85845DD1); - P(A, B, C, D, 8, 6, 0x6FA87E4F); + P(B, C, D, A, 1, 21, 0x85845DD1); + P(A, B, C, D, 8, 6, 0x6FA87E4F); P(D, A, B, C, 15, 10, 0xFE2CE6E0); - P(C, D, A, B, 6, 15, 0xA3014314); + P(C, D, A, B, 6, 15, 0xA3014314); P(B, C, D, A, 13, 21, 0x4E0811A1); - P(A, B, C, D, 4, 6, 0xF7537E82); + P(A, B, C, D, 4, 6, 0xF7537E82); P(D, A, B, C, 11, 10, 0xBD3AF235); - P(C, D, A, B, 2, 15, 0x2AD7D2BB); - P(B, C, D, A, 9, 21, 0xEB86D391); + P(C, D, A, B, 2, 15, 0x2AD7D2BB); + P(B, C, D, A, 9, 21, 0xEB86D391); #undef F @@ -221,7 +217,7 @@ void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]) */ void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t ilen) { - size_t fill; + size_t fill; uint32_t left; if (ilen == 0) { @@ -231,10 +227,10 @@ void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t i left = ctx->total[0] & 0x3F; fill = 64 - left; - ctx->total[0] += (uint32_t) ilen; + ctx->total[0] += (uint32_t)ilen; ctx->total[0] &= 0xFFFFFFFF; - if (ctx->total[0] < (uint32_t) ilen) { + if (ctx->total[0] < (uint32_t)ilen) { ctx->total[1]++; } @@ -242,14 +238,14 @@ void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t i memcpy((void *)(ctx->buffer + left), input, fill); utils_md5_process(ctx, ctx->buffer); input += fill; - ilen -= fill; + ilen -= fill; left = 0; } while (ilen >= 64) { utils_md5_process(ctx, input); input += 64; - ilen -= 64; + ilen -= 64; } if (ilen > 0) { @@ -257,27 +253,23 @@ void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t i } } -static const unsigned char iot_md5_padding[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; +static const unsigned char iot_md5_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* * MD5 final digest */ void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]) { - uint32_t last, padn; - uint32_t high, low; + 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); + high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); - IOT_MD5_PUT_UINT32_LE(low, msglen, 0); + IOT_MD5_PUT_UINT32_LE(low, msglen, 0); IOT_MD5_PUT_UINT32_LE(high, msglen, 4); last = ctx->total[0] & 0x3F; @@ -286,13 +278,12 @@ void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]) utils_md5_update(ctx, iot_md5_padding, padn); utils_md5_update(ctx, msglen, 8); - IOT_MD5_PUT_UINT32_LE(ctx->state[0], output, 0); - IOT_MD5_PUT_UINT32_LE(ctx->state[1], output, 4); - IOT_MD5_PUT_UINT32_LE(ctx->state[2], output, 8); + IOT_MD5_PUT_UINT32_LE(ctx->state[0], output, 0); + IOT_MD5_PUT_UINT32_LE(ctx->state[1], output, 4); + IOT_MD5_PUT_UINT32_LE(ctx->state[2], output, 8); IOT_MD5_PUT_UINT32_LE(ctx->state[3], output, 12); } - /* * output = MD5( input buffer ) */ @@ -313,6 +304,19 @@ int8_t utils_hb2hex(uint8_t hb) return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a'); } +void utils_md5_str(const unsigned char *input, size_t ilen, unsigned char *output) +{ + int i; + unsigned char buf_out[16]; + utils_md5(input, ilen, buf_out); + + // hex to string + for (i = 0; i < 16; ++i) { + output[i * 2] = utils_hb2hex(buf_out[i] >> 4); + output[i * 2 + 1] = utils_hb2hex(buf_out[i]); + } + output[32] = '\0'; +} #ifdef __cplusplus } #endif diff --git a/sdk_src/utils/utils_ringbuff.c b/sdk_src/utils/utils_ringbuff.c new file mode 100755 index 00000000..861af0a2 --- /dev/null +++ b/sdk_src/utils/utils_ringbuff.c @@ -0,0 +1,90 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "utils_ringbuff.h" + +#include +#include + +int ring_buff_init(sRingbuff* ring_buff, char* buff, uint32_t size) +{ + ring_buff->buffer = buff; + ring_buff->size = size; + ring_buff->readpoint = 0; + ring_buff->writepoint = 0; + memset(ring_buff->buffer, 0, ring_buff->size); + ring_buff->full = false; + + return RINGBUFF_OK; +} + +int ring_buff_flush(sRingbuff* ring_buff) +{ + ring_buff->readpoint = 0; + ring_buff->writepoint = 0; + memset(ring_buff->buffer, 0, ring_buff->size); + ring_buff->full = false; + + return RINGBUFF_OK; +} + +int ring_buff_push_data(sRingbuff* ring_buff, uint8_t* pData, int len) +{ + int i; + + if (len > ring_buff->size) { + return RINGBUFF_TOO_SHORT; + } + + for (i = 0; i < len; i++) { + if (((ring_buff->writepoint + 1) % ring_buff->size) == ring_buff->readpoint) { + ring_buff->full = true; + return RINGBUFF_FULL; + } else { + if (ring_buff->writepoint < (ring_buff->size - 1)) { + ring_buff->writepoint++; + } else { + ring_buff->writepoint = 0; + } + ring_buff->buffer[ring_buff->writepoint] = pData[i]; + } + } + + return RINGBUFF_OK; +} + +int ring_buff_pop_data(sRingbuff* ring_buff, uint8_t* pData, int len) +{ + int i; + + if (len > ring_buff->size) { + return RINGBUFF_TOO_SHORT; + } + + for (i = 0; i < len; i++) { + if (ring_buff->writepoint == ring_buff->readpoint) { + break; + } else { + if (ring_buff->readpoint == (ring_buff->size - 1)) { + ring_buff->readpoint = 0; + } else { + ring_buff->readpoint++; + } + pData[i] = ring_buff->buffer[ring_buff->readpoint]; + } + } + + return i; +} diff --git a/src/utils/digest/utils_sha1.c b/sdk_src/utils/utils_sha1.c old mode 100644 new mode 100755 similarity index 67% rename from src/utils/digest/utils_sha1.c rename to sdk_src/utils/utils_sha1.c index a08a5937..060bd03f --- a/src/utils/digest/utils_sha1.c +++ b/sdk_src/utils/utils_sha1.c @@ -1,6 +1,6 @@ /* * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at @@ -13,12 +13,13 @@ * */ +#include "utils_sha1.h" + #include #include -#include "qcloud_iot_import.h" #include "qcloud_iot_export_log.h" -#include "utils_sha1.h" +#include "qcloud_iot_import.h" /* Implementation that should never be optimized out by the compiler */ static void utils_sha1_zeroize(void *v, size_t n) @@ -33,22 +34,20 @@ static void utils_sha1_zeroize(void *v, size_t n) * 32-bit integer manipulation macros (big endian) */ #ifndef IOT_SHA1_GET_UINT32_BE -#define IOT_SHA1_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] ); \ +#define IOT_SHA1_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 IOT_SHA1_PUT_UINT32_BE -#define IOT_SHA1_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) ); \ +#define IOT_SHA1_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 @@ -66,8 +65,7 @@ void utils_sha1_free(iot_sha1_context *ctx) utils_sha1_zeroize(ctx, sizeof(iot_sha1_context)); } -void utils_sha1_clone(iot_sha1_context *dst, - const iot_sha1_context *src) +void utils_sha1_clone(iot_sha1_context *dst, const iot_sha1_context *src) { *dst = *src; } @@ -91,16 +89,16 @@ void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]) { uint32_t temp, W[16], A, B, C, D, E; - IOT_SHA1_GET_UINT32_BE(W[ 0], data, 0); - IOT_SHA1_GET_UINT32_BE(W[ 1], data, 4); - IOT_SHA1_GET_UINT32_BE(W[ 2], data, 8); - IOT_SHA1_GET_UINT32_BE(W[ 3], data, 12); - IOT_SHA1_GET_UINT32_BE(W[ 4], data, 16); - IOT_SHA1_GET_UINT32_BE(W[ 5], data, 20); - IOT_SHA1_GET_UINT32_BE(W[ 6], data, 24); - IOT_SHA1_GET_UINT32_BE(W[ 7], data, 28); - IOT_SHA1_GET_UINT32_BE(W[ 8], data, 32); - IOT_SHA1_GET_UINT32_BE(W[ 9], data, 36); + IOT_SHA1_GET_UINT32_BE(W[0], data, 0); + IOT_SHA1_GET_UINT32_BE(W[1], data, 4); + IOT_SHA1_GET_UINT32_BE(W[2], data, 8); + IOT_SHA1_GET_UINT32_BE(W[3], data, 12); + IOT_SHA1_GET_UINT32_BE(W[4], data, 16); + IOT_SHA1_GET_UINT32_BE(W[5], data, 20); + IOT_SHA1_GET_UINT32_BE(W[6], data, 24); + IOT_SHA1_GET_UINT32_BE(W[7], data, 28); + IOT_SHA1_GET_UINT32_BE(W[8], data, 32); + IOT_SHA1_GET_UINT32_BE(W[9], data, 36); IOT_SHA1_GET_UINT32_BE(W[10], data, 40); IOT_SHA1_GET_UINT32_BE(W[11], data, 44); IOT_SHA1_GET_UINT32_BE(W[12], data, 48); @@ -108,18 +106,15 @@ void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]) IOT_SHA1_GET_UINT32_BE(W[14], data, 56); IOT_SHA1_GET_UINT32_BE(W[15], data, 60); -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) +#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 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); \ +#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]; @@ -128,8 +123,8 @@ void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]) D = ctx->state[3]; E = ctx->state[4]; -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define K 0x5A827999 +#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]); @@ -155,8 +150,8 @@ void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]) #undef K #undef F -#define F(x,y,z) (x ^ y ^ z) -#define K 0x6ED9EBA1 +#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)); @@ -182,8 +177,8 @@ void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]) #undef K #undef F -#define F(x,y,z) ((x & y) | (z & (x | y))) -#define K 0x8F1BBCDC +#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)); @@ -209,8 +204,8 @@ void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]) #undef K #undef F -#define F(x,y,z) (x ^ y ^ z) -#define K 0xCA62C1D6 +#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)); @@ -248,7 +243,7 @@ void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]) */ void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen) { - size_t fill; + size_t fill; uint32_t left; if (ilen == 0) { @@ -258,10 +253,10 @@ void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t left = ctx->total[0] & 0x3F; fill = 64 - left; - ctx->total[0] += (uint32_t) ilen; + ctx->total[0] += (uint32_t)ilen; ctx->total[0] &= 0xFFFFFFFF; - if (ctx->total[0] < (uint32_t) ilen) { + if (ctx->total[0] < (uint32_t)ilen) { ctx->total[1]++; } @@ -269,14 +264,14 @@ void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t memcpy((void *)(ctx->buffer + left), input, fill); utils_sha1_process(ctx, ctx->buffer); input += fill; - ilen -= fill; + ilen -= fill; left = 0; } while (ilen >= 64) { utils_sha1_process(ctx, input); input += 64; - ilen -= 64; + ilen -= 64; } if (ilen > 0) { @@ -284,28 +279,24 @@ void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t } } -static const unsigned char iot_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 -}; +static const unsigned char iot_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 utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]) { - uint32_t last, padn; - uint32_t high, low; + 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); + high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); IOT_SHA1_PUT_UINT32_BE(high, msglen, 0); - IOT_SHA1_PUT_UINT32_BE(low, msglen, 4); + IOT_SHA1_PUT_UINT32_BE(low, msglen, 4); last = ctx->total[0] & 0x3F; padn = (last < 56) ? (56 - last) : (120 - last); @@ -313,14 +304,13 @@ void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]) utils_sha1_update(ctx, iot_sha1_padding, padn); utils_sha1_update(ctx, msglen, 8); - IOT_SHA1_PUT_UINT32_BE(ctx->state[0], output, 0); - IOT_SHA1_PUT_UINT32_BE(ctx->state[1], output, 4); - IOT_SHA1_PUT_UINT32_BE(ctx->state[2], output, 8); + IOT_SHA1_PUT_UINT32_BE(ctx->state[0], output, 0); + IOT_SHA1_PUT_UINT32_BE(ctx->state[1], output, 4); + IOT_SHA1_PUT_UINT32_BE(ctx->state[2], output, 8); IOT_SHA1_PUT_UINT32_BE(ctx->state[3], output, 12); IOT_SHA1_PUT_UINT32_BE(ctx->state[4], output, 16); } - /* * output = SHA-1( input buffer ) */ @@ -334,4 +324,3 @@ void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20 utils_sha1_finish(&ctx, output); utils_sha1_free(&ctx); } - diff --git a/sdk_src/utils/utils_timer.c b/sdk_src/utils/utils_timer.c new file mode 100755 index 00000000..583fea22 --- /dev/null +++ b/sdk_src/utils/utils_timer.c @@ -0,0 +1,95 @@ +/* + * Tencent is pleased to support the open source community by making IoT Hub available. + * Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved. + + * Licensed under the MIT License (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + + * 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "utils_timer.h" + +static const uint8_t sg_day_num[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +void timestamp_to_date(size_t timestamp_sec, RTC_DATE_TIME *date_time, int8_t time_zone) +{ + date_time->sec = timestamp_sec % 60; + + timestamp_sec /= 60; + date_time->minute = timestamp_sec % 60; + timestamp_sec += (size_t)time_zone * 60; // time_zone add + timestamp_sec /= 60; // to all hour + date_time->hour = timestamp_sec % 24; // calc curr hour + + int day_num = timestamp_sec / 24; // to all day_num + + int leap_num = (day_num + 365) / 1461; // calc leap year num + + if (((day_num + 366) % 1461) == 0) { + date_time->year = (day_num / 366) + 1970 - 0; + date_time->month = 12; + date_time->day = 31; + } else { + day_num -= leap_num; // all year to no leap + date_time->year = (day_num / 365) + 1970 - 0; + day_num %= 365; + day_num += 1; + // curr leap year + if (((date_time->year % 4) == 0) && (day_num == 60)) { + date_time->month = 2; + date_time->day = 29; + } else { + if (((date_time->year % 4) == 0) && (day_num > 60)) { + day_num -= 1; // leap year day_num to not leap year day_num + } + // calc month and day + int month_index; + for (month_index = 0; sg_day_num[month_index] < day_num; month_index++) { + day_num -= sg_day_num[month_index]; + } + date_time->month = (month_index + 1); + date_time->day = day_num; + } + } + + return; +} + +bool expired(Timer *timer) +{ + return HAL_Timer_expired(timer); +} + +void countdown_ms(Timer *timer, unsigned int timeout_ms) +{ + HAL_Timer_countdown_ms(timer, timeout_ms); +} + +void countdown(Timer *timer, unsigned int timeout) +{ + HAL_Timer_countdown(timer, timeout); +} + +int left_ms(Timer *timer) +{ + return HAL_Timer_remain(timer); +} + +void InitTimer(Timer *timer) +{ + HAL_Timer_init(timer); +} + +#ifdef __cplusplus +} +#endif diff --git a/src/coap/include/coap_client.h b/src/coap/include/coap_client.h deleted file mode 100644 index cc9b6d12..00000000 --- a/src/coap/include/coap_client.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef IOT_COAP_CLIENT_H_ -#define IOT_COAP_CLIENT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "qcloud_iot_export.h" - -#include "coap_client_net.h" - -#include "utils_net.h" -#include "utils_list.h" -#include "utils_timer.h" - -/* COAP协议版本号 */ -#define COAP_MSG_VER (0x01) - -/* COAP消息初始token */ -#define COAP_MSG_INIT_TOKEN (0x01020304) - -/* CoAP ACK/RESP最小超时时间 */ -#define MIN_COMMAND_TIMEOUT (500) - -/* CoAP ACK/RESP最大超时时间 */ -#define MAX_COMMAND_TIMEOUT (5000) - -/* CoAP 最大链接ID的长度 */ -#define COAP_MAX_CONN_ID_LEN (6) - -/* Message id最大值 */ -#define COAP_MSG_MAX_MSG_ID ((1 << 16) - 1) - -/* Topic最大长度 */ -#define URI_PATH_MAX_LEN (128) - -/* CoAP 鉴权成功 */ -#define COAP_TRUE (1) - -/* CoAP 鉴权失败 */ -#define COAP_FALSE (0) - -/* 设备鉴权URI,该URI唯一,禁止设备创建该URI topic */ -#define COAP_AUTH_URI ("txauth9w0BAQsFA") - -/* token最大长度 */ -#define COAP_MSG_MAX_TOKEN_LEN (8) - -/* COAP 消息最大code class */ -#define COAP_MSG_MAX_CODE_CLASS (7) - -/* COAP 消息最大code detail */ -#define COAP_MSG_MAX_CODE_DETAIL (31) - -/* 获取Option num字段 */ -#define COAP_MSG_OPTION_NUM(option) ((option)->option_num) - -/* 获取Next Option */ -#define COAP_MSG_OP_NEXT(option) ((option)->next) - -/* 判断COAP消息是否为空 */ -#define COAP_MSG_IS_EMPTY(message) (((message)->code_class == 0) && ((message)->code_detail == 0)) - -/* 判断COAP消息是否为空 ACK*/ -#define COAP_MSG_IS_EMPTY_ACK(message) (((message)->code_class == 2) && ((message)->code_detail == 3)) - -/* 判断COAP消息是否为RESP */ -#define COAP_MSG_IS_EMPTY_RSP(message) (((message)->code_class == 2) && ((message)->code_detail == 5)) - -/** - * @brief COAP消息分类 - */ -typedef enum { - COAP_MSG_REQ = 0, // 请求包 - COAP_MSG_SUCCESS = 2, // 成功回包 - COAP_MSG_CLIENT_ERR = 4, // 客户端错误回包 - COAP_MSG_SERVER_ERR = 5, // 后台错误回包 - COAP_MSG_SDKINTERNAL_ERR = 6, -} CoAPMessageClass; - -/** - * @brief COAP消息请求方法 - */ -typedef enum { - COAP_MSG_GET = 1, //GET请求 - COAP_MSG_POST = 2, //POST请求 - COAP_MSG_PUT = 3, - COAP_MSG_DELETE =4 -} CoAPRequestMethod; - -typedef enum { - /* CoAP Success Response code detail */ - COAP_MSG_CODE_201_CREATED = 01, /* Mapping to CoAP codeClass.codeDetail 2.01 */ - COAP_MSG_CODE_202_DELETED = 02, /* Mapping to CoAP codeClass.codeDetail 2.02 */ - COAP_MSG_CODE_203_VALID = 03, /* Mapping to CoAP codeClass.codeDetail 2.03 */ - COAP_MSG_CODE_204_CHANGED = 04, /* Mapping to CoAP codeClass.codeDetail 2.04 */ - COAP_MSG_CODE_205_CONTENT = 05, /* Mapping to CoAP codeClass.codeDetail 2.05 */ - COAP_MSG_CODE_231_CONTINUE = 31, /* Mapping to CoAP codeClass.codeDetail 2.31 */ - - /* CoAP Client Error Response code detail */ - COAP_MSG_CODE_400_BAD_REQUEST = 00, /* Mapping to CoAP codeClass.codeDetail 4.00 */ - COAP_MSG_CODE_401_UNAUTHORIZED = 01, /* Mapping to CoAP codeClass.codeDetail 4.01 */ - COAP_MSG_CODE_402_BAD_OPTION = 02, /* Mapping to CoAP codeClass.codeDetail 4.02 */ - COAP_MSG_CODE_403_FORBIDDEN = 03, /* Mapping to CoAP codeClass.codeDetail 4.03 */ - COAP_MSG_CODE_404_NOT_FOUND = 04, /* Mapping to CoAP codeClass.codeDetail 4.04 */ - COAP_MSG_CODE_405_METHOD_NOT_ALLOWED = 05, /* Mapping to CoAP codeClass.codeDetail 4.05 */ - COAP_MSG_CODE_406_NOT_ACCEPTABLE = 06, /* Mapping to CoAP codeClass.codeDetail 4.06 */ - COAP_MSG_CODE_408_REQUEST_ENTITY_INCOMPLETE = 8, /* Mapping to CoAP codeClass.codeDetail 4.08 */ - COAP_MSG_CODE_412_PRECONDITION_FAILED = 12, /* Mapping to CoAP codeClass.codeDetail 4.12 */ - COAP_MSG_CODE_413_REQUEST_ENTITY_TOO_LARGE = 13, /* Mapping to CoAP codeClass.codeDetail 4.13 */ - COAP_MSG_CODE_415_UNSUPPORTED_CONTENT_FORMAT = 15, /* Mapping to CoAP codeClass.codeDetail 4.15 */ - - /* CoAP Server Error Response code detail */ - COAP_MSG_CODE_500_INTERNAL_SERVER_ERROR = 00, /* Mapping to CoAP codeClass.codeDetail 5.00 */ - COAP_MSG_CODE_501_NOT_IMPLEMENTED = 01, /* Mapping to CoAP codeClass.codeDetail 5.01 */ - COAP_MSG_CODE_502_BAD_GATEWAY = 02, /* Mapping to CoAP codeClass.codeDetail 5.02 */ - COAP_MSG_CODE_503_SERVICE_UNAVAILABLE = 03, /* Mapping to CoAP codeClass.codeDetail 5.03 */ - COAP_MSG_CODE_504_GATEWAY_TIMEOUT = 04, /* Mapping to CoAP codeClass.codeDetail 5.04 */ - COAP_MSG_CODE_505_PROXYING_NOT_SUPPORTED = 05, /* Mapping to CoAP codeClass.codeDetail 5.05 */ - - COAP_MSG_CODE_600_TIMEOUT = 00, /* Mapping to self define CoAP codeClass.codeDetail 6.00 */ -} CoAPRespCodeDetail; - -/** - * @brief Option number enumeration - */ -typedef enum { - COAP_MSG_IF_MATCH = 1, // If-Match option number - COAP_MSG_URI_HOST = 3, // URI-Host option number - COAP_MSG_ETAG = 4, // Entity-Tag option number - COAP_MSG_IF_NONE_MATCH = 5, // If-None-Match option number - COAP_MSG_URI_PORT = 7, // URI-Port option number - COAP_MSG_LOCATION_PATH = 8, // Location-Path option number - COAP_MSG_URI_PATH = 11, // URI-Path option number - COAP_MSG_CONTENT_FORMAT = 12, // Content-Format option number - COAP_MSG_MAX_AGE = 14, // Max-Age option number - COAP_MSG_URI_QUERY = 15, // URI-Query option number - COAP_MSG_ACCEPT = 17, // Accept option number - COAP_MSG_LOCATION_QUERY = 20, // Location-Query option number - COAP_MSG_BLOCK2 = 23, // Block2 option number - COAP_MSG_BLOCK1 = 27, // Block1 option number - COAP_MSG_SIZE2 = 28, // Size2 option number - COAP_MSG_PROXY_URI = 35, // Proxy-URI option number - COAP_MSG_PROXY_SCHEME = 39, // Proxy-Scheme option number - COAP_MSG_SIZE1 = 60, // Size1 option number - - COAP_MSG_AUTH_TOKEN = 61, // 设备鉴权token option number - COAP_MSG_NEED_RESP = 62, // CoAP消息是否需要content response option number -} CoAPMsgOptionNum; - -/* CoAP Client结构体定义 */ -typedef struct Client { - char is_authed; // CoAP Client是否已鉴权 - char conn_id[COAP_MAX_CONN_ID_LEN]; // 标识唯一一条CoAP连接 - - unsigned int message_token; // 标识请求响应条消息对应 - - char *auth_token; // 鉴权token - int auth_token_len; - - uint16_t next_msg_id; // COAP报文标识符 - - size_t send_buf_size; // 发送消息buffer长度 - size_t read_buf_size; // 消息接收buffer长度 - - unsigned char send_buf[COAP_SENDMSG_MAX_BUFLEN]; - unsigned char recv_buf[COAP_RECVMSG_MAX_BUFLEN]; - - void *lock_send_buf; // 输出流的锁 - void *lock_list_wait_ack; // 等待发布消息ack列表的锁 - - Network network_stack; // 网络调用数据结构 - - uint32_t command_timeout_ms; // CoAP消息超时时间, 单位:ms - - List* message_list; // 请求消息列表 - - unsigned char max_retry_count; // CoAP消息最大重试次数 - - CoAPEventHandler event_handle; // 事件回调 - -} CoAPClient; - -/** - * @brief CoAP Option结构体 - */ -typedef struct coap_msg_op -{ - unsigned short option_num; // Option number - unsigned val_len; // Option length - char *val; // Pointer to a buffer containing the option value - struct coap_msg_op *next; // Pointer to the next option structure in the list -} CoAPMsgOption; - -/** - * @brief CoAP Option 链表结构 - */ -typedef struct -{ - CoAPMsgOption *first; // Pointer to the first option structure in the list - CoAPMsgOption *last; // Pointer to the last option structure in the list -} CoAPMsgOptionList; - -/** - * @brief CoAP消息列表中节点状态 - */ -typedef enum { - COAP_NODE_STATE_NORMANL = 0, - COAP_NODE_STATE_INVALID, -} CoAPNodeState; - -typedef struct { - CoAPNodeState node_state; /* 节点状态 */ - void *user_context; - unsigned short msg_id; - char acked; - unsigned char token_len; - unsigned char token[COAP_MSG_MAX_TOKEN_LEN]; - unsigned char retrans_count; - Timer start_time; - unsigned char *message; - unsigned int msglen; - OnRespCallback handler; -} CoAPMsgSendInfo; - -/** - * @brief COAP消息类型 - */ -typedef enum { - COAP_MSG_CON = 0x0, /**< 需要等待回包确认的消息 */ - COAP_MSG_NON = 0x1, /**< 无需等待回包确认的消息 */ - COAP_MSG_ACK = 0x2, /**< ACK消息 */ - COAP_MSG_RST = 0x3 /**< Reset消息 */ -} CoAPMsgType; - -/** - * @brief CoAP消息结构体 - */ -typedef struct -{ - unsigned version; // CoAP协议版本号 - CoAPMsgType type; // 消息类型 - - unsigned code_class; // Code class - unsigned code_detail; // Code detail - - unsigned short msg_id; // 消息id - - char *pay_load; // 消息负载 - size_t pay_load_len; // 消息负载长度 - - char token[COAP_MSG_MAX_TOKEN_LEN]; // 消息token - unsigned token_len; // 消息token长度 - - CoAPMsgOptionList op_list; // Option链表 - - OnRespCallback handler; // CoAP Response消息回调处理函数 - void *user_context; // 用户上下文 -} CoAPMessage; - -#define DEFAULT_COAP_MESSAGE {COAP_MSG_VER, COAP_MSG_CON, COAP_MSG_REQ, COAP_MSG_POST, 0, NULL, 0, {0}, 0, {0}, NULL, NULL} - -/** - * @brief 对CoAPClient对象字段进行初始化 - * - * @param pClient CoAP客户端结构体 - * @param pParams CoAP客户端初始化参数 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int qcloud_iot_coap_init(CoAPClient *pClient, CoAPInitParams *pParams); - -/** - * @brief 生成下一条CoAPMessage 消息Id - * - * @param pClient CoAP客户端结构体 - * @return 消息Id - */ -uint16_t get_next_coap_msg_id(CoAPClient *pClient); - -/** - * @brief 生成下一条CoAPMessage 消息token - * - * @param pClient CoAP客户端结构体 - * @param[in,out] tokenData 消息token返回值 - * @return token长度 - */ -unsigned int get_coap_message_token(CoAPClient *client, char *tokenData); - -/** - * @brief 设置消息类型 - * - * @param message CoAP消息对象 - * @param - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -int coap_message_type_set(CoAPMessage *message, unsigned type); - -/** - * @brief 设置消息code - * - * @param message CoAP消息对象 - * @param code_class CoAPMessageClass - * @param code_detail - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -int coap_message_code_set(CoAPMessage *message, unsigned code_class, unsigned code_detail); - -/** - * @brief 设置消息Id - * - * @param message CoAP消息对象 - * @param msg_id - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -int coap_message_id_set(CoAPMessage *message, unsigned msg_id); - -/** - * @brief 设置消息token - * - * @param message CoAP消息对象 - * @param buf token字符串 - * @param len token长度 - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -int coap_message_token_set(CoAPMessage *message, char *buf, size_t len); - -/** - * @brief 设置消息内容负责 - * - * @param message CoAP消息对象 - * @param buf 消息负载 - * @param len 负载长度 - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -int coap_message_payload_set(CoAPMessage *message, char *buf, size_t len); - -/** - * @brief 增加消息option - * - * @param message CoAP消息对象 - * @param num option number - * @param len option 长度 - * @param val option 字符串内容 - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -int coap_message_option_add(CoAPMessage *message, unsigned num, unsigned len, const char *val); - -/** - * @brief 设置响应消息回调函数 - * - * @param message CoAP消息对象 - * @param callback 回调函数 - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -int coap_message_callback_set(CoAPMessage *message, OnRespCallback callback); - -/** - * @brief 设置用户上下文 - * - * @param message CoAP消息对象 - * @param userContext 用户上下文 - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -int coap_message_context_set(CoAPMessage *message, void *userContext); - -/** - * @brief 根据option number/len/val 构造CoAPMsgOption对象 - * - * @param num CoAP option number - * @param len CoAP option string len - * @param val CoAP option string value - * @return QCLOUD_ERR_SUCCESS: 设置成功; < 0: 设置失败 - */ -CoAPMsgOption* qcloud_iot_coap_option_init(unsigned num, unsigned len, const char *val); - -/** - * @brief 销毁CoAPMessage对象 - * - * @param[in,out] message指针 - */ -void coap_message_destroy(CoAPMessage *message); - -/** - * @brief CoAP消息网络读取、消息处理包裹函数 - * - * @param pClient CoAPClient 对象指针 - * @param timeout_ms 读超时时长 - * @return QCLOUD_ERR_SUCCESS: 成功; < 0: 读循环失败 - */ -int coap_message_cycle(CoAPClient *client, uint32_t timeout_ms); - -/** - * @brief CoAP消息网络发送 - * - * @param client CoAPClient 对象指针 - * @param message 待发送的消息对象 - * @return QCLOUD_ERR_SUCCESS: 写入网络成功; < 0: 失败 - */ -ssize_t coap_message_send(CoAPClient *client, CoAPMessage *message); - -/** - * @brief CoAP消息网络读取 - * - * @param client CoAPClient 对象指针 - * @param timeout_ms 读超时时长 - * @return QCLOUD_ERR_SUCCESS: 写入网络成功; < 0: 失败 - */ -ssize_t coap_message_recv(CoAPClient *client, uint32_t timeout_ms); - -/** - * @brief CoAPClient鉴权函数,发送鉴权消息并等待回包 - * - * @param client CoAPClient 对象指针 - * @return QCLOUD_ERR_SUCCESS: 鉴权消息写入网络成功; < 0: 失败 - */ -int coap_client_auth(CoAPClient *client); - -/** - * @brief Parse a message - * - * @param[in,out] message Pointer to a message structure - * @param[in] buf Pointer to a buffer containing the message - * @param[in] len Length of the buffer - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -ssize_t deserialize_coap_message(CoAPMessage *message, char *buf, size_t len); - -/** - * @brief Format a message - * - * @param[in] message Pointer to a message structure - * @param[out] buf Pointer to a buffer to contain the formatted message - * @param[in] len Length of the buffer - * - * @returns Length of the formatted message or error code - * @retval >0 Length of the formatted message - * @retval <0 Error - */ -ssize_t serialize_coap_message(CoAPMessage *message, char *buf, size_t len); - - -void coap_msg_dump(CoAPMessage* msg); - -#ifdef __cplusplus -} -#endif - - -#endif /* IOT_COAP_CLIENT_H_ */ diff --git a/src/coap/src/coap_client.c b/src/coap/src/coap_client.c deleted file mode 100644 index 5e005121..00000000 --- a/src/coap/src/coap_client.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "coap_client.h" - -#include "ca.h" -#include "device.h" - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" - -#include "utils_base64.h" - -#define HOST_STR_LENGTH 64 -static char s_qcloud_iot_host[HOST_STR_LENGTH] = {0}; -static int s_qcloud_iot_port = 5684; - -#ifndef AUTH_WITH_NOTLS -#ifndef AUTH_MODE_CERT -#define DECODE_PSK_LENGTH 48 /*控制台允许的最大长度为64,对应到原文最大长度64/4*3 = 48*/ -static unsigned char sg_psk_str[DECODE_PSK_LENGTH]; -#endif -#endif - -static uint16_t _get_random_start_packet_id(void) -{ - srand((unsigned)time(NULL)); - return rand() % 65536 + 1; -} - -void* IOT_COAP_Construct(CoAPInitParams *pParams) -{ - POINTER_SANITY_CHECK(pParams, NULL); - STRING_PTR_SANITY_CHECK(pParams->product_id, NULL); - STRING_PTR_SANITY_CHECK(pParams->device_name, NULL); - - CoAPClient *coap_client = NULL; - if ((coap_client = (CoAPClient*) HAL_Malloc (sizeof(CoAPClient))) == NULL) { - Log_e("memory not enough to malloc COAPClient"); - return NULL; - } - - if (iot_device_info_init() == QCLOUD_ERR_SUCCESS) { - iot_device_info_set(pParams->product_id, pParams->device_name); - } - - int rc = qcloud_iot_coap_init(coap_client, pParams); - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("coap init failed: %d", rc); - HAL_Free(coap_client); - return NULL; - } - - if (coap_client->network_stack.connect(&coap_client->network_stack) != QCLOUD_ERR_SUCCESS) { - Log_e("coap connect failed: %d", rc); - HAL_Free(coap_client); - return NULL; - } - else { - Log_i("coap connect success"); - } - - coap_client_auth(coap_client); - while (coap_client->is_authed == -1) { - IOT_COAP_Yield(coap_client, 200); - } - - if (coap_client->is_authed == COAP_TRUE) { - Log_i("device auth successfully, connid: %s", coap_client->conn_id); - return coap_client; - } else { - Log_e("device auth failed, connid: %s", coap_client->conn_id); - void *client = coap_client; - IOT_COAP_Destroy(&client); - return NULL; - } -} - -void IOT_COAP_Destroy(void **pClient) { - POINTER_SANITY_CHECK_RTN(*pClient); - - CoAPClient *coap_client = (CoAPClient *)(*pClient); - - if ((coap_client)->network_stack.handle != 0) { - (coap_client)->network_stack.disconnect(&(coap_client)->network_stack); - } - - list_destroy(coap_client->message_list); - - HAL_MutexDestroy(coap_client->lock_send_buf); - HAL_MutexDestroy(coap_client->lock_list_wait_ack); - - if (coap_client->auth_token != NULL) { - HAL_Free(coap_client->auth_token); - coap_client->auth_token = NULL; - } - coap_client->auth_token_len = 0; - coap_client->is_authed = -1; - - HAL_Free(*pClient); - *pClient = NULL; - - Log_i("coap release!"); -} - -int IOT_COAP_Yield(void *pClient, uint32_t timeout_ms) { - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - CoAPClient* coap_client = (CoAPClient*)pClient; - - return coap_message_cycle(coap_client, timeout_ms); -} - -int IOT_COAP_SendMessage(void *pClient, char *topicName, SendMsgParams *sendParams) { - IOT_FUNC_ENTRY - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(topicName, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(sendParams, QCLOUD_ERR_INVAL); - - if (strlen(topicName) > URI_PATH_MAX_LEN) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MAX_TOPIC_LENGTH); - } - - int ret = QCLOUD_ERR_SUCCESS; - - CoAPClient* coap_client = (CoAPClient*)pClient; - - CoAPMessage send_message = DEFAULT_COAP_MESSAGE; - - coap_message_type_set(&send_message, COAP_MSG_CON); - coap_message_code_set(&send_message, COAP_MSG_REQ, COAP_MSG_POST); - - coap_message_id_set(&send_message, get_next_coap_msg_id(coap_client)); - - char message_token[8] = {0}; - int len = get_coap_message_token(pClient, message_token); - coap_message_token_set(&send_message, message_token, len); - - send_message.pay_load = (char *) HAL_Malloc (sendParams->pay_load_len); - if (NULL == send_message.pay_load) IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - - coap_message_payload_set(&send_message, sendParams->pay_load, sendParams->pay_load_len); - - coap_message_option_add(&send_message, COAP_MSG_URI_PATH, strlen(topicName), topicName); - coap_message_option_add(&send_message, COAP_MSG_AUTH_TOKEN, coap_client->auth_token_len, coap_client->auth_token); - if (sendParams->need_resp == false) { - coap_message_option_add(&send_message, COAP_MSG_NEED_RESP, 1, "0"); - coap_message_context_set(&send_message, sendParams->user_context); - } - else { - coap_message_option_add(&send_message, COAP_MSG_NEED_RESP, 1, "1"); - coap_message_callback_set(&send_message, sendParams->resp_callback); - coap_message_context_set(&send_message, sendParams->user_context); - } - - ret = coap_message_send(coap_client, &send_message); - - HAL_Free(send_message.pay_load); - - if (ret != QCLOUD_ERR_SUCCESS) { - IOT_FUNC_EXIT_RC(ret) - } - - IOT_FUNC_EXIT_RC(send_message.msg_id) -} - -int IOT_COAP_GetMessageId(void *pMessage) { - IOT_FUNC_ENTRY - - POINTER_SANITY_CHECK(pMessage, QCLOUD_ERR_INVAL); - CoAPMessage *message = (CoAPMessage *)pMessage; - - IOT_FUNC_EXIT_RC(message->msg_id) -} - -int IOT_COAP_GetMessagePayload(void *pMessage, char **payload, int *payloadLen) { - IOT_FUNC_ENTRY - - POINTER_SANITY_CHECK(pMessage, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(payload, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(payloadLen, QCLOUD_ERR_INVAL); - - CoAPMessage *message = (CoAPMessage *)pMessage; - if (message->code_class != COAP_MSG_SUCCESS || message->code_detail != COAP_MSG_CODE_205_CONTENT) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) - } - - *payload = message->pay_load; - *payloadLen = message->pay_load_len; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int IOT_COAP_GetMessageCode(void *pMessage) { - IOT_FUNC_ENTRY - - POINTER_SANITY_CHECK(pMessage, QCLOUD_ERR_INVAL); - - CoAPMessage *message = (CoAPMessage *)pMessage; - - int rc = COAP_EVENT_ACK_TIMEOUT; - - if (message->code_class == COAP_MSG_SUCCESS) { - rc = COAP_EVENT_RECEIVE_RESPCONTENT; - } - else if (message->code_class == COAP_MSG_CLIENT_ERR) { - if (message->code_detail == COAP_MSG_CODE_401_UNAUTHORIZED) { - rc = COAP_EVENT_UNAUTHORIZED; - } - else { - rc = COAP_EVENT_FORBIDDEN; - } - } - else if (message->code_class == COAP_MSG_SERVER_ERR) { - rc = COAP_EVENT_INTERNAL_SERVER_ERROR; - } - else if (message->code_class == COAP_MSG_SDKINTERNAL_ERR) { - rc = COAP_EVENT_SEPRESP_TIMEOUT; - } - else { - /** - * no more error code - */ - Log_e("not supported code class: %d", message->code_class); - } - - IOT_FUNC_EXIT_RC(rc) -} - -int qcloud_iot_coap_init(CoAPClient *pClient, CoAPInitParams *pParams) { - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(pParams, QCLOUD_ERR_INVAL); - - memset(pClient, 0x0, sizeof(CoAPClient)); - - int size = HAL_Snprintf(s_qcloud_iot_host, HOST_STR_LENGTH, "%s.%s", pParams->product_id, QCLOUD_IOT_COAP_DEIRECT_DOMAIN); - if (size < 0 || size > HOST_STR_LENGTH - 1) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - pClient->is_authed = -1; - - if (pParams->command_timeout < MIN_COMMAND_TIMEOUT) - pParams->command_timeout = MIN_COMMAND_TIMEOUT; - if (pParams->command_timeout > MAX_COMMAND_TIMEOUT) - pParams->command_timeout = MAX_COMMAND_TIMEOUT; - pClient->command_timeout_ms = pParams->command_timeout; - -#ifndef AUTH_WITH_NOTLS -#ifdef AUTH_MODE_CERT - bool certEmpty = (pParams->cert_file == NULL || pParams->key_file == NULL); - if (certEmpty) { - Log_e("cert file or key file is empty!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - } - Log_d("cert file: %s", pParams->cert_file); - Log_d("key file: %s", pParams->key_file); - - // TLS连接参数初始化 - pClient->network_stack.ssl_connect_params.cert_file = pParams->cert_file; - pClient->network_stack.ssl_connect_params.key_file = pParams->key_file; - pClient->network_stack.ssl_connect_params.ca_crt = iot_ca_get(); - pClient->network_stack.ssl_connect_params.ca_crt_len = strlen(pClient->network_stack.ssl_connect_params.ca_crt); - -#else - pClient->network_stack.ssl_connect_params.psk_id = iot_device_info_get()->client_id; - if (pParams->device_secret != NULL) { - size_t src_len = strlen(pParams->device_secret); - size_t len; - memset(sg_psk_str, 0x00, DECODE_PSK_LENGTH); - qcloud_iot_utils_base64decode(sg_psk_str, sizeof( sg_psk_str ), &len, (unsigned char *)pParams->device_secret, src_len ); - pClient->network_stack.ssl_connect_params.psk = (char *)sg_psk_str; - pClient->network_stack.ssl_connect_params.psk_length = len; - pClient->network_stack.ssl_connect_params.ca_crt = iot_ca_get(); - pClient->network_stack.ssl_connect_params.ca_crt_len = strlen(pClient->network_stack.ssl_connect_params.ca_crt); - } else { - Log_e("psk is empty!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - } -#endif - - pClient->network_stack.host = s_qcloud_iot_host; - pClient->network_stack.port = s_qcloud_iot_port; -#else - pClient->network_stack.host = s_qcloud_iot_host; - pClient->network_stack.port = s_qcloud_iot_port; -#endif - - pClient->auth_token = NULL; - pClient->auth_token_len = 0; - // next_msg_id 取随机数 1- 65536 - pClient->next_msg_id = _get_random_start_packet_id(); - pClient->read_buf_size = COAP_RECVMSG_MAX_BUFLEN; - pClient->send_buf_size = COAP_SENDMSG_MAX_BUFLEN; - - pClient->lock_send_buf = HAL_MutexCreate(); - if (pClient->lock_send_buf == NULL) { - Log_e("create send buf lock failed"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - pClient->lock_list_wait_ack = HAL_MutexCreate(); - if (pClient->lock_list_wait_ack == NULL) { - Log_e("create send buf lock failed"); - goto error; - } - - pClient->message_list = list_new(); - pClient->max_retry_count = pParams->max_retry_count; - pClient->event_handle = pParams->event_handle; - - // 底层网络操作相关的数据结构初始化 - qcloud_iot_coap_network_init(&(pClient->network_stack)); - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); - -error: - if (pClient->lock_send_buf != NULL) { - HAL_MutexDestroy(pClient->lock_send_buf); - pClient->lock_send_buf = NULL; - } - - if (pClient->lock_list_wait_ack != NULL) { - HAL_MutexDestroy(pClient->lock_list_wait_ack); - pClient->lock_list_wait_ack = NULL; - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); -} - -#ifdef __cplusplus -} -#endif - diff --git a/src/coap/src/coap_client_auth.c b/src/coap/src/coap_client_auth.c deleted file mode 100644 index 36209654..00000000 --- a/src/coap/src/coap_client_auth.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "coap_client.h" - -#include "device.h" - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" - -static void _coap_client_auth_callback(void *message, void *userContext) -{ - IOT_FUNC_ENTRY - - POINTER_SANITY_CHECK_RTN(message); - POINTER_SANITY_CHECK_RTN(userContext); - - CoAPClient *client = (CoAPClient *)userContext; - CoAPMessage *msg = (CoAPMessage *)message; - - if (msg->code_class == COAP_MSG_SUCCESS && msg->code_detail == COAP_MSG_CODE_205_CONTENT) { - Log_i("auth token message success, code_class: %d code_detail: %d", msg->code_class, msg->code_detail); - if (msg->pay_load_len == 0 || msg->pay_load == NULL || strlen(msg->pay_load) == 0) { - client->is_authed = COAP_FALSE; - Log_e("auth token response empty"); - } - else { - client->auth_token_len = msg->pay_load_len; - client->auth_token = HAL_Malloc(client->auth_token_len); - strncpy(client->auth_token, msg->pay_load,client->auth_token_len); - client->is_authed = COAP_TRUE; - Log_d("auth_token_len = %d, auth_token = %s", client->auth_token_len, client->auth_token); - } - } - else { - client->is_authed = COAP_FALSE; - Log_e("auth token message failed, code_class: %d code_detail: %d", msg->code_class, msg->code_detail); - } - - IOT_FUNC_EXIT -} - -static void get_coap_next_conn_id(CoAPClient *pclient) { - int i = 0; - - srand((unsigned)time(0)); - - for (i = 0; i < COAP_MAX_CONN_ID_LEN - 1; i++) { - int flag = rand() % 3; - - switch(flag) { - case 0: - pclient->conn_id[i] = (rand() % 26) + 'a'; - break; - case 1: - pclient->conn_id[i] = (rand() % 26) + 'A'; - break; - case 2: - pclient->conn_id[i] = (rand() % 10) + '0'; - break; - } - } - - pclient->conn_id[COAP_MAX_CONN_ID_LEN - 1] = '\0'; - - return; -} - -int coap_client_auth(CoAPClient *pclient) { - IOT_FUNC_ENTRY - - POINTER_SANITY_CHECK(pclient, QCLOUD_ERR_COAP_NULL); - - int ret = QCLOUD_ERR_SUCCESS; - - CoAPClient* coap_client = (CoAPClient*)pclient; - CoAPMessage send_message = DEFAULT_COAP_MESSAGE; - - coap_message_type_set(&send_message, COAP_MSG_CON); - coap_message_code_set(&send_message, COAP_MSG_REQ, COAP_MSG_POST); - - coap_message_id_set(&send_message, get_next_coap_msg_id(coap_client)); - - char message_token[8] = {0}; - int len = get_coap_message_token(pclient, message_token); - coap_message_token_set(&send_message, message_token, len); - - len = MAX_SIZE_OF_PRODUCT_ID + strlen(iot_device_info_get()->device_name) - + strlen(COAP_AUTH_URI) + 4; - char *auth_path = (char*)HAL_Malloc(len); - HAL_Snprintf(auth_path, len, "%s/%s/%s", iot_device_info_get()->product_id, - iot_device_info_get()->device_name, COAP_AUTH_URI); - coap_message_option_add(&send_message, COAP_MSG_URI_PATH, strlen(auth_path), auth_path); - HAL_Free(auth_path); - - coap_message_option_add(&send_message, COAP_MSG_NEED_RESP, 1, "0"); - - coap_message_callback_set(&send_message, _coap_client_auth_callback); - coap_message_context_set(&send_message, pclient); - - get_coap_next_conn_id(coap_client); - - send_message.pay_load_len = strlen(QCLOUD_IOT_DEVICE_SDK_APPID) + COAP_MAX_CONN_ID_LEN + 2; - send_message.pay_load = (char *) HAL_Malloc (send_message.pay_load_len); - if (NULL == send_message.pay_load) IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - - char *temp_pay_load = (char*)HAL_Malloc(send_message.pay_load_len); - if (NULL == temp_pay_load) IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - - HAL_Snprintf(temp_pay_load, send_message.pay_load_len, "%s;%s", QCLOUD_IOT_DEVICE_SDK_APPID, coap_client->conn_id); - - coap_message_payload_set(&send_message, temp_pay_load, send_message.pay_load_len); - - ret = coap_message_send(coap_client, &send_message); - - HAL_Free(temp_pay_load); - HAL_Free(send_message.pay_load); - - IOT_FUNC_EXIT_RC(ret) -} - -#ifdef __cplusplus -} -#endif diff --git a/src/coap/src/coap_client_common.c b/src/coap/src/coap_client_common.c deleted file mode 100644 index 8b7421ab..00000000 --- a/src/coap/src/coap_client_common.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include "coap_client.h" - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" - -/** - * @brief Free an option structure that was allocated by coap_msg_op_new - * - * @param[in,out] op Pointer to the option structure - */ -static void _coap_msg_op_delete(CoAPMsgOption *option) { - IOT_FUNC_ENTRY - HAL_Free(option->val); - HAL_Free(option); - IOT_FUNC_EXIT -} - -/** - * @brief Deinitialise an option linked-list structure - * - * @param[in,out] list Pointer to an option linked-list structure - */ -static void _coap_msg_op_list_destroy(CoAPMsgOptionList *list) { - IOT_FUNC_ENTRY - - CoAPMsgOption *prev = NULL; - CoAPMsgOption *option = NULL; - - option = list->first; - while (option != NULL) - { - prev = option; - option = option->next; - _coap_msg_op_delete(prev); - } - memset(list, 0, sizeof(CoAPMsgOptionList)); - - IOT_FUNC_EXIT -} - -uint16_t get_next_coap_msg_id(CoAPClient *pClient) { - IOT_FUNC_ENTRY - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - unsigned int id = 0; - id = pClient->next_msg_id = (uint16_t) ((COAP_MSG_MAX_MSG_ID == pClient->next_msg_id) ? 1 : (pClient->next_msg_id + 1)); - - IOT_FUNC_EXIT_RC(id) -} - -unsigned int get_coap_message_token(CoAPClient *client, char *tokenData) -{ - unsigned int value = client->message_token; - tokenData[0] = ((value & 0x00FF) >> 0); - tokenData[1] = ((value & 0xFF00) >> 8); - tokenData[2] = ((value & 0xFF0000) >> 16); - tokenData[3] = ((value & 0xFF000000) >> 24); - client->message_token++; - return sizeof(unsigned int); -} - -int coap_message_type_set(CoAPMessage *message, unsigned type) { - IOT_FUNC_ENTRY - - if ((type != COAP_MSG_CON) - && (type != COAP_MSG_NON) - && (type != COAP_MSG_ACK) - && (type != COAP_MSG_RST)) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) - } - message->type = type; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int coap_message_code_set(CoAPMessage *message, unsigned code_class, unsigned code_detail) { - IOT_FUNC_ENTRY - - if (code_class > COAP_MSG_MAX_CODE_CLASS) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) - } - if (code_detail > COAP_MSG_MAX_CODE_DETAIL) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) - } - message->code_class = code_class; - message->code_detail = code_detail; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int coap_message_id_set(CoAPMessage *message, unsigned msg_id) { - IOT_FUNC_ENTRY - - if (msg_id > COAP_MSG_MAX_MSG_ID) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) - } - message->msg_id = msg_id; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int coap_message_token_set(CoAPMessage *message, char *buf, size_t len) { - IOT_FUNC_ENTRY - - if (len > COAP_MSG_MAX_TOKEN_LEN) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL) - } - memcpy(message->token, buf, len); - message->token_len = len; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int coap_message_payload_set(CoAPMessage *message, char *buf, size_t len) { - IOT_FUNC_ENTRY - - message->pay_load_len = 0; - - if (len > 0) - { - if (message->pay_load == NULL) - { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) - } - - memcpy(message->pay_load, buf, len); - message->pay_load_len = len; - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int coap_message_option_add(CoAPMessage *message, unsigned num, unsigned len, const char *val) { - IOT_FUNC_ENTRY - - CoAPMsgOption *prev = NULL; - CoAPMsgOption *option = NULL; - CoAPMsgOptionList *list = &message->op_list; - - if ((option = qcloud_iot_coap_option_init(num, len, val)) == NULL) { - Log_e("allocate new option failed."); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) - } - - if (list->first == NULL) { - /* empty list */ - list->first = option; - list->last = option; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) - } - - if (option->option_num < list->first->option_num) { - /* start of the list */ - option->next = list->first; - list->first = option; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) - } - - prev = list->first; - while (prev != list->last) { - /* middle of the list */ - if ((prev->option_num <= option->option_num) && (option->option_num < prev->next->option_num)) - { - option->next = prev->next; - prev->next = option; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) - } - prev = prev->next; - } - - /* end of the list */ - list->last->next = option; - list->last = option; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int coap_message_callback_set(CoAPMessage *message, OnRespCallback callback) { - IOT_FUNC_ENTRY - - message->handler = callback; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int coap_message_context_set(CoAPMessage *message, void *userContext) { - IOT_FUNC_ENTRY - - message->user_context = userContext; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -CoAPMsgOption * qcloud_iot_coap_option_init(unsigned num, unsigned len, const char *val) { - IOT_FUNC_ENTRY - - CoAPMsgOption *option = NULL; - - option = (CoAPMsgOption *) HAL_Malloc (sizeof(CoAPMsgOption)); - if (option == NULL) { - Log_e("no space to malloc option"); - return NULL; - } - - option->option_num = num; - option->val_len = len; - option->val = (char *) HAL_Malloc (len); - if (option->val == NULL) - { - HAL_Free(option); - option = NULL; - Log_e("no space to malloc option"); - return NULL; - } - - memcpy(option->val, val, len); - option->next = NULL; - - return option; -} - -void coap_message_destroy(CoAPMessage *message) -{ - IOT_FUNC_ENTRY - - _coap_msg_op_list_destroy(&message->op_list); - - if (message->pay_load != NULL) - { - HAL_Free(message->pay_load); - } - - memset(message, 0, sizeof(CoAPMessage)); - - IOT_FUNC_EXIT -} - -void coap_msg_dump(CoAPMessage* msg) -{ - Log_i("msg->version = %u",msg->version); - Log_i("msg->type = %d",msg->type); - Log_i("msg->code_class = %u",msg->code_class); - Log_i("msg->code_detail = %u",msg->code_detail); - Log_i("msg->msg_id = %d",msg->msg_id); - Log_i("msg->pay_load_len = %d",msg->pay_load_len); - Log_i("msg->pay_load: %s",msg->pay_load); - - Log_i("msg->token_len = %u",msg->token_len); - Log_i("msg->token: %s",msg->token); - return; -} - - -#ifdef __cplusplus -} -#endif diff --git a/src/coap/src/coap_client_message.c b/src/coap/src/coap_client_message.c deleted file mode 100644 index 9d3a1b16..00000000 --- a/src/coap/src/coap_client_message.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "coap_client.h" -#include "coap_client_net.h" - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" - -#include "utils_timer.h" - -#define PROCESS_ACK_CMD (0) -#define PROCESS_PIGGY_CMD (1) -#define PROCESS_RESP_CMD (2) -#define PROCESS_WAIT_CMD (3) - -static void _event_message_type_set(CoAPEventMessage* eventMsg, CoAPMessage *message, uint16_t processCmd) { - if (message->code_class == COAP_MSG_SUCCESS && message->code_detail == COAP_MSG_CODE_205_CONTENT) { - eventMsg->event_type = processCmd == PROCESS_RESP_CMD ? COAP_EVENT_RECEIVE_RESPCONTENT : - COAP_EVENT_RECEIVE_ACK; - } - else if (message->code_class == COAP_MSG_CLIENT_ERR && message->code_detail == COAP_MSG_CODE_401_UNAUTHORIZED) { - eventMsg->event_type = COAP_EVENT_UNAUTHORIZED; - Log_e("coap messagefailed, message id: %d, failure reason: %d.%d", - message->msg_id, message->code_class, message->code_detail); - } - else if (message->code_class == COAP_MSG_CLIENT_ERR && message->code_detail == COAP_MSG_CODE_403_FORBIDDEN) { - eventMsg->event_type = COAP_EVENT_FORBIDDEN; - Log_e("coap message failed, message id: %d, failure reason: %d.%d", - message->msg_id, message->code_class, message->code_detail); - } - else { - eventMsg->event_type = COAP_EVENT_INTERNAL_SERVER_ERROR; - Log_e("coap message failed, message id: %d, failure reason: %d.%d", - message->msg_id, message->code_class, message->code_detail); - } -} - -static int _coap_message_list_proc(CoAPClient *client, CoAPMessage *message, uint16_t processCmd) -{ - IOT_FUNC_ENTRY; - POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); - - HAL_MutexLock(client->lock_list_wait_ack); - - if (client->message_list->len <= 0) { - HAL_MutexUnlock(client->lock_list_wait_ack); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - ListIterator *iter; - ListNode *node = NULL; - ListNode *temp_node = NULL; - CoAPMsgSendInfo *send_info = NULL; - - if ((iter = list_iterator_new(client->message_list, LIST_TAIL)) == NULL) { - HAL_MutexUnlock(client->lock_list_wait_ack); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); - } - - for (;;) { - node = list_iterator_next(iter); - - if (NULL != temp_node) { - list_remove(client->message_list, temp_node); - Log_i("remove node"); - temp_node = NULL; - } - - if (NULL == node) { - break; - } - - send_info = (CoAPMsgSendInfo*) node->val; - if (NULL == send_info) { - Log_e("node's value is invalid!"); - continue; - } - - if (processCmd == PROCESS_ACK_CMD) { - if (send_info->msg_id == message->msg_id) { - send_info->acked = 1; /* 标记为已收到ACK */ - InitTimer(&send_info->start_time); - countdown_ms(&send_info->start_time, client->command_timeout_ms); - } - } - else if (processCmd == PROCESS_RESP_CMD) { - if (0 != send_info->token_len && send_info->token_len == message->token_len - && 0 == memcmp(send_info->token, message->token, message->token_len)) { - message->user_context = send_info->user_context; - - if (send_info->handler != NULL) { - send_info->handler(message, send_info->user_context); - } - else if (NULL != client->event_handle.h_fp) { //event handle process - CoAPEventMessage event_msg = {0}; - _event_message_type_set(&event_msg, message, processCmd); - event_msg.message = message; - message->msg_id = send_info->msg_id; - client->event_handle.h_fp(client->event_handle.context, &event_msg); - } - else { - Log_e("nether response callback nor event callback is set"); - } - - Log_d("remove the message id %d from list", send_info->msg_id); - send_info->node_state = COAP_NODE_STATE_INVALID; - } - } - else if (processCmd == PROCESS_PIGGY_CMD) { - if (send_info->msg_id == message->msg_id) { - message->user_context = send_info->user_context; - - if (send_info->handler != NULL) { - send_info->handler(message, send_info->user_context); - } - else if (NULL != client->event_handle.h_fp) { //event handle process - CoAPEventMessage event_msg = {0}; - _event_message_type_set(&event_msg, message, processCmd); - event_msg.message = (void *)(uintptr_t)(message->msg_id); - client->event_handle.h_fp(client->event_handle.context, &event_msg); - } - else { - Log_e("nether response callback nor event callback is set"); - } - - Log_d("remove the message id %d from list", send_info->msg_id); - - send_info->acked = 1; /* 标记为已收到ACK */ - send_info->node_state = COAP_NODE_STATE_INVALID; - } - } - else if (processCmd == PROCESS_WAIT_CMD) { - - if (COAP_NODE_STATE_INVALID == send_info->node_state) { - temp_node = node; - continue; - } - - if (left_ms(&send_info->start_time) > 0) { - continue; - } - - if (send_info->retrans_count < client->max_retry_count && (0 == send_info->acked)) { - InitTimer(&send_info->start_time); - countdown_ms(&send_info->start_time, client->command_timeout_ms); - send_info->retrans_count++; - Log_d("start to retansmit the message id %d len %d", send_info->msg_id, send_info->msglen); - size_t written_len = 0; - int ret = client->network_stack.write(&client->network_stack, send_info->message, send_info->msglen, - left_ms(&send_info->start_time), &written_len); - if (ret != QCLOUD_ERR_SUCCESS) { - Log_e("retansmit the message id %d failed.", send_info->msg_id, send_info->msglen); - continue; - } - } - else { - send_info->node_state = COAP_NODE_STATE_INVALID; - temp_node = node; - - if (send_info->handler != NULL) { - message->type = COAP_MSG_ACK; - message->user_context = send_info->user_context; - message->code_class = COAP_MSG_SDKINTERNAL_ERR; - message->code_detail = COAP_MSG_CODE_600_TIMEOUT; - message->msg_id = send_info->msg_id; - send_info->handler(message, send_info->user_context); - } - else if (NULL != client->event_handle.h_fp){ - CoAPEventMessage event_msg = {0}; - if (send_info->acked) { - event_msg.event_type = COAP_EVENT_SEPRESP_TIMEOUT; - } - else { - event_msg.event_type = COAP_EVENT_ACK_TIMEOUT; - } - event_msg.message = (void *)(uintptr_t)(send_info->msg_id); - client->event_handle.h_fp(client->event_handle.context, &event_msg); - } - else { - Log_e("nether response callback nor event callback is set"); - } - - continue; - } - } - } - - list_iterator_destroy(iter); - HAL_MutexUnlock(client->lock_list_wait_ack); - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - -/** - * @brief 向服务器发送确认消息 - * - * @param[in,out] client 指向客户端结构的指针 - * @param[in] msg 指向消息结构的指针 - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int _coap_client_send_ack(CoAPClient *client, int msgId) { - IOT_FUNC_ENTRY - - CoAPMessage ack = DEFAULT_COAP_MESSAGE; - int ret = 0; - - if ((ret = coap_message_type_set(&ack, COAP_MSG_ACK)) != QCLOUD_ERR_SUCCESS) - { - coap_message_destroy(&ack); - IOT_FUNC_EXIT_RC(ret) - } - - if ((ret = coap_message_id_set(&ack, msgId)) != QCLOUD_ERR_SUCCESS) - { - coap_message_destroy(&ack); - IOT_FUNC_EXIT_RC(ret) - } - - ret = coap_message_send(client, &ack); - coap_message_destroy(&ack); - - IOT_FUNC_EXIT_RC(ret) -} - -static int _coap_piggyresp_message_handle(CoAPClient *client, CoAPMessage *message) { - IOT_FUNC_ENTRY - - int rc = _coap_message_list_proc(client, message, PROCESS_PIGGY_CMD); - - IOT_FUNC_EXIT_RC(rc) -} - -static int _coap_ack_message_handle(CoAPClient *client, CoAPMessage *message) { - IOT_FUNC_ENTRY - - int rc = _coap_message_list_proc(client, message, PROCESS_ACK_CMD); - - IOT_FUNC_EXIT_RC(rc) -} - -static int _coap_resp_message_handle(CoAPClient *client, CoAPMessage *message) { - IOT_FUNC_ENTRY - - int rc = 0; - - if (COAP_MSG_CON == message->type) { - rc = _coap_client_send_ack(client, message->msg_id); - Log_d("send ack message for id: %d rc: %d", message->msg_id, rc); - } - - rc = _coap_message_list_proc(client, message, PROCESS_RESP_CMD); - - IOT_FUNC_EXIT_RC(rc) -} - -static void _coap_message_handle(CoAPClient *client, unsigned char *buf, unsigned short datalen) { - IOT_FUNC_ENTRY - - int rc = QCLOUD_ERR_SUCCESS; - CoAPMessage recv_message; - memset(&recv_message, 0x00, sizeof(CoAPMessage)); - - if ((rc = deserialize_coap_message(&recv_message, (char*)buf, datalen)) != QCLOUD_ERR_SUCCESS) { - Log_e("deserialize message failed: %d", rc); - } - - if (recv_message.type == COAP_MSG_ACK && COAP_MSG_IS_EMPTY_ACK(&recv_message)) { //empty ACK - Log_d("receive coap ACK message, id %d", recv_message.msg_id); - _coap_ack_message_handle(client, &recv_message); - } - else if (recv_message.type == COAP_MSG_ACK && !COAP_MSG_IS_EMPTY(&recv_message)) { //piggy Response - Log_d("receive coap piggy ACK message, id %d", recv_message.msg_id); - _coap_piggyresp_message_handle(client, &recv_message); - } - else if (recv_message.type == COAP_MSG_CON && COAP_MSG_IS_EMPTY_RSP(&recv_message)) { //payload Response - Log_d("receive coap response message, id: %d", recv_message.msg_id); - _coap_resp_message_handle(client, &recv_message); - } - else if (recv_message.type == COAP_MSG_NON && COAP_MSG_IS_EMPTY_RSP(&recv_message)) { //payload Response - Log_d("receive coap response message, id: %d", recv_message.msg_id); - _coap_resp_message_handle(client, &recv_message); - } - else { - Log_e("not recgonized recv message type"); - } - - if (recv_message.pay_load != NULL) { - HAL_Free(recv_message.pay_load); - recv_message.pay_load_len = 0; - } - - IOT_FUNC_EXIT -} - -static int _coap_message_list_add(CoAPClient *client, CoAPMessage *message, int len) { - IOT_FUNC_ENTRY - - CoAPMsgSendInfo *send_info = (CoAPMsgSendInfo*)HAL_Malloc(sizeof(CoAPMsgSendInfo)); - if (send_info == NULL) { - Log_e("no memory to malloc SendInfo"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) - } - - send_info->node_state = COAP_NODE_STATE_NORMANL; - send_info->acked = 0; - send_info->user_context = message->user_context; - send_info->msg_id = message->msg_id; - send_info->handler = message->handler; - send_info->msglen = len; - - if (COAP_MSG_CON == message->type) { - send_info->retrans_count = 0; - InitTimer(&send_info->start_time); - countdown_ms(&send_info->start_time, client->command_timeout_ms); - } - else { - - } - - send_info->token_len = message->token_len; - memcpy(send_info->token, message->token, message->token_len); - send_info->message = (unsigned char *)HAL_Malloc(len); - - if (NULL != send_info->message) { - memcpy(send_info->message, client->send_buf, len); - } - - ListNode *node = list_node_new(send_info); - if (NULL == node) { - Log_e("run list_node_new is error!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) - } - - HAL_MutexLock(client->lock_list_wait_ack); - list_rpush(client->message_list, node); - HAL_MutexUnlock(client->lock_list_wait_ack); - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int coap_message_cycle(CoAPClient *client, uint32_t timeout_ms) { - POINTER_SANITY_CHECK(client, QCLOUD_ERR_INVAL); - - int rc = coap_message_recv(client, timeout_ms); - - if (rc != QCLOUD_ERR_SUCCESS && rc != QCLOUD_ERR_SSL_READ_TIMEOUT) { - IOT_FUNC_EXIT_RC(rc) - } - - CoAPMessage message = DEFAULT_COAP_MESSAGE; - rc = _coap_message_list_proc(client, &message, PROCESS_WAIT_CMD); - - IOT_FUNC_EXIT_RC(rc) -} - -ssize_t coap_message_send(CoAPClient *client, CoAPMessage *message) -{ - IOT_FUNC_ENTRY - - ssize_t ret; - size_t written_len = 0; - - HAL_MutexLock(client->lock_send_buf); - - if ((ret = serialize_coap_message(message, (char*)client->send_buf, - client->send_buf_size)) < 0) - { - Log_e("failed to serialize coap message"); - HAL_MutexUnlock(client->lock_send_buf); - IOT_FUNC_EXIT_RC(ret) - } - - ret = client->network_stack.write(&client->network_stack, client->send_buf, - ret, 0, &written_len); - - if (ret == QCLOUD_ERR_SUCCESS) { - if (message->type == COAP_MSG_CON && message->code_class == COAP_MSG_REQ) { - ret = _coap_message_list_add(client, message, written_len); - Log_i("add coap message id: %d into wait list ret: %d", message->msg_id, ret); - } else { - Log_i("The message doesn't need to be retransmitted"); - } - } - else { - Log_e("coap net fail to write rc: %d", ret); - } - - HAL_MutexUnlock(client->lock_send_buf); - - IOT_FUNC_EXIT_RC(ret) -} - -ssize_t coap_message_recv(CoAPClient *client, uint32_t timeout_ms) -{ - IOT_FUNC_ENTRY - - size_t read_lean = 0; - int rc = 0; - - rc = client->network_stack.read(&client->network_stack, client->recv_buf, client->read_buf_size, timeout_ms, &read_lean); - switch(rc) { - case QCLOUD_ERR_SUCCESS: - _coap_message_handle(client, client->recv_buf, read_lean); - break; - case QCLOUD_ERR_SSL_READ_TIMEOUT: - break; - default: - break; - } - - IOT_FUNC_EXIT_RC(rc) -} - -#ifdef __cplusplus -} -#endif - - diff --git a/src/configs/default_settings.mk b/src/configs/default_settings.mk deleted file mode 100755 index 96cc92c7..00000000 --- a/src/configs/default_settings.mk +++ /dev/null @@ -1,22 +0,0 @@ -SUBDIRS := directory-not-exist-actually - -PLATFORM_CC ?= gcc -PLATFORM_AR ?= ar -PLATFORM_OS ?= linux - -FEATURE_MQTT_COMM_ENABLED ?= y -FEATURE_MQTT_DEVICE_SHADOW ?= $(FEATURE_MQTT_COMM_ENABLED) -FEATURE_COAP_COMM_ENABLED ?= n -FEATURE_NBIOT_COMM_ENABLED ?= n -FEATURE_OTA_COMM_ENABLED ?= n -FEATURE_LOG_UPLOAD_ENABLED ?= y # 是否打开日志上报云端功能 -FEATURE_SYSTEM_COMM_ENABLED ?= y # 是否打开系统通讯(获取iot后台时间等)功能 - -FEATURE_SDKTESTS_ENABLED ?= n #是否开启单元测试编译 仅支持linux -FEATURE_MQTT_RMDUP_MSG_ENABLED ?= n #是否开启MQTT消息去重能力 -FEATURE_GATEWAY_ENABLED ?= n #是否打开网关功能 -FEATURE_MULTITHREAD_TEST_ENABLED ?= n #是否编译多线程测试例程 - -CFLAGS += -DFORCE_SSL_VERIFY - -DEBUG_MAKEFILE = n diff --git a/src/configs/settings.mk b/src/configs/settings.mk deleted file mode 100644 index f3a1430f..00000000 --- a/src/configs/settings.mk +++ /dev/null @@ -1,35 +0,0 @@ -# Basic Settings -# -SHELL := /bin/bash -TOP_DIR ?= $(CURDIR) - -# Settings of input directory -# -CONFIG_DIR := $(TOP_DIR)/src/configs -SCRIPT_DIR := $(TOP_DIR)/src/scripts - -# Settings of output directory -# -TEMP_DIR := $(TOP_DIR)/tmp -DIST_DIR := $(TOP_DIR)/output -FINAL_DIR := $(DIST_DIR)/release - -# Thirdparty libs directory -THIRD_PARTY_PATH := $(TOP_DIR)/external_libs -TEST_LIB_DIR := $(THIRD_PARTY_PATH)/googletest - -# Sample directory -SAMPLE_DIR := $(TOP_DIR)/samples - -# Test directory -TESTS_DIR := $(TOP_DIR)/sdk-tests - -# Settings of makefile echo -# -ifeq ($(DEBUG_MAKEFILE),n) - Q := @ - TOP_Q := @ -else - Q := - TOP_Q := -endif \ No newline at end of file diff --git a/src/device/src/device.c b/src/device/src/device.c deleted file mode 100644 index c183d37b..00000000 --- a/src/device/src/device.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "device.h" - -#include -#include - -static DeviceInfo sg_device_info; -static bool sg_devinfo_initialized; - -int iot_device_info_init() { - if (sg_devinfo_initialized) { - Log_e("device info has been initialized."); - return 0; - } - - memset(&sg_device_info, 0x0, sizeof(DeviceInfo)); - sg_devinfo_initialized = true; - - return QCLOUD_ERR_SUCCESS; -} - -int iot_device_info_set(const char *product_id, const char *device_name) { - - memset(&sg_device_info, 0x0, sizeof(DeviceInfo)); - if ((MAX_SIZE_OF_PRODUCT_ID) < strlen(product_id)) - { - Log_e("product name(%s) length:(%lu) exceeding limitation", product_id, strlen(product_id)); - return QCLOUD_ERR_FAILURE; - } - if ((MAX_SIZE_OF_DEVICE_NAME) < strlen(device_name)) - { - Log_e("device name(%s) length:(%lu) exceeding limitation", device_name, strlen(device_name)); - return QCLOUD_ERR_FAILURE; - } - - strncpy(sg_device_info.product_id, product_id, MAX_SIZE_OF_PRODUCT_ID); - strncpy(sg_device_info.device_name, device_name, MAX_SIZE_OF_DEVICE_NAME); - - /* construct device-id(@product_id+@device_name) */ - memset(sg_device_info.client_id, 0x0, MAX_SIZE_OF_CLIENT_ID); - int ret = HAL_Snprintf(sg_device_info.client_id, MAX_SIZE_OF_CLIENT_ID, "%s%s", product_id, device_name); - if ((ret < 0) || (ret >= MAX_SIZE_OF_CLIENT_ID)) { - Log_e("set device info failed"); - return QCLOUD_ERR_FAILURE; - } - - Log_i("SDK_Ver: %s, Product_ID: %s, Device_Name: %s", QCLOUD_IOT_DEVICE_SDK_VERSION, product_id, device_name); - return QCLOUD_ERR_SUCCESS; -} - -DeviceInfo* iot_device_info_get(void) -{ - return &sg_device_info; -} - -#ifdef __cplusplus -} -#endif diff --git a/src/gateway/include/gateway_common.h b/src/gateway/include/gateway_common.h deleted file mode 100644 index 4cf089cd..00000000 --- a/src/gateway/include/gateway_common.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef IOT_GATEWAY_COMMON_H_ -#define IOT_GATEWAY_COMMON_H_ - -#include "qcloud_iot_export.h" - -#define GATEWAY_PAYLOAD_BUFFER_LEN 1024 -#define GATEWAY_RECEIVE_BUFFER_LEN 1024 -#define GATEWAY_LOOP_MAX_COUNT 100 - - -/* The format of operation of gateway topic */ -#define GATEWAY_TOPIC_OPERATION_FMT "$gateway/operation/%s/%s" - -/* The format of operation result of gateway topic */ -#define GATEWAY_TOPIC_OPERATION_RESULT_FMT "$gateway/operation/result/%s/%s" - -/* The format of gateway client id */ -#define GATEWAY_CLIENT_ID_FMT "%s/%s" - -/* The format of operation result of gateway topic */ -#define GATEWAY_PAYLOAD_STATUS_FMT "{\"type\":\"%s\",\"payload\":{\"devices\":[{\"product_id\":\"%s\",\"device_name\":\"%s\"}]}}" - - - -/* Subdevice seesion status */ -typedef enum _SubdevSessionStatus { - /* Initial */ - SUBDEV_SEESION_STATUS_INIT, - - /* Online */ - SUBDEV_SEESION_STATUS_ONLINE, - - /* Offline */ - SUBDEV_SEESION_STATUS_OFFLINE, - - /* Maximum number of seesion status type */ - SUBDEV_SEESION_STATUS_MAX -}SubdevSessionStatus; - -/* The structure of subdevice session */ -typedef struct _SubdevSession { - char product_id[MAX_SIZE_OF_PRODUCT_ID+1]; - char device_name[MAX_SIZE_OF_DEVICE_NAME+1]; - SubdevSessionStatus session_status; - struct _SubdevSession *next; -} SubdevSession; - - -/* The structure of common reply data */ -typedef struct _ReplyData{ - int32_t result; - char client_id[MAX_SIZE_OF_CLIENT_ID+1]; -}ReplyData; - - -/* The structure of gateway data */ -typedef struct _GatewayData { - int32_t sync_status; - ReplyData online; - ReplyData offline; -} GatewayData; - - -/* The structure of gateway context */ -typedef struct _Gateway { - void *mqtt; - SubdevSession *session_list; - GatewayData gateway_data; - MQTTEventHandler event_handle; - int is_construct; -} Gateway; - - -SubdevSession* subdev_add_session(Gateway *gateway, char *product_id, char *device_name); - -SubdevSession* subdev_find_session(Gateway *gateway, char *product_id, char *device_name); - -int subdev_remove_session(Gateway *gateway, char *product_id, char *device_name); - -int gateway_subscribe_unsubscribe_topic(Gateway *gateway, char *topic_filter, SubscribeParams *params, int is_subscribe); - -int gateway_subscribe_unsubscribe_default(Gateway *gateway, GatewayParam* param); - -int gateway_publish_sync(Gateway *gateway, char *topic, PublishParams *params, int32_t *result); - -#endif /* IOT_GATEWAY_COMMON_H_ */ diff --git a/src/gateway/src/gateway_api.c b/src/gateway/src/gateway_api.c deleted file mode 100755 index dcf1bb65..00000000 --- a/src/gateway/src/gateway_api.c +++ /dev/null @@ -1,299 +0,0 @@ -#include - -#include "qcloud_iot_sdk_impl_internal.h" - -#include "gateway_common.h" -#include "mqtt_client.h" - - -Gateway g_gateway = {0}; - -void _gateway_event_handler(void *client, void *context, MQTTEventMsg *msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - Gateway* gateway = (Gateway*)context; - - POINTER_SANITY_CHECK_RTN(context); - POINTER_SANITY_CHECK_RTN(msg); - MQTTMessage* topic_info = (MQTTMessage*)msg->msg; - - switch (msg->event_type) { - case MQTT_EVENT_SUBCRIBE_SUCCESS: - case MQTT_EVENT_UNSUBCRIBE_SUCCESS: - Log_d("gateway sub|unsub(%d) success, packet-id=%u", msg->event_type, (unsigned int)packet_id); - if (gateway->gateway_data.sync_status == packet_id) { - gateway->gateway_data.sync_status = 0; - return; - } - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - case MQTT_EVENT_SUBCRIBE_NACK: - case MQTT_EVENT_UNSUBCRIBE_NACK: - Log_d("gateway timeout|nack(%d) event, packet-id=%u", msg->event_type, (unsigned int)packet_id); - if (gateway->gateway_data.sync_status == packet_id) { - gateway->gateway_data.sync_status = -1; - return; - } - break; - - case MQTT_EVENT_PUBLISH_RECVEIVED: - Log_d("gateway topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - topic_info->topic_len, - topic_info->ptopic, - topic_info->payload_len, - topic_info->payload); - break; - - default: - break; - } - - if (gateway->event_handle.h_fp != NULL) { - gateway->event_handle.h_fp(client, gateway->event_handle.context, msg); - } - - return; -} - - -void* IOT_Gateway_Construct(GatewayInitParam* init_param) -{ - int rc = 0; - GatewayParam param = DEFAULT_GATEWAY_PARAMS; - POINTER_SANITY_CHECK(init_param, NULL); - - if (g_gateway.is_construct) { - Log_e("gateway have been construct"); - IOT_FUNC_EXIT_RC(NULL); - } - - memset(&g_gateway, 0, sizeof(Gateway)); - - /* replace user event handle */ - g_gateway.event_handle.h_fp = init_param->init_param.event_handle.h_fp; - g_gateway.event_handle.context = init_param->init_param.event_handle.context; - - /* set _gateway_event_handler as mqtt event handle */ - init_param->init_param.event_handle.h_fp = _gateway_event_handler; - init_param->init_param.event_handle.context = &g_gateway; - - /* construct MQTT client */ - g_gateway.mqtt = IOT_MQTT_Construct(&init_param->init_param); - if (NULL == g_gateway.mqtt) { - Log_e("construct MQTT failed"); - IOT_FUNC_EXIT_RC(NULL); - } - - /* subscribe default topic */ - param.product_id = init_param->init_param.product_id; - param.device_name = init_param->init_param.device_name; - rc = gateway_subscribe_unsubscribe_default(&g_gateway, ¶m); - if (QCLOUD_ERR_SUCCESS != rc) { - Log_e("subscribe default topic failed"); - IOT_Gateway_Destroy((void*)&g_gateway); - IOT_FUNC_EXIT_RC(NULL); - } - - g_gateway.is_construct = 1; - - return &g_gateway; -} - - -int IOT_Gateway_Subdev_Online(void *client, GatewayParam* param) -{ - int rc = 0; - char topic[MAX_SIZE_OF_CLOUD_TOPIC +1] = {0}; - char payload[GATEWAY_PAYLOAD_BUFFER_LEN +1] = {0}; - int size = 0; - SubdevSession* session = NULL; - PublishParams params = DEFAULT_PUB_PARAMS; - Gateway* gateway = (Gateway*)client; - - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(param, QCLOUD_ERR_INVAL); - - STRING_PTR_SANITY_CHECK(param->product_id, QCLOUD_ERR_INVAL); - STRING_PTR_SANITY_CHECK(param->device_name, QCLOUD_ERR_INVAL); - STRING_PTR_SANITY_CHECK(param->subdev_product_id, QCLOUD_ERR_INVAL); - STRING_PTR_SANITY_CHECK(param->subdev_device_name, QCLOUD_ERR_INVAL); - - session = subdev_find_session(gateway, param->subdev_product_id, param->subdev_device_name); - if (NULL == session) { - Log_d("there is no session, create a new session"); - - /* create subdev session */ - session = subdev_add_session(gateway, param->subdev_product_id, param->subdev_device_name); - if (NULL == session) { - Log_e("create session error!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_CREATE_SESSION_FAIL); - } - } else { - if (SUBDEV_SEESION_STATUS_ONLINE == session->session_status) { - Log_i("device have online"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_SUBDEV_ONLINE); - } - } - - - size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC+1, GATEWAY_TOPIC_OPERATION_FMT, param->product_id, param->device_name); - if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) - { - Log_e("buf size < topic length!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - - size = HAL_Snprintf(payload, GATEWAY_PAYLOAD_BUFFER_LEN+1, GATEWAY_PAYLOAD_STATUS_FMT, "online", param->subdev_product_id, param->subdev_device_name); - if (size < 0 || size > GATEWAY_PAYLOAD_BUFFER_LEN) - { - Log_e("buf size < payload length!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - size = HAL_Snprintf(gateway->gateway_data.online.client_id, MAX_SIZE_OF_CLIENT_ID, GATEWAY_CLIENT_ID_FMT, param->subdev_product_id, param->subdev_device_name); - if (size < 0 || size > MAX_SIZE_OF_CLIENT_ID) - { - Log_e("buf size < client_id length!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - gateway->gateway_data.online.result = -1; - - params.qos = QOS0; - params.payload_len = strlen(payload); - params.payload = (char *) payload; - - - /* publish packet */ - rc = gateway_publish_sync(gateway, topic, ¶ms, &gateway->gateway_data.online.result); - if (QCLOUD_ERR_SUCCESS != rc) { - subdev_remove_session(gateway, param->subdev_product_id, param->subdev_device_name); - IOT_FUNC_EXIT_RC(rc); - } - - session->session_status = SUBDEV_SEESION_STATUS_ONLINE; - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - - -int IOT_Gateway_Subdev_Offline(void *client, GatewayParam* param) -{ - int rc = 0; - char topic[MAX_SIZE_OF_CLOUD_TOPIC+1] = {0}; - char payload[GATEWAY_PAYLOAD_BUFFER_LEN+1] = {0}; - int size = 0; - SubdevSession* session = NULL; - Gateway* gateway = (Gateway*)client; - - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(param, QCLOUD_ERR_INVAL); - - STRING_PTR_SANITY_CHECK(param->product_id, QCLOUD_ERR_INVAL); - STRING_PTR_SANITY_CHECK(param->device_name, QCLOUD_ERR_INVAL); - STRING_PTR_SANITY_CHECK(param->subdev_product_id, QCLOUD_ERR_INVAL); - STRING_PTR_SANITY_CHECK(param->subdev_device_name, QCLOUD_ERR_INVAL); - - session = subdev_find_session(gateway, param->subdev_product_id, param->subdev_device_name); - if (NULL == session) { - Log_d("no session, can not offline"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_SESSION_NO_EXIST); - - } - if (SUBDEV_SEESION_STATUS_OFFLINE == session->session_status) { - Log_i("device have offline"); - /* free session */ - subdev_remove_session(gateway, param->subdev_product_id, param->subdev_device_name); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_SUBDEV_OFFLINE); - } - - size = HAL_Snprintf(topic, MAX_SIZE_OF_CLOUD_TOPIC+1, GATEWAY_TOPIC_OPERATION_FMT, param->product_id, param->device_name); - if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) - { - Log_e("buf size < topic length!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - - size = HAL_Snprintf(payload, GATEWAY_PAYLOAD_BUFFER_LEN+1, GATEWAY_PAYLOAD_STATUS_FMT, "offline", param->subdev_product_id, param->subdev_device_name); - if (size < 0 || size > GATEWAY_PAYLOAD_BUFFER_LEN) - { - Log_e("buf size < payload length!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - size = HAL_Snprintf(gateway->gateway_data.offline.client_id, MAX_SIZE_OF_CLIENT_ID, GATEWAY_CLIENT_ID_FMT, param->subdev_product_id, param->subdev_device_name); - if (size < 0 || size > MAX_SIZE_OF_CLIENT_ID) - { - Log_e("buf size < client_id length!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - gateway->gateway_data.offline.result = -1; - - - - PublishParams params = DEFAULT_PUB_PARAMS; - params.qos = QOS0; - params.payload_len = strlen(payload); - params.payload = (char *) payload; - - /* publish packet */ - rc = gateway_publish_sync(gateway, topic, ¶ms, &gateway->gateway_data.offline.result); - if (QCLOUD_ERR_SUCCESS != rc) { - IOT_FUNC_EXIT_RC(rc); - } - - session->session_status = SUBDEV_SEESION_STATUS_OFFLINE; - - /* free session */ - subdev_remove_session(gateway, param->subdev_product_id, param->subdev_device_name); - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - - -int IOT_Gateway_Destroy(void *client) -{ - Gateway* gateway = (Gateway*)client; - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - - return IOT_MQTT_Destroy(&gateway->mqtt); -} - - -int IOT_Gateway_Yield(void *client, uint32_t timeout_ms) -{ - Gateway* gateway = (Gateway*)client; - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - - return IOT_MQTT_Yield(gateway->mqtt, timeout_ms); -} - -int IOT_Gateway_Subscribe(void *client, char *topic_filter, SubscribeParams *params) -{ - Gateway* gateway = (Gateway*)client; - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - - return IOT_MQTT_Subscribe(gateway->mqtt, topic_filter, params); -} - - -int IOT_Gateway_Unsubscribe(void *client, char *topic_filter) -{ - Gateway* gateway = (Gateway*)client; - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - - return IOT_MQTT_Unsubscribe(gateway->mqtt, topic_filter); -} - - -int IOT_Gateway_Publish(void *client, char *topic_name, PublishParams *params) -{ - Gateway* gateway = (Gateway*)client; - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - - return IOT_MQTT_Publish(gateway->mqtt, topic_name, params); - -} - diff --git a/src/gateway/src/gateway_common.c b/src/gateway/src/gateway_common.c deleted file mode 100755 index 4590aa01..00000000 --- a/src/gateway/src/gateway_common.c +++ /dev/null @@ -1,344 +0,0 @@ - -#include "lite-utils.h" -#include "mqtt_client.h" -#include "gateway_common.h" - -#define min(a,b) (a) < (b) ? (a) : (b) - -static char cloud_rcv_buf[GATEWAY_RECEIVE_BUFFER_LEN]; - - -static bool get_json_type(char *json, char **v) { - *v= LITE_json_value_of("type", json); - return *v == NULL ? false : true; -} - -static bool get_json_devices(char *json, char **v) { - *v = LITE_json_value_of("payload.devices", json); - return *v == NULL ? false: true; -} - -static bool get_json_result(char *json, int32_t* res) { - char *v = LITE_json_value_of("result", json); - if (v == NULL) { - return false; - } - if (LITE_get_int32(res, v) != QCLOUD_ERR_SUCCESS) { - HAL_Free(v); - return false; - } - HAL_Free(v); - return true; -} - -static bool get_json_product_id(char *json, char **v) { - *v = LITE_json_value_of("product_id", json); - return *v == NULL ? false: true; -} - - -static bool get_json_device_name(char *json, char **v) { - *v = LITE_json_value_of("device_name", json); - return *v == NULL ? false: true; -} - -static void _gateway_message_handler(void *client, MQTTMessage *message, void *user_data) -{ - Qcloud_IoT_Client *mqtt = NULL; - Gateway *gateway = NULL; - char *topic = NULL; - size_t topic_len = 0; - int cloud_rcv_len = 0; - char *type = NULL; - char *devices = NULL, *devices_strip = NULL; - char *product_id = NULL; - char *device_name = NULL; - int32_t result = 0; - char client_id[MAX_SIZE_OF_CLIENT_ID+1] = {0}; - int size = 0; - - POINTER_SANITY_CHECK_RTN(client); - POINTER_SANITY_CHECK_RTN(message); - - mqtt = (Qcloud_IoT_Client *)client; - gateway = (Gateway*)mqtt->event_handle.context; - POINTER_SANITY_CHECK_RTN(gateway); - - topic = (char *)message->ptopic; - topic_len = message->topic_len; - if (NULL == topic || topic_len <= 0) { - Log_e("topic == NULL or topic_len <= 0."); - return; - } - - if (message->payload_len > GATEWAY_RECEIVE_BUFFER_LEN) { - Log_e("message->payload_len > GATEWAY_RECEIVE_BUFFER_LEN."); - return; - } - - cloud_rcv_len = min(GATEWAY_RECEIVE_BUFFER_LEN - 1, message->payload_len); - memcpy(cloud_rcv_buf, message->payload, cloud_rcv_len + 1); - cloud_rcv_buf[cloud_rcv_len] = '\0'; // jsmn_parse relies on a string - - if (!get_json_type(cloud_rcv_buf, &type)) - { - Log_e("Fail to parse type from msg: %s", cloud_rcv_buf); - return; - } - - if (!get_json_devices(cloud_rcv_buf, &devices)) - { - Log_e("Fail to parse devices from msg: %s", cloud_rcv_buf); - HAL_Free(type); - return; - } - - if(devices[0] == '[') { - devices_strip = devices+1; - } else { - devices_strip = devices; - } - - if (!get_json_result(devices_strip, &result)) { - Log_e("Fail to parse result from msg: %s", cloud_rcv_buf); - HAL_Free(type); - HAL_Free(devices); - return; - } - if (!get_json_product_id(devices_strip, &product_id)) { - Log_e("Fail to parse product_id from msg: %s", cloud_rcv_buf); - HAL_Free(type); - HAL_Free(devices); - return; - } - if (!get_json_device_name(devices_strip, &device_name)) { - Log_e("Fail to parse device_name from msg: %s", cloud_rcv_buf); - HAL_Free(type); - HAL_Free(devices); - HAL_Free(product_id); - return; - } - - size = HAL_Snprintf(client_id, MAX_SIZE_OF_CLIENT_ID+1, GATEWAY_CLIENT_ID_FMT, product_id, device_name); - if (size < 0 || size > MAX_SIZE_OF_CLIENT_ID){ - Log_e("generate client_id fail."); - HAL_Free(type); - HAL_Free(devices); - HAL_Free(product_id); - HAL_Free(device_name); - return; - } - - - if (strncmp(type, "online", sizeof("online")-1) == 0) { - if(strncmp(client_id, gateway->gateway_data.online.client_id, size) == 0) { - Log_i("client_id(%s), online success. result %d", client_id, result); - gateway->gateway_data.online.result = result; - } - } else if(strncmp(type, "offline", sizeof("offline")-1) == 0) { - if(strncmp(client_id, gateway->gateway_data.offline.client_id, size) == 0) { - Log_i("client_id(%s), offline success. result %d", client_id, result); - gateway->gateway_data.offline.result = result; - } - } - - HAL_Free(type); - HAL_Free(devices); - HAL_Free(product_id); - HAL_Free(device_name); - return; - -} - -int gateway_subscribe_unsubscribe_topic(Gateway *gateway, char *topic_filter, SubscribeParams *params, int is_subscribe) -{ - int rc = 0; - int loop_count = 0; - uint32_t status = -1; - - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(params, QCLOUD_ERR_INVAL); - - STRING_PTR_SANITY_CHECK(topic_filter, QCLOUD_ERR_INVAL); - - params->qos = QOS1; - gateway->gateway_data.sync_status = status; - - if (is_subscribe) { - /* subscribe */ - rc = IOT_MQTT_Subscribe(gateway->mqtt, topic_filter, params); - } else { - /* unsubscribe */ - rc = IOT_MQTT_Unsubscribe(gateway->mqtt, topic_filter); - } - - if (rc < 0) { - Log_e("subscribe or un(%d), result(%d)", is_subscribe, rc); - IOT_FUNC_EXIT_RC(rc); - } - - gateway->gateway_data.sync_status = status = rc; - while (status == gateway->gateway_data.sync_status) { - if (loop_count > GATEWAY_LOOP_MAX_COUNT) { - Log_i("loop max count, time out"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - IOT_Gateway_Yield(gateway, 200); - loop_count++; - } - - if(gateway->gateway_data.sync_status != 0) { - Log_e("gateway->gateway_data.sync_status(%u) != 0", gateway->gateway_data.sync_status); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - -int gateway_subscribe_unsubscribe_default(Gateway *gateway, GatewayParam *param) -{ - int rc = 0; - int size = 0; - char topic_filter[MAX_SIZE_OF_CLOUD_TOPIC+1] = {0}; - SubscribeParams subscribe_params = DEFAULT_SUB_PARAMS; - - POINTER_SANITY_CHECK(param, QCLOUD_ERR_INVAL); - - STRING_PTR_SANITY_CHECK(param->product_id, QCLOUD_ERR_INVAL); - STRING_PTR_SANITY_CHECK(param->device_name, QCLOUD_ERR_INVAL); - - //subscribe online/offline operation reslut - size = HAL_Snprintf(topic_filter, MAX_SIZE_OF_CLOUD_TOPIC+1, GATEWAY_TOPIC_OPERATION_RESULT_FMT, param->product_id, param->device_name); - if (size < 0 || size > MAX_SIZE_OF_CLOUD_TOPIC) - { - Log_e("buf size < topic length!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - subscribe_params.on_message_handler = _gateway_message_handler; - rc = gateway_subscribe_unsubscribe_topic(gateway, topic_filter, &subscribe_params, IOT_TRUE); - if (QCLOUD_ERR_SUCCESS != rc) { - IOT_FUNC_EXIT_RC(rc); - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - -SubdevSession* subdev_find_session(Gateway *gateway, char *product_id, char *device_name) -{ - SubdevSession* session = NULL; - - POINTER_SANITY_CHECK(gateway, NULL); - STRING_PTR_SANITY_CHECK(product_id, NULL); - STRING_PTR_SANITY_CHECK(device_name, NULL); - - session = gateway->session_list; - - /* session is exist */ - while(session) { - if (0 == strncmp(session->product_id, product_id, strlen(product_id)) && - 0 == strncmp(session->device_name, device_name, strlen(device_name))) { - IOT_FUNC_EXIT_RC(session); - } - session = session->next; - } - - IOT_FUNC_EXIT_RC(NULL); -} - -SubdevSession* subdev_add_session(Gateway *gateway, char *product_id, char *device_name) -{ - SubdevSession* session = NULL; - - POINTER_SANITY_CHECK(gateway, NULL); - STRING_PTR_SANITY_CHECK(product_id, NULL); - STRING_PTR_SANITY_CHECK(device_name, NULL); - - session = HAL_Malloc(sizeof(SubdevSession)); - if(session == NULL) { - Log_e("Not enough memory"); - IOT_FUNC_EXIT_RC(NULL); - } - - /* add session to list */ - session->next = gateway->session_list; - gateway->session_list = session; - - int size = strlen(product_id); - strncpy(session->product_id, product_id, size); - session->product_id[size] = '\0'; - size = strlen(device_name); - strncpy(session->device_name, device_name, size); - session->device_name[size] = '\0'; - session->session_status = SUBDEV_SEESION_STATUS_INIT; - - IOT_FUNC_EXIT_RC(session); -} - -int subdev_remove_session(Gateway *gateway, char *product_id, char *device_name) -{ - SubdevSession* cur_session = NULL; - SubdevSession* pre_session = NULL; - - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_FAILURE); - STRING_PTR_SANITY_CHECK(product_id, QCLOUD_ERR_FAILURE); - STRING_PTR_SANITY_CHECK(device_name, QCLOUD_ERR_FAILURE); - - pre_session = cur_session = gateway->session_list; - - if (NULL == cur_session) { - Log_e("session list is empty"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); - } - - /* session is exist */ - while(cur_session) { - if (0 == strncmp(cur_session->product_id, product_id, strlen(product_id)) && - 0 == strncmp(cur_session->device_name, device_name, strlen(device_name)) ) { - if (cur_session == gateway->session_list) { - gateway->session_list = cur_session->next; - } else { - pre_session->next = cur_session->next; - } - HAL_Free(cur_session); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); - } - pre_session = cur_session; - cur_session = cur_session->next; - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); -} - - -int gateway_publish_sync(Gateway *gateway, char *topic, PublishParams *params, int32_t *result) -{ - int rc = 0; - int loop_count = 0; - int32_t res = *result; - - POINTER_SANITY_CHECK(gateway, QCLOUD_ERR_INVAL); - - rc = IOT_Gateway_Publish(gateway, topic, params); - if(rc != QCLOUD_ERR_SUCCESS) { - Log_e("publish fail."); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - /* wait for response */ - while (res == *result) { - if (loop_count > GATEWAY_LOOP_MAX_COUNT) { - Log_i("loop max count, time out."); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_GATEWAY_SESSION_TIMEOUT); - } - - IOT_Gateway_Yield(gateway, 200); - loop_count++; - } - - if(*result != 0) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - diff --git a/src/mqtt/include/mqtt_client.h b/src/mqtt/include/mqtt_client.h deleted file mode 100755 index 1b49efd6..00000000 --- a/src/mqtt/include/mqtt_client.h +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef IOT_MQTT_CLIENT_H_ -#define IOT_MQTT_CLIENT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" - -#include "mqtt_client_net.h" - -#include "utils_timer.h" -#include "utils_list.h" - -/* 报文id最大值 */ -#define MAX_PACKET_ID (65535) - -/* 连接标识字符串最大长度 */ -#define MAX_CONN_ID_LEN (6) - -/* 成功订阅主题的最大个数 */ -#define MAX_MESSAGE_HANDLERS (10) - -/* 在列表中最大的重新发布数量 */ -#define MAX_REPUB_NUM (20) - -/* 重连最小等待时间 */ -#define MIN_RECONNECT_WAIT_INTERVAL (1000) - -/* MQTT报文最小超时时间 */ -#define MIN_COMMAND_TIMEOUT (500) - -/* MQTT报文最大超时时间 */ -#define MAX_COMMAND_TIMEOUT (5000) - -/* 云端保留主题的最大长度 */ -#define MAX_SIZE_OF_CLOUD_TOPIC ((MAX_SIZE_OF_DEVICE_NAME) + (MAX_SIZE_OF_PRODUCT_ID) + 64 + 6) - -/** - * @brief MQTT Message Type - */ -typedef enum msgTypes { - RESERVED = 0, // Reserved - CONNECT = 1, // Client request to connect to Server - CONNACK = 2, // Connect Acknowledgment - PUBLISH = 3, // Publish message - PUBACK = 4, // Publish Acknowledgment - PUBREC = 5, // Publish Received - PUBREL = 6, // Publish Release - PUBCOMP = 7, // Publish Complete - SUBSCRIBE = 8, // Client Subscribe request - SUBACK = 9, // Subscribe Acknowledgment - UNSUBSCRIBE = 10, // Client Unsubscribe request - UNSUBACK = 11, // Unsubscribe Acknowledgment - PINGREQ = 12, // PING Request - PINGRESP = 13, // PING Response - DISCONNECT = 14 // Client is Disconnecting -} MessageTypes; - -typedef enum { - NOTCONNECTED = 0, - CONNECTED = 1 -} ConnStatus; - - -/** - * MQTT byte 1: fixed header - * bits |7654: Message Type | 3:DUP flag | 21:QoS level | 0:RETAIN | - */ -#define MQTT_HEADER_TYPE_SHIFT 0x04 -#define MQTT_HEADER_TYPE_MASK 0xF0 -#define MQTT_HEADER_DUP_SHIFT 0x03 -#define MQTT_HEADER_DUP_MASK 0x08 -#define MQTT_HEADER_QOS_SHIFT 0x01 -#define MQTT_HEADER_QOS_MASK 0x06 -#define MQTT_HEADER_RETAIN_MASK 0x01 - - -/** - * @brief MQTT 遗嘱消息参数结构体定义 - * - * 当客户端异常断开连接, 若客户端在连接时有设置遗嘱消息, 服务端会发布遗嘱消息。 - */ -typedef struct { - char struct_id[4]; // The eyecatcher for this structure. must be MQTW - uint8_t struct_version; // 结构体 0 - char *topic_name; // 遗嘱消息主题名 - char *message; // 遗嘱消息负载部分数据 - uint8_t retained; // 遗嘱消息retain标志位 - QoS qos; // 遗嘱消息qos标志位 -} WillOptions; - -/** - * MQTT遗嘱消息结构体默认值定义 - */ -#define DEFAULT_WILL_OPTIONS { {'M', 'Q', 'T', 'W'}, 0, NULL, NULL, 0, QOS0 } - -/** - * @brief MQTT 连接参数结构体定义 - * - */ -typedef struct { - char *client_id; // 客户端标识符, 请保持唯一 - char *username; // 用户名 - char *password; // 密码 - - char conn_id[MAX_CONN_ID_LEN]; - - char struct_id[4]; // The eyecatcher for this structure. must be MQTC. - uint8_t struct_version; // 结构体版本号, 必须为0 - uint8_t mqtt_version; // MQTT版本协议号 4 = 3.1.1 - - uint16_t keep_alive_interval; // 心跳周期, 单位: s - uint8_t clean_session; // 清理会话标志位, 具体含义请参考MQTT协议说明文档3.1.2.4小结 - - uint8_t auto_connect_enable; // 是否开启自动重连 - -#ifdef AUTH_WITH_NOTLS - char *device_secret; // 预置密钥 - int device_secret_len; // 预置密钥长度 -#endif - -} MQTTConnectParams; - -/** - * MQTT连接参数结构体默认值定义 - */ -#ifdef AUTH_WITH_NOTLS -#define DEFAULT_MQTTCONNECT_PARAMS { NULL, NULL, NULL, {0}, {'M', 'Q', 'T', 'C'}, 0, 4, 240, 1, 1, NULL} -#else -#define DEFAULT_MQTTCONNECT_PARAMS { NULL, NULL, NULL, {0}, {'M', 'Q', 'T', 'C'}, 0, 4, 240, 1, 1} -#endif - -/** - * @brief 订阅主题对应的消息处理结构体定义 - */ -typedef struct SubTopicHandle { - const char *topic_filter; // 订阅主题名, 可包含通配符 - OnMessageHandler message_handler; // 订阅主题消息回调函数指针 - void *message_handler_data; // 用户数据, 通过回调函数返回 - QoS qos; // 服务质量等级 -} SubTopicHandle; - -/** - * @brief IoT Client结构体定义 - */ -typedef struct Client { - uint8_t is_connected; // 网络是否连接 - uint8_t was_manually_disconnected; // 是否手动断开连接 - uint8_t is_ping_outstanding; // 心跳包是否未完成, 即未收到服务器响应 - - uint16_t next_packet_id; // MQTT报文标识符 - uint32_t command_timeout_ms; // MQTT消息超时时间, 单位:ms - - uint32_t current_reconnect_wait_interval; // MQTT重连周期, 单位:ms - uint32_t counter_network_disconnected; // 网络断开连接次数 - - size_t write_buf_size; // 消息接收buffer长度 - size_t read_buf_size; // 消息接收buffer长度 - unsigned char write_buf[QCLOUD_IOT_MQTT_TX_BUF_LEN]; // MQTT消息发送buffer - unsigned char read_buf[QCLOUD_IOT_MQTT_RX_BUF_LEN]; // MQTT消息接收buffer - - void *lock_generic; // client原子锁 - void *lock_write_buf; // 输出流的锁 - - void *lock_list_pub; // 等待发布消息ack列表的锁 - void *lock_list_sub; // 等待订阅消息ack列表的锁 - - List *list_pub_wait_ack; // 等待发布消息ack列表 - List *list_sub_wait_ack; // 等待订阅消息ack列表 - - MQTTEventHandler event_handle; // 事件句柄 - - MQTTConnectParams options; // 连接相关参数 - - Network network_stack; // MQTT底层使用的网络参数 - - Timer ping_timer; // MQTT心跳包发送定时器 - Timer reconnect_delay_timer; // MQTT重连定时器, 判断是否已到重连时间 - - SubTopicHandle sub_handles[MAX_MESSAGE_HANDLERS]; // 订阅主题对应的消息处理结构数组 - -} Qcloud_IoT_Client; - -/** - * @brief MQTT协议版本 - */ -typedef enum { - MQTT_3_1_1 = 4 -} MQTT_VERSION; - - -typedef enum MQTT_NODE_STATE { - MQTT_NODE_STATE_NORMANL = 0, - MQTT_NODE_STATE_INVALID, -} MQTTNodeState; - -/* 记录已经发布的topic的信息 */ -typedef struct REPUBLISH_INFO { - Timer pub_start_time; /* 发布的时间 */ - MQTTNodeState node_state; /* 节点状态 */ - uint16_t msg_id; /* 发布消息的packet id */ - uint32_t len; /* 消息长度 */ - unsigned char *buf; /* 消息内容 */ -} QcloudIotPubInfo; - -/* 记录已经订阅的topic的信息 */ -typedef struct SUBSCRIBE_INFO { - enum msgTypes type; /* 类型, (sub or unsub) */ - uint16_t msg_id; /* 订阅/取消订阅的 packet id */ - Timer sub_start_time; /* 订阅的开始时间 */ - MQTTNodeState node_state; /* 节点状态 */ - SubTopicHandle handler; /* handle of topic subscribed(unsubcribed) */ - uint16_t len; /* 消息长度 */ - unsigned char *buf; /* 消息内容 */ -} QcloudIotSubInfo; - -/** - * @brief 对结构体Client进行初始化 - * - * @param pClient MQTT客户端结构体 - * @param pParams MQTT客户端初始化参数 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int qcloud_iot_mqtt_init(Qcloud_IoT_Client *pClient, MQTTInitParams *pParams); - -/** - * @brief 建立基于TLS的MQTT连接 - * - * 注意: Client ID不能为NULL或空字符串 - * - * @param pClient MQTT客户端结构体 - * @param pParams MQTT连接相关参数, 可参考MQTT协议说明 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int qcloud_iot_mqtt_connect(Qcloud_IoT_Client *pClient, MQTTConnectParams *pParams); - -/** - * @brief 与服务器重新建立MQTT连接 - * - * 1. 与服务器重新建立MQTT连接 - * 2. 连接成功后, 重新订阅之前的订阅过的主题 - * - * @param pClient MQTT Client结构体 - * - * @return 返回QCLOUD_ERR_MQTT_RECONNECTED, 表示重连成功 - */ -int qcloud_iot_mqtt_attempt_reconnect(Qcloud_IoT_Client *pClient); - -/** - * @brief 断开MQTT连接 - * - * @param pClient MQTT Client结构体 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int qcloud_iot_mqtt_disconnect(Qcloud_IoT_Client *pClient); - -/** - * @brief 发布MQTT消息 - * - * @param pClient MQTT客户端结构体 - * @param topicName 主题名 - * @param pParams 发布参数 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int qcloud_iot_mqtt_publish(Qcloud_IoT_Client *pClient, char *topicName, PublishParams *pParams); - -/** - * @brief 订阅MQTT主题 - * - * @param pClient MQTT客户端结构体 - * @param topicFilter 主题过滤器, 可参考MQTT协议说明 4.7 - * @param pParams 订阅参数 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int qcloud_iot_mqtt_subscribe(Qcloud_IoT_Client *pClient, char *topicFilter, SubscribeParams *pParams); - -/** - * @brief 重新订阅断开连接之前已订阅的主题 - * - * @param pClient MQTT客户端结构体 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int qcloud_iot_mqtt_resubscribe(Qcloud_IoT_Client *pClient); - -/** - * @brief 取消订阅已订阅的MQTT主题 - * - * @param pClient MQTT客户端结构体 - * @param topicFilter 主题过滤器, 可参考MQTT协议说明 4.7 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int qcloud_iot_mqtt_unsubscribe(Qcloud_IoT_Client *pClient, char *topicFilter); - -/** - * @brief 在当前线程为底层MQTT客户端让出一定CPU执行时间 - * - * 在这段时间内, MQTT客户端会用用处理消息接收, 以及发送PING报文, 监控网络状态 - * - * @param pClient MQTT Client结构体 - * @param timeout_ms Yield操作超时时间 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功, 返回QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT, 表示正在重连 - */ -int qcloud_iot_mqtt_yield(Qcloud_IoT_Client *pClient, uint32_t timeout_ms); - -/** - * @brief 客户端自动重连是否开启 - * - * @param pClient MQTT客户端结构体 - * @return 返回true, 表示客户端已开启自动重连功能 - */ -bool qcloud_iot_mqtt_is_autoreconnect_enabled(Qcloud_IoT_Client *pClient); - -/** - * @brief 设置客户端是否开启自动重连 - * - * @param pClient MQTT客户端结构体 - * @param value 是否开启该功能 - * @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功 - */ -int qcloud_iot_mqtt_set_autoreconnect(Qcloud_IoT_Client *pClient, bool value); - -/** - * @brief 获取网络断开的次数 - * - * @param pClient MQTT Client结构体 - * @return 返回客户端MQTT网络断开的次数 - */ -int qcloud_iot_mqtt_get_network_disconnected_count(Qcloud_IoT_Client *pClient); - -/** - * @brief 重置连接断开次数 - * - * @param pClient MQTT Client结构体 - * @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功 - */ -int qcloud_iot_mqtt_reset_network_disconnected_count(Qcloud_IoT_Client *pClient); - -/** - * @brief 获取报文标识符 - * - * @param pClient - * @return - */ -uint16_t get_next_packet_id(Qcloud_IoT_Client *pClient); - -/** - * @brief 获取连接唯一标识connid - * - * @param options - * @return - */ -void get_next_conn_id(char *conn_id); - -/** - * - * @param header - * @param message_type - * @param qos - * @param dup - * @param retained - * @return - */ -int mqtt_init_packet_header(unsigned char *header, MessageTypes message_type, QoS qos, uint8_t dup, uint8_t retained); - -/** - * @brief 接收服务端消息 - * - * @param pClient - * @param timer - * @param packet_type - * @param qos - * @return - */ -int cycle_for_read(Qcloud_IoT_Client *pClient, Timer *timer, uint8_t *packet_type, QoS qos); - -/** - * @brief 发送报文数据 - * - * @param pClient Client结构体 - * @param length 报文长度 - * @param timer 定时器 - * @return - */ -int send_mqtt_packet(Qcloud_IoT_Client *pClient, size_t length, Timer *timer); - -/** - * @brief 等待指定类型的MQTT控制报文 - * - * only used in single-threaded mode where one command at a time is in process - * - * @param pClient MQTT Client结构体 - * @param packet_type 控制报文类型 - * @param timer 定时器 - * @return - */ -int wait_for_read(Qcloud_IoT_Client *pClient, uint8_t packet_type, Timer *timer, QoS qos); - -/** - * @brief 设置MQTT当前连接状态 - * - * @param pClient Client结构体 - * @param connected 0: 连接断开状态 1: 已连接状态 - * @return - */ -void set_client_conn_state(Qcloud_IoT_Client *pClient, uint8_t connected); - -/** - * @brief 获取MQTT当前连接状态 - * - * @param pClient Client结构体 - * @return 0: 连接断开状态 1: 已连接状态 - */ -uint8_t get_client_conn_state(Qcloud_IoT_Client *pClient); - -/** - * @brief 检查 Publish ACK 等待列表,若有成功接收或者超时,则将对应节点从列表中移除 - * - * @param pClient MQTT客户端 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int qcloud_iot_mqtt_pub_info_proc(Qcloud_IoT_Client *pClient); - -/** - * @brief 检查 Subscribe ACK 等待列表,若有成功接收或者超时,则将对应节点从列表中移除 - * - * @param pClient MQTT客户端 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int qcloud_iot_mqtt_sub_info_proc(Qcloud_IoT_Client *pClient); - -int push_sub_info_to(Qcloud_IoT_Client *c, int len, unsigned short msgId, MessageTypes type, - SubTopicHandle *handler, ListNode **node); - -int serialize_pub_ack_packet(unsigned char *buf, size_t buf_len, MessageTypes packet_type, uint8_t dup, - uint16_t packet_id, - uint32_t *serialized_len); - -int serialize_packet_with_zero_payload(unsigned char *buf, size_t buf_len, MessageTypes packetType, uint32_t *serialized_len); - -int deserialize_publish_packet(unsigned char *dup, QoS *qos, uint8_t *retained, uint16_t *packet_id, char **topicName, - uint16_t *topicNameLen, unsigned char **payload, size_t *payload_len, unsigned char *buf, size_t buf_len); - -int deserialize_suback_packet(uint16_t *packet_id, uint32_t max_count, uint32_t *count, - QoS *grantedQoSs, unsigned char *buf, size_t buf_len); - -int deserialize_unsuback_packet(uint16_t *packet_id, unsigned char *buf, size_t buf_len); - -int deserialize_ack_packet(uint8_t *packet_type, uint8_t *dup, uint16_t *packet_id, unsigned char *buf, size_t buf_len); - -#ifdef MQTT_RMDUP_MSG_ENABLED - -void reset_repeat_packet_id_buffer(void); - -#endif -/** - * @brief 根据剩余长度计算整个MQTT报文的长度 - * - * @param rem_len 剩余长度 - * @return 整个MQTT报文的长度 - */ -size_t get_mqtt_packet_len(size_t rem_len); - -size_t mqtt_write_packet_rem_len(unsigned char *buf, uint32_t length); - -int mqtt_read_packet_rem_len_form_buf(unsigned char *buf, uint32_t *value, uint32_t *readBytesLen); - -uint16_t mqtt_read_uint16_t(unsigned char **pptr); - -unsigned char mqtt_read_char(unsigned char **pptr); - -void mqtt_write_char(unsigned char **pptr, unsigned char c); - -void mqtt_write_uint_16(unsigned char **pptr, uint16_t anInt); - -void mqtt_write_utf8_string(unsigned char **pptr, const char *string); - -#ifdef __cplusplus -} -#endif - -#endif //IOT_MQTT_CLIENT_H_ diff --git a/src/mqtt/src/mqtt_client.c b/src/mqtt/src/mqtt_client.c deleted file mode 100644 index 4c08fecb..00000000 --- a/src/mqtt/src/mqtt_client.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#include "mqtt_client.h" - -#include "ca.h" -#include "device.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_export.h" - -#include "utils_base64.h" -#include "utils_list.h" -#include "log_upload.h" -#include "lite-utils.h" - -#define HOST_STR_LENGTH 64 -static char s_qcloud_iot_host[HOST_STR_LENGTH] = {0}; -#ifdef AUTH_WITH_NOTLS -static int s_qcloud_iot_port = 1883; -#else -static int s_qcloud_iot_port = 8883; -#endif - -#ifndef AUTH_MODE_CERT -#define DECODE_PSK_LENGTH 48 /*控制台允许的最大长度为64,对应到原文最大长度64/4*3 = 48*/ -static unsigned char sg_psk_str[DECODE_PSK_LENGTH]; -#endif - - - -static uint16_t _get_random_start_packet_id(void) -{ - srand((unsigned)time(NULL)); - return rand() % 65536 + 1; -} - -void* IOT_MQTT_Construct(MQTTInitParams *pParams) -{ - POINTER_SANITY_CHECK(pParams, NULL); - STRING_PTR_SANITY_CHECK(pParams->product_id, NULL); - STRING_PTR_SANITY_CHECK(pParams->device_name, NULL); - - iot_device_info_init(); - if (iot_device_info_set(pParams->product_id, pParams->device_name) != QCLOUD_ERR_SUCCESS) - { - Log_e("failed to set device info!"); - return NULL; - } - - Qcloud_IoT_Client* mqtt_client = NULL; - - // 初始化MQTTClient - if ((mqtt_client = (Qcloud_IoT_Client*) HAL_Malloc (sizeof(Qcloud_IoT_Client))) == NULL) { - Log_e("malloc MQTTClient failed"); - return NULL; - } - - int rc = qcloud_iot_mqtt_init(mqtt_client, pParams); - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("mqtt init failed: %d", rc); - HAL_Free(mqtt_client); - return NULL; - } - - MQTTConnectParams connect_params = DEFAULT_MQTTCONNECT_PARAMS; - connect_params.client_id = iot_device_info_get()->client_id; - // 超过11.5分钟的心跳间隔自动转为11.5(11.5 * 60)的时长 - connect_params.keep_alive_interval = Min(pParams->keep_alive_interval_ms / 1000, 690); - connect_params.clean_session = pParams->clean_session; - connect_params.auto_connect_enable = pParams->auto_connect_enable; -#if defined(AUTH_WITH_NOTLS) && defined(AUTH_MODE_KEY) - size_t src_len = strlen(pParams->device_secret); - size_t len; - memset(sg_psk_str, 0x00, DECODE_PSK_LENGTH); - rc = qcloud_iot_utils_base64decode(sg_psk_str, sizeof( sg_psk_str ), &len, (unsigned char *)pParams->device_secret, src_len ); - connect_params.device_secret = (char *)sg_psk_str; - connect_params.device_secret_len = len; - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("Device secret decode err, secret:%s", pParams->device_secret); - HAL_Free(mqtt_client); - return NULL; - } -#endif - - rc = qcloud_iot_mqtt_connect(mqtt_client, &connect_params); - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("mqtt connect with id: %s failed: %d", mqtt_client->options.conn_id, rc); - HAL_Free(mqtt_client); - return NULL; - } - else { - Log_i("mqtt connect with id: %s success", mqtt_client->options.conn_id); - } - -#ifdef LOG_UPLOAD - //log subscribe topics - int log_level; - rc = qcloud_get_log_level(mqtt_client, &log_level); - //rc = qcloud_log_topic_subscribe(mqtt_client); - if (rc < 0) { - Log_e("client get log topic failed: %d", rc); - } - set_log_mqtt_client((void *)mqtt_client); - - IOT_Log_Upload(true); -#endif - - return mqtt_client; -} - -int IOT_MQTT_Destroy(void **pClient) { - POINTER_SANITY_CHECK(*pClient, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)(*pClient); - - int rc = qcloud_iot_mqtt_disconnect(mqtt_client); - -#ifdef MQTT_RMDUP_MSG_ENABLED - reset_repeat_packet_id_buffer(); -#endif - - HAL_MutexDestroy(mqtt_client->lock_generic); - HAL_MutexDestroy(mqtt_client->lock_write_buf); - - HAL_MutexDestroy(mqtt_client->lock_list_sub); - HAL_MutexDestroy(mqtt_client->lock_list_pub); - - list_destroy(mqtt_client->list_pub_wait_ack); - list_destroy(mqtt_client->list_sub_wait_ack); - - HAL_Free(*pClient); - *pClient = NULL; -#ifdef LOG_UPLOAD - set_log_mqtt_client(NULL); -#endif - Log_i("mqtt release!"); - - return rc; -} - -int IOT_MQTT_Yield(void *pClient, uint32_t timeout_ms) { - - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - int rc = qcloud_iot_mqtt_yield(mqtt_client, timeout_ms); - -#ifdef LOG_UPLOAD - /* do instant log uploading if MQTT communication error */ - if (rc == QCLOUD_ERR_SUCCESS) - IOT_Log_Upload(false); - else - IOT_Log_Upload(true); -#endif - - return rc; -} - -int IOT_MQTT_Publish(void *pClient, char *topicName, PublishParams *pParams) { - - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - - return qcloud_iot_mqtt_publish(mqtt_client, topicName, pParams); -} - -int IOT_MQTT_Subscribe(void *pClient, char *topicFilter, SubscribeParams *pParams) { - - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - - return qcloud_iot_mqtt_subscribe(mqtt_client, topicFilter, pParams); -} - -int IOT_MQTT_Unsubscribe(void *pClient, char *topicFilter) { - - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - - return qcloud_iot_mqtt_unsubscribe(mqtt_client, topicFilter); -} - -bool IOT_MQTT_IsConnected(void *pClient) { - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - - IOT_FUNC_EXIT_RC(get_client_conn_state(mqtt_client) == 1) -} - -int qcloud_iot_mqtt_init(Qcloud_IoT_Client *pClient, MQTTInitParams *pParams) { - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(pParams, QCLOUD_ERR_INVAL); - - memset(pClient, 0x0, sizeof(Qcloud_IoT_Client)); - - int size = HAL_Snprintf(s_qcloud_iot_host, HOST_STR_LENGTH, "%s.%s", pParams->product_id, QCLOUD_IOT_MQTT_DIRECT_DOMAIN); - if (size < 0 || size > HOST_STR_LENGTH - 1) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - int i = 0; - for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) { - pClient->sub_handles[i].topic_filter = NULL; - pClient->sub_handles[i].message_handler = NULL; - pClient->sub_handles[i].qos = QOS0; - pClient->sub_handles[i].message_handler_data = NULL; - } - - if (pParams->command_timeout < MIN_COMMAND_TIMEOUT) - pParams->command_timeout = MIN_COMMAND_TIMEOUT; - if (pParams->command_timeout > MAX_COMMAND_TIMEOUT) - pParams->command_timeout = MAX_COMMAND_TIMEOUT; - pClient->command_timeout_ms = pParams->command_timeout; - - // packet id 取随机数 1- 65536 - pClient->next_packet_id = _get_random_start_packet_id(); - pClient->write_buf_size = QCLOUD_IOT_MQTT_TX_BUF_LEN; - pClient->read_buf_size = QCLOUD_IOT_MQTT_RX_BUF_LEN; - pClient->is_ping_outstanding = 0; - pClient->was_manually_disconnected = 0; - pClient->counter_network_disconnected = 0; - - pClient->event_handle = pParams->event_handle; - - pClient->lock_generic = HAL_MutexCreate(); - if (NULL == pClient->lock_generic) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE); - } - - set_client_conn_state(pClient, NOTCONNECTED); - - if ((pClient->lock_write_buf = HAL_MutexCreate()) == NULL) { - Log_e("create write buf lock failed."); - goto error; - } - if ((pClient->lock_list_sub = HAL_MutexCreate()) == NULL) { - Log_e("create sub list lock failed."); - goto error; - } - if ((pClient->lock_list_pub = HAL_MutexCreate()) == NULL) { - Log_e("create pub list lock failed."); - goto error; - } - - if ((pClient->list_pub_wait_ack = list_new()) == NULL) { - Log_e("create pub wait list failed."); - goto error; - } - pClient->list_pub_wait_ack->free = HAL_Free; - - if ((pClient->list_sub_wait_ack = list_new()) == NULL) { - Log_e("create sub wait list failed."); - goto error; - } - pClient->list_sub_wait_ack->free = HAL_Free; - -#ifndef AUTH_WITH_NOTLS - // TLS连接参数初始化 -#ifdef AUTH_MODE_CERT - bool certEmpty = (pParams->cert_file == NULL || pParams->key_file == NULL); - if (certEmpty) { - Log_e("cert file or key file is empty!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - } - Log_d("cert file: %s", pParams->cert_file); - Log_d("key file: %s", pParams->key_file); - - pClient->network_stack.ssl_connect_params.cert_file = pParams->cert_file; - pClient->network_stack.ssl_connect_params.key_file = pParams->key_file; - pClient->network_stack.ssl_connect_params.ca_crt = iot_ca_get(); - pClient->network_stack.ssl_connect_params.ca_crt_len = strlen(pClient->network_stack.ssl_connect_params.ca_crt); -#else - if (pParams->device_secret != NULL) { - size_t src_len = strlen(pParams->device_secret); - size_t len; - memset(sg_psk_str, 0x00, DECODE_PSK_LENGTH); - qcloud_iot_utils_base64decode(sg_psk_str, sizeof( sg_psk_str ), &len, (unsigned char *)pParams->device_secret, src_len ); - pClient->network_stack.ssl_connect_params.psk = (char *)sg_psk_str; - pClient->network_stack.ssl_connect_params.psk_length = len; - } else { - Log_e("psk is empty!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - } - pClient->network_stack.ssl_connect_params.psk_id = iot_device_info_get()->client_id; - if (iot_device_info_get()->client_id == NULL) { - Log_e("psk id is empty!"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL); - } - pClient->network_stack.ssl_connect_params.ca_crt = iot_ca_get(); - pClient->network_stack.ssl_connect_params.ca_crt_len = strlen(pClient->network_stack.ssl_connect_params.ca_crt); -#endif - - pClient->network_stack.host = s_qcloud_iot_host; - pClient->network_stack.port = s_qcloud_iot_port; - pClient->network_stack.ssl_connect_params.timeout_ms = QCLOUD_IOT_TLS_HANDSHAKE_TIMEOUT; - -#else - pClient->network_stack.host = s_qcloud_iot_host; - pClient->network_stack.port = s_qcloud_iot_port; -#endif - - // 底层网络操作相关的数据结构初始化 - qcloud_iot_mqtt_network_init(&(pClient->network_stack)); - - // ping定时器以及重连延迟定时器相关初始化 - InitTimer(&(pClient->ping_timer)); - InitTimer(&(pClient->reconnect_delay_timer)); - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); - -error: - if (pClient->list_pub_wait_ack) { - pClient->list_pub_wait_ack->free(pClient->list_pub_wait_ack); - pClient->list_pub_wait_ack = NULL; - } - if (pClient->list_sub_wait_ack) { - pClient->list_sub_wait_ack->free(pClient->list_sub_wait_ack); - pClient->list_sub_wait_ack = NULL; - } - if (pClient->lock_generic) { - HAL_MutexDestroy(pClient->lock_generic); - pClient->lock_generic = NULL; - } - if (pClient->lock_list_sub) { - HAL_MutexDestroy(pClient->lock_list_sub); - pClient->lock_list_sub = NULL; - } - if (pClient->lock_list_pub) { - HAL_MutexDestroy(pClient->lock_list_pub); - pClient->lock_list_pub = NULL; - } - if (pClient->lock_write_buf) { - HAL_MutexDestroy(pClient->lock_write_buf); - pClient->lock_write_buf = NULL; - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE) -} - -int qcloud_iot_mqtt_set_autoreconnect(Qcloud_IoT_Client *pClient, bool value) { - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - pClient->options.auto_connect_enable = (uint8_t) value; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - -bool qcloud_iot_mqtt_is_autoreconnect_enabled(Qcloud_IoT_Client *pClient) { - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - bool is_enabled = false; - if (pClient->options.auto_connect_enable == 1) { - is_enabled = true; - } - - IOT_FUNC_EXIT_RC(is_enabled); -} - -int qcloud_iot_mqtt_get_network_disconnected_count(Qcloud_IoT_Client *pClient) { - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - IOT_FUNC_EXIT_RC(pClient->counter_network_disconnected); -} - -int qcloud_iot_mqtt_reset_network_disconnected_count(Qcloud_IoT_Client *pClient) { - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - pClient->counter_network_disconnected = 0; - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - -#ifdef __cplusplus -} -#endif diff --git a/src/nbiot/src/nbiot_client.c b/src/nbiot/src/nbiot_client.c deleted file mode 100644 index 3628e517..00000000 --- a/src/nbiot/src/nbiot_client.c +++ /dev/null @@ -1,395 +0,0 @@ -#include -#include -#include -#include - -#include "utils_base64.h" -#include "utils_hmac.h" -#include "qcloud_iot_sdk_impl_internal.h" - -#define MAX_SIZE_DATA 1024 -#define MAX_SIZE_TOKEN 1024 -#define DECODE_PSK_LENGTH 48 /*̨󳤶Ϊ64Ӧԭ󳤶64/4*3 = 48*/ - -#define ADDRESS_SIZE 1 -#define LENGTH_SIZE 2 -#define VERSION_SIZE 1 -#define SIGNATURE_SIZE 1 -#define EXPIRY_SIZE 4 -#define TLV_CNT_SIZE 2 -#define T_SIZE 1 -#define L_SIZE 2 -#define V4_SIZE 4 -#define V5_SIZE 1 - -static uint32_t seq = 0; - -typedef enum tlvType { - TLV_TYPE_TOPIC = 1, - TLV_TYPE_TOKEN, - TLV_TYPE_PAYLOAD, - TLV_TYPE_SEQ, - TLV_TYPE_QOS, -} TlvType; - -int toBigEnd32(unsigned char* buf, uint32_t x) -{ - POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); - - buf[0] = (x >> 24) & 0xFF; - buf[1] = (x >> 16) & 0xFF; - buf[2] = (x >> 8) & 0xFF; - buf[3] = x & 0xFF; - //Log_d("%x, %x, %x, %x" , buf[0], buf[1], buf[2], buf[3]); - return QCLOUD_ERR_SUCCESS; -} - -int toBigEnd16(unsigned char* buf, uint16_t x) -{ - POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); - - *buf = ((x) & 0xFF00) >> 8 ; - *(buf+1) = (x) & 0xFF ; - - //Log_d("buf[0]: %x buf[1]: %x", *buf, *(buf+1)); - return QCLOUD_ERR_SUCCESS; -} - -int ntohBig32(uint32_t* x, unsigned char* buf) -{ - POINTER_SANITY_CHECK(x, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); - - *x = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]; - - return QCLOUD_ERR_SUCCESS; -} - -int ntohBig16(uint16_t* x, unsigned char* buf) -{ - POINTER_SANITY_CHECK(x, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); - - *x = (buf[0] << 8) + buf[1]; - - return QCLOUD_ERR_SUCCESS; -} - -void StrToHex(char *pbDest, char *pbSrc, int nLen) -{ - char h1,h2,s1,s2; - int i; - for (i=0; i < nLen; i++) - { - h1 = pbSrc[2*i]; - h2 = pbSrc[2*i + 1]; - s1 = toupper(h1) - 0x30; - if (s1 > 9) - s1 -= 7; - - s2 = toupper(h2) - 0x30; - if (s2 > 9) - s2 -= 7; - - pbDest[i] = s1*16 + s2; - } -} - -int calToken(char* token, int* tokenSize, const unsigned char* keyBase64, char* topic, uint32_t expiry, uint8_t qos, char* payload) -{ - POINTER_SANITY_CHECK(token, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(keyBase64, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(topic, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(payload, QCLOUD_ERR_INVAL); - - size_t len = 0; - - static unsigned char psk_str[DECODE_PSK_LENGTH] = {0}; - char buffer[256] = {0}; - char strTok[256] = {0}; - size_t keyBase64Len = strlen((const char*)keyBase64); - char bufferTemp[11] = {0}; - const char* semicolon = ";"; - - qcloud_iot_utils_base64decode(psk_str, sizeof( psk_str ), &len, keyBase64, keyBase64Len); - Log_d("psk_str: %s, len: %ld, keyBase64: %s, len: %ld", psk_str, len, keyBase64, keyBase64Len); - - strncpy(buffer, topic, strlen(topic)); - strncat(buffer, semicolon, sizeof(char)); - //Log_d("buffer = %s, len = %ld", buffer, strlen(buffer)); - - sprintf(bufferTemp, "%u", expiry); - //Log_d("bufferTemp = %s", bufferTemp); - strncat(buffer, bufferTemp, strlen(bufferTemp)); - strncat(buffer, semicolon, sizeof(char)); - //Log_d("buffer = %s, len = %ld", buffer, strlen(buffer)); - - sprintf(bufferTemp, "%u", seq); - strncat(buffer, bufferTemp, sizeof(char)*4); - strncat(buffer, semicolon, sizeof(char)); - //Log_d("buffer = %s, len = %ld", buffer, strlen(buffer)); - - sprintf(bufferTemp, "%u", qos); - strncat(buffer, bufferTemp, strlen(bufferTemp)); - strncat(buffer, semicolon, sizeof(char)); - //Log_d("buffer = %s, len = %ld", buffer, strlen(buffer)); - - strncat(buffer, payload, strlen(payload)); - //Log_d("buffer = %s, len = %ld", buffer, strlen(buffer)); - - utils_hmac_sha1(buffer, strlen(buffer), strTok, (const char*)psk_str, strlen((char*)psk_str)); - - //Log_d("token = %s, len = %ld", token, *tokenSize); - StrToHex(token, strTok, 20); - *tokenSize = 20; - - return QCLOUD_ERR_SUCCESS; -} - -int addTLV(unsigned char* buf, uint8_t type, char* value) -{ - POINTER_SANITY_CHECK(buf, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(value, QCLOUD_ERR_INVAL); - unsigned char* ptr = buf; - uint16_t length = strlen(value); - - // write type - *ptr = type; - ptr += sizeof(uint8_t); - - // write length - toBigEnd16(ptr, length); - ptr += sizeof(uint16_t); - - // write value - strncpy((char* )ptr, value, length); - ptr += sizeof(uint16_t); - //Log_d("buf[0]:%2x, buf[1]:%2x, buf[2]:%2x",*buf, *(buf+1), *(buf+2)); - - return QCLOUD_ERR_SUCCESS; -} - -int IOT_NB_setMessage(unsigned char* msg, unsigned int* length, NBIoTSetMessage* nbiotMsg) -{ - POINTER_SANITY_CHECK(msg, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(length, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(nbiotMsg, QCLOUD_ERR_INVAL); - - uint16_t v1Size = strlen(nbiotMsg->topic); - if( v1Size > MAX_SIZE_TOPIC ) - { - Log_e("Topic size is %d, oversize MAX_SIZE_TOPIC %d", v1Size, MAX_SIZE_TOPIC); - return QCLOUD_ERR_FAILURE; - } - - uint16_t v3Size = strlen(nbiotMsg->payload); - if( v3Size > MAX_SIZE_PAYLOAD ) - { - Log_e("Payload size is %d, oversize MAX_SIZE_PAYLOAD %d", v3Size, MAX_SIZE_PAYLOAD); - return QCLOUD_ERR_FAILURE; - } - - uint16_t dataLen = 0; - - char token[41] = {0}; - unsigned char base64[MAX_SIZE_MESSAGE] = {0}; - size_t olen = 0; - int v2Size = 0; - static int seq = 0; - - unsigned char data[MAX_SIZE_MESSAGE] = {0}; - unsigned char* ptr = data; - - calToken(token, &v2Size, (const unsigned char*)nbiotMsg->key, nbiotMsg->topic, nbiotMsg->expiry, nbiotMsg->qos, nbiotMsg->payload); - //Log_d("token = %s, len = %d", token, v2Size); - - uint16_t dataLenRaw = VERSION_SIZE + SIGNATURE_SIZE + EXPIRY_SIZE + TLV_CNT_SIZE + T_SIZE*5 + L_SIZE*5 + v1Size + v2Size + v3Size + V4_SIZE + V5_SIZE; - - *ptr = nbiotMsg->version; - ptr += VERSION_SIZE; - - *ptr = nbiotMsg->sigType; - ptr += SIGNATURE_SIZE; - - toBigEnd32(ptr, nbiotMsg->expiry); - ptr += EXPIRY_SIZE; - - toBigEnd16(ptr, TLV_COUNT); - ptr += TLV_CNT_SIZE; - - // write tlv topic - addTLV(ptr, TLV_TYPE_TOPIC, nbiotMsg->topic); - ptr += (T_SIZE + L_SIZE + v1Size); - - // write tlv token - addTLV(ptr, TLV_TYPE_TOKEN, token); - ptr += (T_SIZE + L_SIZE + v2Size); - - // write tlv payload - addTLV(ptr, TLV_TYPE_PAYLOAD, nbiotMsg->payload); - ptr += (T_SIZE + L_SIZE + v3Size); - - // write tlv seq - *ptr = TLV_TYPE_SEQ; - ptr += T_SIZE; - toBigEnd16(ptr, V4_SIZE); - ptr += L_SIZE; - toBigEnd32(ptr, seq); - ptr += V4_SIZE; - seq++; - - // write tlv qos - *ptr = TLV_TYPE_QOS; - ptr += T_SIZE; - toBigEnd16(ptr, V5_SIZE); - ptr += L_SIZE; - *ptr = nbiotMsg->qos; - ptr += V5_SIZE; - - qcloud_iot_utils_base64encode( base64, MAX_SIZE_MESSAGE, &olen, (const unsigned char*)data, dataLenRaw ); - - ptr = msg; - - *ptr = nbiotMsg->address; - ptr += ADDRESS_SIZE; - - dataLen = strlen((const char*)base64); - - toBigEnd16(ptr, dataLen); - ptr += LENGTH_SIZE; - - strncpy((char*)ptr, (const char*)base64, dataLen); - - *length = ADDRESS_SIZE + LENGTH_SIZE + dataLen; - - return QCLOUD_ERR_SUCCESS; -} - -int IOT_NB_getMessage(NBIoTGetMessage* nbiotMsg, unsigned char* msg) -{ - POINTER_SANITY_CHECK(nbiotMsg, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(msg, QCLOUD_ERR_INVAL); - - size_t len = 0; - //uint16_t u16Temp = 0; - uint32_t u32Temp = 0; - uint32_t u32Seq = 0; - uint8_t u8Qos = 0; - - uint16_t u16TlvCnt = 0; - uint16_t v1Length = 0; - uint16_t v2Length = 0; - uint16_t v3Length = 0; - uint16_t v4Length = 0; - uint16_t v5Length = 0; - - - unsigned char* ptr = msg; - unsigned int dataLen = 0; - unsigned char data[MAX_SIZE_DATA] = {0}; - unsigned char dataRaw[MAX_SIZE_DATA] = {0}; - char value[MAX_SIZE_DATA] = {0}; - - nbiotMsg->address = ptr[0]; - dataLen = (ptr[1] << 8 )| ptr[2]; - Log_d("data length: 0x%x", dataLen); - - strncpy((char*)data, (char*)(ptr + ADDRESS_SIZE + LENGTH_SIZE), dataLen); - - qcloud_iot_utils_base64decode(dataRaw, sizeof( dataRaw ), &len, data, dataLen); - - ptr = dataRaw; - nbiotMsg->version = ptr[0]; - ptr += VERSION_SIZE; - - nbiotMsg->sigType = ptr[0]; - ptr += SIGNATURE_SIZE; - - ntohBig32(&u32Temp, ptr); - nbiotMsg->expiry = u32Temp; - ptr += EXPIRY_SIZE; - - ntohBig16(&u16TlvCnt, ptr); - ptr += TLV_CNT_SIZE; - Log_d("tlv count: %d", u16TlvCnt); - - if(ptr[0] == TLV_TYPE_TOPIC) - { - ptr += T_SIZE; - ntohBig16(&v1Length, ptr); - ptr += L_SIZE; - strncpy((char*)(nbiotMsg->topic), (char*)ptr, v1Length); - ptr += v1Length; - Log_d("v1Length: %d, topic: %s", v1Length, nbiotMsg->topic); - } - else - { - Log_e("parse tvl1 topic failed"); - return QCLOUD_ERR_FAILURE; - } - - if(ptr[0] == TLV_TYPE_TOKEN) - { - ptr += T_SIZE; - ntohBig16(&v2Length, ptr); - ptr += L_SIZE; - - strncpy(value, (char*)ptr, v2Length); - ptr += v2Length; - Log_d("v2Length: %d, value: %s", v2Length, value); - } - else - { - Log_e("parse tvl2 token failed"); - return QCLOUD_ERR_FAILURE; - } - - if(ptr[0] == TLV_TYPE_PAYLOAD) - { - ptr += T_SIZE; - ntohBig16(&v3Length, ptr); - ptr += L_SIZE; - - strncpy((char*)(nbiotMsg->payload), (char*)ptr, v3Length); - ptr += v3Length; - Log_d("v3Length: %d, payload: %s", v3Length, nbiotMsg->payload); - } - else - { - Log_e("parse tvl3 payload failed"); - return QCLOUD_ERR_FAILURE; - } - - if(ptr[0] == TLV_TYPE_SEQ) - { - ptr += T_SIZE; - ntohBig16(&v4Length, ptr); - ptr += L_SIZE; - ntohBig32(&u32Seq, ptr); - ptr += v4Length; - Log_d("v4Length: %d, seq: %d", v4Length, u32Seq); - } - else - { - Log_e("parse tvl4 seq failed"); - return QCLOUD_ERR_FAILURE; - } - - if(ptr[0] == TLV_TYPE_QOS) - { - ptr += T_SIZE; - ntohBig16(&v5Length, ptr); - ptr += L_SIZE; - u8Qos = ptr[0]; - Log_d("v1Length: %d, qos: %d", v1Length, u8Qos); - nbiotMsg->qos = u8Qos; - } - else - { - Log_e("parse tvl5 qos failed"); - return QCLOUD_ERR_FAILURE; - } - - - return QCLOUD_ERR_SUCCESS; -} diff --git a/src/ota/src/ota_coap.c b/src/ota/src/ota_coap.c deleted file mode 100644 index 11c7411e..00000000 --- a/src/ota/src/ota_coap.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "ota_client.h" - -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" - -typedef struct { - void *coap; - - const char *product_id; - const char *device_name; - - char topic_upgrade[OTA_MAX_TOPIC_LEN]; - - OnOTAMessageCallback msg_callback; - - void *context; -} OTA_CoAP_Struct_t; - -static void _otacoap_upgrage_cb(void* coap_message, void *pcontext) { - int ret_code = IOT_COAP_GetMessageCode(coap_message); - - switch (ret_code) { - case COAP_EVENT_RECEIVE_ACK: - Log_i("received OTA message ACK, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_RECEIVE_RESPCONTENT: - { - Log_i("received OTA message respconetent."); - char* payload = NULL; - int payload_len = 0; - int ret = -1; - ret = IOT_COAP_GetMessagePayload(coap_message, &payload, &payload_len); - if (ret == QCLOUD_ERR_SUCCESS) { - OTA_CoAP_Struct_t *handle = (OTA_CoAP_Struct_t *) pcontext; - if (NULL != handle->msg_callback) { - handle->msg_callback(handle->context, payload, payload_len); - } - } - else { - Log_e("message received response, content error."); - } - } - break; - case COAP_EVENT_UNAUTHORIZED: - Log_e("coap client auth token expired or invalid, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_FORBIDDEN: - Log_e("coap URI is invalid for this device, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_INTERNAL_SERVER_ERROR: - Log_e("coap server internal error, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_ACK_TIMEOUT: - Log_e("message receive ACK timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - case COAP_EVENT_SEPRESP_TIMEOUT: - Log_i("message received ACK but receive response timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message)); - break; - default: - break; - } -} - -/* Generate topic name according to @OTATopicType, @productId, @deviceName */ -/* and then copy to @buf. */ -/* 0, successful; -1, failed */ -static int _otacoap_gen_topic_name(char *buf, size_t bufLen, const char *OTATopicType, const char *productId, const char *deviceName) -{ - IOT_FUNC_ENTRY; - - int ret; - - ret = HAL_Snprintf(buf, bufLen, "$ota/%s/%s/%s", OTATopicType, productId, deviceName); - - if(ret >= bufLen) IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); - - if (ret < 0) { - Log_e("HAL_Snprintf failed"); - IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - -/* report progress of OTA */ -static int _otacoap_publish(OTA_CoAP_Struct_t *handle, const char *topicType, const char *msg, bool needResp) -{ - IOT_FUNC_ENTRY; - - int ret; - char topic_name[OTA_MAX_TOPIC_LEN]; - - SendMsgParams send_params = DEFAULT_SENDMSG_PARAMS; - send_params.pay_load = (void *)msg; - send_params.pay_load_len = strlen(msg); - send_params.resp_callback = _otacoap_upgrage_cb; - send_params.need_resp = needResp; - send_params.user_context = handle; - - /* inform OTA to topic: "/ota/device/progress/$(product_id)/$(device_name)" */ - ret = _otacoap_gen_topic_name(topic_name, OTA_MAX_TOPIC_LEN, topicType, handle->product_id, handle->device_name); - if (ret < 0) { - Log_e("generate topic name of info failed"); - IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL); - } - - ret = IOT_COAP_SendMessage(handle->coap, topic_name, &send_params); - if (ret < 0) { - Log_e("publish failed"); - IOT_FUNC_EXIT_RC(IOT_OTA_ERR_OSC_FAILED); - } - - IOT_FUNC_EXIT_RC(ret); -} - -void *qcloud_osc_init(const char *productId, const char *deviceName, void *channel, OnOTAMessageCallback callback, void *context) -{ - OTA_CoAP_Struct_t *h_osc = NULL; - - if (NULL == (h_osc = HAL_Malloc(sizeof(OTA_CoAP_Struct_t)))) { - Log_e("allocate for h_osc failed"); - goto do_exit; - } - - memset(h_osc, 0, sizeof(OTA_CoAP_Struct_t)); - - h_osc->coap = channel; - h_osc->product_id = productId; - h_osc->device_name = deviceName; - h_osc->msg_callback = callback; - h_osc->context = context; - - return h_osc; - -do_exit: - if (NULL != h_osc) { - HAL_Free(h_osc); - } - - return NULL; -} - -int qcloud_osc_deinit(void *handle) -{ - IOT_FUNC_ENTRY; - - if (NULL != handle) { - HAL_Free(handle); - } - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS); -} - -/* report progress of OTA */ -int qcloud_osc_report_progress(void *handle, const char *msg) -{ - return _otacoap_publish(handle, "report", msg, false); -} - -/* report version of OTA firmware */ -int qcloud_osc_report_version(void *handle, const char *msg) -{ - return _otacoap_publish(handle, "report", msg, true); -} - -/* report upgrade begin of OTA firmware */ -int qcloud_osc_report_upgrade_result(void *handle, const char *msg) -{ - return _otacoap_publish(handle, "report", msg, false); -} - -/* OSC, OTA signal channel */ - -#ifdef __cplusplus -} -#endif diff --git a/src/scripts/rules-final.mk b/src/scripts/rules-final.mk deleted file mode 100644 index fae840b2..00000000 --- a/src/scripts/rules-final.mk +++ /dev/null @@ -1,21 +0,0 @@ -final-out : - $(TOP_Q) \ - mkdir -p ${FINAL_DIR} ${DIST_DIR} ${FINAL_DIR}/lib \ - ${FINAL_DIR}/include ${FINAL_DIR}/bin ${FINAL_DIR}/src \ - ${FINAL_DIR}/unittest - - $(TOP_Q) \ - mv ${COMP_LIB} ${FINAL_DIR}/lib/ && \ - mv ${PLATFORM_LIB} ${FINAL_DIR}/lib - -ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) - $(TOP_Q) \ - mv ${TEMP_DIR}/*.a ${FINAL_DIR}/lib/ -endif - - $(TOP_Q) \ - rm -rf ${TEMP_DIR} - -.PHONY: mqtt_sample ota_mqtt_sample ota_coap_sample shadow_sample coap_sample nbiot_sample samples_final gateway_sample multi_thread_mqtt_sample - -final : mqtt_sample ota_mqtt_sample ota_coap_sample shadow_sample coap_sample nbiot_sample samples_final gateway_sample multi_thread_mqtt_sample diff --git a/src/sdk-impl/exports/qcloud_iot_export_coap.h b/src/sdk-impl/exports/qcloud_iot_export_coap.h deleted file mode 100644 index 6c8b080c..00000000 --- a/src/sdk-impl/exports/qcloud_iot_export_coap.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_EXPORT_COAP_H_ -#define QCLOUD_IOT_EXPORT_COAP_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -/** - * @brief CoAP needResp类型消息回调处理函数指针定义 - * - * @param message CoAP消息 - * @param userContext 发送消息时携带的用户上下文 - */ -typedef void (*OnRespCallback)(void *message, void *userContext); - -/** - * CoAP 事件类型 - */ -typedef enum { - COAP_EVENT_RECEIVE_ACK = 0, // 收到消息ACK - - COAP_EVENT_RECEIVE_RESPCONTENT = 1, // 收到消息回包响应 - - COAP_EVENT_UNAUTHORIZED = -1, // 设备鉴权失败或鉴权token过期 - - COAP_EVENT_FORBIDDEN = -2, // 设备topic无权限 - - COAP_EVENT_INTERNAL_SERVER_ERROR = -3, // 服务端错误 - - COAP_EVENT_ACK_TIMEOUT = -4, // 消息ACK超时 - - COAP_EVENT_SEPRESP_TIMEOUT = -5, // 消息回包响应超时 -} CoAPEventType; - -typedef struct { - /* 事件类型 */ - CoAPEventType event_type; - /* 事件消息 or 内容消息 */ - void *message; - -} CoAPEventMessage; - -typedef void (*CoAPEventHandleFunc)(void *pcontext, CoAPEventMessage *message); - -/* The structure of COAP event handle */ -typedef struct { - CoAPEventHandleFunc h_fp; - void *context; -} CoAPEventHandler; - -/** - * @brief COAP发布消息结构体 - */ -typedef struct { - bool need_resp; // true: 消息与第三方业务后台交互,等待业务回包,暂不支持;false: 表示数据上报,不需要业务回包 - char *pay_load; // COAP 消息负载 - size_t pay_load_len; // MQTT 消息负载长度 - void *user_context; // 用于用户传递的消息上下文,SDK不做处理在callback时返回 - OnRespCallback resp_callback; // 消息回包callback,仅对need_resp: true 有效 -} SendMsgParams; - -#define DEFAULT_SENDMSG_PARAMS {false, NULL, 0, NULL, NULL} - -/** - * CoAP客户端创建所需初始化参数结构体 - */ -typedef struct { - /* 设备基础信息 */ - char *product_id; // 产品名称 - char *device_name; // 设备名称 - -#ifdef AUTH_MODE_CERT - char *cert_file; // 客户端证书文件路径 - char *key_file; // 客户端私钥文件路径 -#else - char *device_secret; // 对称加密密钥 -#endif - - uint32_t command_timeout; // coap消息等待回包ACK/RESP超时 - - unsigned char max_retry_count; // CoAP消息列表最大节点数 - - CoAPEventHandler event_handle; // 事件回调 - -} CoAPInitParams; - -#ifdef AUTH_MODE_CERT - #define DEFAULT_COAPINIT_PARAMS { NULL, NULL, NULL, NULL, 2000, 5, {0}} -#else - #define DEFAULT_COAPINIT_PARAMS { NULL, NULL, NULL, 2000, 5, {0}} -#endif - -/** - * @brief 构造COAPClient并完成连接和鉴权 - * - * @param pParams COAP协议连接接入与连接维持阶段所需要的参数 - * - * @return 返回 NULL: 构造失败; 非NULL为COAPClient对象指针 - */ -void* IOT_COAP_Construct(CoAPInitParams *pParams); - -/** - * @brief 关闭COAP连接并销毁COAPClient - * - * @param pClient COAPClient对象地址 - * - */ -void IOT_COAP_Destroy(void **pClient); - -/** - * @brief 在当前线程为底层COAP客户端让出一定CPU执行时间 - * - * 在这段时间内, COAP客户端会用于处理消息接收 - * - * @param pClient COAP Client结构体 - * @param timeout_ms Yield操作超时时间 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功, 返回负数, 表示COAP网络出错 - */ -int IOT_COAP_Yield(void *pClient, uint32_t timeout_ms); - -/** - * @brief 发布COAP消息 - * - * @param pClient COAP客户端结构体 - * @param topicName 主题名 - * @param sendParams 消息参数 - * @return > 0, 消息Id; < 0, 表示失败 - */ -int IOT_COAP_SendMessage(void *pClient, char *topicName, SendMsgParams *sendParams); - -/** - * @brief 获取COAP Response消息msgId - * - * @param pMessage COAP Response消息 - * @return > 0, 消息id; < 0, 表示失败 - */ -int IOT_COAP_GetMessageId(void *pMessage); - -/** - * @brief 获取COAP Response消息内容 - * - * @param pMessage COAP Response消息 - * @param payload 消息负载 - * @param payloadLen 消息内容长度 - * @return QCLOUD_ERR_SUCCESS, 表示成功; < 0, 表示失败 - */ -int IOT_COAP_GetMessagePayload(void *pMessage, char **payload, int *payloadLen); - -/** - * @brief 获取COAP Response消息错误码 - * - * @param pMessage COAP Response消息 - * @return COAPEventType 错误码转换为event type,简单标识错误原因 - */ -int IOT_COAP_GetMessageCode(void *pMessage); - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_COAP_H_ */ diff --git a/src/sdk-impl/exports/qcloud_iot_export_error.h b/src/sdk-impl/exports/qcloud_iot_export_error.h deleted file mode 100644 index be987d4f..00000000 --- a/src/sdk-impl/exports/qcloud_iot_export_error.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_EXPORT_ERROR_H_ -#define QCLOUD_IOT_EXPORT_ERROR_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * IOT SDK 错误码 - */ -typedef enum { - QCLOUD_ERR_MQTT_ALREADY_CONNECTED = 4, // 表示与MQTT服务器已经建立连接 - QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED = 3, // 表示服务器接受客户端MQTT连接 - QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED = 2, // 表示与MQTT服务器已经手动断开 - QCLOUD_ERR_MQTT_RECONNECTED = 1, // 表示与MQTT服务器重连成功 - - QCLOUD_ERR_HTTP_CLOSED = -3, // 远程主机关闭连接 - QCLOUD_ERR_HTTP = -4, // HTTP未知错误 - QCLOUD_ERR_HTTP_PRTCL = -5, // 协议错误 - QCLOUD_ERR_HTTP_UNRESOLVED_DNS = -6, // 域名解析失败 - QCLOUD_ERR_HTTP_PARSE = -7, // URL解析失败 - QCLOUD_ERR_HTTP_CONN = -8, // HTTP连接失败 - QCLOUD_ERR_HTTP_AUTH = -9, // HTTP鉴权问题 - QCLOUD_ERR_HTTP_NOT_FOUND = -10, // HTTP 404 - QCLOUD_ERR_HTTP_TIMEOUT = -11, // HTTP 超时 - - QCLOUD_ERR_SUCCESS = 0, // 表示成功返回 - QCLOUD_ERR_FAILURE = -1001, // 表示失败返回 - QCLOUD_ERR_INVAL = -1002, // 表示参数无效错误 - - QCLOUD_ERR_MQTT_PUSH_TO_LIST_FAILED = -102, // 表示往等待 ACK 列表中添加元素失败 - QCLOUD_ERR_MQTT_NO_CONN = -103, // 表示未与MQTT服务器建立连接或已经断开连接 - QCLOUD_ERR_MQTT_UNKNOWN = -104, // 表示MQTT相关的未知错误 - QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT = -105, // 表示正在与MQTT服务重新建立连接 - QCLOUD_ERR_MQTT_RECONNECT_TIMEOUT = -106, // 表示重连已经超时 - QCLOUD_ERR_MQTT_MAX_SUBSCRIPTIONS = -107, // 表示超过可订阅的主题数 - QCLOUD_ERR_MQTT_SUB = -108, // 表示订阅主题失败, 即服务器拒绝 - QCLOUD_ERR_MQTT_NOTHING_TO_READ = -109, // 表示无MQTT相关报文可以读取 - QCLOUD_ERR_MQTT_PACKET_READ = -110, // 表示读取的MQTT报文有问题 - QCLOUD_ERR_MQTT_REQUEST_TIMEOUT = -111, // 表示MQTT相关操作请求超时 - QCLOUD_ERR_MQTT_CONNACK_UNKNOWN = -112, // 表示客户端MQTT连接未知错误 - QCLOUD_ERR_MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION = -113, // 表示客户端MQTT版本错误 - QCLOUD_ERR_MQTT_CONNACK_IDENTIFIER_REJECTED = -114, // 表示客户端标识符错误 - QCLOUD_ERR_MQTT_CONNACK_SERVER_UNAVAILABLE = -115, // 表示服务器不可用 - QCLOUD_ERR_MQTT_CONNACK_BAD_USERDATA = -116, // 表示客户端连接参数中的username或password错误 - QCLOUD_ERR_MQTT_CONNACK_NOT_AUTHORIZED = -117, // 表示客户端连接认证失败 - QCLOUD_ERR_RX_MESSAGE_INVAL = -118, // 表示收到的消息无效 - QCLOUD_ERR_BUF_TOO_SHORT = -119, // 表示消息接收缓冲区的长度小于消息的长度 - QCLOUD_ERR_MQTT_QOS_NOT_SUPPORT = -120, // 表示该QOS级别不支持 - QCLOUD_ERR_MQTT_UNSUB_FAIL = -121, // 表示取消订阅主题失败,比如该主题不存在 - - QCLOUD_ERR_JSON_PARSE = -132, // 表示JSON解析错误 - QCLOUD_ERR_JSON_BUFFER_TRUNCATED = -133, // 表示JSON文档会被截断 - QCLOUD_ERR_JSON_BUFFER_TOO_SMALL = -134, // 表示存储JSON文档的缓冲区太小 - QCLOUD_ERR_JSON = -135, // 表示JSON文档生成错误 - QCLOUD_ERR_MAX_JSON_TOKEN = -136, // 表示超过JSON文档中的最大Token数 - QCLOUD_ERR_MAX_APPENDING_REQUEST = -137, // 表示超过同时最大的文档请求 - QCLOUD_ERR_MAX_TOPIC_LENGTH = -138, // 表示超过规定最大的topic长度 - - QCLOUD_ERR_COAP_CONNRESET = -150, // COAP参数错误 - QCLOUD_ERR_COAP_NULL = -151, // 空指针 - QCLOUD_ERR_COAP_INVALID_LENGTH = -152, // COAP参数长度错误 - QCLOUD_ERR_COAP_DATA_SIZE = -153, // COAP数据大小超出限制 - QCLOUD_ERR_COAP_NOT_FOUND = -154, // COAP查找失败 - QCLOUD_ERR_COAP_NET_INIT_FAILED = -155, // COAP初始化失败 - QCLOUD_ERR_COAP_INTERNAL = -156, // COAP内部错误 - QCLOUD_ERR_COAP_WRITE_FAILED = -157, // COAP写数据失败 - QCLOUD_ERR_COAP_READ_FAILED = -158, // COAP读数据失败 - QCLOUD_ERR_COAP_BADMSG = -159, // COAPbad消息 - QCLOUD_ERR_COAP_TIMEOUT = -160, // COAP超时错误 - QCLOUD_ERR_DTLS_PEER_CLOSE_NOTIFY = -161, // 表示DTLS通道被关闭 - - QCLOUD_ERR_SHADOW_PROPERTY_EXIST = -201, // 表示注册的属性已经存在 - QCLOUD_ERR_SHADOW_NOT_PROPERTY_EXIST = -202, // 表示注册的属性不存在 - QCLOUD_ERR_SHADOW_UPDATE_TIMEOUT = -203, // 表示更新设备影子文档超时 - QCLOUD_ERR_SHADOW_UPDATE_REJECTED = -204, // 表示更新设备影子文档被拒绝 - QCLOUD_ERR_SHADOW_GET_TIMEOUT = -205, // 表示拉取设备影子文档超时 - QCLOUD_ERR_SHADOW_GET_REJECTED = -206, // 表示拉取设备影子文档被拒绝 - - QCLOUD_ERR_GATEWAY_CREATE_SESSION_FAIL = -221, //创建子设备session失败 - QCLOUD_ERR_GATEWAY_SESSION_NO_EXIST = -222, //子设备session不存在 - QCLOUD_ERR_GATEWAY_SESSION_TIMEOUT = -223, //子设备session超时 - QCLOUD_ERR_GATEWAY_SUBDEV_ONLINE = -224, //子设备已在线 - QCLOUD_ERR_GATEWAY_SUBDEV_OFFLINE = -225, //子设备已不在线 - - QCLOUD_ERR_TCP_SOCKET_FAILED = -601, // 表示TCP连接建立套接字失败 - QCLOUD_ERR_TCP_UNKNOWN_HOST = -602, // 表示无法通过主机名获取IP地址 - QCLOUD_ERR_TCP_CONNECT = -603, // 表示建立TCP连接失败 - QCLOUD_ERR_TCP_READ_TIMEOUT = -604, // 表示TCP读超时 - QCLOUD_ERR_TCP_WRITE_TIMEOUT = -605, // 表示TCP写超时 - QCLOUD_ERR_TCP_READ_FAIL = -606, // 表示TCP读错误 - QCLOUD_ERR_TCP_WRITE_FAIL = -607, // 表示TCP写错误 - QCLOUD_ERR_TCP_PEER_SHUTDOWN = -608, // 表示TCP对端关闭了连接 - QCLOUD_ERR_TCP_NOTHING_TO_READ = -609, // 表示底层没有数据可以读取 - - QCLOUD_ERR_SSL_INIT = -701, // 表示SSL初始化失败 - QCLOUD_ERR_SSL_CERT = -702, // 表示SSL证书相关问题 - QCLOUD_ERR_SSL_CONNECT = -703, // 表示SSL连接失败 - QCLOUD_ERR_SSL_CONNECT_TIMEOUT = -704, // 表示SSL连接超时 - QCLOUD_ERR_SSL_WRITE_TIMEOUT = -705, // 表示SSL写超时 - QCLOUD_ERR_SSL_WRITE = -706, // 表示SSL写错误 - QCLOUD_ERR_SSL_READ_TIMEOUT = -707, // 表示SSL读超时 - QCLOUD_ERR_SSL_READ = -708, // 表示SSL读错误 - QCLOUD_ERR_SSL_NOTHING_TO_READ = -709, // 表示底层没有数据可以读取 -} IoT_Error_Code; - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_ERROR_H_ */ diff --git a/src/sdk-impl/exports/qcloud_iot_export_gateway.h b/src/sdk-impl/exports/qcloud_iot_export_gateway.h deleted file mode 100644 index 4665cc6f..00000000 --- a/src/sdk-impl/exports/qcloud_iot_export_gateway.h +++ /dev/null @@ -1,154 +0,0 @@ - -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_EXPORT_GATEWAY_H_ -#define QCLOUD_IOT_EXPORT_GATEWAY_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "qcloud_iot_export_mqtt.h" - -/* 网关 子设备输入参数 */ -typedef struct { - /** - * 网关设备基础信息 - */ - char *product_id; // 产品名称 - char *device_name; // 设备名称 - /** - * 子设备基础信息 - */ - char *subdev_product_id; // 子产品名称 - char *subdev_device_name; // 子设备名称 - -} GatewayParam; - -#define DEFAULT_GATEWAY_PARAMS {NULL, NULL, NULL, NULL} - -/** - * @brief 定义了函数指针的数据类型. 当网关事件发生时,将调用这种类型的函数. - * - * @param context, the program context - * @param client, the gateway client - * @param msg, the event message. - * - * @return none - */ -typedef void (*GatewayEventHandleFun)(void *client, void *context, void *msg); - - -/* The structure of gateway init param */ -typedef struct { - MQTTInitParams init_param; /* MQTT params */ - void *event_context; /* the user context */ - GatewayEventHandleFun event_handler; /* event handler for gateway user*/ -} GatewayInitParam; - -#define DEFAULT_GATEWAY_INIT_PARAMS { DEFAULT_MQTTINIT_PARAMS, NULL, NULL} - - -/** - * @brief 构造Gateway client - * - * @param init_param Gateway MQTT协议连接接入与连接维持阶段所需要的参数 - * - * @return 返回NULL: 构造失败 - */ -void *IOT_Gateway_Construct(GatewayInitParam* init_param); - -/** - * @brief 销毁Gateway client 关闭MQTT连接 - * - * @param Gateway client对象 - * - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_Gateway_Destroy(void *client); - -/** - * @brief 子设备上线 - * - * @param Gateway client对象 - * @param param 网关子设备参数 - * - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_Gateway_Subdev_Online(void *client, GatewayParam* param); - -/** - * @brief 子设备下线 - * - * @param Gateway client对象 - * @param param 网关子设备参数 - * - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_Gateway_Subdev_Offline(void *client, GatewayParam* param); - - -/** - * @brief 发布Gateway MQTT消息 - * - * @param client Gateway client对象 - * @param topic_name 主题名 - * @param params 发布参数 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_Gateway_Publish(void *client, char *topic_name, PublishParams *params); - - -/** - * @brief 订阅Gateway MQTT消息 - * - * @param client Gateway client对象 - * @param topic_filter 主题过滤器 - * @param params 订阅参数 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_Gateway_Subscribe(void *client, char *topic_filter, SubscribeParams *params); - - -/** - * @brief 取消订阅Gateway MQTT消息 - * - * @param client Gateway client对象 - * @param topic_filter 主题过滤器 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_Gateway_Unsubscribe(void *client, char *topic_filter); - - - -/** - * @brief 消息接收, 心跳包管理, 超时请求处理 - * - * @param client Gateway client对象 - * @param timeout_ms 超时时间, 单位:ms - * @return 返回QCLOUD_ERR_SUCCESS, 表示调用成功 - */ -int IOT_Gateway_Yield(void *client, uint32_t timeout_ms); - - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_GATEWAY_H_ */ diff --git a/src/sdk-impl/exports/qcloud_iot_export_log.h b/src/sdk-impl/exports/qcloud_iot_export_log.h deleted file mode 100644 index 724d516d..00000000 --- a/src/sdk-impl/exports/qcloud_iot_export_log.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_EXPORT_LOG_H_ -#define QCLOUD_IOT_EXPORT_LOG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -/** - * 日志输出等级 - * 设置为DISABLE级别时表示不打印或不上传 - */ -typedef enum { - DISABLE = 0, - ERROR = 1, - WARN = 2, - INFO = 3, - DEBUG = 4 -} LOG_LEVEL; - -/** - * 全局日志打印级别标志, 只打印输出小于或等于该等级的日志信息 - */ -extern LOG_LEVEL g_log_print_level; - -/** - * 全局日志上传级别标志, 只上传小于或等于该等级的日志信息 - */ -extern LOG_LEVEL g_log_upload_level; - -/*用户自定义日志打印函数回调*/ -typedef bool (*LogMessageHandler)(const char* message); - -/*单条日志最大长度*/ -#define MAX_LOG_MSG_LEN (255) - -/* - * 日志上报功能相关参数, 影响内存和存储空间使用量及上报频率 - * 以下为默认推荐值 - */ -// 日志上报缓冲区大小,用户可以根据需要调整,但应小于或等于MAX_HTTP_LOG_POST_SIZE -#define LOG_UPLOAD_BUFFER_SIZE 3000 -// 一次日志上报的最大post payload长度,不可修改 -#define MAX_HTTP_LOG_POST_SIZE 5000 -//日志上报失败后通过缓存到非易失性存储区的最大长度,可根据需要调整 -#define MAX_LOG_SAVE_SIZE (3*LOG_UPLOAD_BUFFER_SIZE) -//日志上报的频率,若上报缓冲区比较小,则需要提高上报频率,否则容易丢失日志 -#define LOG_UPLOAD_INTERVAL_MS 2000 //milliseconds - -/* 日志上报服务器地址,不可修改*/ -#define LOG_UPLOAD_SERVER_URL "http://devicelog.iot.cloud.tencent.com/cgi-bin/report-log" -#define LOG_UPLOAD_SERVER_PORT 80 - -/** - * @brief 日志上报功能用户自定义回调函数,用于上报失败时的缓存和通讯恢复后的重传 - */ -//缓存指定长度日志到非易失性存储,返回值为成功写入的长度 -typedef size_t (*LogSaveFunc)(const char *msg, size_t wLen); -//从非易失性存储读取指定长度日志,返回值为成功读取的长度 -typedef size_t (*LogReadFunc)(char *buff, size_t rLen); -//从非易失性存储删除缓存的日志,返回值为0删除成功,非0删除失败 -typedef int (*LogDelFunc)(); -//获取存储在非易失性存储中的log长度,返回0为没有缓存 -typedef size_t (*LogGetSizeFunc)(); - -/** - * @brief 日志上报功能初始化数据结构 - */ -typedef struct { - /*物联网产品信息*/ - const char *product_id; - const char *device_name; - /*校验key,采用PSK方式请传入产品密钥,证书方式请传入客户端证书全路径*/ - const char *sign_key; - /*用户自定义回调函数*/ - LogSaveFunc save_func; - LogReadFunc read_func; - LogDelFunc del_func; - LogGetSizeFunc get_size_func; -} LogUploadInitParams; - - -/** - * @brief 设置全局日志打印级别 - * - * @param level - */ -void IOT_Log_Set_Level(LOG_LEVEL level); - -/** - * @brief 获取当前日志打印等级 - * - * @return - */ -LOG_LEVEL IOT_Log_Get_Level(); - -/** - * @brief 设置全局日志上传级别 - * - * @param level - */ -void IOT_Log_Set_Upload_Level(LOG_LEVEL level); - -/** - * @brief 获取当前日志上传等级 - * - * @return - */ -LOG_LEVEL IOT_Log_Get_Upload_Level(); - - -/** - * @brief 设置日志回调函数,用户接管日志内容用于输出到文件等操作 - * - * @param handler 回调函数指针 - * - */ -void IOT_Log_Set_MessageHandler(LogMessageHandler handler); - - -/** - * @brief 设置日志上报功能相关信息 - * - * @param product_id 产品ID - * @param device_name 设备名称 - * @param sign_key 用于签名的key - * - */ -void IOT_Log_Init_Uploader(LogUploadInitParams *init_params); - - -/** - * @brief 触发一次日志上报 - * - * @param force_upload 为真则强制进行上报,否则会根据预设间隔定时上报 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_Log_Upload(bool force_upload); - - -/** - * @brief 日志打印及上报函数,默认打印到标准输出,当用户设置日志打印handler时,回调handler - * - * 当日志上报功能打开时,会将日志缓存后上报到云端日志服务器 - * - * @param file 源文件名 - * @param func 函数名 - * @param line 行号 - * @param level 日志等级 - */ -void Log_writter(const char *file, const char *func, const int line, const int level, const char *fmt, ...); - -/* 日志打印及上报对外接口*/ -#define Log_d(args...) Log_writter(__FILE__, __FUNCTION__, __LINE__, DEBUG, args) -#define Log_i(args...) Log_writter(__FILE__, __FUNCTION__, __LINE__, INFO, args) -#define Log_w(args...) Log_writter(__FILE__, __FUNCTION__, __LINE__, WARN, args) -#define Log_e(args...) Log_writter(__FILE__, __FUNCTION__, __LINE__, ERROR, args) - -#ifdef IOT_DEBUG - #define IOT_FUNC_ENTRY \ - {\ - printf("FUNC_ENTRY: %s L#%d \n", __FUNCTION__, __LINE__); \ - } - #define IOT_FUNC_EXIT \ - {\ - printf("FUNC_EXIT: %s L#%d \n", __FUNCTION__, __LINE__); \ - return;\ - } - #define IOT_FUNC_EXIT_RC(x) \ - {\ - printf("FUNC_EXIT: %s L#%d Return Code : %ld \n", __FUNCTION__, __LINE__, (long)(x)); \ - return x; \ - } -#else - #define IOT_FUNC_ENTRY - #define IOT_FUNC_EXIT \ - {\ - return;\ - } - #define IOT_FUNC_EXIT_RC(x) \ - {\ - return x; \ - } -#endif - -//#define LOG_UPLOAD_DEBUG -#ifdef LOG_UPLOAD_DEBUG -#define UPLOAD_DBG(fmt, ...) HAL_Printf(">>LOG-DBG>>%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__) -#else -#define UPLOAD_DBG(...) -#endif -#define UPLOAD_ERR(fmt, ...) HAL_Printf(">>LOG-ERR>>%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__) - - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_LOG_H_ */ diff --git a/src/sdk-impl/exports/qcloud_iot_export_mqtt.h b/src/sdk-impl/exports/qcloud_iot_export_mqtt.h deleted file mode 100644 index 3d926460..00000000 --- a/src/sdk-impl/exports/qcloud_iot_export_mqtt.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_EXPORT_MQTT_H_ -#define QCLOUD_IOT_EXPORT_MQTT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -/** - * @brief 服务质量等级 - * - * 服务质量等级表示PUBLISH消息分发的质量等级 - */ -typedef enum _QoS { - QOS0 = 0, // 至多分发一次 - QOS1 = 1, // 至少分发一次, 消息的接收者需回复PUBACK报文 - QOS2 = 2 // 仅分发一次, 目前腾讯物联云不支持该等级 -} QoS; - -/** - * @brief 发布或接收已订阅消息的结构体定义 - */ -typedef struct { - QoS qos; // MQTT 服务质量等级 - uint8_t retained; // RETAIN 标识位 - uint8_t dup; // DUP 标识位 - uint16_t id; // MQTT 消息标识符 - - const char *ptopic; // MQTT topic - size_t topic_len; // topic 长度 - - void *payload; // MQTT 消息负载 - size_t payload_len; // MQTT 消息负载长度 -} MQTTMessage; - -typedef MQTTMessage PublishParams; - -#define DEFAULT_PUB_PARAMS {QOS0, 0, 0, 0, NULL, 0, NULL, 0} - - -/** - * @brief MQTT PUBLISH 消息回调处理函数指针定义 - */ -typedef void (*OnMessageHandler)(void *pClient, MQTTMessage *message, void *pApplicationHandlerData); - -/** - * @brief 订阅主题的结构体定义 - */ -typedef struct { - QoS qos; // 服务质量等级, 目前支持QOS0和QOS1 - OnMessageHandler on_message_handler; // 接收已订阅消息的回调函数 - void *user_data; // 用户数据, 通过callback返回 -} SubscribeParams; - -/** - * MQTT 订阅报文默认参数 - */ -#define DEFAULT_SUB_PARAMS {QOS0, NULL, NULL} - -typedef enum { - - /* 未定义事件 */ - MQTT_EVENT_UNDEF = 0, - - /* MQTT 断开连接 */ - MQTT_EVENT_DISCONNECT = 1, - - /* MQTT 重连 */ - MQTT_EVENT_RECONNECT = 2, - - /* 订阅成功 */ - MQTT_EVENT_SUBCRIBE_SUCCESS = 3, - - /* 订阅超时 */ - MQTT_EVENT_SUBCRIBE_TIMEOUT = 4, - - /* 订阅失败 */ - MQTT_EVENT_SUBCRIBE_NACK = 5, - - /* 取消订阅成功 */ - MQTT_EVENT_UNSUBCRIBE_SUCCESS = 6, - - /* 取消订阅超时 */ - MQTT_EVENT_UNSUBCRIBE_TIMEOUT = 7, - - /* 取消订阅失败 */ - MQTT_EVENT_UNSUBCRIBE_NACK = 8, - - /* 发布成功 */ - MQTT_EVENT_PUBLISH_SUCCESS = 9, - - /* 发布超时 */ - MQTT_EVENT_PUBLISH_TIMEOUT = 10, - - /* 发布失败 */ - MQTT_EVENT_PUBLISH_NACK = 11, - - /* SDK订阅的topic收到后台push消息 */ - MQTT_EVENT_PUBLISH_RECVEIVED = 12, - - -} MQTTEventType; - - -typedef struct { - /* 事件类型 */ - MQTTEventType event_type; - - void *msg; -} MQTTEventMsg; - -/** - * @brief 定义了函数指针的数据类型. 当相关事件发生时,将调用这种类型的函数. - * - * @param context, the program context - * @param pclient, the MQTT client - * @param msg, the event message. - * - * @return none - */ -typedef void (*MQTTEventHandleFun)(void *pclient, void *handle_context, MQTTEventMsg *msg); - - -/* The structure of MQTT event handle */ -typedef struct { - MQTTEventHandleFun h_fp; - void *context; -} MQTTEventHandler; - -typedef struct { - /** - * 设备基础信息 - */ - char *product_id; // 产品名称 - char *device_name; // 设备名称 - -#ifdef AUTH_MODE_CERT - /** - * 非对称加密使用 - */ - char *cert_file; // 客户端证书文件路径 - char *key_file; // 客户端私钥文件路径 -#else - char *device_secret; -#endif - - uint32_t command_timeout; // 发布订阅信令读写超时时间 ms - uint32_t keep_alive_interval_ms; // 心跳周期, 单位: ms - - uint8_t clean_session; // 清理会话标志位 - - uint8_t auto_connect_enable; // 是否开启自动重连 1:启用自动重连 0:不启用自动重连 建议为1 - - MQTTEventHandler event_handle; // 事件回调 - -} MQTTInitParams; - -/** - * MQTT初始化参数结构体默认值定义 - */ -#ifdef AUTH_MODE_CERT - #define DEFAULT_MQTTINIT_PARAMS { NULL, NULL, NULL, NULL, 2000, 240 * 1000, 1, 1, {0}} -#else - #define DEFAULT_MQTTINIT_PARAMS { NULL, NULL, NULL, 2000, 240 * 1000, 1, 1, {0}} -#endif - -/** - * @brief 构造MQTTClient并完成MQTT连接 - * - * @param pInitParams MQTT协议连接接入与连接维持阶段所需要的参数 - * - * @return 返回NULL: 构造失败 - */ -void* IOT_MQTT_Construct(MQTTInitParams *pParams); - -/** - * @brief 关闭MQTT连接并销毁MQTTClient - * - * @param pClient MQTTClient对象地址 - * - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_MQTT_Destroy(void **pClient); - -/** - * @brief 在当前线程为底层MQTT客户端让出一定CPU执行时间 - * - * 在这段时间内, MQTT客户端会用用处理消息接收, 以及发送PING报文, 监控网络状态 - * - * @param pClient MQTT Client结构体 - * @param timeout_ms Yield操作超时时间 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功, 返回QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT, 表示正在重连 - */ -int IOT_MQTT_Yield(void *pClient, uint32_t timeout_ms); - -/** - * @brief 发布MQTT消息 - * - * @param pClient MQTT客户端结构体 - * @param topicName 主题名 - * @param pParams 发布参数 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_MQTT_Publish(void *pClient, char *topicName, PublishParams *pParams); - -/** - * @brief 订阅MQTT主题 - * - * @param pClient MQTT客户端结构体 - * @param topicFilter 主题过滤器, 可参考MQTT协议说明 4.7 - * @param pParams 订阅参数 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_MQTT_Subscribe(void *pClient, char *topicFilter, SubscribeParams *pParams); - -/** - * @brief 取消订阅已订阅的MQTT主题 - * - * @param pClient MQTT客户端结构体 - * @param topicFilter 主题过滤器, 可参考MQTT协议说明 4.7 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_MQTT_Unsubscribe(void *pClient, char *topicFilter); - -/** - * @brief 客户端目前是否已连接 - * - * @param pClient MQTT Client结构体 - * @return 返回true, 表示客户端已连接 - */ -bool IOT_MQTT_IsConnected(void *pClient); - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_MQTT_H_ */ diff --git a/src/sdk-impl/exports/qcloud_iot_export_nbiot.h b/src/sdk-impl/exports/qcloud_iot_export_nbiot.h deleted file mode 100644 index efa41cd5..00000000 --- a/src/sdk-impl/exports/qcloud_iot_export_nbiot.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef QCLOUD_IOT_EXPORT_NBIOT_H_ -#define QCLOUD_IOT_EXPORT_NBIOT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define MAX_SIZE_MESSAGE 1024 -#define MAX_SIZE_PAYLOAD 500 -#define MAX_SIZE_TOPIC 64 -#define TLV_COUNT 5 - -typedef struct nbiotSetMessage -{ - uint8_t address; - uint8_t version; - uint8_t sigType; - uint32_t expiry; - uint8_t qos; - char* topic; - char* payload; - char* key; -}NBIoTSetMessage; - -typedef struct nbiotGetMessage -{ - uint8_t address; - uint8_t version; - uint8_t sigType; - uint32_t expiry; - uint8_t qos; - char* topic; - char* payload; - //char* token; -}NBIoTGetMessage; - -/** - * @brief nbiot平台上行消息编码接口 - * - * 将 nbiot 终端需要发送的消息,通过此接口生成一串十六进制的信息发送到 nbiot 平台 - * - * @param msg 生成的十六进制上行消息编码 - * @param length 十六进制上行消息的长度,以字节为单位 - * @param nbiotMsg nbiot终端发送消息的结构体,包括 address、 version、签名类型、过期时间、传输质量、topic、payload、key等信息 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功, 返回QCLOUD_ERR_FAILURE, 表示失败 - */ -int IOT_NB_setMessage(unsigned char* msg, unsigned int* length, NBIoTSetMessage* nbiotMsg); - -/** - * @brief nbiot平台下行消息解码接口 - * - * 将 nbiot 终端接收的一串十六进制的信息解析出来 - * - * @param nbiotMsg nbiot终端解析出来的消息内容结构体,包括 address、version、签名类型、过期时间、传输质量、topic、payload等信息 - * @param msg nbiot平台发送到设备端的十六进制下行消息编码 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功, 返回QCLOUD_ERR_FAILURE, 表示失败 - */ -int IOT_NB_getMessage(NBIoTGetMessage* nbiotMsg, unsigned char* msg); - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_NBIOT_H_ */ \ No newline at end of file diff --git a/src/sdk-impl/exports/qcloud_iot_export_ota.h b/src/sdk-impl/exports/qcloud_iot_export_ota.h deleted file mode 100644 index 431c9c6c..00000000 --- a/src/sdk-impl/exports/qcloud_iot_export_ota.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_EXPORT_OTA_H_ -#define QCLOUD_IOT_EXPORT_OTA_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "qcloud_iot_import.h" - -#define OTA_CH_SIGNAL_MQTT (1) -#define OTA_CH_SIGNAL_COAP (0) -#define OTA_CH_FETCH_HTTP (1) - -typedef enum { - - IOT_OTA_ERR_FAIL = -1, - IOT_OTA_ERR_INVALID_PARAM = -2, - IOT_OTA_ERR_INVALID_STATE = -3, - IOT_OTA_ERR_STR_TOO_LONG = -4, - IOT_OTA_ERR_FETCH_FAILED = -5, - IOT_OTA_ERR_FETCH_NOT_EXIST = -6, - IOT_OTA_ERR_FETCH_AUTH_FAIL = -7, - IOT_OTA_ERR_FETCH_TIMEOUT = -8, - IOT_OTA_ERR_NOMEM = -9, - IOT_OTA_ERR_OSC_FAILED = -10, - IOT_OTA_ERR_REPORT_VERSION = -11, - IOT_OTA_ERR_NONE = 0 - -} IOT_OTA_Error_Code; - - -/* OTA状态 */ -typedef enum { - IOT_OTAS_UNINITED = 0, /* 未初始化 */ - IOT_OTAS_INITED, /* 初始化完成 */ - IOT_OTAS_FETCHING, /* 正在下载固件 */ - IOT_OTAS_FETCHED, /* 固件下载完成 */ - IOT_OTAS_DISCONNECTED /* 连接已经断开 */ -} IOT_OTA_State_Code; - - -/* OTA进度 */ -typedef enum { - - /* 固件升级失败 */ - IOT_OTAP_BURN_FAILED = -4, - - /* 固件校验失败 */ - IOT_OTAP_CHECK_FALIED = -3, - - /* 固件下载失败 */ - IOT_OTAP_FETCH_FAILED = -2, - - /* 初始化失败 */ - IOT_OTAP_GENERAL_FAILED = -1, - - - /* [0, 100], 进度百分比区间 */ - - /* 进度的最小百分比 */ - IOT_OTAP_FETCH_PERCENTAGE_MIN = 0, - - /* 进度的最大百分比 */ - IOT_OTAP_FETCH_PERCENTAGE_MAX = 100 - -} IOT_OTA_Progress_Code; - - -typedef enum { - - IOT_OTAG_FETCHED_SIZE, /* 固件已经下载的大小 */ - IOT_OTAG_FILE_SIZE, /* 固件总大小 */ - IOT_OTAG_MD5SUM, /* md5(字符串类型) */ - IOT_OTAG_VERSION, /* 版本号(字符串类型)t */ - IOT_OTAG_CHECK_FIRMWARE /* 对固件进行校验 */ - -} IOT_OTA_CmdType; - -typedef enum { - - IOT_OTAR_DOWNLOAD_TIMEOUT = -1, - IOT_OTAR_FILE_NOT_EXIST = -2, - IOT_OTAR_AUTH_FAIL = -3, - IOT_OTAR_MD5_NOT_MATCH = -4, - IOT_OTAR_UPGRADE_FAIL = -5, - IOT_OTAR_NONE = 0, - IOT_OTAR_DOWNLOAD_BEGIN = 1, - IOT_OTAR_DOWNLOADING = 2, - IOT_OTAR_UPGRADE_BEGIN = 3, - IOT_OTAR_UPGRADE_SUCCESS = 4, - -} IOT_OTAReportType; - - -/** - * @brief 初始化OTA模块和返回句柄 - * MQTT客户端必须在调用此接口之前进行初始化 - * - * @param product_id: 指定产品ID - * @param device_name: 指定设备名 - * @param ch_signal: 指定的信号通道. - * - * @see None. - */ -void *IOT_OTA_Init(const char *product_id, const char *device_name, void *ch_signal); - - -/** - * @brief 释放OTA相关的资源 - * 如果在下载之后没有调用重新启动,则必须调用该接口以释放资源 - * - * @param handle: 指定OTA模块 - * - * @retval 0 : 成功 - * @retval < 0 : 失败,返回具体错误码 - */ -int IOT_OTA_Destroy(void *handle); - - -/** - * @brief 向OTA服务器报告固件版本信息。 - * NOTE: 进行OTA前请保证先上报一次本地固件的版本信息,以便服务器获取到设备目前的固件信息 - * - * @param handle: 指定OTA模块 - * @param version: 以字符串格式指定固件版本 - * - * @retval > 0 : 对应publish的packet id - * @retval < 0 : 失败,返回具体错误码 - */ -int IOT_OTA_ReportVersion(void *handle, const char *version); - - -/** - * @brief 向OTA服务器报告详细进度 - * - * @param handle: 指定OTA模块 - * @param progress: 下载进度 - * @param reportType: 指定当前的下载状态 - * - * @retval 0 : 成功 - * @retval < 0 : 失败,返回具体错误码 - */ -// int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_Code progress, IOT_OTAReportType reportType); - -/** - * @brief 当进行升级前,需要向OTA服务器上报即将升级的状态 - * - * @param handle: 指定OTA模块 - * - * @retval > 0 : 对应publish的packet id - * @retval < 0 : 失败,返回具体错误码 - */ -int IOT_OTA_ReportUpgradeBegin(void *handle); - -/** - * @brief 当升级成功之后,需要向OTA服务器上报升级成功的状态 - * - * @param handle: 指定OTA模块 - * @param version: 即将升级的固件信息 - * - * @retval > 0 : 对应publish的packet id - * @retval < 0 : 失败,返回具体错误码 - */ -int IOT_OTA_ReportUpgradeSuccess(void *handle, const char *version); - -/** - * @brief 当升级失败之后,需要向OTA服务器上报升级失败的状态 - * - * @param handle: 指定OTA模块 - * @param version: 即将升级的固件信息 - * - * @retval > 0 : 对应publish的packet id - * @retval < 0 : 失败,返回具体错误码 - */ -int IOT_OTA_ReportUpgradeFail(void *handle, const char *version); - -/** - * @brief 检查是否处于下载固件的状态 - * - * @param handle: 指定OTA模块 - * - * @retval 1 : Yes. - * @retval 0 : No. - */ -int IOT_OTA_IsFetching(void *handle); - - -/** - * @brief 检查固件是否已经下载完成 - * - * @param handle: 指定OTA模块 - * - * @retval 1 : Yes. - * @retval 0 : No. - */ -int IOT_OTA_IsFetchFinish(void *handle); - - -/** - * @brief 从具有特定超时值的远程服务器获取固件 - * 注意:如果你想要下载的更快,那么应该给出更大的“buf” - * - * @param handle: 指定OTA模块 - * @param buf: 指定存储固件数据的空间 - * @param buf_len: 用字节指定“buf”的长度 - * @param timeout_s: 在秒中指定超时值 - * - * @retval < 0 : 对应的错误码 - * @retval 0 : 在“timeout_s”超时期间没有任何数据被下载 - * @retval (0, len] : 在“timeout_s”超时时间内以字节的方式下载数据的长度 - */ -int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s); - - -/** - * @brief 获取指定的OTA信息 - * 通过这个接口,您可以获得诸如状态、文件大小、文件的md5等信息 - * - * @param handle: 指定OTA模块 - * @param type: 指定您想要的信息,请参见详细信息“IOT_OTA_CmdType” - * @param buf: 为数据交换指定缓冲区 - * @param buf_len: 在字节中指定“buf”的长度 - * @return - NOTE: - 1) 如果 type==IOT_OTAG_FETCHED_SIZE, 'buf'需要传入 uint32_t 类型指针, 'buf_len'需指定为 4 - 2) 如果 type==IOT_OTAG_FILE_SIZE, 'buf'需要传入 uint32_t 类型指针, 'buf_len'需指定为 4 - 3) 如果 type==IOT_OTAG_MD5SUM, 'buf'需要传入 buffer, 'buf_len需指定为 33 - 4) 如果 type==IOT_OTAG_VERSION, 'buf'需要传入 buffer, 'buf_len'需指定为 OTA_VERSION_LEN_MAX - 5) 如果 type==IOT_OTAG_CHECK_FIRMWARE, 'buf'需要传入 uint32_t 类型指针, 'buf_len'需指定为 4 - 0, 固件MD5校验不通过, 固件是无效的; 1, 固件是有效的. - * - * @retval 0 : 执行成功 - * @retval < 0 : 执行失败,返回对应的错误码 - */ -int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len); - - -/** - * @brief 得到最后一个错误代码 - * - * @param handle: 指定OTA模块 - * - * @return 对应错误的错误码. - */ -int IOT_OTA_GetLastError(void *handle); - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_OTA_H_ */ diff --git a/src/sdk-impl/exports/qcloud_iot_export_shadow.h b/src/sdk-impl/exports/qcloud_iot_export_shadow.h deleted file mode 100644 index 168c94d1..00000000 --- a/src/sdk-impl/exports/qcloud_iot_export_shadow.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_EXPORT_SHADOW_H_ -#define QCLOUD_IOT_EXPORT_SHADOW_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "qcloud_iot_export_mqtt.h" - -typedef struct { - /** - * 设备基础信息 - */ - char *product_id; // 产品名称 - char *device_name; // 设备名称 - -#ifdef AUTH_MODE_CERT - /** - * 非对称加密使用 - */ - char *cert_file; // 客户端证书文件路径 - char *key_file; // 客户端私钥文件路径 -#else - /** - * 对称加密 - */ - char *device_secret; // 对称加密密钥 -#endif - - uint32_t command_timeout; // 发布订阅信令读写超时时间 ms - uint32_t keep_alive_interval_ms; // 心跳周期, 单位: ms - - uint8_t clean_session; // 清理会话标志位 - - uint8_t auto_connect_enable; // 是否开启自动重连 1:启用自动重连 0:不启用自动重连 建议为1 - - MQTTEventHandler event_handle; // 事件回调 - -} ShadowInitParams; - -#ifdef AUTH_MODE_CERT - #define DEFAULT_SHAWDOW_INIT_PARAMS { NULL, NULL, NULL, NULL, 2000, 240 * 1000, 1, 1, {0}} -#else - #define DEFAULT_SHAWDOW_INIT_PARAMS { NULL, NULL, NULL, 2000, 240 * 1000, 1, 1, {0}} -#endif - -/** - * @brief 请求响应返回的类型 - */ -typedef enum { - ACK_NONE = -3, // 请求超时 - ACK_TIMEOUT = -2, // 请求超时 - ACK_REJECTED = -1, // 请求拒绝 - ACK_ACCEPTED = 0 // 请求接受 -} RequestAck; - -/** - * @brief 操作云端设备文档可以使用的三种方式 - */ -typedef enum { - GET, // 获取云端设备文档 - UPDATE, // 更新或创建云端设备文档 -} Method; - -/** - * @brief JSON文档中支持的数据类型 - */ -typedef enum { - JINT32, // 32位有符号整型 - JINT16, // 16位有符号整型 - JINT8, // 8位有符号整型 - JUINT32, // 32位无符号整型 - JUINT16, // 16位无符号整型 - JUINT8, // 8位无符号整型 - JFLOAT, // 单精度浮点型 - JDOUBLE, // 双精度浮点型 - JBOOL, // 布尔型 - JSTRING, // 字符串 - JOBJECT // JSON对象 -} JsonDataType; - -/** - * @brief 定义设备的某个属性, 实际就是一个JSON文档节点 - */ -typedef struct _JSONNode { - char *key; // 该JSON节点的Key - void *data; // 该JSON节点的Value - JsonDataType type; // 该JSON节点的数据类型 -} DeviceProperty; - -/** - * @brief 每次文档请求响应的回调函数 - * - * @param method 文档操作方式 - * @param requestAck 请求响应类型 - * @param pJsonDocument 云端响应返回的文档 - * @param userContext 用户数据 - * - */ -typedef void (*OnRequestCallback)(void *pClient, Method method, RequestAck requestAck, const char *pJsonDocument, void *userContext); - -/** - * @brief 设备属性处理回调函数 - * - * @param pJsonValueBuffer 设备属性值 - * @param valueLength 设备属性值长度 - * @param DeviceProperty 设备属性结构体 - */ -typedef void (*OnPropRegCallback)(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength, DeviceProperty *pProperty); - -/** - * @brief 构造ShadowClient - * - * @param pInitParams MQTT协议连接接入与连接维持阶段所需要的参数 - * - * @return 返回NULL: 构造失败 - */ -void* IOT_Shadow_Construct(ShadowInitParams *pParams); - -/** - * @brief 发布MQTT消息 - * - * @param handle Shadow客户端结构体 - * @param topicName 主题名 - * @param pParams 发布参数 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_Shadow_Publish(void *handle, char *topicName, PublishParams *pParams); - -/** - * @brief 订阅MQTT消息 - * - * @param handle Shadow客户端结构体 - * @param topicName 主题名 - * @param pParams 发布参数 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_Shadow_Subscribe(void *handle, char *topicFilter, SubscribeParams *pParams); - -/** - * @brief 取消订阅MQTT消息 - * - * @param handle Shadow客户端结构体 - * @param topicName 主题名 - * @return < 0 : 表示失败 - * >= 0 : 返回唯一的packet id - */ -int IOT_Shadow_Unsubscribe(void *handle, char *topicFilter); - -/** - * @brief 客户端目前是否已连接 - * - * @param pClient Shadow Client结构体 - * @return 返回true, 表示客户端已连接 - */ -bool IOT_Shadow_IsConnected(void *handle); - -/** - * @brief 销毁ShadowClient 关闭MQTT连接 - * - * @param pClient ShadowClient对象 - * - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_Shadow_Destroy(void *handle); - -/** - * @brief 消息接收, 心跳包管理, 超时请求处理 - * - * @param timeout_ms 超时时间, 单位:ms - * @return 返回QCLOUD_ERR_SUCCESS, 表示调用成功 - */ -int IOT_Shadow_Yield(void *handle, uint32_t timeout_ms); - -/** - * @brief 异步方式更新设备影子文档 - * - * @param pClient Client结构体 - * @param pJsonDoc 更新到云端的设备文档 - * @param sizeOfBuffer 文档长度 - * @param callback 请求响应处理回调函数 - * @param userContext 用户数据, 请求响应返回时通过回调函数返回 - * @param timeout_ms 请求超时时间, 单位:ms - * @return 返回QCLOUD_ERR_SUCCESS, 表示请求成功 - */ -int IOT_Shadow_Update(void *handle, char *pJsonDoc, size_t sizeOfBuffer, OnRequestCallback callback, void *userContext, uint32_t timeout_ms); - -/** - * @brief 同步方式更新设备影子文档 - * - * @param pClient Client结构体 - * @param pJsonDoc 更新到云端的设备文档 - * @param sizeOfBuffer 文档长度 - * @param timeout_ms 请求超时时间, 单位:ms - * @return QCLOUD_ERR_SUCCESS 请求成功 - * QCLOUD_ERR_SHADOW_UPDATE_TIMEOUT 请求超时 - * QCLOUD_ERR_SHADOW_UPDATE_REJECTED 请求被拒绝 - */ -int IOT_Shadow_Update_Sync(void *handle, char *pJsonDoc, size_t sizeOfBuffer, uint32_t timeout_ms); - -/** - * @brief 获取设备影子文档 - * - * @param pClient Client结构体 - * @param callback 请求响应处理回调函数 - * @param userContext 用户数据, 请求响应返回时通过回调函数返回 - * @param timeout_ms 请求超时时间, 单位:s - * @return 返回QCLOUD_ERR_SUCCESS, 表示请求成功 - */ -int IOT_Shadow_Get(void *handle, OnRequestCallback callback, void *userContext, uint32_t timeout_ms); - -/** - * @brief 获取设备影子文档 - * - * @param pClient Client结构体 - * @param timeout_ms 请求超时时间, 单位:s - * @return QCLOUD_ERR_SUCCESS 请求成功 - * QCLOUD_ERR_SHADOW_GET_TIMEOUT 请求超时 - * QCLOUD_ERR_SHADOW_GET_REJECTED 请求被拒绝 - */ -int IOT_Shadow_Get_Sync(void *handle, uint32_t timeout_ms); - -/** - * @brief 注册当前设备的设备属性 - * - * @param pClient Client结构体 - * @param pProperty 设备属性 - * @param callback 设备属性更新回调处理函数 - * @return 返回QCLOUD_ERR_SUCCESS, 表示请求成功 - */ -int IOT_Shadow_Register_Property(void *handle, DeviceProperty *pProperty, OnPropRegCallback callback); - -/** - * @brief 删除已经注册过的设备属性 - * - * @param pClient Client结构体 - * @param pProperty 设备属性 - * @return 返回QCLOUD_ERR_SUCCESS, 表示请求成功 - */ -int IOT_Shadow_UnRegister_Property(void *handle, DeviceProperty *pProperty); - -/** - * @brief 在JSON文档中添加reported字段,不覆盖更新 - * - * - * @param jsonBuffer 为存储JSON文档准备的字符串缓冲区 - * @param sizeOfBuffer 缓冲区大小 - * @param count 可变参数的个数, 即需上报的设备属性的个数 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_Shadow_JSON_ConstructReport(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...); - -/** - * @brief 在JSON文档中添加reported字段,覆盖更新 - * - * - * @param jsonBuffer 为存储JSON文档准备的字符串缓冲区 - * @param sizeOfBuffer 缓冲区大小 - * @param overwrite 重写字段 - * @param count 可变参数的个数, 即需上报的设备属性的个数 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_Shadow_JSON_Construct_OverwriteReport(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...); - -/** - * @brief 在JSON文档中添加reported字段,同时清空desired字段 - * - * - * @param jsonBuffer 为存储JSON文档准备的字符串缓冲区 - * @param sizeOfBuffer 缓冲区大小 - * @param count 可变参数的个数, 即需上报的设备属性的个数 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int IOT_Shadow_JSON_ConstructReportAndDesireAllNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...); - -/** - * @brief 在JSON文档中添加 "desired": null 字段 - * - * @param jsonBuffer 为存储JSON文档准备的字符串缓冲区 - * @param sizeOfBuffer 缓冲区大小 - */ -int IOT_Shadow_JSON_ConstructDesireAllNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer); - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_SHADOW_H_ */ diff --git a/src/sdk-impl/qcloud_iot_export.h b/src/sdk-impl/qcloud_iot_export.h deleted file mode 100755 index d6cfbe5e..00000000 --- a/src/sdk-impl/qcloud_iot_export.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_EXPORT_H_ -#define QCLOUD_IOT_EXPORT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* IoT C-SDK APPID */ -#define QCLOUD_IOT_DEVICE_SDK_APPID "21010406" - -/* IoT C-SDK version info */ -#define QCLOUD_IOT_DEVICE_SDK_VERSION "2.3.3" - -/* MQTT心跳消息发送周期, 单位:ms */ -#define QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL (240 * 1000) - -/* MQTT 阻塞调用(包括连接, 订阅, 发布等)的超时时间, 单位:ms 建议5000ms */ -#define QCLOUD_IOT_MQTT_COMMAND_TIMEOUT (5 * 1000) - -/* 接收到 MQTT 包头以后,接收剩余长度及剩余包,最大延迟等待时延 */ -#define QCLOUD_IOT_MQTT_MAX_REMAIN_WAIT_MS (2000) - - -/* TLS连接握手超时时间, 单位:ms */ -#define QCLOUD_IOT_TLS_HANDSHAKE_TIMEOUT (5 * 1000) - -/* 设备ID的最大长度, 必须保持唯一 */ -#define MAX_SIZE_OF_CLIENT_ID (80) - -/* 产品名称的最大长度 */ -#define MAX_SIZE_OF_PRODUCT_ID (10) - -/* 设备ID的最大长度 */ -#define MAX_SIZE_OF_DEVICE_NAME (48) - -/* MQTT消息发送buffer大小, 支持最大256*1024 */ -#define QCLOUD_IOT_MQTT_TX_BUF_LEN (2048) - -/* MQTT消息接收buffer大小, 支持最大256*1024 */ -#define QCLOUD_IOT_MQTT_RX_BUF_LEN (2048) - -/* COAP 发送消息buffer大小,最大支持64*1024字节 */ -#define COAP_SENDMSG_MAX_BUFLEN (512) - -/* COAP 接收消息buffer大小,最大支持64*1024字节 */ -#define COAP_RECVMSG_MAX_BUFLEN (512) - -/* 重连最大等待时间 */ -#define MAX_RECONNECT_WAIT_INTERVAL (60 * 1000) - -/* 最大接入有效时间偏移,时间毫秒,0:表示永不过期;>0:表示在当前时间+timeout与后台对时*/ -#define MAX_ACCESS_EXPIRE_TIMEOUT (0) - -/* MQTT连接域名 */ -#define QCLOUD_IOT_MQTT_DIRECT_DOMAIN "iotcloud.tencentdevices.com" - -/* CoAP连接域名 */ -#define QCLOUD_IOT_COAP_DEIRECT_DOMAIN "iotcloud.tencentdevices.com" - -typedef struct { - char product_id[MAX_SIZE_OF_PRODUCT_ID + 1]; - char device_name[MAX_SIZE_OF_DEVICE_NAME + 1]; - char client_id[MAX_SIZE_OF_CLIENT_ID + 1]; -} DeviceInfo; - -#include "qcloud_iot_export_coap.h" -#include "qcloud_iot_export_log.h" -#include "qcloud_iot_export_error.h" -#include "qcloud_iot_export_mqtt.h" -#include "qcloud_iot_export_shadow.h" -#include "qcloud_iot_export_ota.h" -#include "qcloud_iot_export_system.h" -#include "qcloud_iot_export_nbiot.h" -#include "qcloud_iot_export_gateway.h" - - -#ifdef __cplusplus -} -#endif - -#endif /* QCLOUD_IOT_EXPORT_H_ */ diff --git a/src/sdk-impl/qcloud_iot_import.h b/src/sdk-impl/qcloud_iot_import.h deleted file mode 100644 index beff03c2..00000000 --- a/src/sdk-impl/qcloud_iot_import.h +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_IMPORT_H_ -#define QCLOUD_IOT_IMPORT_H_ -#if defined(__cplusplus) -extern "C" { -#endif - -#include -#include -#include -#include -#include -#include -#include - -#define _IN_ /* 表明这是一个输入参数. */ -#define _OU_ /* 表明这是一个输出参数. */ - -#define IOT_TRUE (1) /* indicate boolean value true */ -#define IOT_FALSE (0) /* indicate boolean value false */ - -#define Max(a,b) ((a) > (b) ? (a) : (b)) -#define Min(a,b) ((a) < (b) ? (a) : (b)) - - -/** - * @brief 创建互斥锁 - * - * @return 创建失败返回NULL,成功返回Mutex指针 - */ -void *HAL_MutexCreate(void); - -/** - * @brief 销毁互斥锁 - * - * @param Mutex指针 - */ -void HAL_MutexDestroy(_IN_ void *mutex); - -/** - * @brief 阻塞式加锁 - * - * @param Mutex指针 - */ -void HAL_MutexLock(_IN_ void *mutex); - -/** - * @brief 非阻塞式加锁 - * - * @param Mutex指针 - * @return 如果成功拿到锁,则返回0,否则返回错误值 - */ -int HAL_MutexTryLock(_IN_ void *mutex); - -/** - * @brief 释放锁 - * - * @param Mutex指针 - */ -void HAL_MutexUnlock(_IN_ void *mutex); - -/** - * @brief 分配一块的内存,返回一个指向块开始的指针. - * - * @param size 用字节指定块大小. - * @return 一个指向block开头的指针. - */ -void *HAL_Malloc(_IN_ uint32_t size); - -/** - * @brief 释放内存块 - * - * @param ptr 指向先前分配给平台malloc的内存块的指针. - */ -void HAL_Free(_IN_ void *ptr); - -/** - * @brief 将格式化的数据写入标准输出流中. - * - * @param fmt 要写入的文本的字符串, 它可以选择包含嵌入的格式指定符, 它指定了随后的参数如何转换为输出. - * @param ... 变量参数列表. - */ -void HAL_Printf(_IN_ const char *fmt, ...); - -/** - * @brief 将格式化的数据写入字符串. - * - * @param str 目标字符串. - * @param len 将被写入字符的最大长度 - * @param fmt 要编写的文本的格式,它可以选择包含嵌入的格式指定符, 它指定了随后的参数如何转换为输出. - * @param ... 变量参数列表,用于格式化并插入到生成的字符串中,替换它们各自的指定符. - * @return 成功写入字符串的字节数. - */ -int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...); - -/** - * @brief 将格式化的数据写入字符串. - * - * @param [out] str: 目标字符串. - * @param [in] len: 将被写入字符的最大长度. - * @param [in] fmt: 要编写的文本的格式. - * @param [in] ap: 参数列表. - * @return 成功写入字符串的字节数. - */ -int HAL_Vsnprintf(_OU_ char *str, _IN_ const int len, _IN_ const char *fmt, _IN_ va_list ap); - -/** - * @brief 检索自系统启动以来已运行的毫秒数. - * - * @return 返回毫秒数. - */ -uint32_t HAL_UptimeMs(void); - -/** - * @brief 休眠. - * - * @param ms 休眠的时长, 单位毫秒. - */ -void HAL_SleepMs(_IN_ uint32_t ms); - -/** - * 定义特定平台下的一个定时器结构体, - */ -struct Timer { - struct timeval end_time; -}; - -typedef struct Timer Timer; - -/** - * @brief 判断定时器时间是否已经过期 - * - * @param timer 定时器结构体 - * @return 返回true, 表示定时器已过期 - */ -bool HAL_Timer_expired(Timer *timer); - -/** - * @brief 根据定时器开始计时, 单位:ms - * - * @param timer 定时器结构体 - * @param timeout_ms 超时时间, 单位:ms - */ -void HAL_Timer_countdown_ms(Timer *timer, unsigned int timeout_ms); - -/** - * @brief 根据定时器开始计时, 单位:ms - * - * @param timer 定时器结构体 - * @param timeout 超时时间, 单位:s - */ -void HAL_Timer_countdown(Timer *timer, unsigned int timeout); - -/** - * @brief 检查给定定时器还剩下多少时间 - * - * @param timer 定时器结构体 - * @return 返回剩余时间 - */ -int HAL_Timer_remain(Timer *timer); - -/** - * @brief 初始化定时器结构体 - * - * @param timer 定时器结构体 - */ -void HAL_Timer_init(Timer *timer); - -/** - * @brief 获取当前时间格式化字符串 %Y-%m-%d %z %H:%M:%S - * - * @return 当前时间格式化字符串 - */ -char* HAL_Timer_current(void); - -/** - * @brief 获取当前时间秒数 - * - * @return 当前时间的秒级类型 - */ -long HAL_Timer_current_sec(void); - -#ifndef AUTH_WITH_NOTLS -/** - * @brief TLS连接相关参数定义 - * - * 在初始化时, 必须要将ca证书、客户端证书、客户端私钥文件及服务器域名带上来 - */ -typedef struct { - const char *ca_crt; - uint16_t ca_crt_len; - -#ifdef AUTH_MODE_CERT - /** - * 非对称加密 - */ - const char *cert_file; // 客户端证书 - const char *key_file; // 客户端私钥 -#else - /** - * 对称加密 - */ - const char *psk; // 对称加密密钥 - const char *psk_id; // psk密钥ID -#endif - - size_t psk_length; // psk长度 - - unsigned int timeout_ms; // SSL握手超时时间 - -} SSLConnectParams; - -/********** TLS network **********/ -typedef SSLConnectParams TLSConnectParams; - -/** - * @brief 为MQTT客户端建立TLS连接 - * - * 主要步骤如下: - * 1. 初始化工作, 例如mbedtls库初始化, 相关证书文件加载等 - * 2. 建立TCP socket连接 - * 3. 建立SSL连接, 包括握手, 服务器证书检查等 - * - * @param pConnectParams TLS连接初始化参数 - * @host 连接域名 - * @port 连接端口 - * @return 返回0 表示TLS连接成功 - */ -uintptr_t HAL_TLS_Connect(TLSConnectParams *pConnectParams, const char *host, int port); - -/** - * @brief 断开TLS连接, 并释放相关对象资源 - * - * @param pParams TLS连接参数 - */ -void HAL_TLS_Disconnect(uintptr_t handle); - -/** - * @brief 通过TLS连接写数据 - * - * @param handle TLS连接相关数据结构 - * @param data 写入数据 - * @param totalLen 写入数据长度 - * @param timeout_ms 超时时间, 单位:ms - * @param written_len 已写入数据长度 - * @return 若写数据成功, 则返回写入数据的长度 - */ -int HAL_TLS_Write(uintptr_t handle, unsigned char *data, size_t totalLen, uint32_t timeout_ms, - size_t *written_len); - -/** - * @brief 通过TLS连接读数据 - * - * @param handle TLS连接相关数据结构 - * @param data 读取数据 - * @param totalLen 读取数据的长度 - * @param timeout_ms 超时时间, 单位:ms - * @param read_len 已读取数据的长度 - * @return 若读数据成功, 则返回读取数据的长度 - */ -int HAL_TLS_Read(uintptr_t handle, unsigned char *data, size_t totalLen, uint32_t timeout_ms, - size_t *read_len); - -/********** TCP network **********/ -/** - * @brief 为MQTT客户端建立TCP连接 - * - * @host 连接域名 - * @port 连接端口 - * @return 返回0 表示TCP连接失败;返回 > 0 表示TCP连接描述符FD值 - */ -uintptr_t HAL_TCP_Connect(const char *host, uint16_t port); - -/** - * @brief 断开TCP连接 - * - * @param fd TCP Socket描述符 - * @return 返回0 表示TCP断连成功 - */ -int HAL_TCP_Disconnect(uintptr_t fd); - -/** - * @brief 通过TCP Socket写数据 - * - * @param fd TCP Socket描述符 - * @param buf 写入数据 - * @param len 写入数据长度 - * @param timeout_ms 超时时间 - * @param written_len 已写入数据长度 - * @return 若写数据成功, 则返回写入数据的长度 - */ -int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t timeout_ms, - size_t *written_len); - -/** - * @brief 通过TCP Socket读数据 - * - * @param fd TCP Socket描述符 - * @param buf 读入数据 - * @param len 读入数据长度 - * @param timeout_ms 超时时间 - * @param written_len 已读入数据长度 - * @return 若读数据成功, 则返回读入数据的长度 - */ -int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeout_ms, - size_t *read_len); - - - -/********** DTLS network **********/ -#ifdef COAP_COMM_ENABLED -typedef SSLConnectParams DTLSConnectParams; - -/** - * @brief 为CoAP客户端建立DTLS连接 - * - * 主要步骤如下: - * 1. 初始化工作, 例如mbedtls库初始化, 相关证书文件加载等 - * 2. 建立UDP socket连接 - * 3. 建立SSL连接, 包括握手, 服务器证书检查等 - * - * @param pConnectParams DTLS连接初始化参数 - * @host 连接域名 - * @port 连接端口 - * @return 返回0 表示DTLS连接成功 - */ -uintptr_t HAL_DTLS_Connect(DTLSConnectParams *pConnectParams, const char *host, int port); - -/** - * @brief 断开DTLS连接 - * - * @param handle DTLS连接相关数据结构 - * @return 返回0 表示DTLS断连 - */ -void HAL_DTLS_Disconnect(uintptr_t handle); - -/** - * @brief 通过DTLS连接写数据 - * - * @param pParams DTLS连接相关数据结构 - * @param data 写入数据 - * @param datalen 写入数据长度 - * @param written_len 已写入数据长度 - * @return 若写数据成功, 则返回写入数据的长度 - */ -int HAL_DTLS_Write(uintptr_t handle, const unsigned char *data, size_t datalen, size_t *written_len); - -/** - * @brief 通过DTLS连接读数据 - * - * @param handle DTLS连接相关数据结构 - * @param data 读取数据 - * @param timeout_ms 超时时间, 单位:ms - * @param datalen 读取数据的长度 - * @param read_len 已读取数据的长度 - * @return 若读数据成功, 则返回读取数据的长度 - */ -int HAL_DTLS_Read(uintptr_t handle, unsigned char *data, size_t datalen, uint32_t timeout_ms, - size_t *read_len); - -#endif //CoAP Enabled - -#else -/********** TCP network **********/ -/** - * @brief 为MQTT客户端建立TCP连接 - * - * @host 连接域名 - * @port 连接端口 - * @return 返回0 表示TCP连接失败;返回 > 0 表示TCP连接描述符FD值 - */ -uintptr_t HAL_TCP_Connect(const char *host, uint16_t port); - -/** - * @brief 断开TCP连接 - * - * @param fd TCP Socket描述符 - * @return 返回0 表示TCP断连成功 - */ -int HAL_TCP_Disconnect(uintptr_t fd); - -/** - * @brief 通过TCP Socket写数据 - * - * @param fd TCP Socket描述符 - * @param buf 写入数据 - * @param len 写入数据长度 - * @param timeout_ms 超时时间 - * @param written_len 已写入数据长度 - * @return 若写数据成功, 则返回写入数据的长度 - */ -int HAL_TCP_Write(uintptr_t fd, const unsigned char *buf, uint32_t len, uint32_t timeout_ms, - size_t *written_len); - -/** - * @brief 通过TCP Socket读数据 - * - * @param fd TCP Socket描述符 - * @param buf 读入数据 - * @param len 读入数据长度 - * @param timeout_ms 超时时间 - * @param written_len 已读入数据长度 - * @return 若读数据成功, 则返回读入数据的长度 - */ -int HAL_TCP_Read(uintptr_t fd, unsigned char *buf, uint32_t len, uint32_t timeout_ms, - size_t *read_len); - -/********** UDP network **********/ -#ifdef COAP_COMM_ENABLED -/** - * @brief 建立UDP连接 - * - * @host 连接域名 - * @port 连接端口 - * @return 返回0 表示UDP连接失败;返回 > 0 表示UDP连接描述符FD值 - */ -uintptr_t HAL_UDP_Connect(const char *host, unsigned short port); - -/** - * @brief 断开UDP连接 - * - * @param fd UDP Socket描述符 - * @return - */ -void HAL_UDP_Disconnect(uintptr_t fd); - -/** - * @brief 通过UDP Socket写数据 - * - * @param fd UDP Socket描述符 - * @param buf 写入数据 - * @param len 写入数据长度 - * @return 若写数据成功, 则返回写入数据的长度 - */ -int HAL_UDP_Write(uintptr_t fd, const unsigned char *p_data, unsigned int datalen); - -/** - * @brief 通过TCP Socket读数据 - * - * @param fd UDP Socket描述符 - * @param buf 读入数据 - * @param len 读入数据长度 - * @return 若读数据成功, 则返回读入数据的长度 - */ -int HAL_UDP_Read(uintptr_t fd, unsigned char *p_data, unsigned int datalen); - -/** - * @brief 通过TCP Socket读数据 - * - * @param fd UDP Socket描述符 - * @param buf 读入数据 - * @param len 读入数据长度 - * @param timeout_ms 超时时间 - * @return 若读数据成功, 则返回读入数据的长度 - */ -int HAL_UDP_ReadTimeout(uintptr_t fd, unsigned char *p_data, unsigned int datalen, unsigned int timeout_ms); -#endif -#endif //NOTLS Enabled - -#if defined(__cplusplus) -} -#endif -#endif /* QCLOUD_IOT_IMPORT_H_ */ - diff --git a/src/sdk-impl/qcloud_iot_sdk_impl_internal.h b/src/sdk-impl/qcloud_iot_sdk_impl_internal.h deleted file mode 100644 index 62fa6060..00000000 --- a/src/sdk-impl/qcloud_iot_sdk_impl_internal.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_SDK_IMPL_INTERNAL_H_ -#define QCLOUD_IOT_SDK_IMPL_INTERNAL_H_ - -#if defined(__cplusplus) -extern "C" { -#endif - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" - -#define NUMBERIC_SANITY_CHECK(num, err) \ - do { \ - if (0 == (num)) { \ - Log_e("Invalid argument, numeric 0"); \ - return (err); \ - } \ - } while(0) - -#define NUMBERIC_SANITY_CHECK_RTN(num) \ - do { \ - if (0 == (num)) { \ - Log_e("Invalid argument, numeric 0"); \ - return; \ - } \ - } while(0) - -#define POINTER_SANITY_CHECK(ptr, err) \ - do { \ - if (NULL == (ptr)) { \ - Log_e("Invalid argument, %s = %p", #ptr, ptr); \ - return (err); \ - } \ - } while(0) - -#define POINTER_SANITY_CHECK_RTN(ptr) \ - do { \ - if (NULL == (ptr)) { \ - Log_e("Invalid argument, %s = %p", #ptr, ptr); \ - return; \ - } \ - } while(0) - -#define STRING_PTR_SANITY_CHECK(ptr, err) \ - do { \ - if (NULL == (ptr)) { \ - Log_e("Invalid argument, %s = %p", #ptr, (ptr)); \ - return (err); \ - } \ - if (0 == strlen((ptr))) { \ - Log_e("Invalid argument, %s = '%s'", #ptr, (ptr)); \ - return (err); \ - } \ - } while(0) - -#define STRING_PTR_SANITY_CHECK_RTN(ptr) \ - do { \ - if (NULL == (ptr)) { \ - Log_e("Invalid argument, %s = %p", #ptr, (ptr)); \ - return; \ - } \ - if (0 == strlen((ptr))) { \ - Log_e("Invalid argument, %s = '%s'", #ptr, (ptr)); \ - return; \ - } \ - } while(0) - -#if defined(__cplusplus) -} -#endif - -#endif /* QCLOUD_IOT_SDK_IMPL_INTERNAL_H_ */ diff --git a/src/shadow/include/shadow_client.h b/src/shadow/include/shadow_client.h deleted file mode 100644 index 3cec52b4..00000000 --- a/src/shadow/include/shadow_client.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -/** - * @brief 设备影子文档操作相关的一些接口 - * - * 这里提供一些接口用于管理设备影子文档或与设备影子文档进行交互; 通过DeviceName, - * 可以与设备影子进行交互, 包括当前设备的设备影子和其他设备的设备影子; 一 - * 个设备一共有三种不同操作与设备影子交互: - * 1. Get - * 2. Update - * 3. Delete - * - * 以上三种操作, 底层还是基于MQTT协议, 工作原理也是基于发布/订阅模型, 当执行 - * 上述操作是, 会收到相应的响应: 1. accepted; 2. rejected。例如, 我们执行 - * Get与设备影子进行交互, 设备端将发送和接收到一下信息: - * 1. 发布MQTT主题: $shadow/get/{productName}/{deviceName}; - * 2. 订阅MQTT主题: $shadow/get/accepted/{productName}/{deviceName} 和 $shadow/get/rejected/{productName}/{deviceName} - * 3. 如果整个请求成功的话, 设备端会收到accepted主题, 以及相应设备的json文档。 - */ -#ifndef IOT_SHADOW_CLIENT_H_ -#define IOT_SHADOW_CLIENT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" -#include "qcloud_iot_sdk_impl_internal.h" -#include "device.h" -#include "mqtt_client.h" -#include "shadow_client_json.h" - -/* 在任意给定时间内, 处于appending状态的请求最大个数 */ -#define MAX_APPENDING_REQUEST_AT_ANY_GIVEN_TIME (10) - -/* 一个clientToken的最大长度 */ -#define MAX_SIZE_OF_CLIENT_TOKEN (MAX_SIZE_OF_CLIENT_ID + 10) - -/* 一个仅包含clientToken字段的JSON文档的最大长度 */ -#define MAX_SIZE_OF_JSON_WITH_CLIENT_TOKEN (MAX_SIZE_OF_CLIENT_TOKEN + 20) - -/* 在任意给定时间内, 可以同时操作设备的最大个数 */ -#define MAX_DEVICE_HANDLED_AT_ANY_GIVEN_TIME (10) - -/* 除设备名称之外, 云端保留主题的最大长度 */ -#define MAX_SIZE_OF_CLOUD_TOPIC_WITHOUT_DEVICE_NAME (60) - -/* 接收云端返回的JSON文档的buffer大小 */ -#define CLOUD_IOT_JSON_RX_BUF_LEN (QCLOUD_IOT_MQTT_RX_BUF_LEN + 1) - -/** - * @brief 文档操作请求的参数结构体定义 - */ -typedef struct _RequestParam { - - Method method; // 文档请求方式: GET, UPDATE, DELETE - - uint32_t timeout_sec; // 请求超时时间, 单位:s - - OnRequestCallback request_callback; // 请求回调方法 - - void *user_context; // 用户数据, 会通过回调方法OnRequestCallback返回 - -} RequestParams; - -#define DEFAULT_REQUEST_PARAMS {GET, 4, NULL, NULL}; - -/** - * @brief 该结构体用于保存已登记的设备属性及设备属性处理的回调方法 - */ -typedef struct { - - void *property; // 设备属性 - - OnPropRegCallback callback; // 回调处理函数 - -} PropertyHandler; - -typedef struct _ShadowInnerData { - uint32_t token_num; - uint32_t version; - int32_t sync_status; - List *request_list; - List *property_handle_list; - char *result_topic; -} ShadowInnerData; - -typedef struct _Shadow { - void *mqtt; - void *mutex; - MQTTEventHandler event_handle; - ShadowInnerData inner_data; -} Qcloud_IoT_Shadow; - -int qcloud_iot_shadow_init(Qcloud_IoT_Shadow *pShadow); - -void qcloud_iot_shadow_reset(void *pClient); - -/** - * @brief 处理请求队列中已经超时的请求 - * - * @param pShadow shadow client - */ -void handle_expired_request(Qcloud_IoT_Shadow *pShadow); - -/** - * @brief 所有的云端设备文档操作请求, 通过该方法进行中转分发 - * - * @param pShadow shadow client - * @param pParams 请求参数 - * @param pJsonDoc 请求文档 - * @param sizeOfBuffer 文档缓冲区大小 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int do_shadow_request(Qcloud_IoT_Shadow *pShadow, RequestParams *pParams, char *pJsonDoc, size_t sizeOfBuffer); - -/** - * @brief 订阅设备影子操作结果topic - * - * @param pShadow shadow client - * @param pParams 请求参数 - * @param pJsonDoc 请求文档 - * @param sizeOfBuffer 文档缓冲区大小 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int subscribe_operation_result_to_cloud(Qcloud_IoT_Shadow *pShadow); - -#ifdef __cplusplus -} -#endif - -#endif /* IOT_SHADOW_CLIENT_H_ */ diff --git a/src/shadow/include/shadow_client_json.h b/src/shadow/include/shadow_client_json.h deleted file mode 100644 index 261ca940..00000000 --- a/src/shadow/include/shadow_client_json.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef IOT_SHADOW_CLIENT_JSON_H_ -#define IOT_SHADOW_CLIENT_JSON_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include "qcloud_iot_export.h" -#include "qcloud_iot_import.h" - -#define VERSION_FIELD "version" -#define TYPE_FIELD "type" -#define CLIENT_TOKEN_FIELD "clientToken" -#define RESULT_FIELD "result" - -#define OPERATION_DELTA "delta" -#define OPERATION_GET "get" -#define OPERATION_UPDATE "update" - -#define PAYLOAD_STATE "payload.state" -#define PAYLOAD_VERSION "payload.version" -#define PAYLOAD_STATE_DELTA "payload.state.delta" - -/** - * 将一个JSON节点写入到JSON串中 - * - * @param jsonBuffer JSON串 - * @param sizeOfBuffer 可写入大小 - * @param pKey JSON节点的key - * @param pData JSON节点的value - * @param type JSON节点value的数据类型 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int put_json_node(char *jsonBuffer, size_t sizeOfBuffer, const char *pKey, void *pData, JsonDataType type); - -/** - * @brief 返回一个ClientToken - * - * @param pStrBuffer 存储ClientToken的字符串缓冲区 - * @param sizeOfBuffer 缓冲区大小 - * @param tokenNumber shadow的token值,函数内部每次执行完会自增 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -int generate_client_token(char *pStrBuffer, size_t sizeOfBuffer, uint32_t *tokenNumber); - -/** - * @brief 为GET和DELETE请求构造一个只带有clientToken字段的JSON文档 - * - * @param tokenNumber shadow的token值,函数内部每次执行完会自增 - * @param pJsonBuffer 存储JSON文档的字符串缓冲区 - */ -void build_empty_json(uint32_t *tokenNumber, char *pJsonBuffer); - -/** - * @brief 从JSON文档中解析出clientToken字段 - * - * @param pJsonDoc 待解析的JSON文档 - * @param pClientToken ClientToken字段 - * @return 返回true, 表示解析成功 - */ -bool parse_client_token(char *pJsonDoc, char **pClientToken); - -/** - * @brief 从JSON文档中解析出version字段 - * - * @param pJsonDoc 待解析的JSON文档 - * @param pVersionNumber JSON文档版本号 - * @return 返回true, 表示解析成功 - */ -bool parse_version_num(char *pJsonDoc, uint32_t *pVersionNumber); - -/** - * @brief 从JSON文档中解析出state字段 - * - * @param pJsonDoc 待解析的JSON文档 - * @param pErrorMessage 响应返回错误提示消息 - * @return 返回true, 表示解析成功 - */ -bool parse_shadow_state(char *pJsonDoc, char **pState); - -/** - * @brief 从JSON文档中解析出type字段 - * - * @param pJsonDoc 待解析的JSON文档 - * @param pType 输出tyde字段 - * @return 返回true, 表示解析成功 - */ -bool parse_shadow_operation_type(char *pJsonDoc, char **pType); - -/** - * @brief 从JSON文档中解析出result字段 - * - * @param pJsonDoc 待解析的JSON文档 - * @param pResultCode 操作结果标志码 - * @return 返回true, 表示解析成功 - */ -bool parse_shadow_operation_result_code(char *pJsonDoc, int16_t *pResultCode); - -/** - * @brief 从JSON文档中解析出delta字段, dalta type - * - * @param pJsonDoc 待解析的JSON文档 - * @param pDelta delta字段对应的value - * @return 返回true, 表示解析成功 - */ -bool parse_shadow_operation_delta(char *pJsonDoc, char **pDelta); - -/** - * @brief 从JSON文档中解析出delta字段 , get/update type - * - * @param pJsonDoc 待解析的JSON文档 - * @param pDelta delta字段对应的value - * @return 返回true, 表示解析成功 - */ -bool parse_shadow_operation_get(char *pJsonDoc, char **pDelta); - - -/** - * @brief 如果JSON文档中的key与某个设备属性的key匹配的话, 则更新该设备属性, 该设备属性的值不能为OBJECT类型 - * - * @param pJsonDoc JSON文档 - * @param pProperty 设备属性 - * @return 返回true, 表示成功 - */ -bool update_value_if_key_match(char *pJsonDoc, DeviceProperty *pProperty); - -#ifdef __cplusplus -} -#endif - -#endif //IOT_SHADOW_CLIENT_JSON_H_ diff --git a/src/shadow/src/shadow_client.c b/src/shadow/src/shadow_client.c deleted file mode 100644 index 4aad4c1e..00000000 --- a/src/shadow/src/shadow_client.c +++ /dev/null @@ -1,815 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "shadow_client.h" - -#include -#include -#include - -#include "qcloud_iot_sdk_impl_internal.h" -#include "shadow_client_json.h" -#include "shadow_client_common.h" - - -static void _init_request_params(RequestParams *pParams, Method method, OnRequestCallback callback, void *userContext, uint8_t timeout_sec) { - pParams->method = method; - pParams->user_context = userContext; - pParams->timeout_sec = timeout_sec; - pParams->request_callback = callback; -} - -/** - * @brief 检查函数snprintf的返回值 - * - * @param returnCode 函数snprintf的返回值 - * @param maxSizeOfWrite 可写最大字节数 - * @return 返回QCLOUD_ERR_JSON, 表示出错; 返回QCLOUD_ERR_JSON_BUFFER_TRUNCATED, 表示截断 - */ -static inline int _check_snprintf_return(int32_t returnCode, size_t maxSizeOfWrite) { - - if (returnCode >= maxSizeOfWrite) { - return QCLOUD_ERR_JSON_BUFFER_TRUNCATED; - } else if (returnCode < 0) { // 写入出错 - return QCLOUD_ERR_JSON; - } - - return QCLOUD_ERR_SUCCESS; -} - -static void _shadow_event_handler(void *pclient, void *context, MQTTEventMsg *msg) { - uintptr_t packet_id = (uintptr_t)msg->msg; - Qcloud_IoT_Shadow *shadow_client = (Qcloud_IoT_Shadow *)context; - MQTTMessage* topic_info = (MQTTMessage*)msg->msg; - - switch (msg->event_type) { - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_d("shadow subscribe success, packet-id=%u", (unsigned int)packet_id); - if (shadow_client->inner_data.sync_status > 0) - shadow_client->inner_data.sync_status = 0; - break; - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_d("shadow subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - if (shadow_client->inner_data.sync_status > 0) - shadow_client->inner_data.sync_status = -1; - break; - case MQTT_EVENT_SUBCRIBE_NACK: - Log_d("shadow subscribe nack, packet-id=%u", (unsigned int)packet_id); - if (shadow_client->inner_data.sync_status > 0) - shadow_client->inner_data.sync_status = -1; - break; - case MQTT_EVENT_PUBLISH_RECVEIVED: - Log_d("shadow topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - topic_info->topic_len, - topic_info->ptopic, - topic_info->payload_len, - topic_info->payload); - break; - default: - /* Log_i("Should NOT arrive here."); */ - break; - } - if (shadow_client->event_handle.h_fp != NULL) - { - shadow_client->event_handle.h_fp(shadow_client, shadow_client->event_handle.context, msg); - } -} - -static void _copy_shadow_init_params_to_mqtt(MQTTInitParams *pMqttInitParams, ShadowInitParams *shadowInitParams) -{ - pMqttInitParams->device_name = shadowInitParams->device_name; - pMqttInitParams->product_id = shadowInitParams->product_id; - -#ifdef AUTH_MODE_CERT - pMqttInitParams->cert_file = shadowInitParams->cert_file; - pMqttInitParams->key_file = shadowInitParams->key_file; -#else - pMqttInitParams->device_secret = shadowInitParams->device_secret; -#endif - - pMqttInitParams->command_timeout = shadowInitParams->command_timeout; - pMqttInitParams->keep_alive_interval_ms = shadowInitParams->keep_alive_interval_ms; - pMqttInitParams->clean_session = shadowInitParams->clean_session; - pMqttInitParams->auto_connect_enable = shadowInitParams->auto_connect_enable; -} - -static void _update_ack_cb(void *pClient, Method method, RequestAck requestAck, const char *pReceivedJsonDocument, void *pUserdata) -{ - Log_d("requestAck=%d", requestAck); - - if (NULL != pReceivedJsonDocument) { - Log_d("Received Json Document=%s", pReceivedJsonDocument); - } else { - Log_d("Received Json Document is NULL"); - } - - *((RequestAck *)pUserdata) = requestAck; -} - -void* IOT_Shadow_Construct(ShadowInitParams *pParams) -{ - POINTER_SANITY_CHECK(pParams, NULL); - - Qcloud_IoT_Shadow *shadow_client = NULL; - if ((shadow_client = (Qcloud_IoT_Shadow *)HAL_Malloc(sizeof(Qcloud_IoT_Shadow))) == NULL) { - Log_e("memory not enough to malloc ShadowClient"); - } - - MQTTInitParams mqtt_init_params; - _copy_shadow_init_params_to_mqtt(&mqtt_init_params, pParams); - - mqtt_init_params.event_handle.h_fp = _shadow_event_handler; - mqtt_init_params.event_handle.context = shadow_client; - - void *mqtt_client = NULL; - if ((mqtt_client = IOT_MQTT_Construct(&mqtt_init_params)) == NULL) { - HAL_Free(shadow_client); - goto End; - } - - shadow_client->mqtt = mqtt_client; - shadow_client->event_handle = pParams->event_handle; - shadow_client->inner_data.result_topic = NULL; - shadow_client->inner_data.version = 0; - shadow_client->inner_data.token_num = 0; - - int rc; - - rc = qcloud_iot_shadow_init(shadow_client); //初始化delta - if (rc != QCLOUD_ERR_SUCCESS) { - IOT_MQTT_Destroy(&(shadow_client->mqtt)); - HAL_Free(shadow_client); - goto End; - } - - rc = subscribe_operation_result_to_cloud(shadow_client); - if (rc < 0) - { - Log_e("Subcribe $shadow/operation/results fail!"); - } - else { - shadow_client->inner_data.sync_status = rc; - while (rc == shadow_client->inner_data.sync_status) { - IOT_Shadow_Yield(shadow_client, 100); - } - if (0 == shadow_client->inner_data.sync_status) { - Log_i("Sync device data successfully"); - } else { - Log_e("Sync device data failed"); - } - } - - return shadow_client; - -End: - return NULL; -} - -int IOT_Shadow_Publish(void *handle, char *topicName, PublishParams *pParams) { - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; - - return qcloud_iot_mqtt_publish(shadow->mqtt, topicName, pParams); -} - -int IOT_Shadow_Subscribe(void *handle, char *topicFilter, SubscribeParams *pParams) { - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; - - return qcloud_iot_mqtt_subscribe(shadow->mqtt, topicFilter, pParams); -} - -int IOT_Shadow_Unsubscribe(void *handle, char *topicFilter) { - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow *shadow = (Qcloud_IoT_Shadow *)handle; - - return qcloud_iot_mqtt_unsubscribe(shadow->mqtt, topicFilter); -} - -bool IOT_Shadow_IsConnected(void *handle) -{ - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow* pshadow = (Qcloud_IoT_Shadow*)handle; - - IOT_FUNC_EXIT_RC(IOT_MQTT_IsConnected(pshadow->mqtt)) -} - -int IOT_Shadow_Destroy(void *handle) -{ - IOT_FUNC_ENTRY; - - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow* shadow_client = (Qcloud_IoT_Shadow*)handle; - qcloud_iot_shadow_reset(handle); - - IOT_MQTT_Destroy(&shadow_client->mqtt); - - if (NULL != shadow_client->mutex) { - HAL_MutexDestroy(shadow_client->mutex); - } - - if (NULL != shadow_client->inner_data.result_topic) { - HAL_Free(shadow_client->inner_data.result_topic); - shadow_client->inner_data.result_topic = NULL; - } - - HAL_Free(handle); - - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SUCCESS) -} - -int IOT_Shadow_Yield(void *handle, uint32_t timeout_ms) { - - IOT_FUNC_ENTRY; - int rc; - - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow *pshadow = (Qcloud_IoT_Shadow *)handle; - POINTER_SANITY_CHECK(pshadow, QCLOUD_ERR_INVAL); - - handle_expired_request(pshadow); - - rc = IOT_MQTT_Yield(pshadow->mqtt, timeout_ms); - - IOT_FUNC_EXIT_RC(rc); -} - -int IOT_Shadow_Register_Property(void *handle, DeviceProperty *pProperty, OnPropRegCallback callback) { - - IOT_FUNC_ENTRY; - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow* pshadow = (Qcloud_IoT_Shadow*)handle; - int rc; - - if (IOT_MQTT_IsConnected(pshadow->mqtt) == false) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); - } - - if (shadow_common_check_property_existence(pshadow, pProperty)) - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SHADOW_PROPERTY_EXIST); - - rc = shadow_common_register_property_on_delta(pshadow, pProperty, callback); - - IOT_FUNC_EXIT_RC(rc); -} - -int IOT_Shadow_UnRegister_Property(void *handle, DeviceProperty *pProperty) { - IOT_FUNC_ENTRY; - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - Qcloud_IoT_Shadow* pshadow = (Qcloud_IoT_Shadow*)handle; - - if (IOT_MQTT_IsConnected(pshadow->mqtt) == false) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); - } - - if (!shadow_common_check_property_existence(pshadow, pProperty)) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_SHADOW_NOT_PROPERTY_EXIST); - } - int rc = shadow_common_remove_property(pshadow, pProperty); - IOT_FUNC_EXIT_RC(rc); -} - -int IOT_Shadow_Update(void *handle, char *pJsonDoc, size_t sizeOfBuffer, OnRequestCallback callback, void *userContext, uint32_t timeout_ms) { - - IOT_FUNC_ENTRY; - int rc; - - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(pJsonDoc, QCLOUD_ERR_INVAL); - NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow* shadow = (Qcloud_IoT_Shadow*)handle; - - if (IOT_MQTT_IsConnected(shadow->mqtt) == false) { - Log_e("shadow is disconnected"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); - } - - // 如果没有之前没有订阅$shadow/operation/result成功,再一次订阅 - if (shadow->inner_data.sync_status < 0) { - subscribe_operation_result_to_cloud(shadow); - } - - Log_d("UPDATE Request Document: %s", pJsonDoc); - - RequestParams request_params = DEFAULT_REQUEST_PARAMS; - _init_request_params(&request_params, UPDATE, callback, userContext, timeout_ms/1000); - - rc = do_shadow_request(shadow, &request_params, pJsonDoc, sizeOfBuffer); - IOT_FUNC_EXIT_RC(rc); -} - -int IOT_Shadow_Update_Sync(void *handle, char *pJsonDoc, size_t sizeOfBuffer, uint32_t timeout_ms) { - - IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; - - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(pJsonDoc, QCLOUD_ERR_INVAL); - NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow* shadow = (Qcloud_IoT_Shadow*)handle; - - if (IOT_MQTT_IsConnected(shadow->mqtt) == false) { - Log_e("shadow is disconnected"); - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); - } - - RequestAck ack_update = ACK_NONE; - rc = IOT_Shadow_Update(handle, pJsonDoc, sizeOfBuffer, _update_ack_cb, &ack_update, timeout_ms); - if (rc != QCLOUD_ERR_SUCCESS) IOT_FUNC_EXIT_RC(rc); - - while (ACK_NONE == ack_update) { - IOT_Shadow_Yield(handle, 200); - } - - if (ACK_ACCEPTED == ack_update) { - rc = QCLOUD_ERR_SUCCESS; - } else if (ACK_TIMEOUT == ack_update) { - rc = QCLOUD_ERR_SHADOW_UPDATE_TIMEOUT; - } else if (ACK_REJECTED == ack_update) { - rc = QCLOUD_ERR_SHADOW_UPDATE_REJECTED; - } - - IOT_FUNC_EXIT_RC(rc); -} - -int IOT_Shadow_Get(void *handle, OnRequestCallback callback, void *userContext, uint32_t timeout_ms) { - - IOT_FUNC_ENTRY; - int rc; - - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - POINTER_SANITY_CHECK(callback, QCLOUD_ERR_INVAL); - NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow* shadow = (Qcloud_IoT_Shadow*)handle; - - if (IOT_MQTT_IsConnected(shadow->mqtt) == false) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); - } - - // 如果没有之前没有订阅$shadow/operation/result成功,再一次订阅 - if (shadow->inner_data.sync_status < 0) { - subscribe_operation_result_to_cloud(shadow); - } - - char getRequestJsonDoc[MAX_SIZE_OF_JSON_WITH_CLIENT_TOKEN]; - build_empty_json(&(shadow->inner_data.token_num), getRequestJsonDoc); - Log_d("GET Request Document: %s", getRequestJsonDoc); - - RequestParams request_params = DEFAULT_REQUEST_PARAMS; - _init_request_params(&request_params, GET, callback, userContext, timeout_ms/1000); - - rc = do_shadow_request(shadow, &request_params, getRequestJsonDoc, MAX_SIZE_OF_JSON_WITH_CLIENT_TOKEN); - IOT_FUNC_EXIT_RC(rc); -} - -int IOT_Shadow_Get_Sync(void *handle, uint32_t timeout_ms) { - - IOT_FUNC_ENTRY; - int rc = QCLOUD_ERR_SUCCESS; - - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - NUMBERIC_SANITY_CHECK(timeout_ms, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Shadow* shadow = (Qcloud_IoT_Shadow*)handle; - - if (IOT_MQTT_IsConnected(shadow->mqtt) == false) { - IOT_FUNC_EXIT_RC(QCLOUD_ERR_MQTT_NO_CONN); - } - - RequestAck ack_update = ACK_NONE; - rc = IOT_Shadow_Get(handle, _update_ack_cb, &ack_update, timeout_ms); - if (rc != QCLOUD_ERR_SUCCESS) IOT_FUNC_EXIT_RC(rc); - - while (ACK_NONE == ack_update) { - IOT_Shadow_Yield(handle, 200); - } - - if (ACK_ACCEPTED == ack_update) { - rc = QCLOUD_ERR_SUCCESS; - } else if (ACK_TIMEOUT == ack_update) { - rc = QCLOUD_ERR_SHADOW_GET_TIMEOUT; - } else if (ACK_REJECTED == ack_update) { - rc = QCLOUD_ERR_SHADOW_GET_REJECTED; - } - - IOT_FUNC_EXIT_RC(rc); -} - -/** - * @brief 初始化一个JSON文档 - * - * 本函数主要是为JSON文档添加state字段, 即 "{\"state\":{", 所以在生成JSON文档时, 请先调用该方法 - * - * @param jsonBuffer 为存储JSON文档准备的字符串缓冲区 - * @param sizeOfBuffer 缓冲区大小 - * @return 返回QCLOUD_ERR_SUCCESS, 表示初始化成功 - */ -static int IOT_Shadow_JSON_Init(Qcloud_IoT_Shadow *pShadow, char *jsonBuffer, size_t sizeOfBuffer, bool overwrite) { - - if (jsonBuffer == NULL) { - return QCLOUD_ERR_INVAL; - } - - int32_t rc_of_snprintf = 0; - if (overwrite) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer, sizeOfBuffer, "{\"version\":%d, \"overwriteUpdate\":true, \"state\":{", pShadow->inner_data.version); - } - else { - rc_of_snprintf = HAL_Snprintf(jsonBuffer, sizeOfBuffer, "{\"version\":%d, \"state\":{", pShadow->inner_data.version); - } - - return _check_snprintf_return(rc_of_snprintf, sizeOfBuffer); -} - -/** - * @brief 在JSON文档中添加结尾部分的内容, 包括clientToken字段、version字段 - * - * @param jsonBuffer 为存储JSON文档准备的字符串缓冲区 - * @param sizeOfBuffer 缓冲区大小 - * @return 返回QCLOUD_ERR_SUCCESS, 表示成功 - */ -static int IOT_Shadow_JSON_Finalize(Qcloud_IoT_Shadow *pShadow, char *jsonBuffer, size_t sizeOfBuffer) -{ - int rc; - size_t remain_size = 0; - int32_t rc_of_snprintf = 0; - - if (jsonBuffer == NULL) { - return QCLOUD_ERR_INVAL; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "}, \"%s\":\"", CLIENT_TOKEN_FIELD); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = generate_client_token(jsonBuffer + strlen(jsonBuffer), remain_size, &(pShadow->inner_data.token_num)); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"}"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - return rc; -} - -int IOT_Shadow_JSON_ConstructReport(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...) -{ - Qcloud_IoT_Shadow* pshadow = (Qcloud_IoT_Shadow*)handle; - POINTER_SANITY_CHECK(pshadow, QCLOUD_ERR_INVAL); - - int rc = IOT_Shadow_JSON_Init(pshadow, jsonBuffer, sizeOfBuffer, false); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json init failed: %d", rc); - return rc; - } - - size_t remain_size = 0; - int32_t rc_of_snprintf = 0; - int8_t i; - - if (jsonBuffer == NULL) { - return QCLOUD_ERR_INVAL; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"reported\":{"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - va_list pArgs; - va_start(pArgs, count); - - for (i = 0; i < count; i++) { - DeviceProperty *pJsonNode; - pJsonNode = va_arg(pArgs, DeviceProperty *); - if (pJsonNode != NULL && pJsonNode->key != NULL) { - rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); - - if (rc != QCLOUD_ERR_SUCCESS) { - va_end(pArgs); - return rc; - } - } else { - va_end(pArgs); - return QCLOUD_ERR_INVAL; - } - } - - va_end(pArgs); - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json add report failed: %d", rc); - return rc; - } - - rc = IOT_Shadow_JSON_Finalize(pshadow, jsonBuffer, sizeOfBuffer); - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json finalize failed: %d", rc); - } - - return rc; -} - -int IOT_Shadow_JSON_Construct_OverwriteReport(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...) -{ - Qcloud_IoT_Shadow* pshadow = (Qcloud_IoT_Shadow*)handle; - POINTER_SANITY_CHECK(pshadow, QCLOUD_ERR_INVAL); - - int rc = IOT_Shadow_JSON_Init(pshadow, jsonBuffer, sizeOfBuffer, true); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json init failed: %d", rc); - return rc; - } - - size_t remain_size = 0; - int32_t rc_of_snprintf = 0; - int8_t i; - - if (jsonBuffer == NULL) { - return QCLOUD_ERR_INVAL; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"reported\":{"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - va_list pArgs; - va_start(pArgs, count); - - for (i = 0; i < count; i++) { - DeviceProperty *pJsonNode; - pJsonNode = va_arg(pArgs, DeviceProperty *); - if (pJsonNode != NULL && pJsonNode->key != NULL) { - rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); - - if (rc != QCLOUD_ERR_SUCCESS) { - va_end(pArgs); - return rc; - } - } else { - va_end(pArgs); - return QCLOUD_ERR_INVAL; - } - } - - va_end(pArgs); - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json add report failed: %d", rc); - return rc; - } - - rc = IOT_Shadow_JSON_Finalize(pshadow, jsonBuffer, sizeOfBuffer); - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json finalize failed: %d", rc); - } - - return rc; -} - -int IOT_Shadow_JSON_ConstructReportAndDesireAllNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...) -{ - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - Qcloud_IoT_Shadow* pshadow = (Qcloud_IoT_Shadow*)handle; - - int rc = IOT_Shadow_JSON_Init(pshadow, jsonBuffer, sizeOfBuffer, false); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json init failed: %d", rc); - return rc; - } - - size_t remain_size = 0; - int32_t rc_of_snprintf = 0; - int8_t i; - - if (jsonBuffer == NULL) { - return QCLOUD_ERR_INVAL; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"reported\":{"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - va_list pArgs; - va_start(pArgs, count); - - for (i = 0; i < count; i++) { - DeviceProperty *pJsonNode; - pJsonNode = va_arg(pArgs, DeviceProperty *); - if (pJsonNode != NULL && pJsonNode->key != NULL) { - rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); - - if (rc != QCLOUD_ERR_SUCCESS) { - va_end(pArgs); - return rc; - } - } else { - va_end(pArgs); - return QCLOUD_ERR_INVAL; - } - } - - va_end(pArgs); - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json add report failed: %d", rc); - return rc; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"desired\": null "); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - rc = IOT_Shadow_JSON_Finalize(pshadow, jsonBuffer, sizeOfBuffer); - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json finalize failed: %d", rc); - } - - return rc; -} - -int IOT_Shadow_JSON_ConstructDesireAllNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer) -{ - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - Qcloud_IoT_Shadow* shadow = (Qcloud_IoT_Shadow*)handle; - - int rc = IOT_Shadow_JSON_Init(shadow, jsonBuffer, sizeOfBuffer, false); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json init failed: %d", rc); - return rc; - } - - size_t remain_size = 0; - int32_t rc_of_snprintf = 0; - - if (jsonBuffer == NULL) { - return QCLOUD_ERR_INVAL; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"desired\": null "); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - rc = IOT_Shadow_JSON_Finalize(shadow, jsonBuffer, sizeOfBuffer); - return rc; -} - -int IOT_Shadow_JSON_ConstructDesirePropNull(void *handle, char *jsonBuffer, size_t sizeOfBuffer, uint8_t count, ...) -{ - POINTER_SANITY_CHECK(handle, QCLOUD_ERR_INVAL); - Qcloud_IoT_Shadow* shadow = (Qcloud_IoT_Shadow*)handle; - - int rc = IOT_Shadow_JSON_Init(shadow, jsonBuffer, sizeOfBuffer, false); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json init failed: %d", rc); - return rc; - } - - size_t remain_size = 0; - int32_t rc_of_snprintf = 0; - int8_t i; - - if (jsonBuffer == NULL) { - return QCLOUD_ERR_INVAL; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"desired\":{"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - va_list pArgs; - va_start(pArgs, count); - - for (i = 0; i < count; i++) { - DeviceProperty *pJsonNode; - pJsonNode = va_arg (pArgs, DeviceProperty *); - if (pJsonNode != NULL && pJsonNode->key != NULL) { - rc = put_json_node(jsonBuffer, remain_size, pJsonNode->key, pJsonNode->data, pJsonNode->type); - if (rc != QCLOUD_ERR_SUCCESS) { - va_end(pArgs); - return rc; - } - } else { - va_end(pArgs); - return QCLOUD_ERR_INVAL; - } - } - - va_end(pArgs); - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - // strlen(jsonBuffer) - 1 是为了把最后一项的逗号去掉 - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer) - 1, remain_size, "},"); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - if (rc != QCLOUD_ERR_SUCCESS) { - Log_e("shadow json add desired failed: %d", rc); - return rc; - } - - rc = IOT_Shadow_JSON_Finalize(shadow, jsonBuffer, sizeOfBuffer); - return rc; -} - -#ifdef __cplusplus -} -#endif - diff --git a/src/shadow/src/shadow_client_json.c b/src/shadow/src/shadow_client_json.c deleted file mode 100644 index dd3ed41c..00000000 --- a/src/shadow/src/shadow_client_json.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "shadow_client_json.h" - -#include "device.h" -#include "shadow_client.h" -#include "lite-utils.h" - -static int _direct_update_value(char *value, DeviceProperty *pProperty) { - - int rc = QCLOUD_ERR_SUCCESS; - - if (pProperty->type == JBOOL) { - rc = LITE_get_boolean(pProperty->data, value); - } else if (pProperty->type == JINT32) { - rc = LITE_get_int32(pProperty->data, value); - } else if (pProperty->type == JINT16) { - rc = LITE_get_int16(pProperty->data, value); - } else if (pProperty->type == JINT8) { - rc = LITE_get_int8(pProperty->data, value); - } else if (pProperty->type == JUINT32) { - rc = LITE_get_uint32(pProperty->data, value); - } else if (pProperty->type == JUINT16) { - rc = LITE_get_uint16(pProperty->data, value); - } else if (pProperty->type == JUINT8) { - rc = LITE_get_uint8(pProperty->data, value); - } else if (pProperty->type == JFLOAT) { - rc = LITE_get_float(pProperty->data, value); - } else if (pProperty->type == JDOUBLE) { - rc = LITE_get_double(pProperty->data, value); - } - - return rc; -} - -/** - * 为JSON文档增加client token字段 - * - * @param pJsonDocument JSON串 - * @param maxSizeOfJsonDocument JSON串最大长度 - * @return 添加字段的长度 - */ -static int32_t _add_client_token(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint32_t *tokenNumber) { - - int32_t rc_of_snprintf = HAL_Snprintf(pJsonDocument, maxSizeOfJsonDocument, "%s-%u", iot_device_info_get()->product_id, (*tokenNumber)++); - - return rc_of_snprintf; -} - -/** - * @brief 检查函数snprintf的返回值 - * - * @param returnCode 函数snprintf的返回值 - * @param maxSizeOfWrite 可写最大字节数 - * @return 返回QCLOUD_ERR_JSON, 表示出错; 返回QCLOUD_ERR_JSON_BUFFER_TRUNCATED, 表示截断 - */ -static inline int _check_snprintf_return(int32_t returnCode, size_t maxSizeOfWrite) { - - if (returnCode >= maxSizeOfWrite) { - return QCLOUD_ERR_JSON_BUFFER_TRUNCATED; - } else if (returnCode < 0) { // 写入出错 - return QCLOUD_ERR_JSON; - } - - return QCLOUD_ERR_SUCCESS; -} - -int put_json_node(char *jsonBuffer, size_t sizeOfBuffer, const char *pKey, void *pData, JsonDataType type) { - - int rc; - int32_t rc_of_snprintf = 0; - size_t remain_size = 0; - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"%s\":", pKey); - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - if (rc != QCLOUD_ERR_SUCCESS) { - return rc; - } - - if ((remain_size = sizeOfBuffer - strlen(jsonBuffer)) <= 1) { - return QCLOUD_ERR_JSON_BUFFER_TOO_SMALL; - } - - if (pData == NULL) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "null,"); - } else { - if (type == JINT32) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" - PRIi32 - ",", *(int32_t *) (pData)); - } else if (type == JINT16) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" - PRIi16 - ",", *(int16_t *) (pData)); - } else if (type == JINT8) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" - PRIi8 - ",", *(int8_t *) (pData)); - } else if (type == JUINT32) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" - PRIu32 - ",", *(uint32_t *) (pData)); - } else if (type == JUINT16) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" - PRIu16 - ",", *(uint16_t *) (pData)); - } else if (type == JUINT8) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%" - PRIu8 - ",", *(uint8_t *) (pData)); - } else if (type == JDOUBLE) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%f,", *(double *) (pData)); - } else if (type == JFLOAT) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%f,", *(float *) (pData)); - } else if (type == JBOOL) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%s,", - *(bool *) (pData) ? "true" : "false"); - } else if (type == JSTRING) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "\"%s\",", (char *) (pData)); - } else if (type == JOBJECT) { - rc_of_snprintf = HAL_Snprintf(jsonBuffer + strlen(jsonBuffer), remain_size, "%s,", (char *) (pData)); - } - } - - rc = _check_snprintf_return(rc_of_snprintf, remain_size); - - return rc; -} - -int generate_client_token(char *pStrBuffer, size_t sizeOfBuffer, uint32_t *tokenNumber) { - return _add_client_token(pStrBuffer, sizeOfBuffer, tokenNumber); -} - -void build_empty_json(uint32_t *tokenNumber, char *pJsonBuffer) { - HAL_Snprintf(pJsonBuffer, MAX_SIZE_OF_JSON_WITH_CLIENT_TOKEN, "{\"clientToken\":\"%s-%u\"}", iot_device_info_get()->product_id, (*tokenNumber)++); -} - -bool parse_client_token(char *pJsonDoc, char **pClientToken) { - *pClientToken = LITE_json_value_of(CLIENT_TOKEN_FIELD, pJsonDoc); - return *pClientToken == NULL ? false : true; -} - -bool parse_version_num(char *pJsonDoc, uint32_t *pVersionNumber) { - - bool ret = false; - - char *version_num = LITE_json_value_of(PAYLOAD_VERSION, pJsonDoc); - if (version_num == NULL) return false; - - if (sscanf(version_num, "%" SCNu32, pVersionNumber) != 1) { - Log_e("parse shadow version failed, errCode: %d", QCLOUD_ERR_JSON_PARSE); - } - else { - ret = true; - } - - HAL_Free(version_num); - - return ret; -} - -bool parse_shadow_state(char *pJsonDoc, char **pState) -{ - *pState = LITE_json_value_of(PAYLOAD_VERSION, pJsonDoc); - return *pState == NULL ? false : true; -} - -bool parse_shadow_operation_type(char *pJsonDoc, char **pType) -{ - *pType = LITE_json_value_of(TYPE_FIELD, pJsonDoc); - return *pType == NULL ? false : true; -} - -bool parse_shadow_operation_result_code(char *pJsonDoc, int16_t *pResultCode) -{ - bool ret = false; - - char *result_code = LITE_json_value_of(RESULT_FIELD, pJsonDoc); - if (result_code == NULL) return false; - - if (sscanf(result_code, "%" SCNi16, pResultCode) != 1) { - Log_e("parse shadow result_code failed, errCode: %d", QCLOUD_ERR_JSON_PARSE); - } - else { - ret = true; - } - - HAL_Free(result_code); - - return ret; -} - -bool parse_shadow_operation_delta(char *pJsonDoc, char **pDelta) -{ - *pDelta = LITE_json_value_of(PAYLOAD_STATE, pJsonDoc); - return *pDelta == NULL ? false : true; -} - -bool parse_shadow_operation_get(char *pJsonDoc, char **pDelta) -{ - *pDelta = LITE_json_value_of(PAYLOAD_STATE_DELTA, pJsonDoc); - return *pDelta == NULL ? false : true; -} - - -bool update_value_if_key_match(char *pJsonDoc, DeviceProperty *pProperty) { - - bool ret = false; - - char* property_data = LITE_json_value_of(pProperty->key, pJsonDoc); - if (property_data == NULL) { - } - else { - _direct_update_value(property_data, pProperty); - ret = true; - HAL_Free(property_data); - } - - return ret; -} - -#ifdef __cplusplus -} -#endif diff --git a/src/system/src/log_mqtt.c b/src/system/src/log_mqtt.c deleted file mode 100755 index 6684786b..00000000 --- a/src/system/src/log_mqtt.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef LOG_UPLOAD - -#include - -#include "mqtt_client.h" -#include "lite-utils.h" -#include "device.h" -#include "log_upload.h" - - -static bool sg_log_recv_ok = false; -static bool sg_log_sub_ok = false; -static MQTTEventHandleFun sg_log_EventHandle = NULL; -static int sg_log_level = ERROR; -static unsigned int sg_client_token = 1; - -static bool _get_json_log_level(char *json, int32_t* res) { - char *v = LITE_json_value_of("log_level", json); - if (v == NULL) { - Log_e("Invalid log level from JSON: %s", json); - return false; - } - if (LITE_get_int32(res, v) != QCLOUD_ERR_SUCCESS) { - Log_e("Invalid log level from JSON: %s", json); - HAL_Free(v); - return false; - } - HAL_Free(v); - return true; -} - -static void _log_level_sub_cb(void *pClient, MQTTMessage *message, void *userData) -{ -#define LOG_JSON_LENGTH 128 - char json_buf[LOG_JSON_LENGTH] = {0}; - int32_t json_buf_len = 0; - if (message == NULL) { - return; - } - - json_buf_len = Min(LOG_JSON_LENGTH - 1, message->payload_len); - memcpy(json_buf, message->payload, json_buf_len); - json_buf[json_buf_len] = '\0'; // json_parse relies on a string - - Log_d("Recv Msg Topic:%s, payload:%s", message->ptopic, json_buf); - - if (!_get_json_log_level(json_buf, &sg_log_level)) { - return ; - } - - switch(sg_log_level) { - case DISABLE: - Log_w("Upload log level change to: %d", sg_log_level); - clear_upload_buffer(); - set_log_upload_in_comm_err(true); - IOT_Log_Set_Upload_Level(ERROR); - break; - case ERROR: - case WARN: - case INFO: - case DEBUG: - if (sg_log_level < IOT_Log_Get_Upload_Level()) - clear_upload_buffer(); - IOT_Log_Set_Upload_Level((LOG_LEVEL)sg_log_level); - Log_w("Upload log level change to: %d", sg_log_level); - set_log_upload_in_comm_err(false); - break; - default: - Log_e("Invalid log level: %d", sg_log_level); - break; - } - - sg_log_recv_ok = true; - -} - -static void _log_mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) { - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_d("subscribe success, packet-id=%u", (unsigned int)packet_id); - sg_log_sub_ok = true; - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - sg_log_sub_ok = false; - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - sg_log_sub_ok = false; - break; - case MQTT_EVENT_UNDEF: - case MQTT_EVENT_DISCONNECT: - case MQTT_EVENT_RECONNECT: - case MQTT_EVENT_PUBLISH_RECVEIVED: - case MQTT_EVENT_UNSUBCRIBE_SUCCESS: - case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - case MQTT_EVENT_UNSUBCRIBE_NACK: - case MQTT_EVENT_PUBLISH_SUCCESS: - case MQTT_EVENT_PUBLISH_TIMEOUT: - case MQTT_EVENT_PUBLISH_NACK: - default: - return; - } -} - -static int _iot_log_level_get_publish(void *pClient) -{ - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - DeviceInfo *dev_info = iot_device_info_get(); - POINTER_SANITY_CHECK(dev_info, QCLOUD_ERR_INVAL); - - char topic_name[128] = {0}; - char payload_content[128] = {0}; - - HAL_Snprintf(topic_name, sizeof(topic_name), "$log/operation/%s/%s", dev_info->product_id, dev_info->device_name); - HAL_Snprintf(payload_content, sizeof(payload_content), "{\"type\": \"get_log_level\", " - "\"clientToken\": \"%s-%u\"}", dev_info->product_id, sg_client_token++); - - PublishParams pub_params = DEFAULT_PUB_PARAMS; - pub_params.qos = QOS0; - pub_params.payload = payload_content; - pub_params.payload_len = strlen(payload_content); - - return IOT_MQTT_Publish(mqtt_client, topic_name, &pub_params); -} - -int qcloud_log_topic_subscribe(void *client) -{ - /* subscribe the log topic: "$log/operation/result/${productId}/${deviceName}" */ - char topic_name[128] = {0}; - int size = HAL_Snprintf(topic_name, sizeof(topic_name), "$log/operation/result/%s/%s", - iot_device_info_get()->product_id, iot_device_info_get()->device_name); - if (size < 0 || size > sizeof(topic_name) - 1) - { - Log_e("topic content buf not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); - return QCLOUD_ERR_FAILURE; - } - - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.on_message_handler = _log_level_sub_cb; - sub_params.qos = QOS0; - - return IOT_MQTT_Subscribe(client, topic_name, &sub_params); - -} - - -int qcloud_get_log_level(void* pClient, int *log_level) -{ - int ret = 0; - int cntSub = 0; - int cntRev = 0; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - - //如果第一次订阅$log/operation/get/${productid}/${devicename}, 则执行订阅操作 - //否则,防止多次获取日志等级的情况下,多次重复订阅 - if(!sg_log_sub_ok){ - sg_log_EventHandle = mqtt_client->event_handle.h_fp; - mqtt_client->event_handle.h_fp = _log_mqtt_event_handler; - - for(cntSub = 0; cntSub < 3; cntSub++){ - ret = qcloud_log_topic_subscribe(mqtt_client); - if (ret < 0) { - Log_w("qcloud_log_topic_subscribe failed: %d, cnt: %d", ret, cntSub); - continue; - } - - /* wait for sub ack */ - ret = qcloud_iot_mqtt_yield((Qcloud_IoT_Client *)pClient, 100); - if(sg_log_sub_ok) { - break; - } - } - mqtt_client->event_handle.h_fp = sg_log_EventHandle; - } - - // 如果订阅3次均失败,则直接返回失败 - if(!sg_log_sub_ok){ - Log_e("Subscribe log topic failed!"); - return QCLOUD_ERR_FAILURE; - } - - sg_log_recv_ok = false; - // 发布获取时间 - ret = _iot_log_level_get_publish(mqtt_client); - if (ret < 0) { - Log_e("client publish log topic failed :%d", ret); - return ret; - } - - do{ - ret = qcloud_iot_mqtt_yield((Qcloud_IoT_Client *)pClient, 100); - cntRev++; - }while(!sg_log_recv_ok && cntRev < 20); - - *log_level = sg_log_level; - if (sg_log_recv_ok) - ret = QCLOUD_ERR_SUCCESS; - else - ret = QCLOUD_ERR_FAILURE; - - return ret; -} - -#endif diff --git a/src/system/src/log_upload.c b/src/system/src/log_upload.c deleted file mode 100644 index 1449b5e8..00000000 --- a/src/system/src/log_upload.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef LOG_UPLOAD - -#include -#include -#include -#include -#include -#include - -#include "qcloud_iot_import.h" -#include "qcloud_iot_export.h" -#include "log_upload.h" -#include "utils_httpc.h" -#include "utils_timer.h" -#include "utils_hmac.h" -#include "lite-utils.h" - - - -/* log post header format */ -#define TIMESTAMP_SIZE 10 -#define SIGNATURE_SIZE 40 -#define CTRL_BYTES_SIZE 4 -#define LOG_BUF_FIXED_HEADER_SIZE (SIGNATURE_SIZE + CTRL_BYTES_SIZE + MAX_SIZE_OF_PRODUCT_ID + MAX_SIZE_OF_DEVICE_NAME + TIMESTAMP_SIZE) - -/* do immediate log update if buffer is lower than this threshold (about two max log item) */ -#define LOG_LOW_BUFFER_THRESHOLD (2*MAX_LOG_MSG_LEN) - -/* static allocate log upload buffer */ -static char sg_log_buffer[LOG_UPLOAD_BUFFER_SIZE] = {0}; -static uint32_t sg_write_index = LOG_BUF_FIXED_HEADER_SIZE; - -#define SIGN_KEY_SIZE 24 -static char sg_sign_key[SIGN_KEY_SIZE+1] = {0}; - -/* Log upload feature switch */ -/* To check log http server return msg or not */ -#define LOG_CHECK_HTTP_RET_CODE - - -typedef struct { - - const char *url; - const char *ca_crt; - int port; - HTTPClient http; /* http client */ - HTTPClientData http_data; /* http client data */ - -} LogHTTPStruct; - -static LogHTTPStruct *sg_http_c; - -typedef struct { - - const char *product_id; - const char *device_name; - void *mqtt_client; - bool upload_only_in_comm_err; - - void *lock_buf; - Timer upload_timer; -#ifndef LOG_UPDATE_TIME_WHEN_UPLOAD - Timer time_update_timer; -#endif - long system_time; - - LogSaveFunc save_func; - LogReadFunc read_func; - LogDelFunc del_func; - LogGetSizeFunc get_size_func; - bool log_save_enabled; - - bool uploader_init_done; - -} LogUploaderStruct; - -static LogUploaderStruct *sg_uploader; -static bool sg_log_uploader_init_done = false; - -#ifdef AUTH_MODE_CERT -static int _gen_key_from_file( const char *file_path) -{ - FILE *fp; - int len; - char line_buf[128] = {0}; - - if( ( fp = fopen( file_path, "r" ) ) == NULL ) { - UPLOAD_ERR("fail to open cert file %s", file_path); - return -1; - } - - /* find the begin line */ - do { - if (NULL == fgets(line_buf, sizeof(line_buf), fp)) { - UPLOAD_ERR("fail to fgets file %s", file_path); - return -1; - } - } while (strstr(line_buf, "-----BEGIN ") == NULL); - - if (feof(fp)) { - UPLOAD_ERR("invalid cert file %s", file_path); - return -1; - } - - if (NULL == fgets(line_buf, sizeof(line_buf), fp)) { - UPLOAD_ERR("fail to fgets file %s", file_path); - return -1; - } - - len = strlen(line_buf); - memcpy(sg_sign_key, line_buf, len>SIGN_KEY_SIZE?SIGN_KEY_SIZE:len); - UPLOAD_DBG("sign key %s", sg_sign_key); - - fclose(fp); - - return 0; -} -#endif - - -static long _get_system_time(void) -{ -#ifdef SYSTEM_COMM - if (sg_uploader->mqtt_client == NULL) - return 0; - - long sys_time = 0; - int rc = IOT_SYSTEM_GET_TIME(sg_uploader->mqtt_client, &sys_time); - if (rc == QCLOUD_ERR_SUCCESS) - return sys_time; - else - return 0; -#else - return 0; -#endif -} - -static void _update_system_time(void) -{ -/* to avoid frequent get_system_time */ -#define LOG_TIME_UPDATE_INTERVAL 2 - - if(!expired(&sg_uploader->time_update_timer)) - return; - - sg_uploader->system_time = _get_system_time(); - - countdown(&sg_uploader->time_update_timer, LOG_TIME_UPDATE_INTERVAL); -} - - -static int _check_server_connection() -{ - int rc; - - rc = qcloud_http_client_connect(&sg_http_c->http, sg_http_c->url, sg_http_c->port, sg_http_c->ca_crt); - if (rc != QCLOUD_ERR_SUCCESS) - return rc; - - qcloud_http_client_close(&sg_http_c->http); - - return QCLOUD_ERR_SUCCESS; -} - -#ifdef LOG_CHECK_HTTP_RET_CODE -static bool _get_json_ret_code(char *json, int32_t* res) { - char *v = LITE_json_value_of("Retcode", json); - if (v == NULL) { - UPLOAD_ERR("Invalid json content: %s", json); - return false; - } - if (LITE_get_int32(res, v) != QCLOUD_ERR_SUCCESS) { - UPLOAD_ERR("Invalid json content: %s", json); - HAL_Free(v); - return false; - } - HAL_Free(v); - return true; -} -#endif - -static int _send_log_to_server(char *post_buf, size_t post_size) -{ - int rc = 0; - - if(sg_http_c == NULL) - return QCLOUD_ERR_INVAL; - - sg_http_c->http_data.post_content_type = "text/plain;charset=utf-8"; - sg_http_c->http_data.post_buf = post_buf; - sg_http_c->http_data.post_buf_len = post_size; - - rc = qcloud_http_client_common(&sg_http_c->http, sg_http_c->url, sg_http_c->port, sg_http_c->ca_crt, - HTTP_POST, &sg_http_c->http_data); - if (rc != QCLOUD_ERR_SUCCESS) { - UPLOAD_ERR("qcloud_http_client_common failed, rc = %d", rc); - return rc; - } - UPLOAD_DBG("Log client POST size: %d", post_size); - -#ifdef LOG_CHECK_HTTP_RET_CODE - /* TODO: handle recv data from log server */ - #define HTTP_RET_JSON_LENGTH 256 - #define HTTP_WAIT_RET_TIMEOUT_MS 1000 - char buf[HTTP_RET_JSON_LENGTH] = {0}; - sg_http_c->http_data.response_buf = buf; - sg_http_c->http_data.response_buf_len = sizeof(buf); - - rc = qcloud_http_recv_data(&sg_http_c->http, HTTP_WAIT_RET_TIMEOUT_MS, &sg_http_c->http_data); - if (QCLOUD_ERR_SUCCESS != rc) { - UPLOAD_ERR("qcloud_http_recv_data failed, rc = %d", rc); - } else { - int32_t ret = -1; - - buf[HTTP_RET_JSON_LENGTH - 1] = '\0'; // json_parse relies on a string - if (strlen(buf)>0 && _get_json_ret_code(buf, &ret) && ret == 0) { - UPLOAD_DBG("Log server return SUCCESS: %s", buf); - } else { - UPLOAD_ERR("Log server return FAIL(%d): %s", ret, buf); - rc = QCLOUD_ERR_HTTP; - } - } -#endif - - qcloud_http_client_close(&sg_http_c->http); - - return rc; - -} - -static void _update_time_and_signature(char *log_buf, size_t log_size) -{ - char timestamp[TIMESTAMP_SIZE+1] = {0}; - char signature[SIGNATURE_SIZE+1] = {0}; - - /* get system time from IoT hub first */ - _update_system_time(); - - /* record the timestamp for this log uploading */ - HAL_Snprintf(timestamp, TIMESTAMP_SIZE+1, "%010ld", sg_uploader->system_time); - memcpy(log_buf+LOG_BUF_FIXED_HEADER_SIZE-TIMESTAMP_SIZE, timestamp, strlen(timestamp)); - - /* signature of this log uploading */ - utils_hmac_sha1(log_buf+SIGNATURE_SIZE, log_size - SIGNATURE_SIZE, signature, sg_sign_key, strlen(sg_sign_key)); - memcpy(log_buf, signature, SIGNATURE_SIZE); - -} - -static void _reset_log_buffer(void) -{ - sg_write_index = LOG_BUF_FIXED_HEADER_SIZE; - memset(sg_log_buffer+LOG_BUF_FIXED_HEADER_SIZE, 0, LOG_UPLOAD_BUFFER_SIZE - LOG_BUF_FIXED_HEADER_SIZE); -} - -static int _save_log(char *log_buf, size_t log_size) -{ - int rc = 0; - size_t write_size, current_size = sg_uploader->get_size_func(); - - /* overwrite the previous saved log to avoid too many saved logs */ - if ((current_size + log_size) > MAX_LOG_SAVE_SIZE) { - UPLOAD_ERR("overwrite the previous saved log. %d", current_size); - rc = sg_uploader->del_func(); - if (rc) { - Log_e("fail to delete previous log"); - } - } - - write_size = sg_uploader->save_func(log_buf, log_size); - if (write_size != log_size) { - Log_e("fail to save log. RC %d - log size %d", write_size, log_size); - rc = -1; - } else - rc = 0; - - return rc; - -} - -static int _handle_saved_log(void) -{ -#define LOG_DELIMITER "\n\f" - int rc = QCLOUD_ERR_SUCCESS; - size_t whole_log_size = sg_uploader->get_size_func(); - if (whole_log_size > 0) { - /* only do the job when connection is OK */ - if (_check_server_connection() != QCLOUD_ERR_SUCCESS) - return QCLOUD_ERR_FAILURE; - - size_t buf_size = whole_log_size + LOG_BUF_FIXED_HEADER_SIZE + 1; - char *log_buf = HAL_Malloc(buf_size); - if (log_buf != NULL) { - /* read the whole log to buffer */ - size_t read_len = sg_uploader->read_func(log_buf + LOG_BUF_FIXED_HEADER_SIZE, whole_log_size); - if (read_len == whole_log_size) { - size_t upload_size = whole_log_size + LOG_BUF_FIXED_HEADER_SIZE; - - /* copy header from global log buffer */ - memcpy(log_buf, sg_log_buffer, LOG_BUF_FIXED_HEADER_SIZE); - log_buf[buf_size - 1] = 0; - - if (upload_size > MAX_HTTP_LOG_POST_SIZE) { - /* we need to fragment and post several times */ - - bool end_of_buf = false; - size_t delimiter_len = strlen(LOG_DELIMITER); - char *fragment_buf = log_buf; - do { - char *next_log_buf = NULL; - upload_size = 0; - while ((upload_size + MAX_LOG_MSG_LEN) < MAX_HTTP_LOG_POST_SIZE){ - /* locate the delimiter */ - next_log_buf = strstr(fragment_buf + upload_size, LOG_DELIMITER); - if (next_log_buf == NULL) { - Log_e("illegal saved log content"); - HAL_Free(log_buf); - sg_uploader->del_func(); - return QCLOUD_ERR_FAILURE; - - } - upload_size = (size_t)(next_log_buf - fragment_buf + delimiter_len); - - if (next_log_buf[delimiter_len] == 0) { - end_of_buf = true; - break; - } - } - - _update_time_and_signature(fragment_buf, upload_size); - - rc = _send_log_to_server(fragment_buf, upload_size); - /* delete the saved log if only one upload success */ - if (rc == QCLOUD_ERR_SUCCESS) - sg_uploader->del_func(); - - if (!end_of_buf) { - /*move the buffer header */ - next_log_buf = next_log_buf + delimiter_len - LOG_BUF_FIXED_HEADER_SIZE; - memcpy(next_log_buf, log_buf, LOG_BUF_FIXED_HEADER_SIZE); - fragment_buf = next_log_buf; - } - - } while(!end_of_buf); - } else { - /* one single post is enough */ - _update_time_and_signature(log_buf, upload_size); - - rc = _send_log_to_server(log_buf, upload_size); - if (rc == QCLOUD_ERR_SUCCESS) - sg_uploader->del_func(); - } - HAL_Free(log_buf); - Log_d("handle saved log done! Size: %u", whole_log_size); - - }else { - Log_e("fail to read whole saved log. Size: %u - read: %u", whole_log_size, read_len); - HAL_Free(log_buf); - return QCLOUD_ERR_FAILURE; - } - - } else { - Log_e("Malloc failed, size: %u", buf_size); - return QCLOUD_ERR_FAILURE; - } - } - - return rc; - -} - - -void set_log_mqtt_client(void *client) -{ - if (!sg_log_uploader_init_done) - return ; - - sg_uploader->mqtt_client = client; -} - -void set_log_upload_in_comm_err(bool value) -{ - if (!sg_log_uploader_init_done) - return ; - - sg_uploader->upload_only_in_comm_err = value; -} - - -int append_to_upload_buffer(const char *log_content, size_t log_size) -{ - if (!sg_log_uploader_init_done) - return -1; - - if (log_content == NULL || log_size <= 0) { - UPLOAD_ERR("invalid log content!"); - return -1; - } - - if (HAL_MutexTryLock(sg_uploader->lock_buf) != 0) { - UPLOAD_ERR("trylock buffer failed!"); - return -1; - } - - if ((sg_write_index + log_size + 1) > LOG_UPLOAD_BUFFER_SIZE) { - countdown_ms(&sg_uploader->upload_timer, 0); - HAL_MutexUnlock(sg_uploader->lock_buf); - UPLOAD_ERR("log upload buffer is not enough!"); - return -1; - } - - memcpy(sg_log_buffer+sg_write_index, log_content, log_size); - - sg_write_index += log_size; - - /* replace \r\n to \n\f as delimiter */ - sg_log_buffer[sg_write_index - 1] = '\f'; - sg_log_buffer[sg_write_index - 2] = '\n'; - - HAL_MutexUnlock(sg_uploader->lock_buf); - return 0; -} - - -void clear_upload_buffer() -{ - if (!sg_log_uploader_init_done) - return ; - - HAL_MutexLock(sg_uploader->lock_buf); - _reset_log_buffer(); - HAL_MutexUnlock(sg_uploader->lock_buf); - -} - - -void init_log_uploader(LogUploadInitParams *init_params) -{ - int i; - - if (init_params == NULL || init_params->product_id == NULL || - init_params->device_name == NULL || init_params->sign_key == NULL) { - UPLOAD_ERR("invalid init parameters"); - return ; - } - - int key_len = strlen(init_params->sign_key); - if (key_len == 0) { - UPLOAD_ERR("invalid key length"); - return ; - } - - for(i = 0; isign_key) != 0) { - UPLOAD_ERR("gen_key_from_file failed"); - return ; - } - sg_log_buffer[SIGNATURE_SIZE] = 'C'; -#else - memcpy(sg_sign_key, init_params->sign_key, key_len>SIGN_KEY_SIZE?SIGN_KEY_SIZE:key_len); - sg_log_buffer[SIGNATURE_SIZE] = 'P'; -#endif - - memcpy(sg_log_buffer+SIGNATURE_SIZE+CTRL_BYTES_SIZE, init_params->product_id, MAX_SIZE_OF_PRODUCT_ID); - memcpy(sg_log_buffer+SIGNATURE_SIZE+CTRL_BYTES_SIZE+MAX_SIZE_OF_PRODUCT_ID, init_params->device_name, strlen(init_params->device_name)); - - if (NULL == (sg_uploader = HAL_Malloc(sizeof(LogUploaderStruct)))) { - UPLOAD_ERR("allocate for LogUploaderStruct failed"); - return ; - } - memset(sg_uploader, 0, sizeof(LogUploaderStruct)); - - sg_uploader->product_id = init_params->product_id; - sg_uploader->device_name = init_params->device_name; - sg_uploader->mqtt_client = NULL; - sg_uploader->system_time = 0; - sg_uploader->upload_only_in_comm_err = false; - - /* all the call back functions are necessary to handle log save and re-upload */ - if (init_params->save_func != NULL && init_params->read_func != NULL && - init_params->del_func != NULL && init_params->get_size_func) { - sg_uploader->save_func = init_params->save_func; - sg_uploader->read_func = init_params->read_func; - sg_uploader->del_func = init_params->del_func; - sg_uploader->get_size_func = init_params->get_size_func; - sg_uploader->log_save_enabled = true; - } else - sg_uploader->log_save_enabled = false; - - InitTimer(&sg_uploader->upload_timer); - InitTimer(&sg_uploader->time_update_timer); - - if ((sg_uploader->lock_buf = HAL_MutexCreate()) == NULL) { - UPLOAD_ERR("mutex create failed"); - return ; - } - - if (NULL == (sg_http_c = HAL_Malloc(sizeof(LogHTTPStruct)))) { - HAL_MutexDestroy(sg_uploader->lock_buf); - HAL_Free(sg_uploader); - UPLOAD_ERR("allocate for LogHTTPStruct failed"); - return ; - } - memset(sg_http_c, 0, sizeof(LogHTTPStruct)); - - /* set http request-header parameter */ - sg_http_c->http.header = "Accept:application/json;*/*\r\n"; - sg_http_c->url = LOG_UPLOAD_SERVER_URL; - sg_http_c->port = LOG_UPLOAD_SERVER_PORT; - sg_http_c->ca_crt = NULL; - - _reset_log_buffer(); - sg_log_uploader_init_done = true; - -} - -static bool _check_force_upload(bool force_upload) -{ - if (!force_upload) { - /* Double check if the buffer is low */ - HAL_MutexLock(sg_uploader->lock_buf); - bool is_low_buffer = (LOG_UPLOAD_BUFFER_SIZE - sg_write_index) < LOG_LOW_BUFFER_THRESHOLD ? true : false; - - /* force_upload is false and upload_only_in_comm_err is true */ - if(sg_uploader->upload_only_in_comm_err) { - /* buffer is low but we couldn't upload now, reset buffer */ - if (is_low_buffer) - _reset_log_buffer(); - - HAL_MutexUnlock(sg_uploader->lock_buf); - countdown_ms(&sg_uploader->upload_timer, LOG_UPLOAD_INTERVAL_MS); - return false; - } - HAL_MutexUnlock(sg_uploader->lock_buf); - - if (is_low_buffer) { - /* buffer is low, handle it right now */ - return true; - } else { - return expired(&sg_uploader->upload_timer); - } - - }else - return true; - -} - -int do_log_upload(bool force_upload) -{ - int rc; - int upload_log_size = 0; - static bool unhandle_saved_log = true; - - if (!sg_log_uploader_init_done) - return QCLOUD_ERR_FAILURE; - - /* double check force upload */ - if (!_check_force_upload(force_upload)) - return QCLOUD_ERR_SUCCESS; - - /* handle previously saved log */ - if (sg_uploader->log_save_enabled && unhandle_saved_log) { - rc = _handle_saved_log(); - if (rc == QCLOUD_ERR_SUCCESS) - unhandle_saved_log = false; - } - - /* no more log in buffer */ - if (sg_write_index == LOG_BUF_FIXED_HEADER_SIZE) - return QCLOUD_ERR_SUCCESS; - - HAL_MutexLock(sg_uploader->lock_buf); - upload_log_size = sg_write_index; - HAL_MutexUnlock(sg_uploader->lock_buf); - - _update_time_and_signature(sg_log_buffer, upload_log_size); - - /* save log via user callbacks when log upload fail */ - rc = _send_log_to_server(sg_log_buffer, upload_log_size); - if (rc != QCLOUD_ERR_SUCCESS) { - if (sg_uploader->log_save_enabled) { - /* new error logs should have been added, update log size */ - HAL_MutexLock(sg_uploader->lock_buf); - upload_log_size = sg_write_index; - HAL_MutexUnlock(sg_uploader->lock_buf); - _save_log(sg_log_buffer+LOG_BUF_FIXED_HEADER_SIZE, upload_log_size-LOG_BUF_FIXED_HEADER_SIZE); - unhandle_saved_log = true; - } - } - - /* move the new log during send_log_to_server */ - HAL_MutexLock(sg_uploader->lock_buf); - if (upload_log_size == sg_write_index) { - _reset_log_buffer(); - } else { - memmove(sg_log_buffer+LOG_BUF_FIXED_HEADER_SIZE, sg_log_buffer+upload_log_size, sg_write_index-upload_log_size); - sg_write_index = sg_write_index - upload_log_size + LOG_BUF_FIXED_HEADER_SIZE; - memset(sg_log_buffer+sg_write_index, 0, LOG_UPLOAD_BUFFER_SIZE - sg_write_index); - } - HAL_MutexUnlock(sg_uploader->lock_buf); - - countdown_ms(&sg_uploader->upload_timer, LOG_UPLOAD_INTERVAL_MS); - - return QCLOUD_ERR_SUCCESS; -} - - -#endif diff --git a/src/system/src/system_mqtt.c b/src/system/src/system_mqtt.c deleted file mode 100755 index bac003aa..00000000 --- a/src/system/src/system_mqtt.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef SYSTEM_COMM - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#include "mqtt_client.h" -#include "lite-utils.h" -#include "device.h" - - -static bool sg_sys_recv_ok = false; -static bool sg_sys_sub_ok = false; -static char sg_time[11] = {0}; -static MQTTEventHandleFun sg_sys_EventHandle = NULL; - -static void on_system_mqtt_message_callback(void *pClient, MQTTMessage *message, void *userData) -{ -#define MAX_RECV_LEN (512) - - POINTER_SANITY_CHECK_RTN(message); - - static char rcv_buf[MAX_RECV_LEN + 1]; - size_t len = (message->payload_len > MAX_RECV_LEN)?MAX_RECV_LEN:(message->payload_len); - - if(message->payload_len > MAX_RECV_LEN){ - Log_e("paload len exceed buffer size"); - } - memcpy(rcv_buf, message->payload, len); - rcv_buf[len] = '\0'; // jsmn_parse relies on a string - - Log_d("Recv Msg Topic:%s, payload:%s", message->ptopic, rcv_buf); - - char* value = LITE_json_value_of("time", rcv_buf); - if (value != NULL) { - memcpy(sg_time, value, sizeof(sg_time)/sizeof(char)); - } - sg_sys_recv_ok = true; - HAL_Free(value); - return; -} - -static void system_mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg) { - uintptr_t packet_id = (uintptr_t)msg->msg; - - switch(msg->event_type) { - case MQTT_EVENT_SUBCRIBE_SUCCESS: - Log_d("subscribe success, packet-id=%u", (unsigned int)packet_id); - sg_sys_sub_ok = true; - break; - - case MQTT_EVENT_SUBCRIBE_TIMEOUT: - Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - sg_sys_sub_ok = false; - break; - - case MQTT_EVENT_SUBCRIBE_NACK: - Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id); - sg_sys_sub_ok = false; - break; - case MQTT_EVENT_UNDEF: - case MQTT_EVENT_DISCONNECT: - case MQTT_EVENT_RECONNECT: - case MQTT_EVENT_PUBLISH_RECVEIVED: - case MQTT_EVENT_UNSUBCRIBE_SUCCESS: - case MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - case MQTT_EVENT_UNSUBCRIBE_NACK: - case MQTT_EVENT_PUBLISH_SUCCESS: - case MQTT_EVENT_PUBLISH_TIMEOUT: - case MQTT_EVENT_PUBLISH_NACK: - default: - return; - } -} - -static int _iot_system_info_get_publish(void *pClient) -{ - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - DeviceInfo *dev_info = iot_device_info_get(); - POINTER_SANITY_CHECK(dev_info, QCLOUD_ERR_INVAL); - - char topic_name[128] = {0}; - char payload_content[128] = {0}; - - HAL_Snprintf(topic_name, sizeof(topic_name), "$sys/operation/%s/%s", dev_info->product_id, dev_info->device_name); - HAL_Snprintf(payload_content, sizeof(payload_content), "{\"type\": \"get\", \"resource\": [\"time\"]}"); - - PublishParams pub_params = DEFAULT_PUB_PARAMS; - pub_params.qos = QOS0; - pub_params.payload = payload_content; - pub_params.payload_len = strlen(payload_content); - - return IOT_MQTT_Publish(mqtt_client, topic_name, &pub_params); -} - -static int _iot_system_info_result_subscribe(void *pClient, OnMessageHandler pCallback) -{ - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - - DeviceInfo *dev_info = iot_device_info_get(); - POINTER_SANITY_CHECK(dev_info, QCLOUD_ERR_INVAL); - - char topic_name[128] = {0}; - int size = HAL_Snprintf(topic_name, sizeof(topic_name), "$sys/operation/result/%s/%s", dev_info->product_id, dev_info->device_name); - if (size < 0 || size > sizeof(topic_name) - 1) - { - Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name)); - return QCLOUD_ERR_FAILURE; - } - SubscribeParams sub_params = DEFAULT_SUB_PARAMS; - sub_params.on_message_handler = pCallback; - - return IOT_MQTT_Subscribe(pClient, topic_name, &sub_params); -} - -int IOT_SYSTEM_GET_TIME(void* pClient, long *time) -{ - int ret = 0; - int cntSub = 0; - int cntRev = 0; - - POINTER_SANITY_CHECK(pClient, QCLOUD_ERR_INVAL); - Qcloud_IoT_Client *mqtt_client = (Qcloud_IoT_Client *)pClient; - - //如果第一次订阅$sys/operation/get/${productid}/${devicename}, 则执行订阅操作 - //否则,防止多次获取时间的情况下,多次重复订阅 - if(!sg_sys_sub_ok){ - sg_sys_EventHandle = mqtt_client->event_handle.h_fp; - mqtt_client->event_handle.h_fp = system_mqtt_event_handler; - - for(cntSub = 0; cntSub < 3; cntSub++){ - ret = _iot_system_info_result_subscribe(mqtt_client, on_system_mqtt_message_callback); - if (ret < 0) { - Log_w("_iot_system_info_result_subscribe failed: %d cnt: %d", ret, cntSub); - continue; - } - - ret = qcloud_iot_mqtt_yield((Qcloud_IoT_Client *)pClient, 100); - - if(sg_sys_sub_ok) { - break; - } - } - mqtt_client->event_handle.h_fp = sg_sys_EventHandle; - } - - // 如果订阅3次均失败,则直接返回失败 - if(!sg_sys_sub_ok){ - Log_e("Subscribe sys topic failed!"); - return QCLOUD_ERR_FAILURE; - } - - sg_sys_recv_ok = false; - // 发布获取时间 - ret = _iot_system_info_get_publish(mqtt_client); - if (ret < 0) { - Log_e("client publish sys topic failed :%d.", ret); - return ret; - } - - do{ - ret = qcloud_iot_mqtt_yield((Qcloud_IoT_Client *)pClient, 100); - cntRev++; - }while(!sg_sys_recv_ok && cntRev < 20); - - if (sg_sys_recv_ok) { - *time = atol(sg_time); - Log_d("Get system time success(yield cnt %d). Time is %ld", cntRev, *time); - ret = QCLOUD_ERR_SUCCESS; - } else { - *time = 0; - ret = QCLOUD_ERR_FAILURE; - } - - return QCLOUD_ERR_SUCCESS; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/utils/digest/utils_base64.c b/src/utils/digest/utils_base64.c deleted file mode 100644 index ccd8c9dc..00000000 --- a/src/utils/digest/utils_base64.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "utils_base64.h" - -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 */ - -int qcloud_iot_utils_base64encode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ) -{ - size_t i, n; - 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( QCLOUD_ERR_FAILURE ); - } - - n *= 4; - - if( ( dlen < n + 1 ) || ( NULL == dst ) ) - { - *olen = n + 1; - return( QCLOUD_ERR_FAILURE ); - } - - n = ( slen / 3 ) * 3; - - int C1, C2, C3; - 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 ); -} - -int qcloud_iot_utils_base64decode( 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( QCLOUD_ERR_FAILURE ); - - if( src[i] == '=' && ++j > 2 ) - return( QCLOUD_ERR_FAILURE ); - - if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) - return( QCLOUD_ERR_FAILURE ); - - if( base64_dec_map[src[i]] < 64 && j != 0 ) - return( QCLOUD_ERR_FAILURE ); - - n++; - } - - if( n == 0 ) - { - *olen = 0; - return( 0 ); - } - - n = ( ( n * 6 ) + 7 ) >> 3; - n -= j; - - if( dst == NULL || dlen < n ) - { - *olen = n; - return( QCLOUD_ERR_FAILURE ); - } - - 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 ); -} - -#ifdef __cplusplus -} -#endif diff --git a/src/utils/digest/utils_hmac.c b/src/utils/digest/utils_hmac.c deleted file mode 100644 index 9ef75f97..00000000 --- a/src/utils/digest/utils_hmac.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include "qcloud_iot_export_log.h" -#include "utils_md5.h" -#include "utils_sha1.h" -#include "utils_hmac.h" - -#define KEY_IOPAD_SIZE 64 - -#define MD5_DIGEST_SIZE 16 -#define SHA1_DIGEST_SIZE 20 - -void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len) -{ - if((NULL == msg) || (NULL == digest) || (NULL == key)) { - Log_e("parameter is Null,failed!"); - return; - } - - if(key_len > KEY_IOPAD_SIZE) { - Log_e("key_len > size(%d) of array",KEY_IOPAD_SIZE); - return; - } - - iot_md5_context context; - unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ - unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ - unsigned char out[MD5_DIGEST_SIZE]; - int i; - - /* start out by storing key in pads */ - memset(k_ipad, 0, sizeof(k_ipad)); - memset(k_opad, 0, sizeof(k_opad)); - memcpy(k_ipad, key, key_len); - memcpy(k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < KEY_IOPAD_SIZE; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - /* perform inner MD5 */ - utils_md5_init(&context); /* init context for 1st pass */ - utils_md5_starts(&context); /* setup context for 1st pass */ - utils_md5_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */ - utils_md5_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */ - utils_md5_finish(&context, out); /* finish up 1st pass */ - - /* perform outer MD5 */ - utils_md5_init(&context); /* init context for 2nd pass */ - utils_md5_starts(&context); /* setup context for 2nd pass */ - utils_md5_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */ - utils_md5_update(&context, out, MD5_DIGEST_SIZE); /* then results of 1st hash */ - utils_md5_finish(&context, out); /* finish up 2nd pass */ - - for (i = 0; i < MD5_DIGEST_SIZE; ++i) { - digest[i * 2] = utils_hb2hex(out[i] >> 4); - digest[i * 2 + 1] = utils_hb2hex(out[i]); - } -} - -void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len) -{ - if((NULL == msg) || (NULL == digest) || (NULL == key)) { - Log_e("parameter is Null,failed!"); - return; - } - - if(key_len > KEY_IOPAD_SIZE) { - Log_e("key_len > size(%d) of array",KEY_IOPAD_SIZE); - return; - } - - iot_sha1_context context; - unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ - unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ - unsigned char out[SHA1_DIGEST_SIZE]; - int i; - - /* start out by storing key in pads */ - memset(k_ipad, 0, sizeof(k_ipad)); - memset(k_opad, 0, sizeof(k_opad)); - memcpy(k_ipad, key, key_len); - memcpy(k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < KEY_IOPAD_SIZE; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - /* perform inner SHA */ - utils_sha1_init(&context); /* init context for 1st pass */ - utils_sha1_starts(&context); /* setup context for 1st pass */ - utils_sha1_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */ - utils_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */ - utils_sha1_finish(&context, out); /* finish up 1st pass */ - - /* perform outer SHA */ - utils_sha1_init(&context); /* init context for 2nd pass */ - utils_sha1_starts(&context); /* setup context for 2nd pass */ - utils_sha1_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */ - utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */ - utils_sha1_finish(&context, out); /* finish up 2nd pass */ - - for (i = 0; i < SHA1_DIGEST_SIZE; ++i) { - digest[i * 2] = utils_hb2hex(out[i] >> 4); - digest[i * 2 + 1] = utils_hb2hex(out[i]); - } -} - diff --git a/src/utils/farra/utils_httpc.h b/src/utils/farra/utils_httpc.h deleted file mode 100644 index c64412bf..00000000 --- a/src/utils/farra/utils_httpc.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_UTILS_HTTPC_H_ -#define QCLOUD_IOT_UTILS_HTTPC_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "utils_net.h" - -#define HTTP_PORT 80 -#define HTTPS_PORT 443 - -typedef enum { - HTTP_GET, - HTTP_POST, - HTTP_PUT, - HTTP_DELETE, - HTTP_HEAD -} HttpMethod; - -typedef struct { - int remote_port; // 端口号 - int response_code; // 响应码 - char *header; // 自定义头部 - char *auth_user; // 身份验证的用户名 - char *auth_password; // 身份验证的密码 - Network network_stack; -} HTTPClient; - -typedef struct { - bool is_more; // 是否需要检索更多的数据 - bool is_chunked; // 响应数据是否以分块进行编码 - int retrieve_len; // 要检索的内容长度 - int response_content_len; // 响应内容长度 - int post_buf_len; // post data length - int response_buf_len; // 响应包缓冲区长度 - char *post_content_type; // post数据的内容类型 - char *post_buf; // post的数据 - char *response_buf; // 存储响应数据的缓冲区 -} HTTPClientData; - -/** - * @brief http 网络请求 - * - * @param client http client - * @param url 请求url - * @param port 请求端口 - * @param ca_crt_dir ca证书路径 - * @param method 请求方法 - * @param client_data http数据负载 - * @return 返回QCLOUD_ERR_SUCCESS, 表示设置成功 - */ -int qcloud_http_client_common(HTTPClient *client, const char *url, int port, const char *ca_crt, HttpMethod method, HTTPClientData *client_data); - -int qcloud_http_recv_data(HTTPClient *client, uint32_t timeout_ms, HTTPClientData *client_data); - -int qcloud_http_client_connect(HTTPClient *client, const char *url, int port, const char *ca_crt); - -void qcloud_http_client_close(HTTPClient *client); - - -#ifdef __cplusplus -} -#endif -#endif /* QCLOUD_IOT_UTILS_HTTPC_H_ */ diff --git a/src/utils/farra/utils_net.c b/src/utils/farra/utils_net.c deleted file mode 100644 index 7447d982..00000000 --- a/src/utils/farra/utils_net.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * 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. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "utils_net.h" - -#include "qcloud_iot_export.h" -#include "qcloud_iot_sdk_impl_internal.h" - -static int _utils_net_connected(Network *pNetwork) { - return pNetwork->handle; -} - -#ifndef AUTH_WITH_NOTLS -/*** SSL connection ***/ -static int _read_tls(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - return HAL_TLS_Read(pNetwork->handle, data, datalen, timeout_ms, read_len); -} - -static int _write_tls(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - return HAL_TLS_Write(pNetwork->handle, data, datalen, timeout_ms, written_len); -} - -static int _disconnect_tls(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - HAL_TLS_Disconnect(pNetwork->handle); - pNetwork->handle = 0; - - return 0; -} - -static int _connect_tls(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int ret = QCLOUD_ERR_FAILURE; - - pNetwork->handle = (uintptr_t)HAL_TLS_Connect(&(pNetwork->ssl_connect_params), pNetwork->host, pNetwork->port); - if (pNetwork->handle != 0) { - ret = QCLOUD_ERR_SUCCESS; - } - - return ret; -} - -/*** TCP connection ***/ -/*when tls enable, noTls also can be used*/ - -static int _read_tcp(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) -{ - return HAL_TCP_Read(pNetwork->handle, data, (uint32_t)datalen, timeout_ms, read_len); -} - -static int _write_tcp(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) -{ - return HAL_TCP_Write(pNetwork->handle, data, datalen, timeout_ms, written_len); -} - -static int _disconnect_tcp(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - if (0 == pNetwork->handle) { - return -1; - } - - HAL_TCP_Disconnect(pNetwork->handle); - pNetwork->handle = 0; - return 0; -} - -static int _connect_tcp(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - pNetwork->handle = HAL_TCP_Connect(pNetwork->host, pNetwork->port); - if (0 == pNetwork->handle) { - return -1; - } - return 0; -} - - -#else -/*** TCP connection ***/ -static int _read_tcp(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) -{ - return HAL_TCP_Read(pNetwork->handle, data, (uint32_t)datalen, timeout_ms, read_len); -} - -static int _write_tcp(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) -{ - return HAL_TCP_Write(pNetwork->handle, data, datalen, timeout_ms, written_len); -} - -static int _disconnect_tcp(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - if (0 == pNetwork->handle) { - return -1; - } - - HAL_TCP_Disconnect(pNetwork->handle); - pNetwork->handle = 0; - return 0; -} - -static int _connect_tcp(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - pNetwork->handle = HAL_TCP_Connect(pNetwork->host, pNetwork->port); - if (0 == pNetwork->handle) { - return -1; - } - return 0; -} -#endif - -int utils_net_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int rc = 0; - -#ifndef AUTH_WITH_NOTLS - if(NULL != pNetwork->ssl_connect_params.ca_crt){ - rc = _read_tls(pNetwork, data, datalen, timeout_ms, read_len); - }else{ - rc = _read_tcp(pNetwork, data, datalen, timeout_ms, read_len); - } - -#else - rc = _read_tcp(pNetwork, data, datalen, timeout_ms, read_len); -#endif - - return rc; -} - -int utils_net_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int rc = 0; - -#ifndef AUTH_WITH_NOTLS - if(NULL != pNetwork->ssl_connect_params.ca_crt){ - rc = _write_tls(pNetwork, data, datalen, timeout_ms, written_len); - }else{ - rc = _write_tcp(pNetwork, data, datalen, timeout_ms, written_len); - } - -#else - rc = _write_tcp(pNetwork, data, datalen, timeout_ms, written_len); -#endif - - return rc; -} - -void utils_net_disconnect(Network *pNetwork) -{ - POINTER_SANITY_CHECK_RTN(pNetwork); - -#ifndef AUTH_WITH_NOTLS - if(NULL != pNetwork->ssl_connect_params.ca_crt){ - _disconnect_tls(pNetwork); - }else{ - _disconnect_tcp(pNetwork); - } - -#else - _disconnect_tcp(pNetwork); -#endif -} - -int utils_net_connect(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int rc = 0; - -#ifndef AUTH_WITH_NOTLS - /*when tls enable, noTls also can be used*/ - if(NULL != pNetwork->ssl_connect_params.ca_crt){ - rc = _connect_tls(pNetwork); - }else{ - rc = _connect_tcp(pNetwork); - } - -#else - rc = _connect_tcp(pNetwork); -#endif - - return rc; -} - -int utils_net_init(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int rc = QCLOUD_ERR_SUCCESS; - - pNetwork->connect = utils_net_connect; - pNetwork->read = utils_net_read; - pNetwork->write = utils_net_write; - pNetwork->disconnect = utils_net_disconnect; - pNetwork->is_connected = _utils_net_connected; - pNetwork->handle = 0; - - return rc; -} - -#ifdef COAP_COMM_ENABLED -static int _utils_udp_net_connected(Network *pNetwork) { - return pNetwork->handle; -} - -#ifndef AUTH_WITH_NOTLS -static int _read_dtls(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - return HAL_DTLS_Read(pNetwork->handle, data, datalen, timeout_ms, read_len); -} - -static int _write_dtls(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - return HAL_DTLS_Write(pNetwork->handle, data, datalen, written_len); -} - -static int _disconnect_dtls(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - HAL_DTLS_Disconnect(pNetwork->handle); - pNetwork->handle = 0; - - return 0; -} - -static int _connect_dtls(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int ret = QCLOUD_ERR_FAILURE; - - pNetwork->handle = (uintptr_t)HAL_DTLS_Connect(&(pNetwork->ssl_connect_params), pNetwork->host, pNetwork->port); - if (pNetwork->handle != 0) { - ret = QCLOUD_ERR_SUCCESS; - } - - return ret; -} -#else -static int _read_udp(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int ret = HAL_UDP_ReadTimeout(pNetwork->handle, data, datalen, timeout_ms); - if (ret > 0) { - *read_len = ret; - ret = 0; - } - - return ret; -} - -static int _write_udp(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int ret = HAL_UDP_Write(pNetwork->handle, data, datalen); - if (ret > 0) { - *written_len = ret; - ret = 0; - } - - return ret; -} - -static int _disconnect_udp(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - HAL_UDP_Disconnect(pNetwork->handle); - pNetwork->handle = 0; - - return 0; -} - -static int _connect_udp(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - pNetwork->handle = HAL_UDP_Connect(pNetwork->host, pNetwork->port); - if (0 == pNetwork->handle) { - return -1; - } - return 0; -} -#endif - -int utils_udp_net_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int rc = 0; - -#ifndef AUTH_WITH_NOTLS - rc = _read_dtls(pNetwork, data, datalen, timeout_ms, read_len); -#else - rc = _read_udp(pNetwork, data, datalen, timeout_ms, read_len); -#endif - - return rc; -} - -int utils_udp_net_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int rc = 0; -#ifndef AUTH_WITH_NOTLS - rc = _write_dtls(pNetwork, data, datalen, timeout_ms, written_len); -#else - rc = _write_udp(pNetwork, data, datalen, timeout_ms, written_len); -#endif - - return rc; -} - -void utils_udp_net_disconnect(Network *pNetwork) -{ - POINTER_SANITY_CHECK_RTN(pNetwork); -#ifndef AUTH_WITH_NOTLS - _disconnect_dtls(pNetwork); -#else - _disconnect_udp(pNetwork); -#endif -} - -int utils_udp_net_connect(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int rc = 0; -#ifndef AUTH_WITH_NOTLS - rc = _connect_dtls(pNetwork); -#else - rc = _connect_udp(pNetwork); -#endif - - return rc; -} - -int utils_udp_net_init(Network *pNetwork) -{ - POINTER_SANITY_CHECK(pNetwork, QCLOUD_ERR_INVAL); - - int rc = QCLOUD_ERR_SUCCESS; - - pNetwork->connect = utils_udp_net_connect; - pNetwork->read = utils_udp_net_read; - pNetwork->write = utils_udp_net_write; - pNetwork->disconnect = utils_udp_net_disconnect; - pNetwork->is_connected = _utils_udp_net_connected; - pNetwork->handle = 0; - - return rc; -} -#endif - -#ifdef __cplusplus -} -#endif diff --git a/src/utils/farra/utils_net.h b/src/utils/farra/utils_net.h deleted file mode 100644 index 9263346e..00000000 --- a/src/utils/farra/utils_net.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making IoT Hub available. - * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. - - * Licensed under the MIT License (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://opensource.org/licenses/MIT - - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef QCLOUD_IOT_UTILS_NET_H_ -#define QCLOUD_IOT_UTILS_NET_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "qcloud_iot_import.h" - -/** - * @brief 网络结构类型 - * - * 定义一个网络结构类型, 具体定义如下面所示 - */ -typedef struct Network Network; - -/** - * @brief 网络操作相关的结构体定义 - * - * 定义了底层网络相关的操作, 包括连接, 读/写数据, 断开连接等 - */ -struct Network { - int (*connect)(Network *); - - int (*read)(Network *, unsigned char *, size_t, uint32_t, size_t *); - - int (*write)(Network *, unsigned char *, size_t, uint32_t, size_t *); - - void (*disconnect)(Network *); - - int (*is_connected)(Network *); - - uintptr_t handle; // 连接句柄:0,尚未连接; 非0,已经连接 - -#ifndef AUTH_WITH_NOTLS - SSLConnectParams ssl_connect_params; -#endif - - const char *host; // 服务器地址 - int port; // 服务器端口 -}; - - -int utils_net_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len); -int utils_net_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len); -void utils_net_disconnect(Network *pNetwork); -int utils_net_connect(Network *pNetwork); -int utils_net_init(Network *pNetwork); - -#ifdef COAP_COMM_ENABLED -int utils_udp_net_read(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *read_len); -int utils_udp_net_write(Network *pNetwork, unsigned char *data, size_t datalen, uint32_t timeout_ms, size_t *written_len); -void utils_udp_net_disconnect(Network *pNetwork); -int utils_udp_net_connect(Network *pNetwork); -int utils_udp_net_init(Network *pNetwork); -#endif - -#ifdef __cplusplus -} -#endif -#endif /* QCLOUD_IOT_UTILS_NET_H_ */ diff --git a/src/utils/lite/json_token.c b/src/utils/lite/json_token.c deleted file mode 100644 index 14cade6e..00000000 --- a/src/utils/lite/json_token.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -/** - * Edit by shockcao@tencent.com 2018/3/15 - */ - -#include "json_parser.h" - -#include "lite-utils.h" -#include "qcloud_iot_export_error.h" - -char *LITE_json_value_of(char *key, char *src) -{ - char *value = NULL; - int value_len = -1; - char *ret = NULL; - - char *delim = NULL; - char *key_iter; - char *key_next; - int key_len; - char *src_iter; - - src_iter = src; - key_iter = key; - - do { - if ((delim = strchr(key_iter, '.')) != NULL) { - key_len = delim - key_iter; - key_next = HAL_Malloc(key_len + 1); - strncpy(key_next, key_iter, key_len); - key_next[key_len] = '\0'; - value = json_get_value_by_name(src_iter, strlen(src_iter), key_next, &value_len, 0); - - if (value == NULL) { - HAL_Free(key_next); - return NULL; - } - - src_iter = value; - key_iter = delim + 1; - HAL_Free(key_next); - } - } while (delim); - - value = json_get_value_by_name(src_iter, strlen(src_iter), key_iter, &value_len, 0); - if (NULL == value) { - return NULL; - } - ret = HAL_Malloc((value_len + 1) * sizeof(char)); - if (NULL == ret) { - return NULL; - } - HAL_Snprintf(ret, value_len + 1, "%s", value); - return ret; -} - -list_head_t *LITE_json_keys_of(char *src, char *prefix) -{ - static LIST_HEAD(keylist); - - char *pos = 0, *key = 0, *val = 0; - int klen = 0, vlen = 0, vtype = 0; - - if (src == NULL || prefix == NULL) { - return NULL; - } - - if (!strcmp("", prefix)) { - INIT_LIST_HEAD(&keylist); - } - - json_object_for_each_kv(src, pos, key, klen, val, vlen, vtype) { - if (key && klen && val && vlen) { - - json_key_t *entry = NULL; - - entry = HAL_Malloc(sizeof(json_key_t)); - memset(entry, 0, sizeof(json_key_t)); - entry->key = LITE_format_string("%s%.*s", prefix, klen, key); - list_add_tail(&entry->list, &keylist); - - if (JSOBJECT == vtype) { - char *iter_val = LITE_format_string("%.*s", vlen, val); - char *iter_pre = LITE_format_string("%s%.*s.", prefix, klen, key); - LITE_json_keys_of(iter_val, iter_pre); - HAL_Free(iter_val); - HAL_Free(iter_pre); - } - } - } - - if (!strcmp("", prefix)) { - json_key_t *entry = NULL; - - entry = HAL_Malloc(sizeof(json_key_t)); - memset(entry, 0, sizeof(json_key_t)); - list_add_tail(&entry->list, &keylist); - - return &keylist; - } - - return NULL; -} - -void LITE_json_keys_release(list_head_t *keylist) -{ - json_key_t *pos, *tmp; - - list_for_each_entry_safe(pos, tmp, keylist, list, json_key_t) { - if (pos->key) { - HAL_Free(pos->key); - } - list_del(&pos->list); - HAL_Free(pos); - } -} - -int LITE_get_int32(int32_t *value, char *src) { - return (sscanf(src, "%" SCNi32, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE; -} - -int LITE_get_int16(int16_t *value, char *src) { - return (sscanf(src, "%" SCNi16, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE; -} - -int LITE_get_int8(int8_t *value, char *src) { - return (sscanf(src, "%" SCNi8, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE; -} - -int LITE_get_uint32(uint32_t *value, char *src) { - return (sscanf(src, "%" SCNu32, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE; -} - -int LITE_get_uint16(uint16_t *value, char *src) { - return (sscanf(src, "%" SCNu16, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE; -} - -int LITE_get_uint8(uint8_t *value, char *src) { - return (sscanf(src, "%" SCNu8, value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE; -} - -int LITE_get_float(float *value, char *src) { - return (sscanf(src, "%f", value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE; -} - -int LITE_get_double(double *value, char *src) { - return (sscanf(src, "%lf", value) == 1) ? QCLOUD_ERR_SUCCESS : QCLOUD_ERR_FAILURE; -} - -int LITE_get_boolean(bool *value, char *src) { - if (!strcmp(src, "false")) { - *value = false; - } - else { - *value = true; - } - - return QCLOUD_ERR_SUCCESS; -} - diff --git a/src/utils/lite/lite-utils.h b/src/utils/lite/lite-utils.h deleted file mode 100644 index adb71b4f..00000000 --- a/src/utils/lite/lite-utils.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -/** - * Edit by shockcao@tencent.com 2018/3/15 - */ - -#ifndef __LITE_UTILS_H__ -#define __LITE_UTILS_H__ - -#include -#include -#include -#include -#include -#include -#if defined(_PLATFORM_IS_LINUX_) -#include -#endif - -#include "lite-list.h" -#include "qcloud_iot_import.h" - -#define LITE_TRUE (1) -#define LITE_FALSE (0) - -#ifndef container_of -#define container_of(ptr, type, member) \ - ((type *) ((char *) (ptr) - offsetof(type, member))) -#endif - -#define LITE_MINIMUM(a, b) (((a) <= (b)) ? (a) : (b)) -#define LITE_MAXIMUM(a, b) (((a) >= (b)) ? (a) : (b)) -#define LITE_isdigit(c) (((c) <= '9' && (c) >= '0') ? (LITE_TRUE) : (LITE_FALSE)) - -#if defined(_PLATFORM_IS_LINUX_) -#define LITE_ASSERT(expr) assert(expr) -#else -#define LITE_ASSERT(expr) \ - do { \ - if (!(expr)) { \ - HAL_Printf("### %s | %s(%d): ASSERT FAILED ###: %s is FALSE\r\n", \ - __FILE__, __func__, __LINE__, #expr); \ - } \ - } while(0) -#endif - -char *LITE_strdup(const char *src); -char *LITE_format_string(const char *fmt, ...); -char *LITE_format_nstring(const int len, const char *fmt, ...); -void LITE_hexbuf_convert(unsigned char *digest, char *out, int buflen, int uppercase); -void LITE_hexstr_convert(char *hexstr, uint8_t *out_buf, int len); -void LITE_replace_substr(char orig[], char key[], char swap[]); - -char *LITE_json_value_of(char *key, char *src); -list_head_t *LITE_json_keys_of(char *src, char *prefix); -void LITE_json_keys_release(list_head_t *keylist); - -int LITE_get_int32(int32_t *value, char *src); -int LITE_get_int16(int16_t *value, char *src); -int LITE_get_int8(int8_t *value, char *src); -int LITE_get_uint32(uint32_t *value, char *src); -int LITE_get_uint16(uint16_t *value, char *src); -int LITE_get_uint8(uint8_t *value, char *src); -int LITE_get_float(float *value, char *src); -int LITE_get_double(double *value, char *src); -int LITE_get_boolean(bool *value, char *src); - -typedef struct _json_key_t { - char *key; - list_head_t list; -} json_key_t; - -#define foreach_json_keys_in(src, iter_key, keylist, pos) \ - for(keylist = (void *)LITE_json_keys_of((char *)src, ""), \ - pos = (void *)list_first_entry((list_head_t *)keylist, json_key_t, list), \ - iter_key = ((json_key_t *)pos)->key; \ - (iter_key = ((json_key_t *)pos)->key); \ - pos = list_next_entry((json_key_t *)pos, list, json_key_t)) - -#endif /* __LITE_UTILS_H__ */ diff --git a/src/utils/lite/string_utils.c b/src/utils/lite/string_utils.c deleted file mode 100644 index b2173338..00000000 --- a/src/utils/lite/string_utils.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -/** - * Edit by shockcao@tencent.com 2018/3/15 - */ - -#include "lite-utils.h" - -#include "qcloud_iot_import.h" -#include "qcloud_iot_export_log.h" - -char *LITE_format_string(const char *fmt, ...) -{ -#define TEMP_STRING_MAXLEN (512) - - va_list ap; - char *tmp = NULL; - char *dst; - int rc = -1; - - va_start(ap, fmt); - tmp = HAL_Malloc(TEMP_STRING_MAXLEN); - memset(tmp, 0, TEMP_STRING_MAXLEN); - rc = HAL_Vsnprintf(tmp, TEMP_STRING_MAXLEN, fmt, ap); - va_end(ap); - LITE_ASSERT(tmp); - LITE_ASSERT(rc < 1024); - - dst = LITE_strdup(tmp); - HAL_Free(tmp); - - return dst; - -#undef TEMP_STRING_MAXLEN -} - -char *LITE_format_nstring(const int len, const char *fmt, ...) -{ - va_list ap; - char *tmp = NULL; - char *dst; - int rc = -1; - - va_start(ap, fmt); - tmp = HAL_Malloc(len+2); - memset(tmp, 0, len+2); - rc = HAL_Vsnprintf(tmp, len+1, fmt, ap); - va_end(ap); - LITE_ASSERT(tmp); - LITE_ASSERT(rc < 1024); - - dst = HAL_Malloc(len + 1); - HAL_Snprintf(dst, (len + 1), "%s", tmp); - HAL_Free(tmp); - - return dst; -} - -char *LITE_strdup(const char *src) -{ - int len = 0; - char *dst = NULL; - - if (!src) { - return NULL; - } - len = strlen(src) + 1; - if (len > 1024) { - Log_e("Too long string to duplicate, abort! len = %d", len); - return NULL; - } - - dst = (char *)HAL_Malloc(sizeof(char) * len); - if (!dst) { - return NULL; - } - strncpy(dst, src, len); - - return dst; -} - -void LITE_hexbuf_convert(unsigned char *digest, char *out, int in_len, int uppercase) -{ - static char *zEncode[] = {"0123456789abcdef", "0123456789ABCDEF"}; - int j = 0; - int i = 0; - int idx = uppercase ? 1 : 0; - - for (i = 0; i < in_len; i ++) { - int a = digest[i]; - - out[j++] = zEncode[idx][(a >> 4) & 0xf]; - out[j++] = zEncode[idx][a & 0xf]; - } -} - -static uint8_t _hexval_of_char(char hex) -{ - if (LITE_isdigit(hex)) { - return (hex - '0'); - } - if (hex >= 'a' && hex <= 'f') { - return (hex - 'a' + 10); - } - if (hex >= 'A' && hex <= 'F') { - return (hex - 'A' + 10); - } - - return 0; -} - -void LITE_hexstr_convert(char *hexstr, uint8_t *out_buf, int in_len) -{ - int i = 0; - uint8_t ch0, ch1; - - if (in_len % 2 != 0) { - Log_e("hexstr length (%d) is not even", in_len); - return; - } - - while (i < in_len) { - ch0 = _hexval_of_char((char)hexstr[2 * i]); - ch1 = _hexval_of_char((char)hexstr[2 * i + 1]); - out_buf[i] = (ch0 << 4 | ch1); - i++; - } -} - -void LITE_replace_substr(char originalString[], char key[], char swap[]) -{ - int lengthOfOriginalString, lengthOfKey, lengthOfSwap, i, j, flag; - char tmp[512]; - - lengthOfOriginalString = strlen(originalString); - lengthOfKey = strlen(key); - lengthOfSwap = strlen(swap); - - for (i = 0; i <= lengthOfOriginalString - lengthOfKey; i++) { - flag = 1; - for (j = 0; j < lengthOfKey; j++) { - if (originalString[i + j] != key[j]) { - flag = 0; - break; - } - } - - if (flag) { - strcpy(tmp, originalString); - strcpy(&tmp[i], swap); - strcpy(&tmp[i + lengthOfSwap], &originalString[i + lengthOfKey]); - strcpy(originalString, tmp); - i += lengthOfSwap - 1; - lengthOfOriginalString = strlen(originalString); - } - } -} diff --git a/src/scripts/internal_make_funcs.mk b/tools/build_scripts/internal_make_funcs.mk similarity index 100% rename from src/scripts/internal_make_funcs.mk rename to tools/build_scripts/internal_make_funcs.mk diff --git a/src/scripts/parse_make_settings.mk b/tools/build_scripts/parse_make_settings.mk old mode 100644 new mode 100755 similarity index 69% rename from src/scripts/parse_make_settings.mk rename to tools/build_scripts/parse_make_settings.mk index 0f8be203..0ab31616 --- a/src/scripts/parse_make_settings.mk +++ b/tools/build_scripts/parse_make_settings.mk @@ -1,4 +1,4 @@ -include $(CURDIR)/src/scripts/internal_make_funcs.mk +include $(SCRIPT_DIR)/internal_make_funcs.mk SETTING_VARS := \ BUILD_TYPE \ @@ -12,11 +12,20 @@ SWITCH_VARS := \ FEATURE_OTA_COMM_ENABLED \ FEATURE_MQTT_DEVICE_SHADOW \ FEATURE_AUTH_WITH_NOTLS \ - FEATURE_MQTT_RMDUP_MSG_ENABLED \ - FEATURE_NBIOT_COMM_ENABLED \ FEATURE_GATEWAY_ENABLED \ - FEATURE_MULTITHREAD_TEST_ENABLED \ - + FEATURE_LOG_UPLOAD_ENABLED \ + FEATURE_MULTITHREAD_ENABLED \ + FEATURE_DEV_DYN_REG_ENABLED \ + FEATURE_AT_TCP_ENABLED \ + FEATURE_AT_UART_RECV_IRQ \ + FEATURE_AT_OS_USED \ + FEATURE_AT_DEBUG \ + FEATURE_DEBUG_DEV_INFO_USED \ + FEATURE_OTA_USE_HTTPS \ + FEATURE_BROADCAST_ENABLED \ + FEATURE_RRPC_ENABLED \ + FEATURE_REMOTE_CONFIG_MQTT_ENABLED \ + $(foreach v, \ $(SETTING_VARS) $(SWITCH_VARS), \ $(eval export $(v)=$($(v))) \ @@ -28,10 +37,9 @@ $(foreach v, \ $(eval CFLAGS += -D$(subst FEATURE_,,$(v)))) \ ) -include $(CURDIR)/src/configs/settings.mk ifeq (debug,$(strip $(BUILD_TYPE))) -CFLAGS += -DIOT_DEBUG +CFLAGS += -DIOT_DEBUG -g -O2 endif ifneq (linux,$(strip $(PLATFORM_OS))) @@ -79,10 +87,24 @@ ifeq (y, $(strip $(FEATURE_SYSTEM_COMM_ENABLED))) CFLAGS += -DSYSTEM_COMM endif -ifeq (y, $(strip $(FEATURE_MULTITHREAD_TEST_ENABLED))) -CFLAGS += -DMULTITHREAD_TEST_ENABLED +ifeq (y, $(strip $(FEATURE_REMOTE_CONFIG_MQTT_ENABLED))) +CFLAGS += -DREMOTE_CONFIG_MQTT endif ifeq (y, $(strip $(FEATURE_LOG_UPLOAD_ENABLED))) CFLAGS += -DLOG_UPLOAD endif + +ifeq (y, $(strip $(FEATURE_AT_TCP_ENABLED))) +CFLAGS += -DAT_TCP_ENABLED +ifeq (y, $(strip $(FEATURE_AT_UART_RECV_IRQ))) +CFLAGS += -DAT_UART_RECV_IRQ +endif +ifeq (y, $(strip $(FEATURE_AT_OS_USED))) +CFLAGS += -DAT_OS_USED +endif +ifeq (y, $(strip $(FEATURE_AT_DEBUG))) +CFLAGS += -DFEATURE_AT_DEBUG +endif +endif + diff --git a/src/scripts/rules-tests.mk b/tools/build_scripts/rules-tests.mk similarity index 95% rename from src/scripts/rules-tests.mk rename to tools/build_scripts/rules-tests.mk index 2db7ed88..ccf498b6 100644 --- a/src/scripts/rules-tests.mk +++ b/tools/build_scripts/rules-tests.mk @@ -2,5 +2,4 @@ coap_run_demo_test coap_demo_test_clean tests: run_demo_test run_unit_test run_multi_thread_test coap_run_demo_test - -cleans: \ No newline at end of file + \ No newline at end of file diff --git a/src/scripts/rules.mk b/tools/build_scripts/rules.mk similarity index 69% rename from src/scripts/rules.mk rename to tools/build_scripts/rules.mk index 33e350fa..53aaaf45 100644 --- a/src/scripts/rules.mk +++ b/tools/build_scripts/rules.mk @@ -1,10 +1,9 @@ iot_sdk_objects = $(patsubst %.c,%.o, $(IOTSDK_SRC_FILES)) iot_platform_objects = $(patsubst %.c,%.o, $(IOTPLATFORM_SRC_FILES)) -.PHONY: config mbedtls clean final-out final tests +.PHONY: config mbedtls clean final-out samples tests -all: config mbedtls ${COMP_LIB} ${PLATFORM_LIB} final-out final tests cleans - @sed -i 's/ //g' `find . -name *.sh` +all: config mbedtls ${COMP_LIB} ${PLATFORM_LIB} final-out samples tests $(call Compile_Result) ${COMP_LIB}: ${iot_sdk_objects} @@ -29,11 +28,6 @@ config: mbedtls: ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) - $(TOP_Q) \ - chmod a+x $(SCRIPT_DIR)/update_mbedtls.sh - $(TOP_Q) \ - $(SCRIPT_DIR)/update_mbedtls.sh > /dev/null - $(TOP_Q) \ make -s -C $(THIRD_PARTY_PATH)/mbedtls lib -e CC=$(PLATFORM_CC) AR=$(PLATFORM_AR) @@ -50,6 +44,7 @@ ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) endif ${iot_sdk_objects}:%.o:%.c + $(TOP_Q) echo '' > $(TOP_DIR)/include/config.h $(call Brief_Log,"CC") $(TOP_Q) \ $(PLATFORM_CC) $(CFLAGS) -c $^ -o $@ @@ -59,11 +54,37 @@ ${iot_platform_objects}:%.o:%.c $(TOP_Q) \ $(PLATFORM_CC) $(CFLAGS) -c $^ -o $@ -include $(TOP_DIR)/src/scripts/rules-final.mk -include $(TOP_DIR)/src/scripts/rules-tests.mk +final-out : + $(TOP_Q) \ + mkdir -p ${FINAL_DIR} ${DIST_DIR} ${FINAL_DIR}/lib \ + ${FINAL_DIR}/include ${FINAL_DIR}/bin + + $(TOP_Q) \ + mv ${COMP_LIB} ${FINAL_DIR}/lib/ && \ + mv ${PLATFORM_LIB} ${FINAL_DIR}/lib + + $(TOP_Q) \ + cp -rf $(TOP_DIR)/include $(FINAL_DIR)/ + + $(TOP_Q) \ + cp -rf $(TOP_DIR)/certs $(FINAL_DIR)/bin/ + +ifeq (,$(filter -DAUTH_WITH_NOTLS,$(CFLAGS))) + $(TOP_Q) \ + mv ${TEMP_DIR}/*.a ${FINAL_DIR}/lib/ +endif + + $(TOP_Q) \ + rm -rf ${TEMP_DIR} + +#include $(SCRIPT_DIR)/rules-tests.mk + +samples: + $(TOP_Q) \ + make -s -C $(SAMPLE_DIR) TLSDIR = $(THIRD_PARTY_PATH)/mbedtls -clean: cleans +clean: $(TOP_Q) \ rm -rf ${TEMP_DIR} @@ -75,9 +96,6 @@ ifeq ($(TLSDIR), $(wildcard $(THIRD_PARTY_PATH)/mbedtls)) $(TOP_Q) \ make -s -C $(THIRD_PARTY_PATH)/mbedtls clean endif -else - $(TOP_Q) \ - rm -rf ${THIRD_PARTY_PATH}/mbedtls endif ifeq (,$(filter -DSDKTESTS_ENABLED,$(CFLAGS))) diff --git a/src/scripts/stats_static_lib.sh b/tools/build_scripts/stats_static_lib.sh similarity index 100% rename from src/scripts/stats_static_lib.sh rename to tools/build_scripts/stats_static_lib.sh diff --git a/src/scripts/update_gtest.sh b/tools/build_scripts/update_gtest.sh old mode 100755 new mode 100644 similarity index 100% rename from src/scripts/update_gtest.sh rename to tools/build_scripts/update_gtest.sh diff --git a/src/scripts/update_mbedtls.sh b/tools/build_scripts/update_mbedtls.sh old mode 100755 new mode 100644 similarity index 98% rename from src/scripts/update_mbedtls.sh rename to tools/build_scripts/update_mbedtls.sh index 27dd2943..40807957 --- a/src/scripts/update_mbedtls.sh +++ b/tools/build_scripts/update_mbedtls.sh @@ -8,4 +8,4 @@ else cd ${MBEDTLS_DIR} git pull -q cd - -fi \ No newline at end of file +fi diff --git a/tools/cmake_scripts/config.h.in b/tools/cmake_scripts/config.h.in new file mode 100755 index 00000000..7b3d360e --- /dev/null +++ b/tools/cmake_scripts/config.h.in @@ -0,0 +1,20 @@ +#cmakedefine AUTH_MODE_CERT +#cmakedefine AUTH_MODE_KEY +#cmakedefine AUTH_WITH_NOTLS +#cmakedefine GATEWAY_ENABLED +#cmakedefine COAP_COMM_ENABLED +#cmakedefine OTA_MQTT_CHANNEL +#cmakedefine SYSTEM_COMM +#cmakedefine DEV_DYN_REG_ENABLED +#cmakedefine LOG_UPLOAD +#cmakedefine IOT_DEBUG +#cmakedefine DEBUG_DEV_INFO_USED +#cmakedefine AT_TCP_ENABLED +#cmakedefine AT_UART_RECV_IRQ +#cmakedefine AT_OS_USED +#cmakedefine AT_DEBUG +#cmakedefine OTA_USE_HTTPS +#cmakedefine MULTITHREAD_ENABLED +#cmakedefine BROADCAST_ENABLED +#cmakedefine RRPC_ENABLED +#cmakedefine REMOTE_CONFIG_MQTT diff --git a/tools/cmake_scripts/convert.sh b/tools/cmake_scripts/convert.sh new file mode 100755 index 00000000..2fc471ca --- /dev/null +++ b/tools/cmake_scripts/convert.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +if [ $1 == "linux" ]; then + find $2 -type f -name "*.h" -print -o -name "*.c" -print | xargs -i sed -i '1 s/^\xef\xbb\xbf//' {} + echo "Convert source files to Unix format!!!" +elif [ $1 == "windows" ]; then + find $2 -type f -name "*.h" -print -o -name "*.c" -print | xargs -i sed -i '1 s/^/\xef\xbb\xbf&/' {} + echo "Convert source files to Windows format!!!" +else + echo "Invaild argument!" + echo "Please choose windows or linux !!!" +fi diff --git a/tools/codegen.py b/tools/codegen.py new file mode 100644 index 00000000..79d2299c --- /dev/null +++ b/tools/codegen.py @@ -0,0 +1,352 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import json +import sys +import os +import argparse +import glob +#import cStringIO + +reload(sys) +sys.setdefaultencoding("utf-8") + +try: import simplejson as json +except: import json + + +# {"version":"1.0","properties":[{"id":"light_switch","name":"电灯开关","desc":"控制电灯开灭","required":true,"mode":"rw","define":{"type":"bool","mapping":{"0":"关","1":"开"}}},{"id":"color","name":"颜色","desc":"灯光颜色","mode":"rw","define":{"type":"enum","mapping":{"0":"Red","1":"Green","2":"Blue"}}},{"id":"brightness","name":"颜色","desc":"灯光颜色","mode":"rw","define":{"type":"int","unit":"%","unitDesc":"亮度百分比","min":"0","max":"100"}},{"id":"name","name":"灯位置名称","desc":"灯位置名称:书房、客厅等","mode":"rw","required":true,"define":{"type":"string","min":"0","max":"64"}}]} +class TEMPLATE_CONSTANTS: + VERSION = "version" + TYPE = "type" + NAME = "name" + ID = "id" + MIN = "min" + MAX = "max" + DEFINE = "define" + PROPERTIES = "properties" + EVENTS = "events" + MAPPING = "mapping" + UNIT = "unit" + UNITDESC = "unitDesc" + REQUIRED = "required" + MODE = "mode" + + + +class iot_enum: + def __init__(self, parent, name, index): + self.parent = parent + self.id = name + self.index = index + + def get_c_macro_name(self): + return "e_{}_{}".format(self.parent.upper(), self.id.upper()) + + def get_define_str(self): + return "#define {} {}".format(self.get_c_macro_name(), self.index) + +class iot_field: + def __init__(self,id, name, index, field_obj): + self.default_value = "" + self.enums = [] + self.index = index + self.id = id + self.name = name + self.type_name = field_obj["define"]["type"] + + if self.type_name == "bool": + self.type_define = "TYPE_DEF_TEMPLATE_BOOL" + self.type_id = "TYPE_TEMPLATE_BOOL" + self.default_value = "0" + elif self.type_name == "enum": + self.type_define = "TYPE_DEF_TEMPLATE_ENUM" + self.type_id = "TYPE_TEMPLATEENUM" + if TEMPLATE_CONSTANTS.DEFINE not in field_obj: + raise ValueError("错误:{} 字段定义中未找到枚举定义{} 字段".format(name, TEMPLATE_CONSTANTS.DEFINE)) + + enum_defs = field_obj["define"]["mapping"] + + + for enum_id in enum_defs: + enum_name = enum_defs[enum_id] + current_enum = iot_enum(self.id, enum_name, enum_id) + self.enums.append(current_enum) + if self.default_value == "": + self.default_value = enum_id + if self.default_value == "": + raise ValueError("错误:{} 字段默认值 {} 非法".format(name, field_obj["default"])) + + elif self.type_name == "float": + self.type_define = "TYPE_DEF_TEMPLATE_FLOAT" + self.type_id = "TYPE_TEMPLATE_FLOAT" + + self.min_value = field_obj["define"]["min"] + self.max_value = field_obj["define"]["max"] + self.default_value = field_obj["define"]["start"] + if float(self.default_value) < float(self.min_value) or float(self.default_value) > float(self.max_value): + raise ValueError("错误:{} 字段 default 指定的默认值超出 min~max 取值范围".format(name)) + elif self.type_name == "int": + self.type_define = "TYPE_DEF_TEMPLATE_INT" + self.type_id = "TYPE_TEMPLATE_INT" + + self.min_value = field_obj["define"]["min"] + self.max_value = field_obj["define"]["max"] + self.default_value = field_obj["define"]["start"] + if int(self.default_value) < int(self.min_value) or int(self.default_value) > int(self.max_value): + raise ValueError("错误:{} 字段 default 指定的默认值超出 min~max 取值范围".format(name)) + elif self.type_name == "string": + self.type_define = "TYPE_DEF_TEMPLATE_STRING" + self.type_id = "TYPE_TEMPLATE_STRING" + + self.min_value = field_obj["define"]["min"] + self.max_value = field_obj["define"]["max"] + self.default_value = "{'\\0'}" + elif self.type_name == "timestamp": + self.type_define = "TYPE_DEF_TEMPLATE_TIME" + self.type_id = "TYPE_TEMPLATE_TIME" + self.default_value = 0 + else: + raise ValueError('{} 字段 数据类型 type={} 取值非法,有效值应为:bool,enum,int,float,string'.format(name, field_obj["type"])) + + def get_id_c_macro_name(self): + return "TC_IOT_PROP_{}".format(self.id) + + def get_id_c_member_name(self): + return "m_{}".format(self.id) + + def get_id_default_value(self): + return "{}".format(self.default_value) + + def get_id_define_str(self): + return "#define {} {}".format(self.get_id_c_macro_name(), self.index) + + def get_struct_field_declare(self): + if self.type_id == "TYPE_TEMPLATE_STRING": + return "TYPE_DEF_TEMPLATE_STRING m_{}[{}+1];".format(self.id, str(self.max_value)) + else: + return "{} m_{};".format(self.type_define, self.id) + + def get_global_field_declare(self): + if self.type_id == "TYPE_TEMPLATE_STRING": + return "TYPE_DEF_TEMPLATE_STRING sg_{}[{}+1]={};".format(self.id, str(self.max_value),"{0}") + else: + return "{} sg_{} = {};".format(self.type_define, self.id, self.default_value) + + def get_meta_define_str(self, var_name): + return '{{ "{}", &{}.{}, {} }},' \ + .format(self.id, var_name, self.get_id_c_member_name(), self.type_id) +class iot_event: + def __init__(self,id, name, index, event): + self.index = index + self.id = id + self.name = name + self.event_type = event["type"] + self.desc = event["desc"] + self.event_properties = [] + self.event_property_count = 0 + + for property in event["params"]: + self.event_properties.append(iot_field(property["id"], property["name"], self.event_property_count, property)) + self.event_property_count += 1 + + + def get_sigle_event_info(self): + event_info = "" + event_info += "\n id:{} name:\"{}\" type:\"{}\"\n".format(self.id, self.name, self.event_type) + event_info += " property_count:{} \n params:[".format(self.event_property_count) + + for field in self.event_properties: + event_info += "\n para:{} type:{}".format(field.id, field.type_id) + + event_info += "\n ]" + return event_info + + def gen_sigle_event_info(self): + resault = "" + event_para_info = "" + event_property_info = "" + event_var_info = "" + for field in self.event_properties: + event_para_info += "static {}\n".format(field.get_global_field_declare()) + event_property_info += "\n {" + if field.type_id == "TYPE_TEMPLATE_STRING": + event_property_info += ".key = \"{}\", .data = sg_{}, .type = {}".format(field.id, field.id, field.type_id) + else: + event_property_info += ".key = \"{}\", .data = &sg_{}, .type = {}".format(field.id, field.id, field.type_id) + event_property_info += "}," + event_var_info += "static DeviceProperty g_propertyEvent_{}[] = ".format(self.id) + resault += event_para_info + event_var_info + "{\n"+event_property_info + "\n};\n" + return resault + + + +class iot_struct: + def __init__(self, model): + self.version = model["version"] + self.fields = [] + self.field_id = 0 + self.events = [] + self.event_id = 0 + for field_define in model["properties"]: + if TEMPLATE_CONSTANTS.NAME not in field_define: + raise ValueError("错误:字段定义中未找到 Name 字段") + self.fields.append(iot_field(field_define["id"], field_define["name"], self.field_id, field_define)) + self.field_id += 1 + + for event in model["events"]: + if TEMPLATE_CONSTANTS.NAME not in event: + raise ValueError("错误:字段定义中未找到 Name 字段") + self.events.append(iot_event(event["id"], event["name"], self.event_id, event)) + self.event_id += 1 + + + def dump_data_info(self): + print("dump iot struct,counts:{}".format(self.field_id)) + for temp_field in self.fields: + if temp_field.type_name == "enum": + print("{} {} {} {} ".format(temp_field.id, temp_field.type_name, temp_field.default_value, temp_field.type_define)) + print("enums:{") + for enum in temp_field.enums: + print("{} ".format(enum.get_c_macro_name())) + print("}") + else: + print("{} {} {} {}\n".format(temp_field.id, temp_field.type_name, temp_field.default_value, + temp_field.type_define)) + def dump_event_info(self): + count = 0 + event_str = "" + event_str += ("#define EVENT_COUNTS ({})\n").format(self.event_id) + for event_d in self.events: + event_str += "{}\n".format(event_d.gen_sigle_event_info()) + count += 1 + return event_str + + def data_config_macro_define(self, struct_Template="sDataPoint",var_gTemplate="sg_DataTemplate"): + define_str = "" + define_str += "/*-----------------data config start -------------------*/ \n\n" + define_str += "#define TOTAL_PROPERTY_COUNT {}\n\n".format(self.field_id) + define_str += "static {} {}[TOTAL_PROPERTY_COUNT];\n\n".format(struct_Template, var_gTemplate) + return define_str + + def declare_product_data_struct(self, struct_name="ProductDataDefine", var_gname="sg_ProductData"): + result = "" + result += "typedef struct _" + struct_name + " {\n" + for field in self.fields: + result += " {}\n".format(field.get_struct_field_declare()) + result += "} " + struct_name + ";\n\n" + result += "static " + struct_name + " "+var_gname + ";\n\n" + return result + + def property_data_initializer(self, struct_name="ProductDataDefine", var_gProduct="sg_ProductData", var_gTemplate="sg_DataTemplate"): + count = 0 + init_str = "" + init_str += "static void _init_data_template(void)\n{\n" + #init_str += " memset((void *) & {}, 0, sizeof({}));\n".format(var_gProduct, struct_name) + + for field in self.fields: + + if field.type_define == "TYPE_DEF_TEMPLATE_STRING": + init_str += " {}.{}[0] = {};\n".format(var_gProduct, field.get_id_c_member_name(), "'\\0'") + init_str += " {}[{}].data_property.data = {}.{};\n".format(var_gTemplate, count, var_gProduct, field.get_id_c_member_name()) + else: + init_str += " {}.{} = {};\n".format(var_gProduct, field.get_id_c_member_name(),field.get_id_default_value()) + init_str += " {}[{}].data_property.data = &{}.{};\n".format(var_gTemplate, count, var_gProduct, field.get_id_c_member_name()) + init_str += " {}[{}].data_property.key = \"{}\";\n".format(var_gTemplate, count, field.id) + init_str += " {}[{}].data_property.type = {};\n\n".format(var_gTemplate, count, field.type_id) + count += 1 + init_str += "};\n" + return init_str; + + def gen_data_config(self): + data_config = "" + data_config +="{}".format(self.data_config_macro_define()) + data_config +="{}".format(self.declare_product_data_struct()) + data_config += "{}".format(self.property_data_initializer()) + return data_config + + def gen_event_config(self): + resault = "" + event_config = "" + events_var = "" + event_str = "" + + event_config += ("\n#define EVENT_COUNTS ({})\n\n").format(self.event_id) + events_var += "\nstatic sEvent g_events[]={\n" + for event_d in self.events: + event_config += "{}\n".format(event_d.gen_sigle_event_info()) + event_str += "\n {" + event_str += "\n .event_name = \"{}\",".format(event_d.id) + event_str += "\n .type = \"{}\",".format(event_d.event_type) + event_str += "\n .timestamp = 0," + event_str += "\n .eventDataNum = sizeof(g_propertyEvent_{})/sizeof(g_propertyEvent_{}[0]),".format(event_d.id, event_d.id) + event_str += "\n .pEventData = g_propertyEvent_{},".format(event_d.id) + event_str +="\n }," + resault += event_config + events_var + event_str + "\n};\n" + return resault + + +def main(): + parser = argparse.ArgumentParser(description='Iothub datatemplate and events config code generator.', usage='use "./codegen.py -c xx/config.json" gen config code') + parser.add_argument('-c','--config', dest='config',metavar='xxx.json', required=False,default='xxx.json', + help='copy the generated file (data_config.c and events_config.c) to datatemplate_sample dir ' + 'or your own code dir with datatemplate. ' + '\nconfig file can be download from tencent iot-hub platfrom. https://console.cloud.tencent.com/iotcloud') + parser.add_argument('-d','--dest', dest='dest', required=False,default='.', + help='Dest directory for generated code files, no / at the end.') + + args = parser.parse_args() + + config_path = args.config + if not os.path.exists(config_path): + print(u"错误:配置文件不存在,请重新指定数据模板配置文件路径,请参考用法 ./codegen.py -c xx/data_template.json".format(config_path)) + return 1 + + config_dir = os.path.dirname(config_path) + if config_dir: + config_dir += "/" + + f = open(config_path, "r") + try: + thingmodel = json.load(f) + if 'properties' not in thingmodel: + thingmodel.properties = [] + + if 'events' not in thingmodel: + thingmodel.events = [] + + print(u"加载 {} 文件成功".format(config_path)) + except ValueError as e: + print(u"错误:文件格式非法,请检查 {} 文件是否是 JSON 格式。".format(config_path)) + return 1 + + if TEMPLATE_CONSTANTS.PROPERTIES not in thingmodel: + print(u"错误:{} 文件中未发现 DataTemplate 属性字段,请检查文件格式是否合法。".format(config_path)) + return 1 + + try: + snippet = iot_struct(thingmodel) + + output_data_config_file_name = args.dest + "/data_config.c" + output_file = open(output_data_config_file_name, "w") + output_file.write("{}".format(snippet.gen_data_config())) + output_file.close() + + output_event_config_file_name = args.dest + "/events_config.c" + output_file = open(output_event_config_file_name, "w") + output_file.write("#ifdef EVENT_POST_ENABLED\n{}\n#endif\n".format(snippet.gen_event_config())) + output_file.close() + + + print(u"文件 {} 生成成功".format(output_data_config_file_name)) + print(u"文件 {} 生成成功".format(output_event_config_file_name)) + + return 0 + except ValueError as e: + print(e) + return 1 + + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/tools/example_config.json b/tools/example_config.json new file mode 100755 index 00000000..3dfd4f97 --- /dev/null +++ b/tools/example_config.json @@ -0,0 +1,230 @@ +{ + "version": "1.0", + "properties": [ + { + "id": "time", + "name": "time", + "required": false, + "desc": "", + "mode": "rw", + "define": { + "type": "timestamp" + } + }, + { + "id": "float", + "name": "float", + "required": false, + "desc": "", + "mode": "r", + "define": { + "type": "float", + "min": "-10", + "max": "10", + "start": "-5", + "step": "0.5", + "unit": "cm" + } + }, + { + "id": "light_switch", + "name": "电灯开关", + "required": true, + "desc": "控制电灯开灭", + "mode": "rw", + "define": { + "type": "bool", + "mapping": { + "0": "关", + "1": "开" + } + } + }, + { + "id": "color", + "name": "颜色", + "desc": "灯光颜色", + "mode": "rw", + "define": { + "type": "enum", + "mapping": { + "0": "Red", + "1": "Green", + "2": "Blue" + } + } + }, + { + "id": "brightness", + "name": "亮度", + "required": false, + "desc": "灯光亮度", + "mode": "rw", + "define": { + "type": "int", + "min": "-9", + "max": "100", + "start": "-1", + "step": "5", + "unit": "cm" + } + }, + { + "id": "name", + "name": "灯位置名称", + "desc": "灯位置名称:书房、客厅等", + "mode": "rw", + "required": true, + "define": { + "type": "string", + "min": "1", + "max": "64" + } + } + ], + "events": [ + { + "id": "all_function", + "name": "ALL_FUNCTION", + "required": false, + "desc": "", + "params": [ + { + "id": "bool", + "name": "bool", + "desc": "", + "define": { + "type": "bool", + "mapping": { + "0": "关", + "1": "开" + } + } + }, + { + "id": "int", + "name": "int", + "desc": "", + "define": { + "type": "int", + "min": "1", + "max": "100", + "start": "1", + "step": "1", + "unit": "cm" + } + }, + { + "id": "str", + "name": "str", + "desc": "", + "define": { + "type": "string", + "min": "1", + "max": "64" + } + }, + { + "id": "float", + "name": "float", + "desc": "", + "define": { + "type": "float", + "min": "0", + "max": "100", + "start": "0", + "step": "1.5", + "unit": "cm" + } + }, + { + "id": "enum1", + "name": "enum1", + "desc": "", + "define": { + "type": "enum", + "mapping": { + "0": "color", + "1": "door" + } + } + }, + { + "id": "time", + "name": "time", + "desc": "", + "define": { + "type": "timestamp" + } + } + ], + "type": "alert" + }, + { + "id": "status_report", + "name": "DeviceStatus", + "desc": "Report the device status我是中文", + "type": "info", + "required": true, + "params": [ + { + "id": "status", + "name": "running_state", + "desc": "Report current device running state", + "define": { + "type": "bool", + "mapping": { + "0": "normal", + "1": "fault" + } + } + }, + { + "id": "message", + "name": "Message", + "desc": "Some extra message", + "define": { + "type": "string", + "min": "1", + "max": "64" + } + } + ] + }, + { + "id": "hardware_fault", + "name": "Hardware_fault", + "required": false, + "desc": "Report hardware fault", + "params": [ + { + "id": "name", + "name": "Name", + "desc": "Name like: memory,tf card, censors ...", + "define": { + "type": "string", + "min": "1", + "max": "64" + } + }, + { + "id": "error_code", + "name": "Error_Code", + "desc": "Error code for fault", + "define": { + "type": "int", + "unit": "", + "step": "1", + "min": "0", + "max": "2000", + "start": "0" + } + } + ], + "type": "fault" + } + ], + "profile": { + "productID": "C0NEMO9UO0" + } +} \ No newline at end of file diff --git a/tools/run-clang-tidy b/tools/run-clang-tidy new file mode 100755 index 00000000..f5776896 --- /dev/null +++ b/tools/run-clang-tidy @@ -0,0 +1,296 @@ +#!/usr/bin/env python +# +#===- run-clang-tidy.py - Parallel clang-tidy runner ---------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# FIXME: Integrate with clang-tidy-diff.py + +""" +Parallel clang-tidy runner +========================== + +Runs clang-tidy over all files in a compilation database. Requires clang-tidy +and clang-apply-replacements in $PATH. + +Example invocations. +- Run clang-tidy on all files in the current working directory with a default + set of checks and show warnings in the cpp files and all project headers. + run-clang-tidy.py $PWD + +- Fix all header guards. + run-clang-tidy.py -fix -checks=-*,llvm-header-guard + +- Fix all header guards included from clang-tidy and header guards + for clang-tidy headers. + run-clang-tidy.py -fix -checks=-*,llvm-header-guard extra/clang-tidy \ + -header-filter=extra/clang-tidy + +Compilation database setup: +http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html +""" + +from __future__ import print_function + +import argparse +import glob +import json +import multiprocessing +import os +import re +import shutil +import subprocess +import sys +import tempfile +import threading +import traceback +import yaml + +is_py2 = sys.version[0] == '2' + +if is_py2: + import Queue as queue +else: + import queue as queue + +def find_compilation_database(path): + """Adjusts the directory until a compilation database is found.""" + result = './' + while not os.path.isfile(os.path.join(result, path)): + if os.path.realpath(result) == '/': + print('Error: could not find compilation database.') + sys.exit(1) + result += '../' + return os.path.realpath(result) + + +def make_absolute(f, directory): + if os.path.isabs(f): + return f + return os.path.normpath(os.path.join(directory, f)) + + +def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path, + header_filter, extra_arg, extra_arg_before, quiet): + """Gets a command line for clang-tidy.""" + start = [clang_tidy_binary] + if header_filter is not None: + start.append('-header-filter=' + header_filter) + else: + # Show warnings in all in-project headers by default. + start.append('-header-filter=^' + build_path + '/.*') + if checks: + start.append('-checks=' + checks) + if tmpdir is not None: + start.append('-export-fixes') + # Get a temporary file. We immediately close the handle so clang-tidy can + # overwrite it. + (handle, name) = tempfile.mkstemp(suffix='.yaml', dir=tmpdir) + os.close(handle) + start.append(name) + for arg in extra_arg: + start.append('-extra-arg=%s' % arg) + for arg in extra_arg_before: + start.append('-extra-arg-before=%s' % arg) + start.append('-p=' + build_path) + if quiet: + start.append('-quiet') + start.append(f) + return start + + +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # The fixes suggested by clang-tidy >= 4.0.0 are given under + # the top level key 'Diagnostics' in the output yaml files + mergekey="Diagnostics" + merged=[] + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): + content = yaml.safe_load(open(replacefile, 'r')) + if not content: + continue # Skip empty files. + merged.extend(content.get(mergekey, [])) + + if merged: + # MainSourceFile: The key is required by the definition inside + # include/clang/Tooling/ReplacementsYaml.h, but the value + # is actually never used inside clang-apply-replacements, + # so we set it to '' here. + output = { 'MainSourceFile': '', mergekey: merged } + with open(mergefile, 'w') as out: + yaml.safe_dump(output, out) + else: + # Empty the file: + open(mergefile, 'w').close() + + +def check_clang_apply_replacements_binary(args): + """Checks if invoking supplied clang-apply-replacements binary works.""" + try: + subprocess.check_call([args.clang_apply_replacements_binary, '--version']) + except: + print('Unable to run clang-apply-replacements. Is clang-apply-replacements ' + 'binary correctly specified?', file=sys.stderr) + traceback.print_exc() + sys.exit(1) + + +def apply_fixes(args, tmpdir): + """Calls clang-apply-fixes on a given directory.""" + invocation = [args.clang_apply_replacements_binary] + if args.format: + invocation.append('-format') + if args.style: + invocation.append('-style=' + args.style) + invocation.append(tmpdir) + subprocess.call(invocation) + + +def run_tidy(args, tmpdir, build_path, queue): + """Takes filenames out of queue and runs clang-tidy on them.""" + while True: + name = queue.get() + invocation = get_tidy_invocation(name, args.clang_tidy_binary, args.checks, + tmpdir, build_path, args.header_filter, + args.extra_arg, args.extra_arg_before, + args.quiet) + sys.stdout.write(' '.join(invocation) + '\n') + subprocess.call(invocation) + queue.task_done() + + +def main(): + parser = argparse.ArgumentParser(description='Runs clang-tidy over all files ' + 'in a compilation database. Requires ' + 'clang-tidy and clang-apply-replacements in ' + '$PATH.') + parser.add_argument('-clang-tidy-binary', metavar='PATH', + default='clang-tidy-6.0', + help='path to clang-tidy binary') + parser.add_argument('-clang-apply-replacements-binary', metavar='PATH', + default='clang-apply-replacements-6.0', + help='path to clang-apply-replacements binary') + parser.add_argument('-checks', default=None, + help='checks filter, when not specified, use clang-tidy ' + 'default') + parser.add_argument('-header-filter', default=None, + help='regular expression matching the names of the ' + 'headers to output diagnostics from. Diagnostics from ' + 'the main file of each translation unit are always ' + 'displayed.') + parser.add_argument('-export-fixes', metavar='filename', dest='export_fixes', + help='Create a yaml file to store suggested fixes in, ' + 'which can be applied with clang-apply-replacements.') + parser.add_argument('-j', type=int, default=0, + help='number of tidy instances to be run in parallel.') + parser.add_argument('files', nargs='*', default=['.*'], + help='files to be processed (regex on path)') + parser.add_argument('-fix', action='store_true', help='apply fix-its') + parser.add_argument('-format', action='store_true', help='Reformat code ' + 'after applying fixes') + parser.add_argument('-style', default='file', help='The style of reformat ' + 'code after applying fixes') + parser.add_argument('-p', dest='build_path', + help='Path used to read a compile command database.') + parser.add_argument('-extra-arg', dest='extra_arg', + action='append', default=[], + help='Additional argument to append to the compiler ' + 'command line.') + parser.add_argument('-extra-arg-before', dest='extra_arg_before', + action='append', default=[], + help='Additional argument to prepend to the compiler ' + 'command line.') + parser.add_argument('-quiet', action='store_true', + help='Run clang-tidy in quiet mode') + args = parser.parse_args() + + db_path = 'compile_commands.json' + + if args.build_path is not None: + build_path = args.build_path + else: + # Find our database + build_path = find_compilation_database(db_path) + + try: + invocation = [args.clang_tidy_binary, '-list-checks'] + invocation.append('-p=' + build_path) + if args.checks: + invocation.append('-checks=' + args.checks) + invocation.append('-') + subprocess.check_call(invocation) + except: + print("Unable to run clang-tidy.", file=sys.stderr) + sys.exit(1) + + # Load the database and extract all files. + database = json.load(open(os.path.join(build_path, db_path))) + files = [make_absolute(entry['file'], entry['directory']) + for entry in database] + + max_task = args.j + if max_task == 0: + max_task = multiprocessing.cpu_count() + + tmpdir = None + if args.fix or args.export_fixes: + check_clang_apply_replacements_binary(args) + tmpdir = tempfile.mkdtemp() + + # Build up a big regexy filter from all command line arguments. + file_name_re = re.compile('|'.join(args.files)) + + try: + # Spin up a bunch of tidy-launching threads. + task_queue = queue.Queue(max_task) + for _ in range(max_task): + t = threading.Thread(target=run_tidy, + args=(args, tmpdir, build_path, task_queue)) + t.daemon = True + t.start() + + # Fill the queue with files. + for name in files: + if file_name_re.search(name): + task_queue.put(name) + + # Wait for all threads to be done. + task_queue.join() + + except KeyboardInterrupt: + # This is a sad hack. Unfortunately subprocess goes + # bonkers with ctrl-c and we start forking merrily. + print('\nCtrl-C detected, goodbye.') + if tmpdir: + shutil.rmtree(tmpdir) + os.kill(0, 9) + + return_code = 0 + if args.export_fixes: + print('Writing fixes to ' + args.export_fixes + ' ...') + try: + merge_replacement_files(tmpdir, args.export_fixes) + except: + print('Error exporting fixes.\n', file=sys.stderr) + traceback.print_exc() + return_code=1 + + if args.fix: + print('Applying fixes ...') + try: + apply_fixes(args, tmpdir) + except: + print('Error applying fixes.\n', file=sys.stderr) + traceback.print_exc() + return_code=1 + + if tmpdir: + shutil.rmtree(tmpdir) + sys.exit(return_code) + +if __name__ == '__main__': + main() diff --git a/tools/update_from_old_SDK.sh b/tools/update_from_old_SDK.sh new file mode 100755 index 00000000..861be043 --- /dev/null +++ b/tools/update_from_old_SDK.sh @@ -0,0 +1,22 @@ +#! /bin/bash + +sed -i "s/QCLOUD_ERR_SUCCESS/QCLOUD_RET_SUCCESS/g" `grep -rwl QCLOUD_ERR_SUCCESS ./*` +sed -i "s/QCLOUD_ERR_MQTT_RECONNECTED/QCLOUD_RET_MQTT_RECONNECTED/g" `grep -rwl QCLOUD_ERR_MQTT_RECONNECTED ./*` +sed -i "s/QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED/QCLOUD_RET_MQTT_MANUALLY_DISCONNECTED/g" `grep -rwl QCLOUD_ERR_MQTT_MANUALLY_DISCONNECTED ./*` +sed -i "s/QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED/QCLOUD_RET_MQTT_CONNACK_CONNECTION_ACCEPTED/g" `grep -rwl QCLOUD_ERR_MQTT_CONNACK_CONNECTION_ACCEPTED ./*` +sed -i "s/QCLOUD_ERR_MQTT_ALREADY_CONNECTED/QCLOUD_RET_MQTT_ALREADY_CONNECTED/g" `grep -rwl QCLOUD_ERR_MQTT_ALREADY_CONNECTED ./*` +sed -i "s/MAX_SIZE_OF_DEVICE_SERC/MAX_SIZE_OF_DEVICE_SECRET/g" `grep -rwl MAX_SIZE_OF_DEVICE_SERC ./*` +sed -i "s/devCertFileName/dev_cert_file_name/g" `grep -rwl devCertFileName ./*` +sed -i "s/devPrivateKeyFileName/dev_key_file_name/g" `grep -rwl devPrivateKeyFileName ./*` +sed -i "s/devSerc/device_secret/g" `grep -rwl devSerc ./*` +sed -i "s/MAX_SIZE_OF_PRODUCT_KEY/MAX_SIZE_OF_PRODUCT_SECRET/g" `grep -rwl MAX_SIZE_OF_PRODUCT_KEY ./*` +sed -i "s/product_key/product_secret/g" `grep -rwl product_key ./*` +sed -i "s/DEBUG/eLOG_DEBUG/g" `grep -rwl DEBUG ./*` +sed -i "s/INFO/eLOG_INFO/g" `grep -rwl INFO ./*` +sed -i "s/WARN/eLOG_WARN/g" `grep -rwl WARN ./*` +sed -i "s/ERROR/eLOG_ERROR/g" `grep -rwl ERROR ./*` +sed -i "s/DISABLE/eLOG_DISABLE/g" `grep -rwl DISABLE ./*` +sed -i "s/Log_writter/IOT_Log_Gen/g" `grep -rwl Log_writter ./*` +sed -i "s/qcloud_iot_dyn_reg_dev/IOT_DynReg_Device/g" `grep -rwl qcloud_iot_dyn_reg_dev ./*` +sed -i "s/IOT_SYSTEM_GET_TIME/IOT_Get_SysTime/g" `grep -rwl IOT_SYSTEM_GET_TIME ./*` +