diff --git a/code/application/sifarsdk/.gitignore b/code/application/sifarsdk/.gitignore new file mode 100644 index 000000000..359a83f9b --- /dev/null +++ b/code/application/sifarsdk/.gitignore @@ -0,0 +1,10 @@ +.vscode +cmake-shell-linux/ +external/gtest/googletest-release-1.11.0/ +external/openssl/openssl-1.1.1s/ +external/openssl/openssl-3.1.0/ +external/openssl/build/ +external/curl/curl-8.1.2/ +test/testReport/allTest +test/testReport/allTest.html +out/ \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/333DE_design.md b/code/application/sifarsdk/333DE/333DE_design.md new file mode 100644 index 000000000..e34c266a1 --- /dev/null +++ b/code/application/sifarsdk/333DE/333DE_design.md @@ -0,0 +1,19 @@ +# 1. Sigmastart平台333DE芯片设计文档 + +## 1.1. 概述 +   在SifarSDK的基础上,进行跨平台的代码适配设计和开发。 + +## 1.2. UML类图 + +## 1.3. 双核机制 + +### 1.3.1. rtos的参数怎么传递给linux? +一共有3种类型的宏定义 +1. CONFIG_IOCTL_MSYS_GET_MODULE_HW_PHY//配置此参数可传给linux(是否配置此功能);kernel\drivers\sstar\msys,ms_msys.c里定义 +2. IOCTL_MSYS_GET_MODULE_DATA,2处需要定义(内存地址的标识号) +alkaid/kernel/drivers/sstar/include/mdrv_msys_io.h; +alkaid/sdk/verify/Cardvimpl/cardv/inc/module_common.h +ms_msys.c使用,linux下module_video.cpp使用 +1. INTEROS_SC_R2L_MODULE_HW_PHY,2处需要定义(共享内存的地址) +kernel\drivers\sstar\msys,ms_msys.c 里定义和使用 +rtk\proj\sc\application\rtos_preload,rtos_preload.c 里定义和使用 \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/CMakeLists.txt b/code/application/sifarsdk/333DE/CMakeLists.txt new file mode 100644 index 000000000..4eb7e272a --- /dev/null +++ b/code/application/sifarsdk/333DE/CMakeLists.txt @@ -0,0 +1,14 @@ + +# cmake_minimum_required(VERSION 2.8.0) + +link_directories( + ${LIBS_OUTPUT_PATH} + ${PLATFORM_PATH}/lib/mi_libs/static + ${PLATFORM_PATH}/lib/ex_libs/static +) + +add_subdirectory(application) +add_subdirectory(hal) +add_subdirectory(test) + + diff --git a/code/application/sifarsdk/333DE/Makefile b/code/application/sifarsdk/333DE/Makefile new file mode 100644 index 000000000..c42e70794 --- /dev/null +++ b/code/application/sifarsdk/333DE/Makefile @@ -0,0 +1,9 @@ +cmake: + $(MAKE) -C ./build/cmake all +all:cmake + $(MAKE) -C ../cmake-shell-linux all +sf_cs_app:cmake + $(MAKE) -C ../cmake-shell-linux sf_cs_app + $(MAKE) -C ../cmake-shell-linux SifarSDK_libs +clean: + $(MAKE) -C ../ clean \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/README.md b/code/application/sifarsdk/333DE/README.md new file mode 100644 index 000000000..cccb60a26 --- /dev/null +++ b/code/application/sifarsdk/333DE/README.md @@ -0,0 +1,37 @@ +# 1. 333DE芯片平台代码工程 + +## 1.1. 概述 +   该目录存放333DE芯片平台的代码,主要是依赖原厂SDK接口的适配代码。该目录必须依赖SifarSDK源码目录才能完成项目构建。 + + +   详见333DE_design.md + + +## 1.2. 编译: +工程师在开发应用程序时使用下述指令进行编译。在333DE目录下执行命令: + +make cmake + +cd ../cmake-shell-linux/ + +make + +## 1.3. 一键编译并拷贝输出文件 + +芯片SDK依赖SifarSDK构建烧录文件时,遵循下述流程: +1. 拉取SifarSDK源码,在SDK的存放目录没有限制; +2. 需要在合适的编译环节编译SifarSDK,在cmake-shell-linux目录执行make sf_cs_app即可;此时生成sf_cs_app可执行文件在out/bin/目录下; +3. 芯片SDK拷贝out/bin/sf_cs_app到打包目录,并根据芯片打包脚本进行烧录文件打包; + +Makefile解析: +``` +cmake: + $(MAKE) -C ./build/cmake all +all:cmake + $(MAKE) -C ../cmake-shell-linux all +sf_cs_app:cmake // 芯片SDK可编译此目标完成可执行文件和依赖库的输出 + $(MAKE) -C ../cmake-shell-linux sf_cs_app + $(MAKE) -C ../cmake-shell-linux SifarSDK_libs +clean: + $(MAKE) -C ../ clean +``` \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/application/CMakeLists.txt b/code/application/sifarsdk/333DE/application/CMakeLists.txt new file mode 100644 index 000000000..5c94b2c85 --- /dev/null +++ b/code/application/sifarsdk/333DE/application/CMakeLists.txt @@ -0,0 +1,5 @@ + +# cmake_minimum_required(VERSION 2.8.0) +add_subdirectory(main) + + diff --git a/code/application/sifarsdk/333DE/application/main/CMakeLists.txt b/code/application/sifarsdk/333DE/application/main/CMakeLists.txt new file mode 100644 index 000000000..25923f6af --- /dev/null +++ b/code/application/sifarsdk/333DE/application/main/CMakeLists.txt @@ -0,0 +1,38 @@ +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${PLATFORM_PATH}/application/main/src" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${PLATFORM_PATH}/hal/include" CACHE STRING INTERNAL FORCE) +include_directories( + ${MAIN_INCLUDE_PATH} +) + +link_directories( + ${LIBS_OUTPUT_PATH} + ${PLATFORM_PATH}/lib/mi_libs/static +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) + +file(GLOB_RECURSE MAIN_SRC_FILE_THIS src/*.cpp src/*.c) +set(MAIN_SRC_FILE "${MAIN_SRC_FILE};${MAIN_SRC_FILE_THIS}" CACHE STRING INTERNAL FORCE) + +set(TARGET_NAME hunting_333DE) +add_executable(${TARGET_NAME} ${SRC_FILES} ${MAIN_SRC_FILE}) + +# set(LINK_LIB HalChipBoard) +set(MAIN_LINK_LIB "${MAIN_LINK_LIB};${LINK_LIB}" CACHE STRING INTERNAL FORCE) +target_link_libraries(${TARGET_NAME} ${MAIN_LINK_LIB} HalChipBoard) + +add_custom_target( + sf_cs_app + COMMAND echo "Make sf_cs_app." + DEPENDS hunting_333DE + COMMAND arm-linux-gnueabihf-9.1.0-strip ${EXEC_OUTPUT_PATH}/* + COMMAND cp ${EXEC_OUTPUT_PATH}/hunting_333DE ${EXEC_OUTPUT_PATH}/sf_cs_app + WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/ +) \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/application/main/main.cpp b/code/application/sifarsdk/333DE/application/main/main.cpp new file mode 100644 index 000000000..5aeff6ec8 --- /dev/null +++ b/code/application/sifarsdk/333DE/application/main/main.cpp @@ -0,0 +1,25 @@ +#include "MainThread.h" +#include "Log.h" +#include "ChipBoardMainThread.h" +#include +#include + +static void OpenCustomizationMainThread(void) +{ +} +static void ReleaseCustomizationMainThread(void) +{ +} +int main(int argc, char *argv[]) +{ + std::shared_ptr mainThread = std::make_shared(); + MainThread::GetInstance(&mainThread); + + OpenCustomizationMainThread(); + MainThread::GetInstance()->Init(); + LogInfo("333DE start.\n"); + MainThread::GetInstance()->Runing(); + MainThread::GetInstance()->UnInit(); + ReleaseCustomizationMainThread(); + return 0; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/application/main/src/ChipBoardMainThread.cpp b/code/application/sifarsdk/333DE/application/main/src/ChipBoardMainThread.cpp new file mode 100644 index 000000000..4b083657a --- /dev/null +++ b/code/application/sifarsdk/333DE/application/main/src/ChipBoardMainThread.cpp @@ -0,0 +1,6 @@ +#include "ChipBoardMainThread.h" +#include "IHal333DE.h" +void ChipBoardMainThread::CustomizationInit(void) +{ + Hal333DEMakePtrOverride(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/application/main/src/ChipBoardMainThread.h b/code/application/sifarsdk/333DE/application/main/src/ChipBoardMainThread.h new file mode 100644 index 000000000..86e960c2b --- /dev/null +++ b/code/application/sifarsdk/333DE/application/main/src/ChipBoardMainThread.h @@ -0,0 +1,11 @@ +#ifndef CHIP_BOARD_MAIN_THREAD_H +#define CHIP_BOARD_MAIN_THREAD_H +#include "MainThread.h" +class ChipBoardMainThread : public MainThread +{ +public: + ChipBoardMainThread() = default; + ~ChipBoardMainThread() = default; + void CustomizationInit(void) override; +}; +#endif // !CHIP_BOARD_MAIN_THREAD_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/build/README.md b/code/application/sifarsdk/333DE/build/README.md new file mode 100644 index 000000000..d5b15466f --- /dev/null +++ b/code/application/sifarsdk/333DE/build/README.md @@ -0,0 +1,3 @@ +# cmake编译配置 +## 目录 +./toolchain:配置交叉编译工具链 \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/build/cmake/Makefile b/code/application/sifarsdk/333DE/build/cmake/Makefile new file mode 100644 index 000000000..e71f1eb1e --- /dev/null +++ b/code/application/sifarsdk/333DE/build/cmake/Makefile @@ -0,0 +1,8 @@ +all: + @mkdir -p ../../../cmake-shell-linux;\ + cd ../../../cmake-shell-linux;\ + pwd;\ + cmake -DCMAKE_TOOLCHAIN_FILE="./333DE/build/cmake/toolchain/sigmastart_333DE.toolchain.cmake" ..;\ + cd .. +clean: + rm -rf ../../cmake-shell-linux \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/build/cmake/README.md b/code/application/sifarsdk/333DE/build/cmake/README.md new file mode 100644 index 000000000..97dfa0045 --- /dev/null +++ b/code/application/sifarsdk/333DE/build/cmake/README.md @@ -0,0 +1,2 @@ +# cmake + diff --git a/code/application/sifarsdk/333DE/build/cmake/toolchain/sigmastart_333DE.toolchain.cmake b/code/application/sifarsdk/333DE/build/cmake/toolchain/sigmastart_333DE.toolchain.cmake new file mode 100644 index 000000000..c97ee3605 --- /dev/null +++ b/code/application/sifarsdk/333DE/build/cmake/toolchain/sigmastart_333DE.toolchain.cmake @@ -0,0 +1,56 @@ + +INCLUDE(CMakeForceCompiler) + +set(CMAKE_C_COMPILER arm-linux-gnueabihf-9.1.0-gcc) +set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-9.1.0-g++) +# set(CMAKE_C_COMPILER gcc) +# set(CMAKE_CXX_COMPILER g++) + + +# path to compiler and utilities +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + + + + +# Name of the target platform +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm) + +# Version of the system +set(CMAKE_SYSTEM_VERSION 1) + + +add_definitions(-Wall -O2 -Os) +add_definitions(-Wno-unused-local-typedefs) +add_definitions(-Wstrict-aliasing -Wwrite-strings) + + +set(TOOLCHAIN_NAME arm-linux-gnueabihf) + +set(PROJECT_333DE_PATH "${CMAKE_SOURCE_DIR}") +set(TARGET_PLATFORM "sigmastart_333DE") +# set(TARGET_PLATFORM "linux") +set(PLATFORM_PATH "${CMAKE_SOURCE_DIR}/333DE") +set(AT_COMMAND_PATH "${CMAKE_SOURCE_DIR}/at-command/eg91") +set(COVERAGE_ON "false") +set(LIVE_PLATFORM_SRC_PATH "ali_live") +set(AT_COMMAND_SRC_PATH "eg91") +set(CONFIG_FILE_PATH "/misc/sfSysParm.bin") +set(CONFIG_FILE_STATIC_PATH "/mnt/mmc/DCIM/THUMB/sfStatisticsParm.bin") +set(SF_DCF_EXT_PHOTO "jpg") +set(SF_DCF_EXT_MOV "mp4") +set(SF_SD_ROOT "/mnt/mmc/") +set(SF_DCF_DIR_NAME_SUFFIX "SYCAM") +set(SF_DCF_ROOT_DIR_NAME "DCIM") +set(SF_DCF_THM_DIR_NAME "THUMB") +set(SF_DCF_FILE_NAME_PREFIX "HRTP") + + +# ------------ build curl + openssl ------------ start +set(CROSS_COMPILE_PREFIX "arm-linux-gnueabihf-9.1.0-") +set(CURL_OPENSSL_LIB_SHARED_ENABLE "false") +set(CURL_SHARED_LIBS_PATH "/mnt/mmc") +# ------------ build curl + openssl ------------ end \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/build_333de.sh b/code/application/sifarsdk/333DE/build_333de.sh new file mode 100755 index 000000000..efd869a42 --- /dev/null +++ b/code/application/sifarsdk/333DE/build_333de.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# 编译打猎相机并拷贝输出文件到指定目录 +# 用法:./build_333de.sh + path +# example: ./build_333de.sh /home/xiaojiazhu/project_codes/sifarsdk +# CP_PATH=$1 +# echo "Compile 333DE, target will copy to = $CP_PATH." +export ROOT_PATH=$PWD +make clean; +make cmake; +cd ../cmake-shell-linux; +make sf_cs_app -j8; +make SifarSDK_libs +# SIFARSDK_OUT=$CP_PATH/SifarSDK_output +# SIFARSDK_INCLUDE=$SIFARSDK_OUT/include +# SIFARSDK_CONFIG=$SIFARSDK_OUT/Config +# SIFARSDK_LIBS=$SIFARSDK_OUT/libs +# SIFARSDK_BIN=$SIFARSDK_OUT/bin +# mkdir $SIFARSDK_OUT +# mkdir $SIFARSDK_INCLUDE +# mkdir $SIFARSDK_CONFIG +# mkdir $SIFARSDK_LIBS +# mkdir $SIFARSDK_BIN +# cp ../out/bin/sf_cs_app $SIFARSDK_BIN +# cp ../out/libs/libReturnCode.a $SIFARSDK_LIBS +# cp ../out/libs/libLog.a $SIFARSDK_LIBS +# cp ../out/libs/libConfig.a $SIFARSDK_LIBS +# cp ../component/Config/include/* $SIFARSDK_INCLUDE +# cp ../component/Config/README.md $SIFARSDK_CONFIG +cd $ROOT_PATH +# echo "Target was copied to = $CP_PATH." +echo "Exit build_gtest.sh." \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/CMakeLists.txt b/code/application/sifarsdk/333DE/hal/CMakeLists.txt new file mode 100644 index 000000000..211e5ea5d --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/CMakeLists.txt @@ -0,0 +1,29 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./ + ${HAL_SOURCE_PATH} + ${HAL_SOURCE_PATH}/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/utils/include + ${PLATFORM_PATH}/lib/mi_libs/include +) +#do not rely on any other library +link_directories( + ${PLATFORM_PATH}/lib/mi_libs/static +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) + +set(TARGET_NAME HalChipBoard) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} Hal ReturnCode Log -Wl,--gc-sections -Wl,--start-group mi_venc mi_sys mi_ai cam_os_wrapper cam_fs_wrapper -Wl,--end-group) \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/CameraChip333DE.cpp b/code/application/sifarsdk/333DE/hal/CameraChip333DE.cpp new file mode 100644 index 000000000..912d18c8a --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/CameraChip333DE.cpp @@ -0,0 +1,393 @@ +#include "CameraChip333DE.h" +#include "IHalCommon.h" +#include "Log.h" +#include "SfTypeDefine.h" +#include +#include +CameraChip333DE::CameraChip333DE() : ShareMem("/tmp/sf_file") +{ + pThumbFileCfg = nullptr; + mOwnerStartedTask = false; + mAudioRuning = false; + mVideoRuning = false; +} +void CameraChip333DE::Init(void) +{ + ShareMem::Create(sizeof(SF_SRCFILE_ATTR_S)); + pThumbFileCfg = (SF_SRCFILE_ATTR_S *)ShareMem::Get(); + if (!pThumbFileCfg) + { + LogError("Creat share mem failed!!!\n"); + } + Message333DE::GetInstance()->SetCameraMessageHandle(shared_from_this()); +} +void CameraChip333DE::UnInit(void) +{ + ShareMem::Destory(); +} +void CameraChip333DE::CameraTaskMessageResponse(void) +{ + std::vector files; + if (pThumbFileCfg) + { + LogInfo("Count = %d.\n", pThumbFileCfg->filecnt); + for (int i = 0; i < pThumbFileCfg->filecnt; i++) + { + CameraFileMessage file; + LogInfo("enFileTye = %d.\n", pThumbFileCfg->stfileattr[i].enFileTye); + file.enFileTye = pThumbFileCfg->stfileattr[i].enFileTye; + file.mThumbFileName = pThumbFileCfg->stfileattr[i].thumbfileName; + file.mThumbFilePath = pThumbFileCfg->stfileattr[i].thumbfilePath; + files.push_back(file); + } + } + else + { + LogError("pThumbFileCfg is nullptr.\n"); + return; + } + if (!GetTaskRuning()) + { + LogInfo("Camera upload files spontaneously without owner send task."); + AddSpontaneousFiles(files); + return; + } + auto owner = mOwner.lock(); + if (!owner) + { + LogWarning("Owner is nullptr.\n"); + return; + } + if (mOwner.expired()) + { + LogWarning("Owner shared ptr expired failed.\n"); + return; + } + TaskFinshed(); + owner->CameraFinshTask(files); +} +RETURN_CODE CameraChip333DE::SetCameraOwner(std::shared_ptr &owner) +{ + mOwner = owner; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraChip333DE::StartSingleTask(const CameraTaskData &data) +{ + if (!SetTaskRuning()) + { + LogWarning("CameraChip333DE only run single task, please retry later.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + int result = -1; + // SF_MESSAGE_BUF_S stMessageBuf = {0}; + // stMessageBuf.cmdId = 0x0112; + // stMessageBuf.arg1 = data.mIsNight; + // Message333DE::GetInstance()->MessageQueueSend(&stMessageBuf); + signed char isNight = data.mIsNight; + Message333DE::GetInstance()->sf_cardv_message_send(0x0112, &(isNight), sizeof(isNight)); + switch (data.mType) + { + case CameraTaskType::PICTURE: + { + LogInfo("Camera task PICTURE\n"); + if (data.mMultiShot <= 1) + { + result = system("echo rtkmode 0 > /tmp/cardv_fifo"); + LogInfo("system result = %d\n", result); + } + else + { + result = system("echo rtkmode 2 > /tmp/cardv_fifo"); + LogInfo("system result = %d\n", result); + } + break; + } + case CameraTaskType::VIDEO: + { + LogInfo("Camera task VIDEO\n"); + result = system("echo rtkmode 3 > /tmp/cardv_fifo"); + LogInfo("system result = %d\n", result); + break; + } + case CameraTaskType::PICTURE_AND_VIDEO: + { + LogInfo("Camera task PICTURE_AND_VIDEO\n"); + if (data.mMultiShot <= 1) + { + result = system("echo rtkmode 4 > /tmp/cardv_fifo"); + LogInfo("system result = %d\n", result); + } + else + { + result = system("echo rtkmode 6 > /tmp/cardv_fifo"); + LogInfo("system result = %d\n", result); + } + break; + } + default: + break; + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +bool CameraChip333DE::SetTaskRuning(void) +{ + std::lock_guard locker(mMutex); + if (mOwnerStartedTask) + { + return false; + } + mOwnerStartedTask = true; + return true; +} +bool CameraChip333DE::GetTaskRuning(void) +{ + std::lock_guard locker(mMutex); + return mOwnerStartedTask; +} +void CameraChip333DE::TaskFinshed(void) +{ + std::lock_guard locker(mMutex); + mOwnerStartedTask = false; +} +void CameraChip333DE::AddSpontaneousFiles(const std::vector &files) +{ + std::lock_guard locker(mMutex); + std::copy(files.begin(), files.end(), std::back_inserter(mSpontaneousFiles)); +} +void CameraChip333DE::CheckSpontaneousFilesToUpload(void) +{ + std::lock_guard locker(mMutex); + if (mSpontaneousFiles.size() == 0) + { + return; + } + auto owner = mOwner.lock(); + if (!owner) + { + LogWarning("Owner is nullptr.\n"); + return; + } + if (mOwner.expired()) + { + LogWarning("Owner shared ptr expired failed.\n"); + return; + } + LogInfo("Camera upload spontaneous files.\n"); + owner->SpontaneousTaskFromCamera(mSpontaneousFiles); + mSpontaneousFiles.clear(); +} +RETURN_CODE CameraChip333DE::StopTask(void) +{ + // SF_MESSAGE_BUF_S stMessageBuf = {0}; + // stMessageBuf.cmdId = 0x0111; + // Message333DE::GetInstance()->MessageQueueSend(&stMessageBuf); + Message333DE::GetInstance()->sf_cardv_message_send(0x0111, nullptr, 0); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraChip333DE::SetNightMode(const bool &isNight) +{ + constexpr int IS_NIGHT = 1; + constexpr int IS_NOT_NIGHT = 0; + // SF_MESSAGE_BUF_S stMessageBuf = {0}; + // stMessageBuf.cmdId = 0x0112; + // stMessageBuf.arg1 = isNight ? IS_NIGHT : IS_NOT_NIGHT; + // Message333DE::GetInstance()->MessageQueueSend(&stMessageBuf); + signed char param = isNight ? IS_NIGHT : IS_NOT_NIGHT; + Message333DE::GetInstance()->sf_cardv_message_send(0x0112, &(param), sizeof(param)); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraChip333DE::HalBeReadyForLive(void) +{ + system("echo p2p 1 > /tmp/cardv_fifo"); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void CameraChip333DE::sf_venc_stream_start(void) +{ + auto videoStart = [](std::shared_ptr camera) + { + camera->_VideoUserGetFrame(); + }; + mVideoRuning = true; + mVideoThread = std::thread(videoStart, shared_from_this()); +} +void CameraChip333DE::sf_venc_stream_stop(void) +{ + mVideoRuning = false; + if (mVideoThread.joinable()) + { + mVideoThread.join(); + } +} +void CameraChip333DE::sf_audio_stream_start(void) +{ + auto audioStart = [](std::shared_ptr camera) + { + camera->_VideoUserGetFrame(); + }; + mAudioRuning = true; + mAudioThread = std::thread(audioStart, shared_from_this()); +} +void CameraChip333DE::sf_audio_stream_stop(void) +{ + mAudioRuning = false; + if (mAudioThread.joinable()) + { + mAudioThread.join(); + } +} +MI_S32 CameraChip333DE::_VideoUserGetFrame(void) +{ + auto owner = mOwner.lock(); + if (!owner) + { + LogWarning("Owner is nullptr.\n"); + return -1; + } + if (mOwner.expired()) + { + LogWarning("Owner shared ptr expired failed.\n"); + return -1; + } + MI_S32 _s32VencChn = 0; + MI_VENC_DupChn(_s32VencChn); + MI_VENC_ChnStat_t stStat; + MI_VENC_Stream_t *pstStream = NULL; + MI_S32 s32Ret; + MI_U32 u32FrameSize; + while (mVideoRuning) + { + memset(&stStat, 0, sizeof(MI_VENC_ChnStat_t)); + s32Ret = MI_VENC_Query(_s32VencChn, &stStat); + if (MI_SUCCESS != s32Ret || stStat.u32CurPacks == 0) + { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + continue; + } + + pstStream = (MI_VENC_Stream_t *)malloc(sizeof(MI_VENC_Stream_t)); + if (pstStream == NULL) + { + break; + } + + pstStream->u32PackCount = STREAM_PACK_CNT; + pstStream->pstPack = (MI_VENC_Pack_t *)malloc(sizeof(MI_VENC_Pack_t) * STREAM_PACK_CNT); + if (pstStream->pstPack == NULL) + { + free(pstStream); + pstStream = NULL; + break; + } + memset(pstStream->pstPack, 0, sizeof(MI_VENC_Pack_t) * STREAM_PACK_CNT); + + s32Ret = MI_VENC_GetStream(_s32VencChn, pstStream, 0); + if (MI_SUCCESS == s32Ret) + { + // stStat.u32CurPacks is from first frame in ring pool, + // but we need get current frame info here, and we maybe already get more than one frame here. + // so we need to calculate current frame packet count. + pstStream->u32PackCount = 0; + while (pstStream->pstPack[pstStream->u32PackCount++].bFrameEnd == 0) + { + if (pstStream->u32PackCount == STREAM_PACK_CNT) + { + printf("STREAM_PACK_CNT not enough\n"); + break; + } + } + + u32FrameSize = 0; + for (int i = 0; i < STREAM_PACK_CNT; i++) + { + u32FrameSize += pstStream->pstPack[i].u32Len; + } + + // VideoUserGetFrame(pstStream->pstPack, u32FrameSize, pstStream->pstPack[pstStream->u32PackCount - 1].u64PTS); + for (int i = 0; i < STREAM_PACK_CNT && pstStream->pstPack[i].u32Len; i++) + { + // sf_ipc_live_VideoStream_write((char *)pstPack[i].pu8Addr, pstPack[i].u32Len, framePts, pstPack[i].stDataType.eH265EType); + owner->VideoStream_write((char *)pstStream->pstPack[i].pu8Addr, pstStream->pstPack[i].u32Len, u32FrameSize, pstStream->pstPack[i].stDataType.eH265EType); + } + + MI_VENC_ReleaseStream(_s32VencChn, pstStream); + free(pstStream->pstPack); + free(pstStream); + pstStream->pstPack = NULL; + pstStream = NULL; + } + } + return 0; +} +void CameraChip333DE::VideoUserGetFrame(MI_VENC_Pack_t *pstPack, MI_U32 u32FrameSize, MI_U64 framePts) // TODO: delete +{ + // Customers TODO: + // Customers need to implement this function according to their own need. + // Note that the function runs as short as possible, or it maybe drops frame! + // Here SigmaStar just dump 300 frames to file for demo. + for (int i = 0; i < STREAM_PACK_CNT && pstPack[i].u32Len; i++) + { + // sf_ipc_live_VideoStream_write((char *)pstPack[i].pu8Addr, pstPack[i].u32Len, framePts, pstPack[i].stDataType.eH265EType); + } +} +MI_S32 CameraChip333DE::_AudioUserGetFrame(void) +{ + MI_AI_CHN AiChn = 0; + MI_AUDIO_DEV AiDevId = 0; + sf_audio_frame_get(AiChn, AiDevId); + + return 0; +} +SINT32 CameraChip333DE::sf_audio_frame_get(UINT8 AiDevId, UINT8 AiChn) +{ + auto owner = mOwner.lock(); + if (!owner) + { + LogWarning("Owner is nullptr.\n"); + return -1; + } + if (mOwner.expired()) + { + LogWarning("Owner shared ptr expired failed.\n"); + return -1; + } + MI_S32 ret; + MI_AUDIO_Frame_t stAiChFrame; + MI_AUDIO_AecFrame_t stAecFrame; + + MI_AI_DupChn(AiDevId, AiChn); + + while (mAudioRuning) + { + ret = MI_AI_GetFrame(AiDevId, AiChn, &stAiChFrame, &stAecFrame, 0); + if (MI_SUCCESS != ret) + continue; + + if (0 < stAiChFrame.u32Len[0]) + { + // sf_audioInUserGetFrame(&stAiChFrame, &stAecFrame); + owner->AudioStream_write((char *)(&stAiChFrame)->apVirAddr[0], (&stAiChFrame)->u32Len[0], (&stAiChFrame)->u64TimeStamp); + MI_AI_ReleaseFrame(AiDevId, AiChn, &stAiChFrame, &stAecFrame); + } + } + return 0; +} +void CameraChip333DE::sf_audioInUserGetFrame(MI_AUDIO_Frame_t *pstAudioFrame, MI_AUDIO_AecFrame_t *pstAecFrame) // TODO: delete +{ + sf_ipc_live_AudioStream_write((char *)pstAudioFrame->apVirAddr[0], pstAudioFrame->u32Len[0], pstAudioFrame->u64TimeStamp); +} +int CameraChip333DE::sf_ipc_live_AudioStream_write(char *pu8Addr, UINT32 u32Len, UINT32 TimeStamp) // TODO: delete +{ + auto owner = mOwner.lock(); // TODO: 影响效率 + if (!owner) + { + LogWarning("Owner is nullptr.\n"); + return -1; + } + if (mOwner.expired()) + { + LogWarning("Owner shared ptr expired failed.\n"); + return -1; + } + owner->AudioStream_write(pu8Addr, u32Len, TimeStamp); + return SF_SUCCESS; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/CameraChip333DE.h b/code/application/sifarsdk/333DE/hal/CameraChip333DE.h new file mode 100644 index 000000000..578bc874b --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/CameraChip333DE.h @@ -0,0 +1,57 @@ +#ifndef CAMER_CHIP_333DE_H +#define CAMER_CHIP_333DE_H +#include "IHal.h" +#include "MessageQueue.h" +#include "ShareMem.h" +#include "CameraHal.h" +#include "Message333DE.h" +#include "mi_venc.h" +#include "mi_ai.h" +#include +#include +constexpr int STREAM_PACK_CNT = 2; +class CameraChip333DE : public CameraHal, public ShareMem, public VCameraMessageHandle, public std::enable_shared_from_this +{ +public: + CameraChip333DE(); + virtual ~CameraChip333DE() = default; + void Init(void) override; + void UnInit(void) override; + RETURN_CODE SetCameraOwner(std::shared_ptr &owner) override; + RETURN_CODE StartSingleTask(const CameraTaskData &data) override; + void CameraTaskMessageResponse(void) override; + void CheckSpontaneousFilesToUpload(void) override; + RETURN_CODE StopTask(void) override; + RETURN_CODE SetNightMode(const bool &isNight) override; + RETURN_CODE HalBeReadyForLive(void) override; + void sf_venc_stream_start(void) override; + void sf_venc_stream_stop(void) override; + void sf_audio_stream_start(void) override; + void sf_audio_stream_stop(void) override; + +private: + bool SetTaskRuning(void); + bool GetTaskRuning(void); + void TaskFinshed(void); + void AddSpontaneousFiles(const std::vector &files); + +private: + MI_S32 _VideoUserGetFrame(void); + MI_S32 _AudioUserGetFrame(void); + SINT32 sf_audio_frame_get(UINT8 AiDevId, UINT8 AiChn); + void sf_audioInUserGetFrame(MI_AUDIO_Frame_t *pstAudioFrame, MI_AUDIO_AecFrame_t *pstAecFrame); + int sf_ipc_live_AudioStream_write(char *pu8Addr, UINT32 u32Len, UINT32 TimeStamp); + void VideoUserGetFrame(MI_VENC_Pack_t *pstPack, MI_U32 u32FrameSize, MI_U64 framePts); + +private: + SF_SRCFILE_ATTR_S *pThumbFileCfg; + std::weak_ptr mOwner; + std::mutex mMutex; + bool mOwnerStartedTask; + std::vector mSpontaneousFiles; + std::thread mAudioThread; + std::thread mVideoThread; + bool mAudioRuning; + bool mVideoRuning; +}; +#endif // !CAMER_CHIP_333DE_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/CameraHal.cpp b/code/application/sifarsdk/333DE/hal/CameraHal.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/333DE/hal/CameraHal.h b/code/application/sifarsdk/333DE/hal/CameraHal.h new file mode 100644 index 000000000..8b2440e35 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/CameraHal.h @@ -0,0 +1,12 @@ +#ifndef CAMERA_HAL_H +#define CAMERA_HAL_H +#include "IHal.h" +class CameraHal : public VCameraHal +{ +public: + CameraHal() = default; + virtual ~CameraHal() = default; + virtual void Init(void) {} + virtual void UnInit(void) {} +}; +#endif // !CAMERA_HAL_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/Gpio.cpp b/code/application/sifarsdk/333DE/hal/Gpio.cpp new file mode 100644 index 000000000..18ba03191 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/Gpio.cpp @@ -0,0 +1,109 @@ +#include "Gpio.h" +#include "Log.h" +#include "linux_api.h" +#include + +const char *GPIO_EXPORT = "/sys/class/gpio/export"; +const char *GPIO_EXPORT_MODE = "w"; +const char *GPIO_ID_DIR = "/sys/class/gpio/gpio%d/direction"; +const char *GPIO_DIR_MODE = "rb+"; +const char *GPIO_ID_VALUE = "/sys/class/gpio/gpio%d/value"; +const char *GPIO_UNEXPORT = "/sys/class/gpio/unexport"; + +SINT32 Gpio::GpioInit(const U32 &pinNum, const char *dir) +{ + FILE *fp = nullptr; + char file_name[64] = {0}; + if (dir == NULL) + { + LogError("pointer is NULL\n"); + return SF_FAILURE; + } + + fp = fopen(GPIO_EXPORT, GPIO_EXPORT_MODE); + if (fp == NULL) + { + LogError("Cannot open %s.\n", GPIO_EXPORT); + return SF_FAILURE; + } + + fprintf_gpio(fp, pinNum); + linux_fclose(fp); + sprintf(file_name, GPIO_ID_DIR, pinNum); + fp = fopen(file_name, GPIO_DIR_MODE); + if (fp == NULL) + { + LogError("Cannot open %s\n", file_name); + return SF_FAILURE; + } + + fprintf_dir(fp, dir); + + linux_fclose(fp); + return SF_SUCCESS; +} +SINT32 Gpio::GpioSet(const U32 &pinNum, const U32 &nval) +{ + FILE *fp = nullptr; + char file_name[64] = {0}; + U8 buf[10] = {0}; + + sprintf(file_name, GPIO_ID_VALUE, pinNum); + fp = fopen(file_name, "rb+"); + if (fp == NULL) + { + LogError("Cannot open %s.\n", file_name); + return SF_FAILURE; + } + + if (nval == 0) + strcpy((char *)buf, "0"); + else + strcpy((char *)buf, "1"); + + fwrite(buf, sizeof(char), sizeof(buf) - 1, fp); + linux_fclose(fp); + + return SF_SUCCESS; +} +SINT32 Gpio::GpioGet(const U32 &pinNum, SINT8 &nval) +{ + FILE *fp = nullptr; + char file_name[64] = {0}; + U8 buf[10] = {0}; + int snval = 0; + int nret = 0; + + sprintf(file_name, GPIO_ID_VALUE, pinNum); + fp = fopen(file_name, GPIO_DIR_MODE); + if (fp == NULL) + { + LogError("Cannot open %s.\n", file_name); + return SF_FAILURE; + } + nret = linux_fread(buf, sizeof(char), sizeof(buf) - 1, fp); + linux_fclose(fp); + + if (nret > 0) + { + snval = atoi((char *)&buf[0]); + nval = (SINT8)snval; + } + else + return SF_FAILURE; + + return SF_SUCCESS; +} +SINT32 Gpio::GpioDeinit(const U32 &pinNum) +{ + FILE *fp = nullptr; + fp = fopen(GPIO_UNEXPORT, GPIO_EXPORT_MODE); + if (fp == NULL) + { + LogError("no export gpio[%d]\n", pinNum); + return SF_FAILURE; + } + fprintf_gpio(fp, pinNum); + linux_fclose(fp); + return SF_SUCCESS; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/Gpio.h b/code/application/sifarsdk/333DE/hal/Gpio.h new file mode 100644 index 000000000..bada78d6f --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/Gpio.h @@ -0,0 +1,67 @@ +#ifndef GPIO_H +#define GPIO_H +#include "IHal.h" +#include "SfTypeDefine.h" +#include +// class GpioKeyContrl : public VKeyContrl +// { +// }; +typedef enum sfHAL_LED_GPIO_IDX_E +{ + SF_HAL_LED_IDX_0 = 0, /** monitor, void *context) +{ + mInputMonitor = monitor; + mContext = context; +} +void GpioInputHandle::CheckInputValue(void) +{ + auto monitor = mInputMonitor.lock(); + if (mInputMonitor.expired()) + { + return; + } + SINT8 pinValue = 0; + GpioGet(mPin, pinValue); + // LogInfo("GpioInputHandle::CheckInputValue pin = %d, pinValue = %d\n", mPin, pinValue); + if (pinValue == mInvalidInput && mInvalidInput != mLastPinValue) + { + monitor->InputTransform(mGpio, GpioInputValue::INVALID, mContext); + } + if (pinValue != mInvalidInput && mInvalidInput == mLastPinValue) + { + monitor->InputTransform(mGpio, GpioInputValue::VALID, mContext); + } + mLastPinValue = pinValue; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/GpioInputHandle.h b/code/application/sifarsdk/333DE/hal/GpioInputHandle.h new file mode 100644 index 000000000..cf0b7028f --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/GpioInputHandle.h @@ -0,0 +1,22 @@ +#ifndef GPIO_INPUT_HANDLE_H +#define GPIO_INPUT_HANDLE_H +#include "Gpio.h" +class GpioInputHandle : public VGpioInputHandle, public Gpio +{ +public: + GpioInputHandle(const GpioPin &gpio, const unsigned int &pin, const signed char invalidInput); + virtual ~GpioInputHandle() = default; + void Init(void) override; + void UnInit(void) override; + void SetInputMonitor(std::shared_ptr monitor, void *context) override; + void CheckInputValue(void); + +private: + const GpioPin mGpio; + const unsigned int mPin; + const signed char mInvalidInput; + SINT8 mLastPinValue; + std::weak_ptr mInputMonitor; + void *mContext; +}; +#endif // !GPIO_INPUT_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/Hal333DE.cpp b/code/application/sifarsdk/333DE/hal/Hal333DE.cpp new file mode 100644 index 000000000..d2add4a77 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/Hal333DE.cpp @@ -0,0 +1,241 @@ +#include "Hal333DE.h" +#include "CameraChip333DE.h" +#include "Log.h" +#include "KeyContrl.h" +#include +static void GpioHandleThread(std::shared_ptr halManager) +{ + while (halManager->IsHalRuning()) + { + halManager->CheckAllPins(); + std::this_thread::sleep_for(std::chrono::milliseconds(PERIPHERAL_CHECK_PERIOD_MS)); + } +} +Hal333DE::Hal333DE() +{ + mHalRuning = false; + mMainCamera = std::make_shared(); + mSdCardHal = std::make_shared(); +} +RETURN_CODE Hal333DE::Init(void) +{ + LogInfo("hal 333DE.\n"); + auto loadDrivers = [](std::shared_ptr hal) + { + hal->LoadDrivers(); + }; + std::thread func(loadDrivers, shared_from_this()); + if (func.joinable()) + { + func.join(); + } + InitAllLeds(); + InitAllKeys(); + InitCameras(); + InitAllGpios(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateSdCardHal(mSdCardHal); + mHalRuning = true; + mGpioHandle = std::thread(GpioHandleThread, shared_from_this()); + std::shared_ptr tmp = std::dynamic_pointer_cast(mSdCardHal); + Message333DE::GetInstance()->SetSDCardMessageHandle(tmp); + Message333DE::GetInstance()->Init(); + HalX86::Init(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DE::UnInit(void) +{ + HalX86::UnInit(); + Message333DE::GetInstance()->UnInit(); + mHalRuning = false; + if (mGpioHandle.joinable()) + { + mGpioHandle.join(); + } + UnInitAllLeds(); + UnInitAllKeys(); + UnInitCameras(); + UnInitAllGpios(); + mSdCardHal.reset(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DE::GetKeyContrlHandle(const SfKeyDefine &key, std::shared_ptr &keyContrl) +{ + keyContrl = mKeys[key]; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DE::GetGpioInputHandle(const GpioPin &gpio, std::shared_ptr &gpioHandle) +{ + gpioHandle = mGpios[gpio]; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DE::GetLedContrlHandle(const SfLedIndex &led, std::shared_ptr &ledContrl) +{ + ledContrl = mLeds[led]; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DE::GetCameraHal(const CameraType &type, std::shared_ptr &camera) +{ + camera = mMainCamera; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +const char *RTC_DEVICE = "/dev/rtc0"; +const RtcDevice &Hal333DE::GetRtcDevice(void) +{ + static RtcDevice rtc(RTC_DEVICE, RtcDeviceSupport::SUPPORT); + return rtc; +} +void Hal333DE::InitAllLeds(void) +{ + for (int i = 0; i < static_cast(SfLedIndex::SF_LED_END); i++) + { + auto ledHandle = std::make_shared(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioLedContrlInstance(static_cast(i), ledHandle); + ledHandle->Init(); + mLeds[static_cast(i)] = ledHandle; + } +} +void Hal333DE::UnInitAllLeds(void) +{ + if (mLeds.empty()) + { + return; + } + for (int i = 0; i < static_cast(SfLedIndex::SF_LED_END); i++) + { + mLeds[static_cast(i)]->UnInit(); + } + mLeds.clear(); +} +void Hal333DE::InitAllKeys(void) +{ + for (int i = 0; i < static_cast(SfKeyDefine::KEY_PIN_END); i++) + { + auto keyHandle = std::make_shared(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioKeyContrlInstance(static_cast(i), keyHandle); + keyHandle->Init(); + mKeys[static_cast(i)] = keyHandle; + } +} +void Hal333DE::UnInitAllKeys(void) +{ + if (mKeys.empty()) + { + return; + } + for (int i = 0; i < static_cast(SfKeyDefine::KEY_PIN_END); i++) + { + mKeys[static_cast(i)]->UnInit(); + } + mKeys.clear(); +} +void Hal333DE::InitCameras(void) +{ + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateCameraChip(CameraType::MAIN_CAMERA, mMainCamera); + if (!mMainCamera) + { + LogError("Camera init failed.\n"); + return; + } + mMainCamera->Init(); + LogInfo("Camera init succeed.\n"); +} +void Hal333DE::UnInitCameras(void) +{ + mMainCamera->UnInit(); +} +void Hal333DE::InitAllGpios(void) +{ + for (int i = 0; i < static_cast(GpioPin::END); i++) + { + std::shared_ptr gpio; + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioInputInstance(static_cast(i), gpio); + gpio->Init(); + mGpios[static_cast(i)] = gpio; + } +} +void Hal333DE::UnInitAllGpios(void) +{ + if (mGpios.empty()) + { + return; + } + for (int i = 0; i < static_cast(GpioPin::END); i++) + { + mGpios[static_cast(i)]->UnInit(); + } + mGpios.clear(); +} +RETURN_CODE Hal333DE::GetLightWeightCPU(std::shared_ptr &lcpu) +{ + auto code = + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateLightWeightCPU(lcpu); + return code; +} +const char *SERIAL_DEVICE_PATH = "/dev/ttyS2"; +const McuDeviceInformation Hal333DE::GetMcuDeviceInformation(void) +{ + LogInfo("Get mcu serial = %s\n", SERIAL_DEVICE_PATH); + McuDeviceInformation info(SERIAL_DEVICE_PATH, 115200, 'N', 8, 1, 'N'); + return info; +} +void Hal333DE::DoSomethingBeforPowerOff(void) +{ + int result = -1; + result = system("umount misc"); + result = system("echo cli sycmd -wpara > /proc/dualos/rtos"); + LogInfo("system result = %d\n", result); +} +RETURN_CODE Hal333DE::GetSDCardHal(std::shared_ptr &sdCardHal) +{ + sdCardHal = mSdCardHal; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +const NetWorkUpgradeResult Hal333DE::NetworkModuleUpgrade(void) +{ + if ((access("/mnt/mmc/EG95", F_OK) == 0)) + { + system("/customer/QFirehose -f /mnt/mmc/EG95"); + // app_system_poweroff(SF_POWEROFF_REBOOT); + NetWorkUpgradeResult info(NETWORK_MODULE_UPGRADE_RESULT::SUCCEED); + return info; + } + else + { + NetWorkUpgradeResult info(NETWORK_MODULE_UPGRADE_RESULT::FAILED); + return info; + } +} +void Hal333DE::CheckAllPins(void) +{ + std::shared_ptr keyContrl; + for (int i = 0; i < static_cast(SfKeyDefine::KEY_PIN_END); i++) + { + keyContrl = std::dynamic_pointer_cast(mKeys[static_cast(i)]); + if (keyContrl) + { + keyContrl->CheckKeyValue(); + } + } + for (int i = 0; i < static_cast(GpioPin::END); i++) + { + std::dynamic_pointer_cast(mGpios[static_cast(i)])->CheckInputValue(); + } +} +bool Hal333DE::IsHalRuning(void) +{ + return mHalRuning; +} +void Hal333DE::LoadDrivers(void) +{ + LogInfo("LoadDrivers.\n"); + int result = -1; + result = system("insmod /config/modules/4.9.84/usb-storage.ko"); + result = system("insmod /config/modules/4.9.84/usbnet.ko"); + result = system("insmod /config/modules/4.9.84/cdc_ether.ko"); + result = system("insmod /config/modules/4.9.84/rndis_host.ko"); + result = system("insmod /config/modules/4.9.84/usbserial.ko"); + result = system("insmod /config/modules/4.9.84/usb_wwan.ko"); + result = system("insmod /config/modules/4.9.84/option.ko"); + result = system("insmod /customer/GobiNet.ko"); + LogInfo("LoadDrivers. result = %d\n", result); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/Hal333DE.h b/code/application/sifarsdk/333DE/hal/Hal333DE.h new file mode 100644 index 000000000..7aabec4e3 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/Hal333DE.h @@ -0,0 +1,54 @@ +#ifndef HAL_333DE_H +#define HAL_333DE_H +#include "HalX86.h" +#include "Hal333DEMakePtr.h" +#include "CameraHal.h" +#include "GpioInputHandle.h" +#include "Message333DE.h" +#include +#include +class Hal333DE : public HalX86, public std::enable_shared_from_this +{ +public: + Hal333DE(); + virtual ~Hal333DE() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + RETURN_CODE GetKeyContrlHandle(const SfKeyDefine &key, std::shared_ptr &keyContrl) override; + RETURN_CODE GetGpioInputHandle(const GpioPin &gpio, std::shared_ptr &gpioHandle) override; + RETURN_CODE GetLedContrlHandle(const SfLedIndex &led, std::shared_ptr &ledContrl) override; + RETURN_CODE GetCameraHal(const CameraType &type, std::shared_ptr &camera) override; + const RtcDevice &GetRtcDevice(void) override; + RETURN_CODE GetLightWeightCPU(std::shared_ptr &lcpu) override; + const McuDeviceInformation GetMcuDeviceInformation(void) override; + const char *GetSDCardSystemPath(void) override { return "/mnt/mmc/"; } + const char *GetPictureThumbPath(void) override { return "/mnt/mmc/DCIM/THUMB/"; } + const char *GetVideoStreamPath(void) override { return "/mnt/mmc/DCIM/SMALL/"; } + const char *GetSDCardCheckPath(void) override { return "/mnt/mmc/DCIM"; } + void DoSomethingBeforPowerOff(void) override; + RETURN_CODE GetSDCardHal(std::shared_ptr &sdCardHal) override; + const NetWorkUpgradeResult NetworkModuleUpgrade(void) override; + virtual void CheckAllPins(void); + bool IsHalRuning(void); + void LoadDrivers(void); + +private: + void InitAllLeds(void); + void UnInitAllLeds(void); + void InitAllKeys(void); + void UnInitAllKeys(void); + void InitCameras(void); + void UnInitCameras(void); + void InitAllGpios(void); + void UnInitAllGpios(void); + +private: + std::map> mKeys; + std::map> mLeds; + std::map> mGpios; + bool mHalRuning; + std::shared_ptr mMainCamera; + std::thread mGpioHandle; + std::shared_ptr mSdCardHal; +}; +#endif // !HAL_333DE_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/Hal333DEMakePtr.cpp b/code/application/sifarsdk/333DE/hal/Hal333DEMakePtr.cpp new file mode 100644 index 000000000..bfb6711cd --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/Hal333DEMakePtr.cpp @@ -0,0 +1,144 @@ +#include "Hal333DEMakePtr.h" +#include "Hal333DE.h" +#include "NetworkModule333DE.h" +#include "CameraChip333DE.h" +#include "Log.h" +#include "Gpio.h" +#include "LightWeightCPU.h" +#include "GpioInputHandle.h" +#include "KeyContrl.h" +#include "OneColorLed.h" +#include "MultiColorLed.h" +#include "SDCardHal.h" +void Hal333DEMakePtrOverride(void) +{ + std::shared_ptr makePtr = std::make_shared(); + HalX86MakePtr::GetInstance(&makePtr); +} +Hal333DEMakePtr::Hal333DEMakePtr() +{ + mKeyInfo[SfKeyDefine::KEY_PIN_RESET] = {SF_KEY_PIN_RESET, HIGHT_MEANS_KEY_UP}; + mKeyInfo[SfKeyDefine::KEY_PIN_SYNC] = {SF_KEY_PIN_SYNC, HIGHT_MEANS_KEY_UP}; + mKeyInfo[SfKeyDefine::KEY_PIN_FORMAT] = {SF_KEY_PIN_FORMAT, HIGHT_MEANS_KEY_UP}; + mKeyInfo[SfKeyDefine::KEY_PIN_DATAREADY] = {SF_KEY_PIN_DATAREADY, LOW_MEANS_KEY_UP}; + // mKeyInfo[SfKeyDefine::KEY_PIN_FILESTATUS] = {SF_KEY_PIN_FILESTATUS, HIGHT_MEANS_KEY_UP}; +} +RETURN_CODE Hal333DEMakePtr::CreateHalModuleInstance(std::shared_ptr &impl) +{ + LogInfo("Hal333DEMakePtr make ptr.\n"); + impl = std::make_shared(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DEMakePtr::CreateGpioLedContrlInstance(const SfLedIndex &led, std::shared_ptr &ledContrl) +{ + switch (led) + { + case SfLedIndex::SF_LED_STATUS: + { + LogInfo("Create led of status.\n"); + auto ledOut = std::make_shared(led, SF_HAL_LED_STATUS_G); + ledContrl = ledOut; + break; + } + case SfLedIndex::SF_LED_WIFI: + { + LogInfo("Create led of wifi.\n"); + auto ledOut = std::make_shared(led, SF_HAL_LED_WIFI); + ledContrl = ledOut; + break; + } + case SfLedIndex::SF_LED_BAT: + { + LogInfo("Create led of bat.\n"); + auto ledOut = std::make_shared(led, SF_HAL_LED_BAT_R, SF_HAL_LED_BAT_G); + ledContrl = ledOut; + break; + } + case SfLedIndex::SF_LED_SD: + { + LogInfo("Create led of sd card.\n"); + auto ledOut = std::make_shared(led, SF_HAL_LED_SD_R, SF_HAL_LED_SD_G); + ledContrl = ledOut; + break; + } + case SfLedIndex::SF_LED_SIG1: + { + LogInfo("Create led of signal.\n"); + auto ledOut = std::make_shared(led, SF_HAL_LED_SIG1_R, SF_HAL_LED_SIG1_G); + ledContrl = ledOut; + break; + } + case SfLedIndex::SF_LED_USERBIND: + { + LogInfo("Create led of signal.\n"); + auto ledOut = std::make_shared(led, SF_HAL_LED_USERBIND_R, SF_HAL_LED_USERBIND_G); + ledContrl = ledOut; + break; + } + default: + break; + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DEMakePtr::CreateGpioKeyContrlInstance(const SfKeyDefine &key, std::shared_ptr &keyContrl) +{ + std::map::iterator iter; + iter = mKeyInfo.find(key); + if (iter == mKeyInfo.end()) + { + LogWarning("Want to create undefine key contrl, failed.key = %d\n", static_cast(key)); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + auto keyOut = std::make_shared(key, mKeyInfo[key].pinNumber, mKeyInfo[key].valueMeansKeyUp); + // keyOut->Init(); + keyContrl = keyOut; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DEMakePtr::CreateGpioInputInstance(const GpioPin &gpio, std::shared_ptr &gpioInput) +{ + constexpr int GPIOID_PIR_TEST = 3; + constexpr int GPIOID_USB_INSERT = 61; + switch (gpio) + { + case GpioPin::PIR: + { + auto impl = std::make_shared(gpio, GPIOID_PIR_TEST, HIGHT_PIN_MEANS_INVALID); + gpioInput = impl; + break; + } + case GpioPin::USB: + { + auto impl = std::make_shared(gpio, GPIOID_USB_INSERT, LOW_PIN_MEANS_INVALID); + gpioInput = impl; + break; + } + + default: + break; + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DEMakePtr::CreateCameraChip(const CameraType &type, std::shared_ptr &camera) +{ + auto tmp = std::make_shared(); + camera = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DEMakePtr::CreateLightWeightCPU(std::shared_ptr &lcpu) +{ + auto tmp = std::make_shared(); + lcpu = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DEMakePtr::CreateSdCardHal(std::shared_ptr &sdCardHal) +{ + auto tmp = std::make_shared(); + sdCardHal = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Hal333DEMakePtr::CreateNetworkModuleHandle(std::shared_ptr &impl) +{ + LogInfo("CreateNetworkModuleHandle NetworkModule333DE.\n"); + impl = std::make_shared(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/Hal333DEMakePtr.h b/code/application/sifarsdk/333DE/hal/Hal333DEMakePtr.h new file mode 100644 index 000000000..d54d0092c --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/Hal333DEMakePtr.h @@ -0,0 +1,34 @@ +#ifndef HAL_333DE_MAKE_PTR_H +#define HAL_333DE_MAKE_PTR_H +#include "ReturnCode.h" +#include "IHal.h" +#include "Gpio.h" +#include "HalX86MakePtr.h" +#include "CameraHal.h" +#include +typedef struct SF_KEYMNG_INFO_S +{ + SF_KEY_PIN_E pinNumber; /* serial number*/ + SF_BOOL valueMeansKeyUp; /* PIN state*/ + // SINT16 u32keycount; /* Count value*/ + // SINT16 ShortLongMaxCount; /* Pin number*/ + // SF_KEY_STATE_E enState; /* Initial state*/ +} SF_KEYMNG_INFO_S; +class Hal333DEMakePtr : public HalX86MakePtr +{ +public: + Hal333DEMakePtr(); + virtual ~Hal333DEMakePtr() = default; + RETURN_CODE CreateHalModuleInstance(std::shared_ptr &impl) override; + RETURN_CODE CreateNetworkModuleHandle(std::shared_ptr &impl) override; + virtual RETURN_CODE CreateGpioLedContrlInstance(const SfLedIndex &led, std::shared_ptr &ledContrl); + virtual RETURN_CODE CreateGpioKeyContrlInstance(const SfKeyDefine &key, std::shared_ptr &keyContrl); + virtual RETURN_CODE CreateGpioInputInstance(const GpioPin &gpio, std::shared_ptr &gpioInput); + virtual RETURN_CODE CreateCameraChip(const CameraType &type, std::shared_ptr &camera); + virtual RETURN_CODE CreateLightWeightCPU(std::shared_ptr &lcpu); + virtual RETURN_CODE CreateSdCardHal(std::shared_ptr &sdCardHal); + +private: + std::map mKeyInfo; +}; +#endif // !HAL_333DE_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/KeyContrl.cpp b/code/application/sifarsdk/333DE/hal/KeyContrl.cpp new file mode 100644 index 000000000..c2b9ec957 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/KeyContrl.cpp @@ -0,0 +1,48 @@ +#include "KeyContrl.h" +#include "Log.h" +KeyContrl::KeyContrl(const SfKeyDefine &key, const SF_KEY_PIN_E &pin, const SF_BOOL &valueMeansKeyUp) + : mKey(key), mPin(pin), mValueMeansKeyUp(valueMeansKeyUp) +{ + mEventContext = nullptr; + mLastPinValue = valueMeansKeyUp; + LogInfo("mLastPinValue = %d\n", mLastPinValue); + mKeyMonitor = std::make_shared(); +} +KeyContrl::~KeyContrl() +{ +} +void KeyContrl::Init(void) +{ + LogInfo("KeyContrl::Init pin = %d\n", mPin); + GpioInit(mPin, GPIO_DIR_IN); +} +void KeyContrl::UnInit(void) +{ + GpioDeinit(mPin); + mKeyMonitor.reset(); +} +void KeyContrl::SetKeyEventMonitor(std::shared_ptr monitor, void *context) +{ + mKeyMonitor = monitor; + mEventContext = context; +} +void KeyContrl::CheckKeyValue(void) +{ + auto monitor = mKeyMonitor.lock(); + if (mKeyMonitor.expired()) + { + return; + } + SINT8 pinValue = 0; + GpioGet(mPin, pinValue); + // LogInfo("KeyContrl::CheckKeyValue pin = %d, pinValue = %d\n", mPin, pinValue); + if (pinValue == mValueMeansKeyUp && mValueMeansKeyUp != mLastPinValue) + { + monitor->HalKeyEventHappened(mKey, SfKeyEvent::KEY_EVENT_UN_PRESSED, mEventContext); + } + if (pinValue != mValueMeansKeyUp && mValueMeansKeyUp == mLastPinValue) + { + monitor->HalKeyEventHappened(mKey, SfKeyEvent::KEY_EVENT_PRESSED, mEventContext); + } + mLastPinValue = pinValue; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/KeyContrl.h b/code/application/sifarsdk/333DE/hal/KeyContrl.h new file mode 100644 index 000000000..17a0b6b0c --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/KeyContrl.h @@ -0,0 +1,29 @@ +#ifndef KEY_CONTRL_H +#define KEY_CONTRL_H +#include "Gpio.h" +constexpr SINT8 INVALID_PIN_VALUE = -1; +constexpr SINT8 PIN_VALUE_HIGHT = 1; +constexpr SINT8 PIN_VALUE_LOW = 0; +constexpr SF_BOOL HIGHT_MEANS_KEY_UP = 1; +constexpr SF_BOOL LOW_MEANS_KEY_UP = 0; +constexpr SINT8 LOW_PIN_MEANS_INVALID = 0; +constexpr SINT8 HIGHT_PIN_MEANS_INVALID = 1; +class KeyContrl : public VKeyContrl, public Gpio +{ +public: + KeyContrl(const SfKeyDefine &key, const SF_KEY_PIN_E &pin, const SF_BOOL &valueMeansKeyUp); + ~KeyContrl(); + void Init(void) override; + void UnInit(void) override; + void SetKeyEventMonitor(std::shared_ptr monitor, void *context) override; + void CheckKeyValue(void); + +private: + const SfKeyDefine mKey; + const SF_KEY_PIN_E mPin; + std::weak_ptr mKeyMonitor; + void *mEventContext; + SINT8 mLastPinValue; + const SF_BOOL mValueMeansKeyUp; +}; +#endif // !KEY_CONTRL_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/LightWeightCPU.cpp b/code/application/sifarsdk/333DE/hal/LightWeightCPU.cpp new file mode 100644 index 000000000..58d4162be --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/LightWeightCPU.cpp @@ -0,0 +1,81 @@ +#include "LightWeightCPU.h" +#include "SfTypeDefine.h" +#include "Log.h" +#include +#include +#include +#include +#include + +#define MSYS_IOCTL_MAGIC 'S' +#define IOCTL_MSYS_GET_SY_RTOS_DATA _IO(MSYS_IOCTL_MAGIC, 0x97) +#define IOCTL_MSYS_SET_RTOS_CMD _IO(MSYS_IOCTL_MAGIC, 0x98) +typedef struct ONLY_FOR_GET_DATA +{ + // unsigned int test1; + // unsigned int test2; + // unsigned int test3; + // unsigned int IsNight; + // unsigned int BatPer; + // unsigned int Fctemp; + // unsigned short McuVer; + // unsigned char McuSubVer; + // unsigned int rtosBootTime; + unsigned int test1; + unsigned int test2; + unsigned int test3; + unsigned int IsNight; + unsigned int BatPer; + unsigned int LiveBatPer; + unsigned int currentBatvalue; + unsigned int recorddone; + unsigned int Fctemp; + unsigned short McuVer; + unsigned char McuSubVer; + unsigned int rtosBootTime; +} ONLY_FOR_GET_DATA; +bool LightWeightCPU::Read(char *readBuf, const unsigned int length) +{ + SINT32 nMsysFd = SF_FAILURE; + ONLY_FOR_GET_DATA info = {0}; + for (SINT32 cnt = 0; cnt < 100; cnt++) + { + if (0 > (nMsysFd = open("/dev/msys", O_RDONLY | O_SYNC))) + { + LogError("open /dev/msys failed!!\n"); + usleep(20000); + continue; + } + else + { + ioctl(nMsysFd, IOCTL_MSYS_GET_SY_RTOS_DATA, &info); + memcpy(readBuf, &info, sizeof(ONLY_FOR_GET_DATA)); + close(nMsysFd); + return true; + } + } + LogError("LightWeightCPU::Read failed.\n"); + return false; +} +bool LightWeightCPU::Write(const char *writeBuf, const unsigned length) +{ + SINT32 nMsysFd = -1; + SINT32 ret = -1; + for (SINT32 cnt = 0; cnt < 10; cnt++) + { + if (0 > (nMsysFd = open("/dev/msys", O_RDONLY | O_SYNC))) + { + LogError("%s open /dev/msys failed!!\n", __FUNCTION__); + // usleep(20000); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + continue; + } + else + { + ret = ioctl(nMsysFd, IOCTL_MSYS_SET_RTOS_CMD, &writeBuf); + close(nMsysFd); + return ret; + } + } + return false; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/LightWeightCPU.h b/code/application/sifarsdk/333DE/hal/LightWeightCPU.h new file mode 100644 index 000000000..5e59d7842 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/LightWeightCPU.h @@ -0,0 +1,12 @@ +#ifndef LIGHTWEIGHT_CPU_H +#define LIGHTWEIGHT_CPU_H +#include "IHal.h" +class LightWeightCPU : public VLightWeightCPU +{ +public: + LightWeightCPU() = default; + ~LightWeightCPU() = default; + bool Read(char *readBuf, const unsigned int length) override; + bool Write(const char *writeBuf, const unsigned length) override; +}; +#endif // !LIGHTWEIGHT_CPU_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/Message333DE.cpp b/code/application/sifarsdk/333DE/hal/Message333DE.cpp new file mode 100644 index 000000000..e762a5ed8 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/Message333DE.cpp @@ -0,0 +1,107 @@ +#include "Message333DE.h" +#include "SfTypeDefine.h" +#include "Log.h" +#include +Message333DE::Message333DE() : MessageQueue("/tmp/sf_message") +{ + pThumbFileCfg = nullptr; + mRecvThreadRuning = false; + mCameraHandle = std::make_shared(); + mSDCardHandle = std::make_shared(); +} +std::shared_ptr &Message333DE::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + instance = *impl; + } + return instance; +} +void Message333DE::Init(void) +{ + MessageQueueCreate(); + auto recvThread = [](std::shared_ptr message) + { + message->RecvThread(); + }; + mMessageHandle = std::thread(recvThread, shared_from_this()); +} +void Message333DE::UnInit(void) +{ + mRecvThreadRuning = false; + if (mMessageHandle.joinable()) + { + mMessageHandle.join(); + } + mCameraHandle.reset(); +} +SINT32 Message333DE::sf_cardv_message_send(SINT32 cmdId, SINT8 *param, SINT32 paramLen) +{ + SF_MESSAGE_BUF_S stMessagebuf = {0}; + memset(&stMessagebuf, 0, sizeof(SF_MESSAGE_BUF_S)); + stMessagebuf.mtype = 1; + stMessagebuf.cmdId = cmdId; + stMessagebuf.paramLen = paramLen; + if (param) + { + memcpy(stMessagebuf.paramBuf, param, paramLen); + } + MessageQueue::MessageQueueSend(&stMessagebuf); + return 0; +} +void Message333DE::RecvThread(void) +{ + LogInfo("Camera recv from queue.\n"); + SINT32 ret = 0; + SF_MESSAGE_BUF_S stMessagebuf = {0}; + mRecvThreadRuning = true; + while (mRecvThreadRuning) + { + memset(&stMessagebuf, 0, sizeof(SF_MESSAGE_BUF_S)); + ret = MessageQueueRecv(&stMessagebuf); + if (ret != SF_SUCCESS) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // TODO: Use select to handle?? + mCameraHandle->CheckSpontaneousFilesToUpload(); + continue; + } + LogInfo("cmdId:[%#x,%s]\n", stMessagebuf.cmdId, AppProcessMessageGetstatusstring(static_cast(stMessagebuf.cmdId))); + switch (stMessagebuf.cmdId & CMD_SERIES_FIX) + { + case CMD_FILE: + mCameraHandle->CameraTaskMessageResponse(); + break; + case CMD_SD: + app_process_cmd_SD(&stMessagebuf); + break; + default: + break; + } + } +} +const SF_CHAR *Message333DE::AppProcessMessageGetstatusstring(const SF_MESSAGE_TYPE_E &enType) +{ + switch (enType) + { + case CMD_KEY: + return "CMD_KEY"; + case CMD_SD: + return "CMD_SD"; + case CMD_LED: + return "CMD_LED"; + case CMD_FILE: + return "CMD_FILE"; + case CMD_POWEROFF: + return "CMD_POWEROFF"; + case CMD_VENC: + return "CMD_VENC"; + default: + return "Unknown"; + } +} +SINT32 Message333DE::app_process_cmd_SD(SF_MESSAGE_BUF_S *pMessageBuf) +{ + mSDCardHandle->SetSDCardMessage(static_cast(pMessageBuf->cmdId)); // TODO: + return SF_SUCCESS; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/Message333DE.h b/code/application/sifarsdk/333DE/hal/Message333DE.h new file mode 100644 index 000000000..381fb7df4 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/Message333DE.h @@ -0,0 +1,70 @@ +#ifndef MESSAGE_333DE_H +#define MESSAGE_333DE_H +#include "MessageQueue.h" +#include "IHal.h" +#include +#include +#include +#include +#define SF_MAX_PATH_LEN 128 +#define SF_MAX_PIC_LEN 64 +#define SF_SRCFILE_MAX 4 +#define SF_THUMB_FILE_MAX_LEN 20 +typedef struct sf_FILE_ATTR_S +{ + SF_FILE_TYPE_E enFileTye; + SF_CHAR thumbfileName[SF_MAX_PIC_LEN]; + SF_CHAR thumbfilePath[SF_MAX_PATH_LEN]; + SF_CHAR txtfilePath[SF_MAX_PATH_LEN]; + SF_CHAR txtfileName[SF_MAX_PIC_LEN]; + UINT32 thumbfileSize; + +} SF_FILE_ATTR_S; +typedef struct sf_SRCFILE_ATTR_S +{ + UINT8 filecnt; + SF_FILE_ATTR_S stfileattr[SF_SRCFILE_MAX]; +} SF_SRCFILE_ATTR_S; +class VCameraMessageHandle +{ +public: + VCameraMessageHandle() = default; + virtual ~VCameraMessageHandle() = default; + virtual void CameraTaskMessageResponse(void) {} + virtual void CheckSpontaneousFilesToUpload(void) {} +}; +class VSDCardMessageHandle +{ +public: + VSDCardMessageHandle() = default; + virtual ~VSDCardMessageHandle() = default; + virtual void SetSDCardMessage(const SF_MESSAGE_CMD_SD_E &message) {} +}; +class Message333DE : public MessageQueue, public std::enable_shared_from_this +{ +public: + Message333DE(); + ~Message333DE() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + void Init(void); + void UnInit(void); + void SetCameraMessageHandle(const std::shared_ptr &handle) { mCameraHandle = handle; } + void SetSDCardMessageHandle(const std::shared_ptr &handle) { mSDCardHandle = handle; } + SINT32 sf_cardv_message_send(SINT32 cmdId, SINT8 *param, SINT32 paramLen); + +private: + void RecvThread(void); + // void CheckSpontaneousFilesToUpload(void); + const SF_CHAR *AppProcessMessageGetstatusstring(const SF_MESSAGE_TYPE_E &enType); + SINT32 app_process_cmd_SD(SF_MESSAGE_BUF_S *pMessageBuf); + +private: + std::mutex mMutex; + SF_SRCFILE_ATTR_S *pThumbFileCfg; + bool mRecvThreadRuning; + std::thread mMessageHandle; + std::vector mSpontaneousFiles; + std::shared_ptr mCameraHandle; + std::shared_ptr mSDCardHandle; +}; +#endif // !MESSAGE_333DE_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/MessageQueue.cpp b/code/application/sifarsdk/333DE/hal/MessageQueue.cpp new file mode 100644 index 000000000..d62e21eea --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/MessageQueue.cpp @@ -0,0 +1,63 @@ +#include "MessageQueue.h" +#include "Log.h" +#include +#include +#include +#include +#include +#include +#include +#include +MessageQueue::MessageQueue(const SF_CHAR *path) : pathname(path) +{ + pMsgQueueId = -1; +} +SINT32 MessageQueue::MessageQueueCreate(void) +{ + key_t key; + SF_CHAR touchPath[128] = {0}; + if (access(pathname, F_OK) != 0) + { + sprintf(touchPath, "%s %s", "touch", pathname); + system(touchPath); + } + if ((key = ftok(pathname, 'z')) < 0) + { + LogInfo("ftok error"); + return SF_FAILURE; + } + if ((pMsgQueueId = msgget(key, IPC_CREAT | 0660)) == -1) + { + LogError("MsgQueueId = %#x\n", pMsgQueueId); + LogError("msgget failed errno.%02d is: %s\n", errno, strerror(errno)); + return SF_FAILURE; + } + LogInfo("MsgQueueId = %#x\n", pMsgQueueId); + return SF_SUCCESS; +} +SINT32 MessageQueue::MessageQueueRecv(SF_MESSAGE_BUF_S *pMessageBuf) +{ + // size_t msgsz = sizeof(pMessageBuf->cmdId) + sizeof(pMessageBuf->s32Wait) + sizeof(pMessageBuf->arg1) + sizeof(pMessageBuf->arg2) + sizeof(pMessageBuf->arg3); + size_t msgsz = sizeof(pMessageBuf->cmdId) + sizeof(pMessageBuf->s32Wait) + sizeof(pMessageBuf->paramLen) + QUEUE_BUF_LENGTH; + if (msgrcv(pMsgQueueId, pMessageBuf, msgsz, 0, IPC_NOWAIT) == -1) + { + return SF_FAILURE; + } + return SF_SUCCESS; +} +SINT32 MessageQueue::MessageQueueSend(SF_MESSAGE_BUF_S *pMessageBuf) +{ + if (!pMessageBuf) + { + LogError("pMessageBuf is nullptr.\n"); + return SF_FAILURE; + } + pMessageBuf->mtype = 1; + // size_t msgsz = sizeof(pMessageBuf->cmdId) + sizeof(pMessageBuf->s32Wait) + sizeof(pMessageBuf->arg1) + sizeof(pMessageBuf->arg2) + sizeof(pMessageBuf->arg3); + size_t msgsz = sizeof(pMessageBuf->cmdId) + sizeof(pMessageBuf->s32Wait) + sizeof(pMessageBuf->paramLen) + pMessageBuf->paramLen; + if (msgsnd(pMsgQueueId, pMessageBuf, msgsz, 0) == -1) + { + return SF_FAILURE; + } + return SF_SUCCESS; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/MessageQueue.h b/code/application/sifarsdk/333DE/hal/MessageQueue.h new file mode 100644 index 000000000..f763804d6 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/MessageQueue.h @@ -0,0 +1,50 @@ +#ifndef MESSAGE_QUEUE_H +#define MESSAGE_QUEUE_H +#include "SfTypeDefine.h" +constexpr int QUEUE_BUF_LENGTH = 256; +constexpr signed int CMD_SERIES_FIX = 0xFF00; +typedef struct sf_MESSAGE_Buf_S +{ + long mtype; + SINT32 cmdId; + SINT32 s32Wait; + SINT32 paramLen; + SINT8 paramBuf[QUEUE_BUF_LENGTH]; +} SF_MESSAGE_BUF_S; +typedef enum sf_MESSAGE_TYPE_E +{ + CMD_KEY = 0x1A00, + CMD_SD = 0x1B00, + CMD_LED = 0x1C00, + CMD_FILE = 0x1D00, + CMD_POWEROFF = 0x1E00, + CMD_VENC = 0x1F00, +} SF_MESSAGE_TYPE_E; +typedef enum sf_MESSAGE_CMD_SD_e +{ + // CMD_SD_MOUNT_SUCCESS = 0x01, + // CMD_SD_ERROR = 0x02, + // CMD_SD_OUT = 0x03, + // CMD_SD_FULL = 0x04, + // CMD_SD_MOUNT_FAILURE = 0x05, + CMD_SD_MOUNT_SUCCESS = 0x01 | CMD_SD, + CMD_SD_ERROR = 0x02 | CMD_SD, + CMD_SD_OUT = 0x03 | CMD_SD, + CMD_SD_FULL = 0x04 | CMD_SD, + CMD_SF_SD_FORMAT = 0x05 | CMD_SD, +} SF_MESSAGE_CMD_SD_E; +constexpr int PATH_NAME_LENGTH = 256; +class MessageQueue +{ +public: + MessageQueue(const SF_CHAR *path); + virtual ~MessageQueue() = default; + SINT32 MessageQueueCreate(void); + SINT32 MessageQueueRecv(SF_MESSAGE_BUF_S *pMessageBuf); + SINT32 MessageQueueSend(SF_MESSAGE_BUF_S *pMessageBuf); + +private: + SINT32 pMsgQueueId; + const SF_CHAR *pathname; +}; +#endif // !MESSAGE_QUEUE_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/MultiColorLed.cpp b/code/application/sifarsdk/333DE/hal/MultiColorLed.cpp new file mode 100644 index 000000000..ed6fd62bc --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/MultiColorLed.cpp @@ -0,0 +1,46 @@ +#include "MultiColorLed.h" + +MultiColorLed::MultiColorLed(const SfLedIndex &led, const SF_LED_GPIO_IDX_E &pinRed, const SF_LED_GPIO_IDX_E &pinGreen) + : mLed(led), mPinRed(pinRed), mPinGreen(pinGreen) +{ +} +MultiColorLed::~MultiColorLed() +{ + // UnInit(); +} +void MultiColorLed::Init(void) +{ + GpioInit(mPinRed, GPIO_DIR_OUT); + GpioInit(mPinGreen, GPIO_DIR_OUT); +} +void MultiColorLed::UnInit(void) +{ + GpioDeinit(mPinRed); + GpioDeinit(mPinGreen); +} +bool MultiColorLed::SetLedState(const SfLedState &state) +{ + switch (state) + { + case SfLedState::SF_LED_STATE_GREEN: + GpioSet(mPinRed, SF_HAL_LED_STATE_OFF); + GpioSet(mPinGreen, SF_HAL_LED_STATE_ON); + break; + case SfLedState::SF_LED_STATE_RED: + GpioSet(mPinGreen, SF_HAL_LED_STATE_OFF); + GpioSet(mPinRed, SF_HAL_LED_STATE_ON); + break; + case SfLedState::SF_LED_STATE_YELLOW: + GpioSet(mPinGreen, SF_HAL_LED_STATE_ON); + GpioSet(mPinRed, SF_HAL_LED_STATE_ON); + break; + case SfLedState::SF_LED_STATE_OFF: + GpioSet(mPinGreen, SF_HAL_LED_STATE_OFF); + GpioSet(mPinRed, SF_HAL_LED_STATE_OFF); + break; + + default: + break; + } + return true; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/MultiColorLed.h b/code/application/sifarsdk/333DE/hal/MultiColorLed.h new file mode 100644 index 000000000..4b4584007 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/MultiColorLed.h @@ -0,0 +1,19 @@ +#ifndef MULTI_COLOR_LED_H +#define MULTI_COLOR_LED_H +#include "Gpio.h" +class MultiColorLed : public VLedContrl, public Gpio +{ +public: + MultiColorLed() = default; + MultiColorLed(const SfLedIndex &led, const SF_LED_GPIO_IDX_E &pinRed, const SF_LED_GPIO_IDX_E &pinGreen); + ~MultiColorLed(); + void Init(void) override; + void UnInit(void) override; + bool SetLedState(const SfLedState &state) override; + +private: + const SfLedIndex mLed; // This member variable cannot be changed. + const SF_LED_GPIO_IDX_E mPinRed; + const SF_LED_GPIO_IDX_E mPinGreen; +}; +#endif // !MULTI_COLOR_LED_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/NetworkModule333DE.cpp b/code/application/sifarsdk/333DE/hal/NetworkModule333DE.cpp new file mode 100644 index 000000000..97ec0af3f --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/NetworkModule333DE.cpp @@ -0,0 +1,85 @@ +#include "NetworkModule333DE.h" +#include "SfTypeDefine.h" +#include "Log.h" +#include +#include +constexpr U32 GPIOID_SIM_INSRET = 4; +constexpr U32 GPIOID_USB_MUX1 = 16; + +RETURN_CODE NetworkModule333DE::Init(void) +{ + LogInfo("NetworkModule333DE::Init.\n"); + GpioInit(GPIOID_SIM_INSRET, GPIO_DIR_IN); + GpioInit(GPIOID_USB_MUX1, GPIO_DIR_OUT); + GpioSet(GPIOID_USB_MUX1, GPIO_PIN_HIGHT); + NetworkModule::Init(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} + +RETURN_CODE NetworkModule333DE::UnInit(void) +{ + NetworkModule::UnInit(); + GpioDeinit(GPIOID_SIM_INSRET); + GpioDeinit(GPIOID_USB_MUX1); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkModule333DE::IsHardwareSupport(void) +{ + LogInfo("NetworkModule333DE::IsHardwareSupport.\n"); + SINT8 regValue = 0; + // TODO: Multi thread safe? + // GpioInit(GPIOID_SIM_INSRET, GPIO_DIR_IN); + GpioGet(GPIOID_SIM_INSRET, regValue); + // GpioDeinit(GPIOID_SIM_INSRET); + if (regValue & 0xFF) + { + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + LogError("Don't support usd network module.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); +} +RETURN_CODE NetworkModule333DE::NetDriverLoad(void) +{ + constexpr int CMD_BUF_LENGTH = 128; + char cmd[CMD_BUF_LENGTH] = {0}; + int ret = SF_FAILURE; + for (UINT8 i = 0; i < 40; i++) + { + if (access("/dev/qcqmi0", F_OK) == SF_SUCCESS) + { + ret = SF_SUCCESS; + LogInfo("usb net ko exist!\n"); + break; + } + else + { + usleep(100 * 1000); + } + } + if (ret == SF_SUCCESS) + { + sprintf(cmd, "/customer/quectel-CM -n %d&", E_PDP_INDEX); + int resutl = system(cmd); + LogInfo("system function result = %d\n", resutl); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 5)); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); +} +unsigned int NetworkModule333DE::GetPdpIndex(void) +{ + return E_PDP_INDEX; +} +const char *USB_NODE = "/dev/ttyUSB2"; +SF_SERIAL_DATA_FRAME_TYPE_S NetworkModule333DE::GetUsbNode(void) +{ + SF_SERIAL_DATA_FRAME_TYPE_S node = { + USB_NODE, + 'N', + 'N', + 8, + 1, + 460800}; + // LogInfo("Get 333DE node message.\n"); + return node; +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/NetworkModule333DE.h b/code/application/sifarsdk/333DE/hal/NetworkModule333DE.h new file mode 100644 index 000000000..ac94afb76 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/NetworkModule333DE.h @@ -0,0 +1,20 @@ +#ifndef NETWORK_MODULE_333DE_H +#define NETWORK_MODULE_333DE_H +#include "NetworkModule.h" +#include "Gpio.h" +#define E_PDP_INDEX 7 +#define V_PDP_INDEX 3 +#define A_PDP_INDEX 1 +class NetworkModule333DE : public NetworkModule, public Gpio +{ +public: + NetworkModule333DE() = default; + virtual ~NetworkModule333DE() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + RETURN_CODE IsHardwareSupport(void) override; + RETURN_CODE NetDriverLoad(void) override; + unsigned int GetPdpIndex(void) override; + SF_SERIAL_DATA_FRAME_TYPE_S GetUsbNode(void) override; +}; +#endif // !NETWORK_MODULE_333DE_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/OneColorLed.cpp b/code/application/sifarsdk/333DE/hal/OneColorLed.cpp new file mode 100644 index 000000000..db9380738 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/OneColorLed.cpp @@ -0,0 +1,35 @@ +#include "OneColorLed.h" +#include "Log.h" +OneColorLed::OneColorLed(const SfLedIndex &led, const SF_LED_GPIO_IDX_E &pin) + : mLed(led), mPin(pin) +{ +} +OneColorLed::~OneColorLed() +{ + // UnInit(); +} +void OneColorLed::Init(void) +{ + GpioInit(mPin, GPIO_DIR_OUT); +} +void OneColorLed::UnInit(void) +{ + GpioDeinit(mPin); +} +bool OneColorLed::SetLedState(const SfLedState &state) +{ + // LogInfo("SetLedState, PIN = %d\n", mPin); + switch (state) + { + case SfLedState::SF_LED_STATE_ON: + GpioSet(mPin, SF_HAL_LED_STATE_ON); + break; + case SfLedState::SF_LED_STATE_OFF: + GpioSet(mPin, SF_HAL_LED_STATE_OFF); + break; + + default: + break; + } + return true; +} diff --git a/code/application/sifarsdk/333DE/hal/OneColorLed.h b/code/application/sifarsdk/333DE/hal/OneColorLed.h new file mode 100644 index 000000000..065463c28 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/OneColorLed.h @@ -0,0 +1,18 @@ +#ifndef ONE_COLOR_LED_H +#define ONE_COLOR_LED_H +#include "Gpio.h" +class OneColorLed : public VLedContrl, public Gpio +{ +public: + OneColorLed() = default; + OneColorLed(const SfLedIndex &led, const SF_LED_GPIO_IDX_E &pin); + ~OneColorLed(); + void Init(void); + void UnInit(void); + bool SetLedState(const SfLedState &state) override; + +private: + const SfLedIndex mLed; // This member variable cannot be changed. + const SF_LED_GPIO_IDX_E mPin; +}; +#endif // !ONE_COLOR_LED_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/SDCardHal.cpp b/code/application/sifarsdk/333DE/hal/SDCardHal.cpp new file mode 100644 index 000000000..cd65bcf4e --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/SDCardHal.cpp @@ -0,0 +1,65 @@ +#include "SDCardHal.h" +#include "Log.h" +SDCardHal::SDCardHal() +{ + mState = SdCardEvent::END; + mSDCardMessageConvert[CMD_SD_MOUNT_SUCCESS] = SdCardEvent::MOUNT_SUCCEED; + mSDCardMessageConvert[CMD_SF_SD_FORMAT] = SdCardEvent::MOUNT_FAILED; // TODO: + mSDCardMessageConvert[CMD_SD_ERROR] = SdCardEvent::SD_ERROR; + mSDCardMessageConvert[CMD_SD_OUT] = SdCardEvent::SD_OUT; + mSDCardMessageConvert[CMD_SD_FULL] = SdCardEvent::SD_FULL; +} +RETURN_CODE SDCardHal::GetSdCardState(SdCardEvent &state) +{ + state = mState; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE SDCardHal::SetOwner(const std::shared_ptr &owner) +{ + mOwner = owner; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void SDCardHal::SetSDCardMessage(const SF_MESSAGE_CMD_SD_E &message) +{ + std::map::iterator iter; + iter = mSDCardMessageConvert.find(message); + if (iter != mSDCardMessageConvert.end()) + { + LogInfo("SetSDCardMessage = %d\n", static_cast(message)); + mState = mSDCardMessageConvert[message]; + ReportMessageToOwner(mState); + return; + } + LogError("SF_MESSAGE_CMD_SD_E wrong = %d.\n", static_cast(message)); +} +RETURN_CODE SDCardHal::Format(void) +{ + system("echo format > /tmp/cardv_fifo"); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE SDCardHal::MsdcMode(void) +{ + system("/customer/gadget/udc-msdc.sh"); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE SDCardHal::UvcMode(void) +{ + system("echo uvc 1 > /tmp/cardv_fifo"); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void SDCardHal::ReportMessageToOwner(const SdCardEvent &message) +{ + auto owner = mOwner.lock(); + if (!owner) + { + LogWarning("Owner is nullptr.\n"); + return; + } + if (mOwner.expired()) + { + LogWarning("Owner shared ptr expired failed.\n"); + return; + } + LogInfo("ReportMessageToOwner.\n"); + owner->SDCardHalEvent(message); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/SDCardHal.h b/code/application/sifarsdk/333DE/hal/SDCardHal.h new file mode 100644 index 000000000..bac1a63f0 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/SDCardHal.h @@ -0,0 +1,26 @@ +#ifndef SD_CARD_HAL_H +#define SD_CARD_HAL_H +#include "IHal.h" +#include "Message333DE.h" +#include +class SDCardHal : public VSDCardHal, public VSDCardMessageHandle +{ +public: + SDCardHal(); + ~SDCardHal() = default; + RETURN_CODE GetSdCardState(SdCardEvent &state) override; + RETURN_CODE SetOwner(const std::shared_ptr &owner) override; + void SetSDCardMessage(const SF_MESSAGE_CMD_SD_E &message) override; + RETURN_CODE Format(void) override; + RETURN_CODE MsdcMode(void) override; + RETURN_CODE UvcMode(void) override; + +private: + void ReportMessageToOwner(const SdCardEvent &message); + +private: + SdCardEvent mState; + std::map mSDCardMessageConvert; + std::weak_ptr mOwner; +}; +#endif // !SD_CARD_HAL_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/ShareMem.cpp b/code/application/sifarsdk/333DE/hal/ShareMem.cpp new file mode 100644 index 000000000..a6503ef74 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/ShareMem.cpp @@ -0,0 +1,51 @@ +#include "ShareMem.h" +#include +// #include +// #include +// #include +#include +#include +#include +#include +#include +#include + +ShareMem::ShareMem(const SF_CHAR *path) : pathname(path) +{ + mSharMemId = -1; +} +int ShareMem::Create(int size) +{ + SF_CHAR touchPath[128] = {0}; + if (access(pathname, F_OK) != 0) + { + sprintf(touchPath, "%s %s", "touch", pathname); + system(touchPath); + } + key_t key = ftok(pathname, 111); + if (key < 0) + { + perror("ftok"); + return SF_FAILURE; + } + mSharMemId = shmget(key, size, IPC_CREAT | 0666); + if (mSharMemId == -1) + { + perror("shmget"); + return SF_FAILURE; + } + return SF_SUCCESS; +} +int ShareMem::Destory(void) +{ + if (shmctl(mSharMemId, IPC_RMID, NULL) < 0) + { + perror("shmctl"); + return SF_FAILURE; + } + return SF_SUCCESS; +} +void *ShareMem::Get(void) +{ + return shmat(mSharMemId, NULL, 0); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/ShareMem.h b/code/application/sifarsdk/333DE/hal/ShareMem.h new file mode 100644 index 000000000..697055f06 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/ShareMem.h @@ -0,0 +1,17 @@ +#ifndef SHARE_MEM_H +#define SHARE_MEM_H +#include "SfTypeDefine.h" +class ShareMem +{ +public: + ShareMem(const SF_CHAR *path); + virtual ~ShareMem() = default; + int Create(int size); + int Destory(void); + void *Get(void); + +private: + const SF_CHAR *pathname; + int mSharMemId; +}; +#endif // !SHARE_MEM_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/hal/include/IHal333DE.h b/code/application/sifarsdk/333DE/hal/include/IHal333DE.h new file mode 100644 index 000000000..648c8f6f9 --- /dev/null +++ b/code/application/sifarsdk/333DE/hal/include/IHal333DE.h @@ -0,0 +1,4 @@ +#ifndef I_HAL_333DE_H +#define I_HAL_333DE_H +void Hal333DEMakePtrOverride(void); +#endif // !I_HAL_333DE_H \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/README.MD b/code/application/sifarsdk/333DE/lib/README.MD new file mode 100644 index 000000000..c18b5771b --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/README.MD @@ -0,0 +1,2 @@ +# 依赖库目录 +   用于存放三方的依赖库中间文件。 \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/README.md b/code/application/sifarsdk/333DE/lib/README.md new file mode 100644 index 000000000..c18b5771b --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/README.md @@ -0,0 +1,2 @@ +# 依赖库目录 +   用于存放三方的依赖库中间文件。 \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/AED_LICENSE_1.txt b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/AED_LICENSE_1.txt new file mode 100644 index 000000000..697fc9986 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/AED_LICENSE_1.txt @@ -0,0 +1,12 @@ +/* + * http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html + * Copyright Takuya OOURA, 1996-2001 + * + * You may use, copy, modify and distribute this code for any purpose (include + * commercial use) and without fee. Please refer to this package when you modify + * this code. + * + * Changes: + * Trivial type modifications by the WebRTC authors. + * Trivial type modifications by the MSTAR authors. + */ \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/AED_LICENSE_2.txt b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/AED_LICENSE_2.txt new file mode 100644 index 000000000..25568c6ea --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/AED_LICENSE_2.txt @@ -0,0 +1,29 @@ +Copyright (c) 2011, The WebRTC project authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/APC_LICENSE_1.txt b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/APC_LICENSE_1.txt new file mode 100644 index 000000000..697fc9986 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/APC_LICENSE_1.txt @@ -0,0 +1,12 @@ +/* + * http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html + * Copyright Takuya OOURA, 1996-2001 + * + * You may use, copy, modify and distribute this code for any purpose (include + * commercial use) and without fee. Please refer to this package when you modify + * this code. + * + * Changes: + * Trivial type modifications by the WebRTC authors. + * Trivial type modifications by the MSTAR authors. + */ \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/APC_LICENSE_2.txt b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/APC_LICENSE_2.txt new file mode 100644 index 000000000..25568c6ea --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/APC_LICENSE_2.txt @@ -0,0 +1,29 @@ +Copyright (c) 2011, The WebRTC project authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavcodec.so.58.35.100 b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavcodec.so.58.35.100 new file mode 100644 index 000000000..05062c446 Binary files /dev/null and b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavcodec.so.58.35.100 differ diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavformat.so.58.20.100 b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavformat.so.58.20.100 new file mode 100644 index 000000000..0ecc6d06f Binary files /dev/null and b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavformat.so.58.20.100 differ diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavutil.so.56.22.100 b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavutil.so.56.22.100 new file mode 100644 index 000000000..ec59a12c7 Binary files /dev/null and b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libavutil.so.56.22.100 differ diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libfdk-aac.so.2.0.0 b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libfdk-aac.so.2.0.0 new file mode 100644 index 000000000..b4311f932 Binary files /dev/null and b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libfdk-aac.so.2.0.0 differ diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libswresample.so.3.3.100 b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libswresample.so.3.3.100 new file mode 100644 index 000000000..42f10b8c2 Binary files /dev/null and b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libswresample.so.3.3.100 differ diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libswscale.so.5.3.100 b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libswscale.so.5.3.100 new file mode 100644 index 000000000..d23b203e7 Binary files /dev/null and b/code/application/sifarsdk/333DE/lib/ex_libs/dynamic/libswscale.so.5.3.100 differ diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/static/AED_LICENSE_1.txt b/code/application/sifarsdk/333DE/lib/ex_libs/static/AED_LICENSE_1.txt new file mode 100644 index 000000000..697fc9986 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/ex_libs/static/AED_LICENSE_1.txt @@ -0,0 +1,12 @@ +/* + * http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html + * Copyright Takuya OOURA, 1996-2001 + * + * You may use, copy, modify and distribute this code for any purpose (include + * commercial use) and without fee. Please refer to this package when you modify + * this code. + * + * Changes: + * Trivial type modifications by the WebRTC authors. + * Trivial type modifications by the MSTAR authors. + */ \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/static/AED_LICENSE_2.txt b/code/application/sifarsdk/333DE/lib/ex_libs/static/AED_LICENSE_2.txt new file mode 100644 index 000000000..25568c6ea --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/ex_libs/static/AED_LICENSE_2.txt @@ -0,0 +1,29 @@ +Copyright (c) 2011, The WebRTC project authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/static/APC_LICENSE_1.txt b/code/application/sifarsdk/333DE/lib/ex_libs/static/APC_LICENSE_1.txt new file mode 100644 index 000000000..697fc9986 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/ex_libs/static/APC_LICENSE_1.txt @@ -0,0 +1,12 @@ +/* + * http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html + * Copyright Takuya OOURA, 1996-2001 + * + * You may use, copy, modify and distribute this code for any purpose (include + * commercial use) and without fee. Please refer to this package when you modify + * this code. + * + * Changes: + * Trivial type modifications by the WebRTC authors. + * Trivial type modifications by the MSTAR authors. + */ \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/ex_libs/static/APC_LICENSE_2.txt b/code/application/sifarsdk/333DE/lib/ex_libs/static/APC_LICENSE_2.txt new file mode 100644 index 000000000..25568c6ea --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/ex_libs/static/APC_LICENSE_2.txt @@ -0,0 +1,29 @@ +Copyright (c) 2011, The WebRTC project authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/CusEarlyInit_para.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/CusEarlyInit_para.h new file mode 100644 index 000000000..d46dfc8ac --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/CusEarlyInit_para.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +Sigmastar Technology Corp. and be kept in strict confidence +(Sigmastar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of Sigmastar Confidential +Information is unlawful and strictly prohibited. Sigmastar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _CUSEARLYINIT_PARA_H_ +#define _CUSEARLYINIT_PARA_H_ + +enum { + EARLYINIT_PARAM_TYPE_MASTER, + EARLYINIT_PARAM_TYPE_CUST_ROSE +}; + +typedef struct +{ + unsigned short u16SnrEarlyFps; + unsigned short u16SnrEarlyFlicker; + unsigned long u32SnrEarlyShutter; + unsigned long u32SnrEarlyGainX1024; + unsigned long u32SnrEarlyDGain; + unsigned long u32SnrEarlyShutterShort; + unsigned long u32SnrEarlyGainX1024Short; + unsigned long u32SnrEarlyDGainShort; + unsigned short u16SnrEarlyAwbRGain; + unsigned short u16SnrEarlyAwbGGain; + unsigned short u16SnrEarlyAwbBGain; +} __attribute__ ((packed)) MasterEarlyInitParam_t; + +typedef struct +{ + unsigned short u16SnrEarlyFps; + unsigned short u16SnrEarlyFlicker; + unsigned long u32SnrEarlyShutter; + unsigned long u32SnrEarlyGainX1024; + unsigned long u32SnrEarlyDGain; + unsigned long u32DeBugLevel_AWB_PERIOD; + unsigned long u32DeBugLevel_AeEarlyStageCnt; + unsigned short u16SnrEarlyAwbRGain; + unsigned short u16SnrEarlyAwbGGain; + unsigned short u16SnrEarlyAwbBGain; +} __attribute__ ((packed)) CusEarlyInitParam_t; + +typedef struct +{ + unsigned long u32Revision; + unsigned long u32Size; + + union + { + MasterEarlyInitParam_t tMasSnrEarlyInitParam; + + // Add customize early-init parameter here, if any + CusEarlyInitParam_t tCusSnrEarlyInitParam; + + unsigned char u8Data[64]; + } u; + +} IspSensorEarlyInitParam_t; + +#endif // _CUSEARLYINIT_PARA_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/drivers/sensorif/drv_ms_cus_sensor.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/drivers/sensorif/drv_ms_cus_sensor.h new file mode 100644 index 000000000..de6abeee5 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/drivers/sensorif/drv_ms_cus_sensor.h @@ -0,0 +1,977 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +Sigmastar Technology Corp. and be kept in strict confidence +(Sigmastar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of Sigmastar Confidential +Information is unlawful and strictly prohibited. Sigmastar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/*! @file drv_ms_cus_sensor.h + @brief This file contains Infinity ISP sensor driver interface. +*/ + +/** @defgroup group1 ISP Sensor Driver Interface +* @{ +*/ + +#ifndef DRV_MS_CUS_SENSOR_H_ +#define DRV_MS_CUS_SENSOR_H_ +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#define I2C_RETRYTIME (5) + +#ifndef SUCCESS +#define FAIL (-1) +#define SUCCESS 0 +#endif + +#ifdef __cplusplus +#define EXPORT_CUS extern "C" +#else +#define EXPORT_CUS +#endif + +#define CUS_MSTART_CAMSENSOR_CAP_VERSION 0x0001 + +//#define usleep(usec) CamOsMsSleep(usec*1000); +//#define usleep(usec) udelay(usec) +//#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +#define SENSOR_DRIVER_MODE_NOT_SUUPORT (0xFFFF) + +struct __ms_cus_sensor; /**< Sensor driver handle */ +//struct __ISensorAPI; /**< Sensor to ISP control interface */ + +/*! @brief Resolution descriptor*/ +typedef struct _cus_camsensor_res{ + u32 width; /**< Image crop width */ + u32 height; /**< Image crop height */ + u32 max_fps; /**< Max fps in this resolution */ + u32 min_fps; /**< Min fps in this resolution*/ + u32 crop_start_x; + u32 crop_start_y; + u32 nOutputWidth; /**< Sensor actual output width */ + u32 nOutputHeight; /**< Sensor actual output height */ + char strResDesc[32]; +} __attribute__((packed, aligned(4))) cus_camsensor_res; + +/*! @brief Resolution list*/ +typedef struct _cus_camsensor_res_list +{ + u32 num_res; /**< number of sensor resolution in list */ + u32 ulcur_res; /**< current sensor resolution*/ + cus_camsensor_res res[12]; /**< resolution list */ +} __attribute__((packed, aligned(4))) cus_camsensor_res_list; + + +/*! @brief Select sensor type */ +typedef enum { + ISP_SOC, /**< Not support */ + ISP_EXT /**< sensor without built-in ISP */ +} CUS_CAMSENSOR_ISPTYPE; + +/*! @brief Sensor bayer raw pixel order */ +typedef enum { + CUS_BAYER_RG = 0, /**< bayer data start with R channel */ + CUS_BAYER_GR, /**< bayer data start with Gr channel */ + CUS_BAYER_BG, /**< bayer data start with B channel */ + CUS_BAYER_GB /**< bayer data start with Gb channel */ +} CUS_SEN_BAYER; + +typedef enum { + CUS_RGBIR_R0 = 0, + CUS_RGBIR_G0 = 1, + CUS_RGBIR_B0 = 2, + CUS_RGBIR_G1 = 3, + CUS_RGBIR_G2 = 4, + CUS_RGBIR_I0 = 5, + CUS_RGBIR_G3 = 6, + CUS_RGBIR_I1 = 7, + CUS_RGBIR_NONE = 8 +} CUS_SEN_RGBIR; + +/*! @brief Set sensor image mirror and flip.*/ +typedef enum { + CUS_ORIT_M0F0, /**< mirror, flip unchanged */ + CUS_ORIT_M1F0, /**< mirror changed, flip unchanged */ + CUS_ORIT_M0F1, /**< mirror unchanged, flip changed */ + CUS_ORIT_M1F1, /**< mirror and flip changed */ +} CUS_CAMSENSOR_ORIT; + + +/*! @brief Get input source type.*/ +typedef enum { + CUS_SNR_ANADEC_SRC_NO_READY, /**< input no ready */ + CUS_SNR_ANADEC_SRC_PAL, /**< input type is PAL */ + CUS_SNR_ANADEC_SRC_NTSC, /**< input type is NTSC */ + CUS_SNR_ANADEC_SRC_HD, /**< input source type is HD */ + CUS_SNR_ANADEC_SRC_FHD, /**< input source type is FHD */ + CUS_SNR_ANADEC_SRC_DISCNT, /**< input disconnect */ + CUS_SNR_ANADEC_SRC_MAX, /**< input num max */ +}CUS_SNR_ANADEC_SRC_TYPE; + + +/*! @brief ISP AE event notifycation*/ +typedef enum { + CUS_FRAME_INACTIVE = 0, /**< Frame end */ + CUS_FRAME_ACTIVE = 1,/**< Frame start */ +} CUS_CAMSENSOR_AE_STATUS_NOTIFY; + +/*! @brief Sensor bayer raw (8/10 bits) to 12bits mode control */ +typedef enum { + CUS_SEN_8TO12_7074, /**< Do not use*/ + CUS_SEN_8TO12_7000, /**< Sensor bayer raw is 8 bits*/ + CUS_SEN_8TO12_114118, /**< Do not use*/ + CUS_SEN_8TO12_11400, /**< Do not use*/ + CUS_SEN_10TO12_9098, /**< Do not use*/ + CUS_SEN_10TO12_9000, /**< Sensor bayer raw is 10 bits*/ + CUS_SEN_10TO12_1121110, /**< Do not use*/ + CUS_SEN_10TO12_11200 /**< Do not use*/ +} CUS_SEN_FMT_CONV_MODE; + +/*! @brief Sensor input raw data precision */ +typedef enum { + CUS_DATAPRECISION_8 = 0, /**< raw data precision is 8bits */ + CUS_DATAPRECISION_10 = 1, /**< raw data precision is 10bits */ + CUS_DATAPRECISION_16 = 2, /**< raw data precision is 16bits */ + CUS_DATAPRECISION_12 = 3, /**< raw data precision is 12bits */ + CUS_DATAPRECISION_14 = 4, /**< raw data precision is 14bits */ +} CUS_DATAPRECISION; + +/*! @brief Select sensor data intarface */ +typedef enum { + CUS_SENIF_BUS_PARL = 0, /**< sensor data bus is parallel bus */ + CUS_SENIF_BUS_MIPI = 1, /**< sensor data bus is mipi */ + CUS_SENIF_BUS_BT601 = 2, + CUS_SENIF_BUS_BT656 = 3, + CUS_SENIF_BUS_BT1120 = 4, +} CUS_SENIF_BUS; + +typedef enum { + CUS_SEN_INPUT_FORMAT_YUV422, + CUS_SEN_INPUT_FORMAT_RGB, +} CUS_SEN_INPUT_FORMAT; + +/*! @brief Select pin polarity */ +typedef enum { + CUS_CLK_POL_POS = 0, /**< High active */ + CUS_CLK_POL_NEG /**< Low active */ +} CUS_CLK_POL; + +typedef enum +{ + CUS_SENSOR_YUV_ORDER_CY = 0, + CUS_SENSOR_YUV_ORDER_YC = 1, +}CUS_SENSOR_YUV_ORDER; + +/*! @brief Sensor master clock select */ +typedef enum { + CUS_CMU_CLK_27MHZ, + CUS_CMU_CLK_21P6MHZ, + CUS_CMU_CLK_12MHZ, + CUS_CMU_CLK_5P4MHZ, + CUS_CMU_CLK_36MHZ, + CUS_CMU_CLK_54MHZ, + CUS_CMU_CLK_43P2MHZ, + CUS_CMU_CLK_61P7MHZ, + CUS_CMU_CLK_72MHZ, + CUS_CMU_CLK_48MHZ, + CUS_CMU_CLK_24MHZ, + CUS_CMU_CLK_37P125MHZ, + CUS_CMU_CLK_LPLL_DIV1, + CUS_CMU_CLK_LPLL_DIV2, + CUS_CMU_CLK_LPLL_DIV4, + CUS_CMU_CLK_LPLL_DIV8, +} CUS_MCLK_FREQ; //Depends on chip. + +//Depends on chip definition. +typedef enum { + CUS_SR0_PAR_DISABLE, + CUS_SR0_PAR_MODE_1, + CUS_SR0_PAR_MODE_2, +} CUS_SR0_PAR_MODE; + +//Depends on chip definition. +typedef enum { + CUS_SR0_BT656_DISABLE, + CUS_SR0_BT656_MODE_1, + CUS_SR0_BT656_MODE_2, + CUS_SR0_BT656_MODE_3, + CUS_SR0_BT656_MODE_4, +} CUS_SR0_BT656_MODE; + +//Depends on chip definition. +typedef enum { + CUS_SR1_BT656_DISABLE, + CUS_SR1_BT656_MODE_1, +} CUS_SR1_BT656_MODE; + +//Depends on chip definition. +typedef enum { + CUS_SR0_BT601_DISABLE, + CUS_SR0_BT601_MODE_1, + CUS_SR0_BT601_MODE_2, + CUS_SR0_BT601_MODE_3, + CUS_SR0_BT601_MODE_4, +} CUS_SR0_BT601_MODE; + +//Depends on chip definition. +typedef enum { + CUS_SR0_MIPI_DISABLE, + CUS_SR0_MIPI_MODE_1, + CUS_SR0_MIPI_MODE_2, +} CUS_SR0_MIPI_MODE; + +//Depends on chip definition. +typedef enum { + CUS_SR1_MIPI_DISABLE, + CUS_SR1_MIPI_MODE_1, + CUS_SR1_MIPI_MODE_2, + CUS_SR1_MIPI_MODE_3, + CUS_SR1_MIPI_MODE_4, +} CUS_SR1_MIPI_MODE; + +//Depends on chip definition. +typedef enum +{ + CUS_VIF_BT656_EAV_DETECT = 0, + CUS_VIF_BT656_SAV_DETECT = 1, +}CUS_VIF_BT656_CHANNEL_SELECT; + +//Depends on chip definition. +typedef enum +{ + CUS_VIF_BT656_VSYNC_DELAY_1LINE = 0, + CUS_VIF_BT656_VSYNC_DELAY_2LINE = 1, + CUS_VIF_BT656_VSYNC_DELAY_0LINE = 2, + CUS_VIF_BT656_VSYNC_DELAY_AUTO = 3, +}CUS_VIF_BT656_VSYNC_DELAY; + +typedef enum +{ + CUS_SENSOR_FUNC_DISABLE = 0, + CUS_SENSOR_FUNC_ENABLE = 1, +}CUS_SENSOR_FUNC; + +typedef enum +{ + CUS_SENSOR_PAD_GROUP_A = 0, + CUS_SENSOR_PAD_GROUP_B = 1, +}CUS_SENSOR_PAD_GROUP; + +typedef enum +{ + CUS_SENSOR_CHANNEL_MODE_REALTIME_NORMAL = 0, + CUS_SENSOR_CHANNEL_MODE_REALTIME_HDR = 1, + CUS_SENSOR_CHANNEL_MODE_RAW_STORE = 2, + CUS_SENSOR_CHANNEL_MODE_RAW_STORE_HDR = 3, +}CUS_SENSOR_CHANNEL_MODE; + +typedef struct { + unsigned int gain; + unsigned int offset; +} CUS_GAIN_GAP_ARRAY; + +////////////////////////////////////// +// sensor functions +////////////////////////////////////// + +typedef struct { + u32 length; //header length + u32 version; //version +}CUS_CAMSENSOR_CAP; + +/////////////////// ISP for SENSOR API /////////////////// +typedef enum { + CUS_INT_TASK_AE = (1<<0), + CUS_INT_TASK_AWB = (1<<1), + CUS_INT_TASK_AF = (1<<2), + CUS_INT_TASK_VS = (1<<3), + CUS_INT_TASK_VDOS = (1<<4), +} CUS_INT_TASK_TYPE; + +#define MAX_RUN_ORDER 16 +typedef struct { + u8 RunLength; + u8 Orders[MAX_RUN_ORDER]; + u8 CurTaskType; +} CUS_INT_TASK_ORDER; + +/////////////////// Shutter Info /////////////////////// +/*! @brief Report shutter information */ +typedef struct { + u32 length; /**< struct size */ + u32 max; /**< maximun shutter in us*/ + u32 min; /**< minimum shutter in us*/ + u32 step; /**< shutter in step us*/ +} CUS_SHUTTER_INFO; + +////////////////// CSI CLOCK //////////////////////// +/*! @brief Select MIPI clock*/ +typedef enum { + CUS_CSI_CLK_DISABLE = -1, /**< Disable MIPI clock*/ + CUS_CSI_CLK_108M = 0, /**< MIPI pixel rate 864Mbps (1-lane)*/ + CUS_CSI_CLK_86M = 1, /**< MIPI pixel rate 344Mbps(1-lane)*/ + CUS_CSI_CLK_144M = 2, /**< MIPI pixel rate 1152Mbps(1-lane)*/ + CUS_CSI_CLK_172M = 3, + CUS_CSI_CLK_216M = 4, + CUS_CSI_CLK_288M = 5, + CUS_CSI_CLK_40M = 6, + CUS_CSI_CLK_24M = 7, + CUS_CSI_CLK_12M = 8, + CUS_CSI_CLK_123M = 9 +}CUS_CSI_CLK; + +///////////////// SENSOR PIN CONFIG///////////////// +/*! @brief Sensor pin assignment*/ +typedef enum { + CUS_SR_PAD_CFG_1 = 1, /**< Pin config for MIPI 1/2 lanes*/ + CUS_SR_PAD_CFG_MIPI = 1, /**< Pin config for MIPI 1/2 lanes*/ + CUS_SR_PAD_CFG_2 = 2, /**< Reserved */ + CUS_SR_PAD_CFG_3 = 3, /**< Reserved */ + CUS_SR_PAD_CFG_10BITS = 4, /**< Pin config for parallel interface 10 bits */ + CUS_SR_PAD_CFG_4 = 4, /**< Pin config for parallel interface 12 bits */ + CUS_SR_PAD_CFG_12BITS = 5, /**< Pin config for parallel interface 12 bits */ + CUS_SR_PAD_CFG_5 = 5, /**< Pin config for parallel interface 12 bits */ + CUS_SR_PAD_CFG_6 = 6 /**< Pin config for parallel interface 12 bits */ + }CUS_SR_PAD_CFG; + +/*! @brief virtual channel0 hsync. mode */ +typedef enum +{ + PACKET_HEADER_EDGE1 = 0, /**< packet header edge */ + PACKET_HEADER_EDGE2 = 1, /**< line end edge */ + PACKET_HEADER_EDGE3 = 2, /**< line start edge */ + PACKET_FOOTER_EDGE = 3, /**< packet footer edge */ +}CUS_CSI_VC_HS_MODE; + +typedef enum +{ + CUS_HDR_MODE_NONE = 0, + CUS_HDR_MODE_SONY_DOL = 1, + CUS_HDR_MODE_DCG = 2, + CUS_HDR_MODE_EMBEDDED_RAW8 = 3, + CUS_HDR_MODE_EMBEDDED_RAW10 = 4, + CUS_HDR_MODE_EMBEDDED_RAW12 = 5, + CUS_HDR_MODE_EMBEDDED_RAW16 = 6, //Only for OV2718? + CUS_HDR_MODE_LI = 7, + CUS_HDR_MODE_MULTI_VC = 8, +}CUS_HDR_MODE; + +typedef enum +{ + // Index 0 + SENSOR_DRIVER_MODE_VGA_30P_RESOLUTION, // 640*360 30P + SENSOR_DRIVER_MODE_VGA_50P_RESOLUTION, // 640*360 50P + SENSOR_DRIVER_MODE_VGA_60P_RESOLUTION, // 640*360 60P + SENSOR_DRIVER_MODE_VGA_100P_RESOLUTION, // 640*360 100P + SENSOR_DRIVER_MODE_VGA_120P_RESOLUTION, // 640*360 120P + + // Index 5 + SENSOR_DRIVER_MODE_HD_24P_RESOLUTION, // 1280*720 24P + SENSOR_DRIVER_MODE_HD_30P_RESOLUTION, // 1280*720 30P + SENSOR_DRIVER_MODE_HD_50P_RESOLUTION, // 1280*720 50P + SENSOR_DRIVER_MODE_HD_60P_RESOLUTION, // 1280*720 60P + SENSOR_DRIVER_MODE_HD_100P_RESOLUTION, // 1280*720 100P + + // Index 10 + SENSOR_DRIVER_MODE_HD_120P_RESOLUTION, // 1280*720 120P + SENSOR_DRIVER_MODE_1600x900_30P_RESOLUTION, // 1600*900 30P + SENSOR_DRIVER_MODE_FULL_HD_15P_RESOLUTION, // 1920*1080 15P + SENSOR_DRIVER_MODE_FULL_HD_24P_RESOLUTION, // 1920*1080 24P + SENSOR_DRIVER_MODE_FULL_HD_25P_RESOLUTION, // 1920*1080 25P + + // Index 15 + SENSOR_DRIVER_MODE_FULL_HD_30P_RESOLUTION, // 1920*1080 30P + SENSOR_DRIVER_MODE_FULL_HD_50P_RESOLUTION, // 1920*1080 50P + SENSOR_DRIVER_MODE_FULL_HD_60P_RESOLUTION, // 1920*1080 60P + SENSOR_DRIVER_MODE_SUPER_HD_30P_RESOLUTION, // 2304*1296 30P + SENSOR_DRIVER_MODE_SUPER_HD_25P_RESOLUTION, // 2304*1296 25P + + // Index 20 + SENSOR_DRIVER_MODE_SUPER_HD_24P_RESOLUTION, // 2304*1296 24P + SENSOR_DRIVER_MODE_1440_30P_RESOLUTION, // 2560*1440 30P + SENSOR_DRIVER_MODE_2D7K_15P_RESOLUTION, // 2704*1524 15P + SENSOR_DRIVER_MODE_2D7K_30P_RESOLUTION, // 2704*1524 30P + SENSOR_DRIVER_MODE_4K2K_15P_RESOLUTION, // 3840*2160 15P + + // Index 25 + SENSOR_DRIVER_MODE_4K2K_30P_RESOLUTION, // 3840*2160 30P + SENSOR_DRIVER_MODE_4TO3_VGA_30P_RESOLUTION, // 640*480 30P + SENSOR_DRIVER_MODE_4TO3_1D2M_30P_RESOLUTION, // 1280*960 30P + SENSOR_DRIVER_MODE_4TO3_1D5M_30P_RESOLUTION, // 1440*1080 30P + SENSOR_DRIVER_MODE_4TO3_3M_15P_RESOLUTION, // 2048*1536 15P + + // Index 30 + SENSOR_DRIVER_MODE_4TO3_3M_30P_RESOLUTION, // 2048*1536 30P + SENSOR_DRIVER_MODE_4TO3_5M_15P_RESOLUTION, // 2560*1920 15P + SENSOR_DRIVER_MODE_4TO3_5M_30P_RESOLUTION, // 2560*1920 30P + SENSOR_DRIVER_MODE_4TO3_8M_15P_RESOLUTION, // 3264*2448 15P + SENSOR_DRIVER_MODE_4TO3_8M_30P_RESOLUTION, // 3264*2448 30P + + // Index 35 + SENSOR_DRIVER_MODE_4TO3_10M_15P_RESOLUTION, // 3648*2736 15P + SENSOR_DRIVER_MODE_4TO3_10M_30P_RESOLUTION, // 3648*2736 30P + SENSOR_DRIVER_MODE_4TO3_12M_15P_RESOLUTION, // 4032*3024 15P + SENSOR_DRIVER_MODE_4TO3_12M_30P_RESOLUTION, // 4032*3024 30P + SENSOR_DRIVER_MODE_4TO3_14M_15P_RESOLUTION, // 4352*3264 15P + + // Index 40 + SENSOR_DRIVER_MODE_4TO3_14M_30P_RESOLUTION, // 4352*3264 30P + SENSOR_DRIVER_MODE_4K2K_24P_RESOLUTION, + SENSOR_DRIVER_MODE_PAL_25P_RESOLUTION, + SENSOR_DRIVER_MODE_NTSC_30P_RESOLUTION, + + // For Camera Preview + SENSOR_DRIVER_MODE_BEST_CAMERA_PREVIEW_RESOLUTION, + SENSOR_DRIVER_MODE_BEST_CAMERA_CAPTURE_16TO9_RESOLUTION, + SENSOR_DRIVER_MODE_BEST_CAMERA_CAPTURE_4TO3_RESOLUTION, + SENSOR_DRIVER_MODE_FULL_HD_30P_RESOLUTION_HDR, +} CUS_SNR_RESOLUTION; + + +#ifdef __cplusplus +extern "C" +#endif +/**@brief ISP sensor interface control API */ +typedef struct __ISensorIfAPI //isp sensor interface API +{ + /**@brief Reserved */ + void* pdata; + + /** @brief Set sensor power down pin. + @param[in] idx Sensor pad ID. + @param[in] pol pin polarity. + @retval SUCCESS or FAIL if error occurs. + */ + int (*PowerOff)(u32 idx, CUS_CLK_POL pol); + + /** @brief Set sensor power reset pin. + @param[in] idx Sensor pad ID. + @param[in] pol pin polarity. + @retval SUCCESS or FAIL if error occurs. + */ + int (*Reset)(u32 idx, CUS_CLK_POL pol); + + /** @brief Configure sensor master clock. + @param[in] idx Sensor pad ID. + @param[in] bONOFF Clock ON/OFF control. + @param[in] mclk Clock frequency Hz. + @retval SUCCESS or FAIL if error occurs. + */ + int (*MCLK)(u32 idx, u8 bONOFF, CUS_MCLK_FREQ mclk); + + /** @brief Query sensor master clock. + @param[in] idx Sensor pad ID. + @param[in] mclk Query if clock frequency Hz is available. + @retval SUCCESS or FAIL if error occurs. + */ + int (*QueryMCLK)(u32 idx, CUS_MCLK_FREQ mclk); + + /** @brief Query MIPI lane number. + @param[in] idx Sensor pad ID. + @param[in] lane_num Query max lane number. + @retval SUCCESS or FAIL if error occurs. + */ + int (*QueryLaneNum)(u32 idx, u8 *max_lane); +#if 0 + /** @brief Select pixel clock source + @remarks Parallel interface only + @param[in] handle Handle to sensor driver. + @param[in] pclk_source Clock source. + @retval SUCCESS or FAIL if error occurs. + */ + int (*PCLK)(CUS_PCLK_SOURCE pclk_source); //senect sensor + + /** @brief Configure HSYNC pin polarity. + @remarks Parallel interface only + @param[in] handle Handle to sensor driver. + @param[in] pol pin polarity. + @retval SUCCESS or FAIL if error occurs. + */ + int (*HsyncPol)(CUS_CLK_POL pol); + + /** @brief [parallel interface only] Configure VSYNC pin polarity. + @param[in] handle Handle to sensor driver. + @param[in] pol pin polarity. + @retval SUCCESS or FAIL if error occurs. + */ + int (*VsyncPol)(CUS_CLK_POL pol); + + /** @brief Configure PCLK pin polarity. + @param[in] handle Handle to sensor driver. + @param[in] pol pin polarity. + @retval SUCCESS or FAIL if error occurs. + */ + int (*ClkPol)(CUS_CLK_POL pol); + + /** @brief Configure sensor bayer raw pixel order + @param[in] handle Handle to sensor driver. + @param[in] bayer_id Select pixel order + @retval SUCCESS or FAIL if error occurs. + */ + int (*BayerFmt)(CUS_SEN_BAYER bayer_id); + + /** @brief Configure sensor RGBIR (8 or 10bits) convert to 12bit bits isp input, This config will be ignore for 12/16 bits sensor bayer raw input. + @param[in] handle Handle to sensor driver. + @param[in] mode Mode select + @retval SUCCESS or FAIL if error occurs. + */ + int (*FmtConv)(CUS_SEN_FMT_CONV_MODE mode); + + /** @brief Select sensor image data interface + @param[in] handle Handle to sensor driver. + @param[in] bus Sensor interface + @retval SUCCESS or FAIL if error occurs. + */ + int (*DataBus)(CUS_SENIF_BUS bus); + + /** @brief Configure sensor bayer raw pixel bits + @param[in] handle Handle to sensor driver. + @param[in] prec Select pixel bits + @retval SUCCESS or FAIL if error occurs. + */ + int (*DataPrecision)(CUS_DATAPRECISION prec); + + /** @brief Wait isp frame start event + @param[in] handle Handle to sensor driver. + @param[in] ms Max timeout in ms + @retval SUCCESS or FAIL if error occurs. + */ + int (*WaitVStart)(int ms); + + /** @brief Wait isp frame end event + @param[in] handle Handle to sensor driver. + @param[in] ms Max timeout in ms + @retval SUCCESS or FAIL if error occurs. + */ + int (*WaitVEnd)(int ms); + + /** @brief Configure 3A task order table + @param[in] handle Handle to sensor driver. + @param[in] tasks Task order table + @retval SUCCESS or FAIL if error occurs. + */ + int (*Set3ATaskOrder)(CUS_INT_TASK_ORDER tasks); +#endif + /** @brief Select sensor IO pin assignment + @param[in] idx Sensor pad ID. + @param[in] ulSnrType Interface type. + @param[in] ulSnrPadCfg Pin config. + @retval SUCCESS or FAIL if error occurs. + */ + int (*SetIOPad)(u32 idx, CUS_SENIF_BUS ulSnrType, u32 ulSnrPadCfg); + + //FOR CSI + + /** @brief Set maximum mipi data rate (amount of all lans) + @remarks MIPI interface only. + @param[in] idx Sensor pad ID. + @param[in] clk Max data rate. + @retval SUCCESS or FAIL if error occurs. + */ + int (*SetCSI_Clk)(u32 idx, CUS_CSI_CLK clk); + + /** @brief Set number of MIPI lanes + @remarks MIPI interface only. + @param[in] idx Sensor pad ID. + @param[in] num_lan Number of lanes. + @param[in] bon_off Clock ON/OFF control. + @retval SUCCESS or FAIL if error occurs. + */ + int (*SetCSI_Lane)(u32 idx, u16 num_lan, u8 bon_off); + + /** @brief Enable long packet type + @remarks MIPI interface only + @param[in] idx Sensor pad ID. + @param[in] ctl_cfg0_15 Control flag bit[0:15] + @param[in] ctl_cfg16_31 Control flag bit[16:31] + @param[in] ctl_cfg32_47 Control flag bit[32:47] + @retval SUCCESS or FAIL if error occurs. + */ + int (*SetCSI_LongPacketType)(u32 idx, u16 ctl_cfg0_15, u16 ctl_cfg16_31, u16 ctl_cfg32_47); + + /** @brief Virtual channel0 hsync mode + @remarks MIPI interface only + @param[in] idx Sensor pad ID. + @param[in] mode HSYNC mode. + @retval SUCCESS or FAIL if error occurs. + */ + int (*SetCSI_VC0HSmode)(CUS_CSI_VC_HS_MODE mode); + + /** @brief Configure MIPI capture start timing + @remarks MIPI interface only + @param[in] idx Sensor pad ID. + @param[in] rx_clk_skip_ns + @param[in] rx_data_skip_ns + @retval SUCCESS or FAIL if error occurs. + */ + int (*SetCSI_clk_data_skip)(u32 idx, u8 rx_clk_skip_ns,u8 rx_data_skip_ns); + + /** @brief Configure MIPI hdr mode + @remarks MIPI interface only + @param[in] idx Sensor pad ID. + @param[in] hdr_mode HDR mode. + @param[in] bon_off Clock ON/OFF control. + @retval SUCCESS or FAIL if error occurs. + */ + int (*SetCSI_hdr_mode)(u32 idx, CUS_HDR_MODE hdr_mode, u8 bon_off); + +#if 0 + /** @brief Configure sensor RGBIR raw pixel order + @param[in] handle Handle to sensor driver. + @param[in] bayer_id Select pixel order + @retval SUCCESS or FAIL if error occurs. + */ + int (*RGBIRFmt)(CUS_SEN_RGBIR RGBIR_id); + + /** @brief Skip input frame + @param[in] handle Handle to sensor driver. + @param[in] number of frames to skip + @retval SUCCESS or FAIL if error occurs. + */ + int (*SetSkipFrame)(int cnt); +#endif +}ISensorIfAPI; + +typedef union { + //Parallel sensor + struct { + u32 parallel_reserved; //No additional attribute. + } attr_parallel; + + //MIPI sensor + struct { + u32 mipi_lane_num; + u32 mipi_data_format; //0: YUV 422 format. 1: RGB pattern. + u32 mipi_yuv_order; //YUYV or UYVY + u32 mipi_hsync_mode; + u32 mipi_sampling_delay; /** < MIPI start sampling delay */ /*bit 0~7: clk_skip_ns. bit 8~15: data_skip_ns*/ + CUS_HDR_MODE mipi_hdr_mode; + u32 mipi_hdr_virtual_channel_num; + } attr_mipi; + + //BT656 sensor + struct { + u32 bt656_total_ch; + u32 bt656_cur_ch; + u32 bt656_ch_det_en; + CUS_VIF_BT656_CHANNEL_SELECT bt656_ch_det_sel; + u32 bt656_bit_swap; + u32 bt656_8bit_mode; + CUS_VIF_BT656_VSYNC_DELAY bt656_vsync_delay; + u32 bt656_hsync_inv; + u32 bt656_vsync_inv; + u32 bt656_clamp_en; + } attr_bt656; +} InterfaceAttr_u; + + +/////////////////////////////////////////////////////// + +/** @brief Sensor driver interface \n +The function here are implemented by sensor driver. +*/ +typedef struct __ms_cus_sensor{ + short lib_idx; /**< Reserved , Do not use */ + char model_id[32]; /**< Please fill the sensor modle id string here then libcamera user can read model_id by using cameraGetSensorModelID() .*/ + void *sen_handle; /**< Reserved , Do not use */ + void *private_data;/**< sensor driver dependent variables should store in private_data and free when release */ + + app_i2c_cfg i2c_cfg; /**< Sensor i2c setting */ + i2c_handle_t *i2c_bus; /**< Handle to sensor i2c API. */ + ISensorIfAPI sensor_if_api; /**< sensor interface API */ + // ae parameters + int ae_gain_delay; /**< How many frame delay from writing AE gain to take effect*/ + int ae_shutter_delay;/**< How many frame delay from writing AE shutter to take effect*/ + + int ae_gain_ctrl_num; + int ae_shutter_ctrl_num; + + // polarity + CUS_CLK_POL reset_POLARITY; /** < Sensor REST pin polarity */ + CUS_CLK_POL pwdn_POLARITY; /** < Sensor Power Down pin polarity */ + CUS_CLK_POL VSYNC_POLARITY; /** < Sensor VSYNC polarity */ + CUS_CLK_POL HSYNC_POLARITY; /** < Sensor HSYNC pin polarity */ + CUS_CLK_POL PCLK_POLARITY; //** < Sensor Plxel Clock pin polarity */ + + // sensor data + CUS_CAMSENSOR_ISPTYPE isp_type; /** < Always use ISP_EXT */ + CUS_SEN_BAYER bayer_id; /** < Sensor bayer raw pixel order */ + CUS_SEN_RGBIR RGBIR_id; /** < Sensor bayer raw pixel order */ + CUS_SENIF_BUS sif_bus; /** < Select sensor interface */ + CUS_DATAPRECISION data_prec; /** < Raw data bits */ + CUS_SEN_FMT_CONV_MODE data_mode; /** < Data convert mode*/ + CUS_CAMSENSOR_ORIT orient; /** < Sensor mirror/flip */ + u32 mclk; /** < Sensor master clock frequency */ + + cus_camsensor_res_list video_res_supported; /** < Resolution list */ + //sensor calibration + u32 sat_mingain; /**< Minimum AE gain */ + + CUS_SENSOR_PAD_GROUP snr_pad_group; + u32 channel_num; //Which VIF/ISP channel is occupied. + u32 channel_mode; //real-time, RAW store, HDR... + + InterfaceAttr_u interface_attr; + + //////////////////////////////////////////////// + // system functions + //////////////////////////////////////////////// + + /** @brief Sensor power on sequence, I2C must be ready after calling this function + @param[in] handle Handle to sensor driver. + @remark Following configuration need to set up at this stage \n + @ref __ISensorIfAPI::Reset Reset sensor \n + @ref __ISensorIfAPI::PowerOff Sensor power down pin \n + @ref __ISensorIfAPI::MCLK Sensor master clock \n + @ref __ISensorIfAPI::SetIOPad ISP sensor IO \n + @ref __ISensorIfAPI::SetCSI_Clk [MIPI sensor only] MIPI clock\n + @ref __ISensorIfAPI::HsyncPol Hsync polarity\n + @ref __ISensorIfAPI::VsyncPol Vsync polarity\n + @ref __ISensorIfAPI::ClkPol [Parallel sensor only] Pixel clock polarity\n + @ref __ISensorIfAPI::BayerFmt Raw data format\n + @ref __ISensorIfAPI::DataPrecision Raw data pixel bits\n + @ref __ISensorIfAPI::FmtConv Raw data to ISP pixel convert\n + @retval SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_poweron)(struct __ms_cus_sensor* handle, u32 idx); + + /** @brief Sensor power off + @param[in] handle Handle to sensor driver. + @retval SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_poweroff)(struct __ms_cus_sensor* handle, u32 idx); + + /** @brief Sensor initialization + @param[in] handle Handle to sensor driver. + @retval SUCCESS or FAIL if error occurs. + @remark Fill sensor initial table here, Sensor beginning to output raw images after calling this function . + */ + int (*pCus_sensor_init)(struct __ms_cus_sensor* handle); + + /** @brief Release resources those allocated in cus_camsensor_init_handle() + @param[in] handle Handle to sensor driver. + @retval SUCCESS or FAIL if error occurs. + @remark Release resource allocated in \ref cus_camsensor_init_handle + */ + int (*pCus_sensor_release)(struct __ms_cus_sensor* handle); + + /** @brief Enter sensor suspend mode + @param[in] handle Handle to sensor driver. + @retval SUCCESS or FAIL if error occurs. + @remark ISP call this function before enter power saving mode + */ + int (*pCus_sensor_suspend)(struct __ms_cus_sensor* handle); + + /** @brief Sensor wakeup + @param[in] handle Handle to sensor driver. + @retval SUCCESS or FAIL if error occurs. + @remark ISP call this function after exit power saving mode + */ + int (*pCus_sensor_resume)(struct __ms_cus_sensor* handle); + + /** @brief Enable sensor pattern mode if sensor hardward supported + @param[in] handle Handle to sensor driver. + @param[in] mode Pattern select, if 0 disable pattern mode. + @retval SUCCESS or FAIL if error occurs. + @remark This function is optional + */ + int (*pCus_sensor_SetPatternMode)(struct __ms_cus_sensor* handle,u32 mode); + + // Normal + + /** @brief Check sensor ID and report to ISP sensor match or not + @param[in] handle Handle to sensor driver. + @param[out] id Receive 4 bytes customer defined sensor ID. + @retval Return SUCCESS if sensor matched or Retuen FAIL if sensor mismatch. + @remark Read sensor ID through I2C + */ + int (*pCus_sensor_GetSensorID)(struct __ms_cus_sensor* handle, u32 *id); + + /** @brief Get resolution list + @param[in] handle Handle to sensor driver. + @param[out] id Receive supported resolution list + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_GetVideoRes)(struct __ms_cus_sensor* handle, u32 res_idx, cus_camsensor_res **res); + + /** @brief Get resolution list + @param[in] handle Handle to sensor driver. + @param[out] id Receive supported resolution list + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_GetCurVideoRes)(struct __ms_cus_sensor* handle, u32 *cur_idx, cus_camsensor_res **res); + + /** @brief Select a sensor output resolution sensor list + @param[in] handle Handle to sensor driver. + @param[in] res_id Resolution id + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_SetVideoRes)(struct __ms_cus_sensor* handle, u32 res_id); + + /** @brief Get sensor current mirror flip setting + @param[in] handle Handle to sensor driver. + @param[out] ori Receive Mirror/Flip setting. + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_GetOrien)(struct __ms_cus_sensor* handle, CUS_CAMSENSOR_ORIT *ori); + + /** @brief Select a sensor mirror flip + @param[in] handle Handle to sensor driver. + @param[in] ori Mirror/Flip configuration. + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_SetOrien)(struct __ms_cus_sensor* handle, CUS_CAMSENSOR_ORIT ori); + + /** @brief Get sensor capability + @param[in] handle Handle to sensor driver. + @param[out] cap Receive sensor capability + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_GetSensorCap)(struct __ms_cus_sensor* handle, CUS_CAMSENSOR_CAP *cap); + + /////////////////////////////////////////////////////// + // AE + /////////////////////////////////////////////////////// + // unit: micro seconds + + /** @brief AE/Frame status change notification + @param[in] handle Handle to sensor driver. + @param[in] status Current status + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_AEStatusNotify)(struct __ms_cus_sensor* handle, CUS_CAMSENSOR_AE_STATUS_NOTIFY status); + + /** @brief Get sensor shutter setting in us + @param[in] handle Handle to sensor driver. + @param[out] us Receive current shutter setting + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_GetAEUSecs)(struct __ms_cus_sensor* handle, u32 *us); + + /** @brief Set sensor shutter in us + @param[in] handle Handle to sensor driver. + @param[in] us Shutter setting in us + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_SetAEUSecs)(struct __ms_cus_sensor* handle, u32 us); + + // Gain: 1x = 1024 + /** @brief Get sensor current AE gain + @param[in] handle Handle to sensor driver. + @param[out] gain Receive current AE gain + @retval Return SUCCESS or FAIL if error occurs. + @remark gain: 1x = 1024 + */ + int (*pCus_sensor_GetAEGain)(struct __ms_cus_sensor* handle, u32* gain); + + /** @brief Set sensor AE gain + @param[in] handle Handle to sensor driver. + @param[in] gain AE gain + @retval Return SUCCESS or FAIL if error occurs. + @remark gain: 1x = 1024 + */ + int (*pCus_sensor_SetAEGain)(struct __ms_cus_sensor* handle, u32 gain); + + /** @brief Get supported shutter range + @param[in] handle Handle to sensor driver. + @param[out] min Receive minimum shutter which sensor can supported + @param[out] min Receive maxiimum shutter which sensor can supported + @retval Return SUCCESS or FAIL if error occurs. + @remark gain: 1x = 1024 + */ + int (*pCus_sensor_GetAEMinMaxUSecs)(struct __ms_cus_sensor* handle, u32 *min, u32 *max); + + /** @brief Get supported AE gain range + @param[in] handle Handle to sensor driver. + @param[out] min Receive minimum gain which sensor can supported + @param[out] min Receive maxiimum gain which sensor can supported + @retval Return SUCCESS or FAIL if error occurs. + @remark gain: 1x = 1024 + */ + int (*pCus_sensor_GetAEMinMaxGain)(struct __ms_cus_sensor* handle, u32 *min, u32 *max); + + // frame rate control + /** @brief Get current fps + @param[in] handle Handle to sensor driver. + @retval Return current frame rate per second + */ + int (*pCus_sensor_GetFPS)(struct __ms_cus_sensor* handle); + + /** @brief Set sensor output fps + @param[in] handle Handle to sensor driver. + @param[in] fps + @retval Return SUCCESS or FAIL if fps is out of range. + */ + int (*pCus_sensor_SetFPS)(struct __ms_cus_sensor* handle, u32 fps); + + //[OPTIONAL] sensor calibration + /** @brief Optional function */ + int (*pCus_sensor_SetAEGain_cal)(struct __ms_cus_sensor* handle, u32); + + /** @brief Optional function */ + int (*pCus_sensor_setCaliData_gain_linearity)(struct __ms_cus_sensor* handle, CUS_GAIN_GAP_ARRAY* pArray ,u32 num); + + //Get shutter information + /** @brief Get shutter information + @param[in] handle Handle to sensor driver. + @param[out] info return shutter information. + @retval Return current frame rate per second + */ + int (*pCus_sensor_GetShutterInfo)(struct __ms_cus_sensor* handle,CUS_SHUTTER_INFO *info); + + /** @brief Get resolution list number + @param[in] handle Handle to sensor driver. + @param[out] ulres_num resolution list number + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_GetVideoResNum)(struct __ms_cus_sensor* handle, u32 *ulres_num); + + //Get shutter information + /** @brief Sensor vendor command + @param[in] handle Handle to sensor driver. + @param[in] reserved + @param[in] param Command input + @param[out] out Command output + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_CustDefineFunction)(struct __ms_cus_sensor* handle,u32 cmd_id, void *param); + + //Get Source Type + /** @brief Get Source Type + @param[in] handle Handle to sensor driver. + @param[out] psrc_type info + @retval Return SUCCESS or FAIL if error occurs. + */ + int (*pCus_sensor_GetSrcType)(struct __ms_cus_sensor* handle, CUS_SNR_ANADEC_SRC_TYPE *psrc_type); + +} ms_cus_sensor; + +/** @brief Sensor driver entry. ISP call this function before start using sensor driver. \n +ISP pass \ref ms_cus_sensor struct to obtain the driver information and function entries. \n +And all allocated resources here should be released at \ref __ms_cus_sensor::pCus_sensor_release. +Every sensor driver must implement this api. +@param[in] drv_handle A uninitialized \ref ms_cus_sensor struct from ISP, Sensor driver fill the driver information and function entries to drv_handle. +@retval SUCCESS or FAIL if error occurs. +*/ + +typedef int (*SensorInitHandle)(ms_cus_sensor* handle); + +#ifdef __cplusplus +} +#endif + +#endif /* DRV_MS_CUS_SENSOR_H_ */ +/** @} */ // end of ISP Sensor Driver Interface diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/drivers/sensorif/sensor_i2c_api.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/drivers/sensorif/sensor_i2c_api.h new file mode 100644 index 000000000..7463bddf4 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/drivers/sensorif/sensor_i2c_api.h @@ -0,0 +1,161 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +Sigmastar Technology Corp. and be kept in strict confidence +(Sigmastar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of Sigmastar Confidential +Information is unlawful and strictly prohibited. Sigmastar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/*! @file isp_i2c_api.h + @brief This file contains Infinity ISP I2C basic API. +*/ + +/** @defgroup group1 ISP I2C API +* @{ +*/ + +#ifndef ISP_I2C_API_H +#define ISP_I2C_API_H + +#define SENSOR_I2C_SUCCESS (0) +#define SENSOR_I2C_FAIL (-1) +#define SENSOR_I2C_NOT_SUPPORT (-2) + +/*! @brief I2C API handle.*/ +struct __i2c_handle_t; + +/*! @brief I2C batch read/write data.*/ +typedef struct _I2C_ARRAY{ + u16 reg; /**< Register address.*/ + u16 data; /**< Data.*/ +} I2C_ARRAY; + +/*! @brief I2C burst read/write data.*/ +typedef struct _I2C_ARRAY_BURST{ + u16 reg; /**< Register address.*/ + u16 *data; /**< Data.*/ +} I2C_ARRAY_BURST; + +/*! @brief I2C data direction*/ +typedef enum { + I2C_RW_R, /**< Data direction read.*/ + I2C_RW_W,/**< Data direction write.*/ +} I2C_RW; + +/*! @brief Use for i2c_array_rw only */ +typedef struct _I2C_CPX_ARRAY{ + I2C_RW rw; /**< Data direction */ + u16 reg; /**< Device register address */ + u16 data; /**< Data write to device or read from device*/ +}__attribute__((packed, aligned(1))) I2C_CPX_ARRAY; + +/*! @brief Internal use for I2C API*/ +typedef enum { + I2C_FMT_A8D8, /**< 8 bits Address, 8 bits Data */ + I2C_FMT_A16D8,/**< 16 bits Address 8 bits Data */ + I2C_FMT_A8D16,/**< 8 bits Address 16 bits Data */ + I2C_FMT_A16D16,/**< 16 bits Address 16 bits Data */ + I2C_FMT_END/**< Reserved */ +} ISP_I2C_FMT; + +/*! @brief ISP_I2C_MODE Internal use for I2C API*/ +typedef enum { + I2C_LEGACY_MODE, /**< Do not use */ + I2C_NORMAL_MODE /**< Sensor driver can only use I2C_NORMAL_MODE */ +} ISP_I2C_MODE; + + +/*! @brief app_i2c_cfg I2C setting for sensor and bus.*/ +typedef struct _app_i2c_cfg{ + ISP_I2C_MODE mode; //!< I2C_NORMAL_MODE only + ISP_I2C_FMT fmt; //!< I2C data format + u32 speed; //!< I2C clock in Hz + u16 address; //!< Sensor slave address , bit[7~1] are available, bit[0] user don't care + u16 reserved; +}__attribute__((packed, aligned(1))) app_i2c_cfg; + +/*! @brief The interface of I2C APIs export to user*/ +typedef struct _i2c_handle_t { + int version; + void *pdata; //i2c_private_data + + u32 nSensorID; + /** @brief Open isp i2c port. This function must be called before using isp I2C APIs. + Call i2c_close to close isp i2c port and allocated resource. + @param[in] handle Handle to isp i2c api. + @param[in] cfg I2C initial configuration. + @retval SENSOR_I2C_SUCCESS or SENSOR_I2C_FAIL if error occurs. + */ + int (*i2c_open)(struct _i2c_handle_t* handle, app_i2c_cfg *cfg); + + /** @brief Close isp I2C port. Call this functon to release resource which allocated form i2c_open. + @param[in] handle Handle to isp i2c api. + @param[in] cfg I2C configuration mode and spped are necessary in this stage. + @retval SENSOR_I2C_SUCCESS or SENSOR_I2C_FAIL if error occurs. + */ + int (*i2c_close)(struct _i2c_handle_t* handle ); + + /** @brief Write single data to device. + @param[in] handle Handle to isp i2c api. + @param[in] cfg I2C config, fmd and address are necessary in this stage. + @param[in] reg Device register address address width depend on cfg->fmt. + @param[in] data Data to write, data width depend on cfg->fmt. + @retval SENSOR_I2C_SUCCESS or SENSOR_I2C_FAIL if error occurs. + */ + int (*i2c_tx)(struct _i2c_handle_t* handle , app_i2c_cfg cfg, short reg, short data); + + /** @brief Read single data from device. + @param[in] handle Handle to isp i2c api. + @param[in] cfg I2C config, fmd and address are necessary in this stage. + @param[in] reg Device register address address width depend on cfg->fmt. + @param[out] data Data buffer for read, data width depend on cfg->fmt. + @retval SENSOR_I2C_SUCCESS or SENSOR_I2C_FAIL if error occurs. + */ + int (*i2c_rx)(struct _i2c_handle_t* handle, app_i2c_cfg cfg, short reg, volatile short *data); + + /** @brief Batch write to device. + @param[in] handle Handle to isp i2c api. + @param[in] cfg I2C config, fmd and address are necessary in this stage. + @param[in] pdata Data array. + @param[in] len Array size. + @retval SENSOR_I2C_SUCCESS or SENSOR_I2C_FAIL if error occurs. + */ + int (*i2c_array_tx)(struct _i2c_handle_t* handle, app_i2c_cfg cfg, I2C_ARRAY *pdata, int len); + + /** @brief Burst write to device. + @param[in] handle Handle to isp i2c api. + @param[in] cfg I2C config, fmd and address are necessary in this stage. + @param[in] pdata Data array. + @param[in] len Array size. + @retval SENSOR_I2C_SUCCESS or SENSOR_I2C_FAIL if error occurs. + */ + int (*i2c_burst_tx)(struct _i2c_handle_t* handle, app_i2c_cfg cfg, I2C_ARRAY_BURST *pdata, int len); + + /** @brief Batch read from device. + @param[in] handle Handle to isp i2c api. + @param[in] cfg I2C config, fmd and address are necessary in this stage. + @param[out] pdata Data array. + @param[in] len Array size. + @retval SENSOR_I2C_SUCCESS or SENSOR_I2C_FAIL if error occurs. + */ + int (*i2c_array_rx)(struct _i2c_handle_t* handle, app_i2c_cfg cfg, I2C_ARRAY *pdata, int len); + + /** @brief Composite batch read/write + @param[in] handle Handle to isp i2c api. + @param[in] cfg I2C config, fmd and address are necessary in this stage. + @param[in][out] pdata Data description array. + @param[in] len Array size. + @retval SENSOR_I2C_SUCCESS or SENSOR_I2C_FAIL if error occurs. + */ + int (*i2c_array_rw)(struct _i2c_handle_t* handle, app_i2c_cfg cfg, I2C_CPX_ARRAY *pdata, int len); +} i2c_handle_t; + +/** @} */ // end of ISP I2C API + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/mi_ipu.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/mi_ipu.h new file mode 100644 index 000000000..142f1832c --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/mi_ipu.h @@ -0,0 +1,66 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_IPU_H_ +#define _MI_IPU_H_ + +#include "mi_common.h" +#include "mi_common_datatype.h" +#include "mi_sys_datatype.h" +#include "cam_os_wrapper.h" +#include "mi_ipu_datatype.h" + +//#define PERFORMANCE_DEBUG +//#define IPU_DEBUG +#define ipu_err(fmt, args...) CamOsPrintf(fmt, ##args) + +#ifdef IPU_DEBUG +#define ipu_info(fmt, args...) CamOsPrintf(fmt,##args) +#else +#define ipu_info(fmt, args...) +#endif + + +#define IPU_MAJOR_VERSION 1 +#define IPU_SUB_VERSION 0 +#define MACRO_TO_STR(macro) #macro +#define IPU_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_ipu_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_ipu_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_ipu_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_IPU_API_VERSION IPU_VERSION_STR(IPU_MAJOR_VERSION,IPU_SUB_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + +MI_S32 MI_IPU_CreateDevice(MI_IPU_DevAttr_t *pstIPUDevAttr, SerializedReadFunc pReadFunc, char *pReadCtx, MI_U32 FWSize); +MI_S32 MI_IPU_DestroyDevice(void); +MI_S32 MI_IPU_CreateCHN(MI_IPU_CHN *ptChnId, MI_IPUChnAttr_t *pstIPUChnAttr,SerializedReadFunc pReadFunc, char *pReadCtx); +MI_S32 MI_IPU_DestroyCHN(MI_IPU_CHN u32ChnId); +MI_S32 MI_IPU_GetInOutTensorDesc(MI_IPU_CHN u32ChnId, MI_IPU_SubNet_InputOutputDesc_t *pstDesc); +MI_S32 MI_IPU_GetInputTensors(MI_IPU_CHN u32ChnId, MI_IPU_TensorVector_t *pstInputTensorVector); +MI_S32 MI_IPU_PutInputTensors(MI_IPU_CHN u32ChnId, MI_IPU_TensorVector_t *pstInputTensorVector); +MI_S32 MI_IPU_GetOutputTensors(MI_IPU_CHN u32ChnId, MI_IPU_TensorVector_t *pstInputTensorVector); +MI_S32 MI_IPU_PutOutputTensors(MI_IPU_CHN u32ChnId, MI_IPU_TensorVector_t *pstInputTensorVector); +MI_S32 MI_IPU_Invoke(MI_IPU_CHN u32ChnId, MI_IPU_TensorVector_t *pstInputTensorVector, MI_IPU_TensorVector_t *pstOuputTensorVector); +MI_S32 MI_IPU_GetOfflineModeStaticInfo(SerializedReadFunc pReadFunc, char *pReadCtx, MI_IPU_OfflineModelStaticInfo_t *pStaticInfo); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/pudding/mi_ipu_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/pudding/mi_ipu_datatype.h new file mode 100644 index 000000000..d7d314bac --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/pudding/mi_ipu_datatype.h @@ -0,0 +1,134 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_IPU_DATATYPE_H_ +#define _MI_IPU_DATATYPE_H_ + + +#define MI_IPU_MAX_TENSOR_DIM 8 +#define MI_IPU_CHN_MAX 48 +#define MI_IPU_MAX_INPUT_TENSOR_CNT 61 +#define MI_IPU_MAX_OUTPUT_TENSOR_CNT 61 +#define MI_IPU_MAX_TENSOR_CNT \ + ((MI_IPU_MAX_INPUT_TENSOR_CNT>MI_IPU_MAX_OUTPUT_TENSOR_CNT)? \ + MI_IPU_MAX_INPUT_TENSOR_CNT:MI_IPU_MAX_OUTPUT_TENSOR_CNT) + +#define MAX_TENSOR_NAME_LEN 256 +#define MAX_IPU_INPUT_OUTPUT_BUF_DEPTH 3 +#define MI_IPU_MAX_TIMEOUT (20*1000) //20 seconds +#define MI_IPU_BOOT_MAX_TIMEOUT (5*1000) //5 seconds + +#define YUV420_W_PITCH_ALIGNMENT 16 +#define YUV420_H_PITCH_ALIGNMENT 2 +#define XRGB_W_PITCH_ALIGNMENT 16 + + +typedef MI_U32 MI_IPU_CHN; +typedef int (*SerializedReadFunc)(void *dst_buf,int offset, int size, char *ctx); + +typedef enum +{ + MI_IPU_FORMAT_U8, + MI_IPU_FORMAT_NV12, + MI_IPU_FORMAT_INT16, + MI_IPU_FORMAT_INT32, + MI_IPU_FORMAT_INT8, + MI_IPU_FORMAT_FP32, + MI_IPU_FORMAT_UNKNOWN, + MI_IPU_FORMAT_ARGB8888, + MI_IPU_FORMAT_ABGR8888, +} MI_IPU_ELEMENT_FORMAT; + +typedef enum +{ + E_IPU_ERR_INVALID_CHNID = 1, /* invalid channel ID */ + E_IPU_ERR_CHNID_EXIST, /* channel exists */ + E_IPU_ERR_CHNID_UNEXIST, /* channel unexists */ + E_IPU_ERR_NOMEM, /* failure caused by malloc memory */ + E_IPU_ERR_NOBUF, /* failure caused by malloc buffer */ + E_IPU_ERR_BADADDR, /* bad address, buffer address doesn't get from IPU buffer allocator */ + E_IPU_ERR_SYS_TIMEOUT, /* system timeout*/ + E_IPU_ERR_FILE_OPERATION, /* file cannot be open or read or write */ + E_IPU_ERR_ILLEGAL_TENSOR_BUFFER_SIZE, /* tensor buffer size cannot meet the requirement, usually less than requirement*/ + E_IPU_ERR_ILLEGAL_BUFFER_DEPTH, /* input or output buffer depth quantum is more than maximum number */ + E_IPU_ERR_ILLEGAL_INPUT_OUTPUT_DESC, /* network description is illegal, usually mean input or output buffer quantum is wrong */ + E_IPU_ERR_ILLEGAL_INPUT_OUTPUT_PARAM, /* user's input or output buffer quantum isn't match network description */ + E_IPU_ERR_MAP, /* address mapping error */ + E_IPU_ERR_INIT_FIRMWARE, /* fail to init ipu firmware */ + E_IPU_ERR_CREATE_CHANNEL, /* fail to create channel */ + E_IPU_ERR_DESTROY_CHANNEL, /* fail to destroy channel */ + E_IPU_ERR_INVOKE, /* fail to invoke */ + E_IPU_ERR_SET_MALLOC_REGION, /* fail to set malloc region for freertos */ + E_IPU_ERR_SET_IPU_PARAMETER, /* fail to set IPU parameter */ + E_IPU_ERR_INVALID_PITCH_ALIGNMENT, /* invalid pitch alignment */ + E_IPU_ERR_NO_CREATED_IPU_DEVICE, /* there is no created IPU device */ + E_IPU_ERR_GET_IPU_VERSION, /* fail to get ipu version from ipu firmware */ + E_IPU_ERR_MISMATCH_IPU_HEAD_FILE, /* ipu head files version isn't matching */ + E_IPU_ERR_NO_SUPPORT_REQ, /* ipu firmware do not support this request */ + E_IPU_ERR_FAILED, /* unexpected error */ + E_IPU_ERR_SEND_REQUEST, /* failt to send request to IPU */ + E_IPU_ERR_GET_FIRMWARE_INFO, /* fail to get ipu firmware information */ + E_IPU_ERR_NO_AVAILABLE_CHNID = 1<<8, /* there is no available channel */ +}IPU_ErrCode_e; + +typedef struct MI_IPU_TensorDesc_s { + MI_U32 u32TensorDim; + MI_IPU_ELEMENT_FORMAT eElmFormat; + MI_U32 u32TensorShape[MI_IPU_MAX_TENSOR_DIM]; // 3,299,299 + char name[MAX_TENSOR_NAME_LEN]; + MI_U32 u32InnerMostStride; + MI_FLOAT fScalar; + MI_S64 s64ZeroPoint; + MI_S32 s32AlignedBufSize; +} MI_IPU_TensorDesc_t; + +typedef struct MI_IPU_SubNet_InputOutputDesc_s { + MI_U32 u32InputTensorCount; + MI_U32 u32OutputTensorCount; + MI_IPU_TensorDesc_t astMI_InputTensorDescs[MI_IPU_MAX_INPUT_TENSOR_CNT]; + MI_IPU_TensorDesc_t astMI_OutputTensorDescs[MI_IPU_MAX_OUTPUT_TENSOR_CNT]; +} MI_IPU_SubNet_InputOutputDesc_t; + +typedef struct MI_IPU_Tensor_s { + //MI_IPU_TensorShape_t *pstTensorShape; + //MI_BOOL bRewiseRGBOrder;//only valid under U8 & C=3,4 or NV12 + void *ptTensorData[2]; + MI_PHY phyTensorAddr[2];//notice that this is miu bus addr,not cpu bus addr. +} MI_IPU_Tensor_t; + +typedef struct MI_IPU_TensorVector_s { + MI_U32 u32TensorCount; + MI_IPU_Tensor_t astArrayTensors[MI_IPU_MAX_TENSOR_CNT]; +} MI_IPU_TensorVector_t; + +typedef struct MI_IPU_DevAttr_s { + MI_U32 u32MaxVariableBufSize; + MI_U32 u32YUV420_W_Pitch_Alignment; //default is 16 + MI_U32 u32YUV420_H_Pitch_Alignment; //default is 2 + MI_U32 u32XRGB_W_Pitch_Alignment; //default is 16 +} MI_IPU_DevAttr_t; + +typedef struct MI_IPUChnAttr_s { + MI_U32 u32SubNetId; + MI_U32 u32OutputBufDepth; + MI_U32 u32InputBufDepth; +} MI_IPUChnAttr_t; + +typedef struct MI_IPU_OfflineModelStaticInfo_s { + MI_U32 u32VariableBufferSize; + MI_U32 u32OfflineModelSize; +} MI_IPU_OfflineModelStaticInfo_t; + +#endif // !_MI_IPU_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/tiramisu/mi_ipu_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/tiramisu/mi_ipu_datatype.h new file mode 100644 index 000000000..c222174ad --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/ipu/tiramisu/mi_ipu_datatype.h @@ -0,0 +1,134 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_IPU_DATATYPE_H_ +#define _MI_IPU_DATATYPE_H_ + + +#define MI_IPU_MAX_TENSOR_DIM 8 +#define MI_IPU_CHN_MAX 16 +#define MI_IPU_MAX_INPUT_TENSOR_CNT 61 +#define MI_IPU_MAX_OUTPUT_TENSOR_CNT 61 +#define MI_IPU_MAX_TENSOR_CNT \ + ((MI_IPU_MAX_INPUT_TENSOR_CNT>MI_IPU_MAX_OUTPUT_TENSOR_CNT)? \ + MI_IPU_MAX_INPUT_TENSOR_CNT:MI_IPU_MAX_OUTPUT_TENSOR_CNT) + +#define MAX_TENSOR_NAME_LEN 256 +#define MAX_IPU_INPUT_OUTPUT_BUF_DEPTH 3 +#define MI_IPU_MAX_TIMEOUT (20*1000) //20 seconds +#define MI_IPU_BOOT_MAX_TIMEOUT (5*1000) //5 seconds + +#define YUV420_W_PITCH_ALIGNMENT 16 +#define YUV420_H_PITCH_ALIGNMENT 2 +#define XRGB_W_PITCH_ALIGNMENT 16 + + +typedef MI_U32 MI_IPU_CHN; +typedef int (*SerializedReadFunc)(void *dst_buf,int offset, int size, char *ctx); + +typedef enum +{ + MI_IPU_FORMAT_U8, + MI_IPU_FORMAT_NV12, + MI_IPU_FORMAT_INT16, + MI_IPU_FORMAT_INT32, + MI_IPU_FORMAT_INT8, + MI_IPU_FORMAT_FP32, + MI_IPU_FORMAT_UNKNOWN, + MI_IPU_FORMAT_ARGB8888, + MI_IPU_FORMAT_ABGR8888, +} MI_IPU_ELEMENT_FORMAT; + +typedef enum +{ + E_IPU_ERR_INVALID_CHNID = 1, /* invalid channel ID */ + E_IPU_ERR_CHNID_EXIST, /* channel exists */ + E_IPU_ERR_CHNID_UNEXIST, /* channel unexists */ + E_IPU_ERR_NOMEM, /* failure caused by malloc memory */ + E_IPU_ERR_NOBUF, /* failure caused by malloc buffer */ + E_IPU_ERR_BADADDR, /* bad address, buffer address doesn't get from IPU buffer allocator */ + E_IPU_ERR_SYS_TIMEOUT, /* system timeout*/ + E_IPU_ERR_FILE_OPERATION, /* file cannot be open or read or write */ + E_IPU_ERR_ILLEGAL_TENSOR_BUFFER_SIZE, /* tensor buffer size cannot meet the requirement, usually less than requirement*/ + E_IPU_ERR_ILLEGAL_BUFFER_DEPTH, /* input or output buffer depth quantum is more than maximum number */ + E_IPU_ERR_ILLEGAL_INPUT_OUTPUT_DESC, /* network description is illegal, usually mean input or output buffer quantum is wrong */ + E_IPU_ERR_ILLEGAL_INPUT_OUTPUT_PARAM, /* user's input or output buffer quantum isn't match network description */ + E_IPU_ERR_MAP, /* address mapping error */ + E_IPU_ERR_INIT_FIRMWARE, /* fail to init ipu firmware */ + E_IPU_ERR_CREATE_CHANNEL, /* fail to create channel */ + E_IPU_ERR_DESTROY_CHANNEL, /* fail to destroy channel */ + E_IPU_ERR_INVOKE, /* fail to invoke */ + E_IPU_ERR_SET_MALLOC_REGION, /* fail to set malloc region for freertos */ + E_IPU_ERR_SET_IPU_PARAMETER, /* fail to set IPU parameter */ + E_IPU_ERR_INVALID_PITCH_ALIGNMENT, /* invalid pitch alignment */ + E_IPU_ERR_NO_CREATED_IPU_DEVICE, /* there is no created IPU device */ + E_IPU_ERR_GET_IPU_VERSION, /* fail to get ipu version from ipu firmware */ + E_IPU_ERR_MISMATCH_IPU_HEAD_FILE, /* ipu head files version isn't matching */ + E_IPU_ERR_NO_SUPPORT_REQ, /* ipu firmware do not support this request */ + E_IPU_ERR_FAILED, /* unexpected error */ + E_IPU_ERR_SEND_REQUEST, /* failt to send request to IPU */ + E_IPU_ERR_GET_FIRMWARE_INFO, /* fail to get ipu firmware information */ + E_IPU_ERR_NO_AVAILABLE_CHNID = 1<<8, /* there is no available channel */ +}IPU_ErrCode_e; + +typedef struct MI_IPU_TensorDesc_s { + MI_U32 u32TensorDim; + MI_IPU_ELEMENT_FORMAT eElmFormat; + MI_U32 u32TensorShape[MI_IPU_MAX_TENSOR_DIM]; // 3,299,299 + char name[MAX_TENSOR_NAME_LEN]; + MI_U32 u32InnerMostStride; + MI_FLOAT fScalar; + MI_S64 s64ZeroPoint; + MI_S32 s32AlignedBufSize; +} MI_IPU_TensorDesc_t; + +typedef struct MI_IPU_SubNet_InputOutputDesc_s { + MI_U32 u32InputTensorCount; + MI_U32 u32OutputTensorCount; + MI_IPU_TensorDesc_t astMI_InputTensorDescs[MI_IPU_MAX_INPUT_TENSOR_CNT]; + MI_IPU_TensorDesc_t astMI_OutputTensorDescs[MI_IPU_MAX_OUTPUT_TENSOR_CNT]; +} MI_IPU_SubNet_InputOutputDesc_t; + +typedef struct MI_IPU_Tensor_s { + //MI_IPU_TensorShape_t *pstTensorShape; + //MI_BOOL bRewiseRGBOrder;//only valid under U8 & C=3,4 or NV12 + void *ptTensorData[2]; + MI_PHY phyTensorAddr[2];//notice that this is miu bus addr,not cpu bus addr. +} MI_IPU_Tensor_t; + +typedef struct MI_IPU_TensorVector_s { + MI_U32 u32TensorCount; + MI_IPU_Tensor_t astArrayTensors[MI_IPU_MAX_TENSOR_CNT]; +} MI_IPU_TensorVector_t; + +typedef struct MI_IPU_DevAttr_s { + MI_U32 u32MaxVariableBufSize; + MI_U32 u32YUV420_W_Pitch_Alignment; //default is 16 + MI_U32 u32YUV420_H_Pitch_Alignment; //default is 2 + MI_U32 u32XRGB_W_Pitch_Alignment; //default is 16 +} MI_IPU_DevAttr_t; + +typedef struct MI_IPUChnAttr_s { + MI_U32 u32SubNetId; + MI_U32 u32OutputBufDepth; + MI_U32 u32InputBufDepth; +} MI_IPUChnAttr_t; + +typedef struct MI_IPU_OfflineModelStaticInfo_s { + MI_U32 u32VariableBufferSize; + MI_U32 u32OfflineModelSize; +} MI_IPU_OfflineModelStaticInfo_t; + +#endif // !_MI_IPU_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ikayaki/mi_isp_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ikayaki/mi_isp_datatype.h new file mode 100644 index 000000000..b058e1868 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ikayaki/mi_isp_datatype.h @@ -0,0 +1,430 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp_datatype.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_ISP_DATATYPE_H_ +#define _MI_ISP_DATATYPE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mi_common.h" +#include "mi_sys_datatype.h" +#include "mi_isp_3a_datatype.h" +#include "mi_isp_iq_datatype.h" + +/************************************* AF - Define the structure declaration - START *************************************/ + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************** Cus3A ***********************/ + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; + MI_U8 uAvgY; +} MI_ISP_AE_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AE_AVGS nAvg[128*90]; +}MI_ISP_AE_HW_STATISTICS_t; + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; +} MI_ISP_AWB_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AWB_AVGS nAvg[128*90]; +} MI_ISP_AWB_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[128]; +} MI_ISP_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[256]; +} MI_ISP_RGBIR_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_BOOL bAE; + MI_BOOL bAWB; + MI_BOOL bAF; +}Cus3AEnable_t; + +typedef struct +{ + MI_U32 Size; /**< struct size*/ + char sensor_id[32]; /**< sensor module id*/ + MI_U32 shutter; /**< shutter Shutter in ns*/ + MI_U32 shutter_step; /**< shutter Shutter step ns*/ + MI_U32 shutter_min; /**< shutter Shutter min us*/ + MI_U32 shutter_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gain; /**< sensor_gain Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + MI_U32 isp_gain; /**< isp_gain Isp digital gain , 1X = 1024 */ + MI_U32 isp_gain_max; /**< isp_gain Maximum Isp digital gain , 1X = 1024 */ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 fps; /**< initial frame per second*/ + MI_U32 shutterHDRShort_step; /**< shutter Shutter step ns*/ + MI_U32 shutterHDRShort_min; /**< shutter Shutter min us*/ + MI_U32 shutterHDRShort_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gainHDRShort_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gainHDRShort_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + /*CUS3A v1.1*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ +}CusAEInitParam_t,CusAeInitParam_t; + +/*! @brief ISP report to AE, hardware statistic */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + void *hist1; /**< HW statistic histogram 1*/ + void *hist2; /**< HW statistic histogram 2*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ + void * avgs; /**< HW statistics average block data*/ + MI_U32 Shutter; /**< Current shutter in ns*/ + MI_U32 SensorGain; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< Current ISP gain, 1X = 1024*/ + MI_U32 ShutterHDRShort; /**< Current shutter in ns*/ + MI_U32 SensorGainHDRShort; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGainHDRShort; /**< Current ISP gain, 1X = 1024*/ + /*CUS3A V1.1*/ + MI_U32 PreAvgY; /**< Previous frame brightness*/ + MI_U8 HDRCtlMode; /**< 0 = HDR off; */ + /**< 1 = Separate shutter & Separate sensor gain settings */ + /**< 2 = Separate shutter & Share sensor gain settings */ + /**< 3 = Share shutter & Separate sensor gain settings */ + MI_U32 FNx10; /**< Aperture in FNx10*/ + MI_U32 CurFPS; /**Current sensor FPS */ + MI_U32 PreWeightY; /**< Previous frame brightness with ROI weight*/ +} __attribute__((packed, aligned(1))) CusAEInfo_t, CusAeInput_t; + +/*! @brief ISP ae algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 Shutter; /**< Shutter in ns */ + MI_U32 SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< ISP gain, 1X = 1024 */ + MI_U32 ShutterHdrShort; /**< Shutter in ns */ + MI_U32 SensorGainHdrShort; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGainHdrShort; /**< ISP gain, 1X = 1024 */ + MI_U32 u4BVx16384; /**< Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_U32 AvgY; /**< frame brightness */ + MI_U32 HdrRatio; /**< hdr ratio, 1X = 1024 */ + /*CUS3A V1.1*/ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 DebandFPS; /** Target fps when running auto debanding**/ + MI_U32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAEResult_t, CusAeOutput_t; + +/*! @brief AWB HW statistics data*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 AvgBlkX; + MI_U32 AvgBlkY; + MI_U32 CurRGain; + MI_U32 CurGGain; + MI_U32 CurBGain; + void *avgs; //ISP_AWB_SAMPLE + /*CUS3A V1.1*/ + MI_U8 HDRMode; /**< Noramal or HDR mode*/ + void* *pAwbStatisShort; /**< Short Shutter AWB statistic data */ + MI_U32 u4BVx16384; /**< From AE output, Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_S32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAWBInfo_t, CusAWBInput_t; + +/*! @brief AWB algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 R_gain; /**< AWB gain for R channel*/ + MI_U32 G_gain; /**< AWB gain for G channel*/ + MI_U32 B_gain; /**< AWB gain for B channel*/ + MI_U32 ColorTmp; /**< Return color temperature*/ +}CusAWBResult_t, CusAwbOutput_t;; + +typedef enum __attribute__ ((aligned (1))) +{ + SS_AE_16x24 = 0, + SS_AE_32x24, + SS_AE_64x48, + SS_AE_64x45, + SS_AE_128x80, + SS_AE_128x90, + SS_AE_32x32 +} MS_CUST_AE_WIN_BLOCK_NUM_TYPE_e; + +typedef struct { + MI_U16 u2Stawin_x_offset; + MI_U16 u2Stawin_x_size; + MI_U16 u2Stawin_y_offset; + MI_U16 u2Stawin_y_size; + MI_U16 u2WinIdx; +} CusAEHistWin_t; + +typedef struct +{ + MI_U32 SizeX; + MI_U32 SizeY; + MI_U32 IncRatio; +}CusAWBSample_t; + +typedef struct +{ + MI_U16 CropX; // 0~1023 + MI_U16 CropY; // 0~1023 + MI_U16 CropW; // 0~1023 + MI_U16 CropH; // 0~1023 +}CusAEAWBCropSize_t; + +typedef struct +{ + MI_U8 iir_1[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 iir_2[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 luma[4*16]; //[4]: luma 32bit, use 4*u8 datatype, [16]: 16wins + MI_U8 fir_v[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 fir_h[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 ysat[3*16]; //[3]: ysat 22bit, use 3*u8 datatype, [16]: 16wins +} AF_STATS_PARAM_t; + +typedef struct +{ + AF_STATS_PARAM_t stParaAPI[16]; +} CusAFStats_t; + +typedef struct AF_WINDOW_PARAM_s +{ + MI_U32 u32StartX; /*range : 0~1023*/ + MI_U32 u32StartY; /*range : 0~1023*/ + MI_U32 u32EndX; /*range : 0~1023*/ + MI_U32 u32EndY; /*range : 0~1023*/ +} AF_WINDOW_PARAM_t; + +typedef struct +{ + MI_U8 u8WindowIndex; + AF_WINDOW_PARAM_t stParaAPI; +} CusAFWin_t; + +typedef struct +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; + + MI_U16 u16IIR1_e1_en; + MI_U16 u16IIR1_e1_a0; + MI_U16 u16IIR1_e1_a1; + MI_U16 u16IIR1_e1_a2; + MI_U16 u16IIR1_e1_b1; + MI_U16 u16IIR1_e1_b2; + MI_U16 u16IIR1_e2_en; + MI_U16 u16IIR1_e2_a0; + MI_U16 u16IIR1_e2_a1; + MI_U16 u16IIR1_e2_a2; + MI_U16 u16IIR1_e2_b1; + MI_U16 u16IIR1_e2_b2; + + MI_U16 u16IIR2_e1_en; + MI_U16 u16IIR2_e1_a0; + MI_U16 u16IIR2_e1_a1; + MI_U16 u16IIR2_e1_a2; + MI_U16 u16IIR2_e1_b1; + MI_U16 u16IIR2_e1_b2; + MI_U16 u16IIR2_e2_en; + MI_U16 u16IIR2_e2_a0; + MI_U16 u16IIR2_e2_a1; + MI_U16 u16IIR2_e2_a2; + MI_U16 u16IIR2_e2_b1; + MI_U16 u16IIR2_e2_b2; +} CusAFFilter_t; + +typedef struct +{ + MI_U16 u16Coeff[70]; +} CusAFFilter_Geo_t; + +typedef struct +{ + MI_BOOL bSobelYSatEn; + MI_U16 u16SobelYThd; + + MI_BOOL bIIRSquareAccEn; + MI_BOOL bSobelSquareAccEn; + + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} CusAFFilterSq_t; + + +typedef enum __attribute__ ((aligned (1))) +{ + AF_ROI_MODE_NORMAL, + AF_ROI_MODE_MATRIX +} ISP_AF_ROI_MODE_e; + +typedef struct +{ + ISP_AF_ROI_MODE_e mode; + MI_U32 u32_vertical_block_number; +} CusAFRoiMode_t; + +/* Raw store control */ +typedef enum +{ + eRawStoreNode_P0HEAD = 0, /* Control by VIF, Do not use */ + eRawStoreNode_P1HEAD = 1, /* Control by VIF, Do not use */ + eRawStoreNode_P0TAIL = 2, + eRawStoreNode_P1TAIL = 3, + eRawStoreNode_ISPOUT = 4, + eRawStoreNode_VDOS = 5, + eRawStoreNode_ISPOUT_BEFORE_YEE = 6, + eRawStoreNode_RGBIR_IR_ONLY = 7 +}CameraRawStoreNode_e; + +typedef struct +{ + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusImageResolution_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; +} CusISPOutImage_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusHdrRawImage_t; + +typedef struct +{ + MI_U64 u64Pts; /** frame PTS */ + MI_U32 u32Shutter; /**< Shutter in us */ + MI_U32 u32SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 u32ColorTmp; /**< Return color temperature*/ +} IspFrameMetaInfo_t; + +/*! @brief ISP report to AF, hardware status */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 MinPos; /**< Maximum position of AF motor */ + MI_U32 MaxPos; /**< Minimum position of AF motor */ + MI_U32 CurPos; /**< Current position of AF motor */ +} __attribute__((packed, aligned(1))) CusAFInfo_t, CusAfInput_t; + +/*! @brief AF algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 NextPos; /**< Next absolute position of AF motor */ +}__attribute__((packed, aligned(1))) CusAfResult_t, CusAfOutput_t; + +typedef struct +{ + MI_U32 u32SlaveAddr; //sensor slave address + MI_U32 u32RegLen; //sensor register length , 1 or 2 bytes + MI_U32 u32DataLen; //sensor register data length, 1 or 2 bytes + MI_U32 u32I2cSpeed; //i2c speed , 100/200/300/400 KHz + MI_U32 u32Reg; //sensor register address + MI_U32 u32Data; //sensor register data +}CusSensorI2cParam_t; + +/***************************** end of Cus3A ****************************/ + +// COMMON API +typedef struct MI_ISP_API_CHANNEL_ID_TYPE_s +{ + MI_U32 u32ChannelID; +} MI_ISP_API_CHANNEL_ID_TYPE_t; + +typedef struct MI_ISP_API_USERSPACE3A_ATTR_s +{ + MI_SYS_PixelFormat_e ePixelFmt; + MI_U32 eSensorBindId; +} MI_ISP_API_USERSPACE3A_ATTR_t; + +typedef struct +{ + MI_S8 strIspRoot[64]; +} MI_ISP_ROOT_PATH_T; + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_MI_ISP_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ikayaki/mi_isp_iq_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ikayaki/mi_isp_iq_datatype.h new file mode 100644 index 000000000..ee9a9e7be --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ikayaki/mi_isp_iq_datatype.h @@ -0,0 +1,1347 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* + * iq_apiset.h + * + * Created on: 2016/8/16 + * Author: Elsa-cf.Lin + */ + +#ifndef _MI_ISP_IQ_DATATYPE_H_ +#define _MI_ISP_IQ_DATATYPE_H_ + +#include "mi_isp_3a_datatype.h" + +//put here temporarily, should add mi_isp_cali_datatype.h? + +typedef enum __attribute__ ((aligned (1))) +{ + SS_CALI_ITEM_AWB = 0, + SS_CALI_ITEM_OBC = 1, + SS_CALI_ITEM_SDC = 2, + SS_CALI_ITEM_ALSC = 3, + SS_CALI_ITEM_LSC = 4, + SS_CALI_ITEM_MAX, +} MI_ISP_CALI_ITEM_e; + +/************************************* AF - Define the structure declaration - START *************************************/ + +typedef struct MI_ISP_AF_HW_ROI_MODE_TYPE_s +{ + MI_U8 u8Mode; // 0: Normal, 1: Matrix + MI_U32 u32VerticalBlockNumber; +} MI_ISP_AF_HW_ROI_MODE_TYPE_t; + +typedef struct MI_ISP_AF_HW_WIN_TYPE_s +{ + MI_U16 u16Win[4*16]; +} MI_ISP_AF_HW_WIN_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTER_ATTR_TYPE_s +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; + + MI_U16 u16IIR1_e1_en; + MI_U16 u16IIR1_e1_a0; + MI_U16 u16IIR1_e1_a1; + MI_U16 u16IIR1_e1_a2; + MI_U16 u16IIR1_e1_b1; + MI_U16 u16IIR1_e1_b2; + MI_U16 u16IIR1_e2_en; + MI_U16 u16IIR1_e2_a0; + MI_U16 u16IIR1_e2_a1; + MI_U16 u16IIR1_e2_a2; + MI_U16 u16IIR1_e2_b1; + MI_U16 u16IIR1_e2_b2; + + MI_U16 u16IIR2_e1_en; + MI_U16 u16IIR2_e1_a0; + MI_U16 u16IIR2_e1_a1; + MI_U16 u16IIR2_e1_a2; + MI_U16 u16IIR2_e1_b1; + MI_U16 u16IIR2_e1_b2; + MI_U16 u16IIR2_e2_en; + MI_U16 u16IIR2_e2_a0; + MI_U16 u16IIR2_e2_a1; + MI_U16 u16IIR2_e2_a2; + MI_U16 u16IIR2_e2_b1; + MI_U16 u16IIR2_e2_b2; +} MI_ISP_AF_HW_FILTER_ATTR_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTERSQ_TYPE_s +{ + MI_U8 bSobelYSatEn; + MI_U16 u16SobelYThd; + MI_U8 bIIRSquareAccEn; + MI_U8 bSobelSquareAccEn; + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} MI_ISP_AF_HW_FILTERSQ_TYPE_t; + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************************* IQ - Define the structure declaration - START *************************************/ + +typedef struct +{ + MI_U16 u16NumOfPoints; + MI_S32 s32Y[16]; + MI_S32 s32X[16]; +} MI_INTP_LUT_IQ; + +#if 1 //API20 struct + +#define MI_ISP_AUTO_NUM (16) +#define ALSC_TBL_MAX 459 +#define ENABLE_CCM_COEFF_SUM_INFO 1 + +typedef enum __attribute__ ((aligned (4))) +{ + API20_AUTO = 0, //[00] + //API2.0 + API20_FPN, //[01] + API20_CCM, //[02] + API20_SAT, //[03] + API20_OBC, //[04] + API20_OBC_P1, //[05] + API20_FCOLOR, //[06] + API20_CR, //[07] + API20_NR_DeSpike, //[08] + API20_SHP, //[09] + API20_NR_3D, //[10] + API20_BRI, //[11] + API20_LIG, //[12] + API20_CST, //[13] + API20_GMA, //[14] + API20_CTG, //[15] + API20_NR_NLM, //[16] + API20_DEFOG, //[17] + API20_DRC, //[18] + API20_DPC, //[19] + API20_HSV, //[20] + API20_WDR_LOC, //[21] + API20_RGBIR, //[22] + API20_YUVGMA, //[23] + API20_HDR16to12, //[24] + API20_COLORTRANS, //[25] + API20_HDR, //[26] + API20_EFFECT, //[27] + API20_PFC, //[28] + API20_SIIR, //[29] + API20_DM, //[30] + API20_NR_3D_P1, //[31] + API20_WDRCurveAdv, //[32] + API20_MXNR, //[33] + API20_R2Y, //[34] + API20_LSC, //[35] + API20_LSC_CTRL, //[36] + API20_ALSC, //[37] + API20_ALSC_CTRL, //[38] + API20_DPC_CLUSTER, //[39] + API20_PFC_EX, //[40] + API20_HDR_EX, //[41] + API20_SHP_EX, //[42] + API20_NR_3D_EX, //[43] + API20_GNR, //[44] + API20_DUMMY, //[45] + API20_DUMMY_EX, //[46] + API20_WDRCurveFull, //[47] + API20_ADAPTIVE_GMA, //[48] + API20_XNR, //[49] + API20_TEMP, //[50] + API20_TEMP_INFO, //[51] + API20_MAX, //for para reset +} MI_ISP_API_ID_e; + +typedef struct MI_ISP_IQ_COLORTOGRAY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 +} MI_ISP_IQ_COLORTOGRAY_TYPE_t; + +typedef struct LEVEL_BASE_PARAM_s +{ + MI_U32 u32Lev; //0 ~ 100 +} LEVEL_BASE_PARAM_t; + +typedef struct LIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} LIGHTNESS_MANUAL_ATTR_t; + +typedef struct LIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} LIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_LIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + LIGHTNESS_AUTO_ATTR_t stAuto; + LIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_LIGHTNESS_TYPE_t; + +typedef struct CONTRAST_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} CONTRAST_MANUAL_ATTR_t; + +typedef struct CONTRAST_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CONTRAST_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CONTRAST_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + CONTRAST_AUTO_ATTR_t stAuto; + CONTRAST_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CONTRAST_TYPE_t; + +typedef struct BRIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} BRIGHTNESS_MANUAL_ATTR_t; + +typedef struct BRIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} BRIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_BRIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + BRIGHTNESS_AUTO_ATTR_t stAuto; + BRIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_BRIGHTNESS_TYPE_t; + + +typedef struct RGBGAMMA_PARAM_s +{ + MI_U16 u16LutR[256]; //0 ~ 4095 + MI_U16 u16LutG[256]; //0 ~ 4095 + MI_U16 u16LutB[256]; //0 ~ 4095 +} RGBGAMMA_PARAM_t; + +typedef struct RGBGAMMA_MANUAL_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI; +} RGBGAMMA_MANUAL_ATTR_t; + +typedef struct RGBGAMMA_AUTO_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBGAMMA_AUTO_ATTR_t stAuto; + RGBGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBGAMMA_TYPE_t; + +typedef struct YUVGAMMA_PAMAR_s +{ + MI_U16 u16LutY[256]; //0 ~ 1023 + MI_U16 u16LutU[128]; //0 ~ 511 + MI_U16 u16LutV[128]; //0 ~ 511 +} YUVGAMMA_PAMAR_t; + +typedef struct YUVGAMMA_MANUAL_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI; +} YUVGAMMA_MANUAL_ATTR_t; + +typedef struct YUVGAMMA_AUTO_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI[MI_ISP_AUTO_NUM]; +} YUVGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_YUVGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + YUVGAMMA_AUTO_ATTR_t stAuto; + YUVGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_YUVGAMMA_TYPE_t; + +typedef struct SATURATION_PARAM_s +{ + MI_U8 u8SatAllStr; //0 ~ 127 (32 = 1X) + MI_U8 u8SatByYSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatByYLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatBySSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatBySLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatCoring; +} SATURATION_PARAM_t; + +typedef struct SATURATION_MANUAL_ATTR_s +{ + SATURATION_PARAM_t stParaAPI; +} SATURATION_MANUAL_ATTR_t; + +typedef struct SATURATION_AUTO_ATTR_s +{ + SATURATION_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SATURATION_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SATURATION_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SATURATION_AUTO_ATTR_t stAuto; + SATURATION_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SATURATION_TYPE_t; + +typedef struct DEFOG_PARAM_s +{ + MI_U8 u8Strength; +} DEFOG_PARAM_t; + +typedef struct DEFOG_MANUAL_ATTR_s +{ + DEFOG_PARAM_t stParaAPI; +} DEFOG_MANUAL_ATTR_t; + +typedef struct DEFOG_AUTO_ATTR_s +{ + DEFOG_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DEFOG_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DEFOG_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DEFOG_AUTO_ATTR_t stAuto; + DEFOG_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEFOG_TYPE_t; + +typedef struct RGBMATRIX_PARAM_s +{ + MI_U16 u16CCTthr; +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_PARAM_t; + +typedef struct RGBMATRIX_MANUAL_ATTR_s +{ +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_MANUAL_ATTR_t; + +typedef struct RGBMATRIX_AUTO_ATTR_s +{ + MI_ISP_BOOL_e bISOActEn; //0 ~ 1 + RGBMATRIX_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBMATRIX_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBMATRIX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBMATRIX_AUTO_ATTR_t stAuto; + RGBMATRIX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBMATRIX_TYPE_t; + +typedef struct MI_ISP_IQ_CCM_INFO_TYPE_s +{ + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) + MI_U16 u16CCT; +} MI_ISP_IQ_CCM_INFO_TYPE_t; + +typedef struct FALSECOLOR_PARAM_s +{ + MI_U8 u8FreqThrd; //0~255 default:140 + MI_U8 u8EdgeScoreThrd; //0~255 default:31 + MI_U8 u8ChromaThrdOfStrengthMax; //0~127 default:10 + MI_U8 u8ChromaThrdOfStrengthMid; //0~127 default:40 + MI_U8 u8ChromaThrdOfStrengthMin; //0~127 default:80 + MI_U8 u8StrengthMid; //0~7 default:7 + MI_U8 u8StrengthMin; //0~7 default:7 +} FALSECOLOR_PARAM_t; + +typedef struct FALSECOLOR_MANUAL_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI; +} FALSECOLOR_MANUAL_ATTR_t; + +typedef struct FALSECOLOR_AUTO_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} FALSECOLOR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_FALSECOLOR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + FALSECOLOR_AUTO_ATTR_t stAuto; + FALSECOLOR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_FALSECOLOR_TYPE_t; + +typedef struct NR3D_PARAM_s +{ + MI_U8 u8MdThd; //0~255 + MI_U16 u16MdGain; //0~1023 + MI_U8 u8TfStr; //0~64 + MI_U8 u8TfStrEx; //0~64 + MI_U8 u8MdThdByY[16]; //0~255 + MI_U8 u8MdGainByY[16]; //0~255 + MI_U8 u8M2SLut[16]; //0~31 + MI_U16 u16TfLut[16]; //0~4095 + MI_U8 u8YSfBlendLut[16]; //0~16 + MI_U8 u8YSfBlendOffset; //0~16 +} NR3D_PARAM_t; + +typedef struct NR3D_MANUAL_ATTR_s +{ + NR3D_PARAM_t stParaAPI; +} NR3D_MANUAL_ATTR_t; + +typedef struct NR3D_AUTO_ATTR_s +{ + NR3D_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NR3D_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NR3D_AUTO_ATTR_t stAuto; + NR3D_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_TYPE_t; + +typedef struct NR3D_EX_PARAM_s +{ + MI_ISP_BOOL_e bAREn; //0~1 + MI_U8 u8ARLumaTh[2]; //0~255 + MI_U8 u8ARMotTh[2]; //0~255 + MI_ISP_BOOL_e bPREn; //0~1 + MI_U16 u16PRDiffTh; //0~4095 + MI_U8 u8PRRatioConf[4]; //0~16 + MI_U8 u8PRContrastTh[2]; //0~15 + MI_U8 u8PRMotTh[2]; //0~255 +} NR3D_EX_PARAM_t; + +typedef struct NR3D_EX_MANUAL_ATTR_s +{ + NR3D_EX_PARAM_t stParaAPI; +} NR3D_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + NR3D_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_EX_TYPE_t; + +typedef struct MI_ISP_IQ_NR3D_P1_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NR3D_P1_TYPE_t; + +typedef struct NRDESPIKE_PARAM_s +{ + MI_U8 u8BlendRatio; //0 ~ 15 + MI_U8 u8StrengthCenterNeighbor; //0 ~ 5 + MI_U8 u8StrengthMeanStd; //0 ~ 5 + MI_U8 u8StrengthCornerCross; //0 ~ 5 + MI_U8 u8DiffGainMeanStd; //0 ~ 31 + MI_U8 u8DiffGainCenterNeighbor; //0 ~ 255 + MI_U8 u8DiffThdCornerCross; //0 ~ 255 + MI_U16 u16BlendLut[5]; //0 ~ 2047 + MI_U8 u8StrengthByY[15]; //0 ~ 127 +} NRDESPIKE_PARAM_t; + +typedef struct NRDESPIKE_MANUAL_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI; +} NRDESPIKE_MANUAL_ATTR_t; + +typedef struct NRDESPIKE_AUTO_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRDESPIKE_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRDESPIKE_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRDESPIKE_AUTO_ATTR_t stAuto; + NRDESPIKE_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRDESPIKE_TYPE_t; + +typedef struct NRLUMA_PARAM_s +{ + MI_U8 u8Strength; + MI_U8 u8GMaskSel; + MI_U16 u16SpfBlendLut[2]; +} NRLUMA_PARAM_t; + +typedef struct NRLUMA_MANUAL_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI; +} NRLUMA_MANUAL_ATTR_t; + +typedef struct NRLUMA_AUTO_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLUMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_AUTO_ATTR_t stAuto; + NRLUMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLUMA_TYPE_t; + +typedef struct NRLUMA_Adv_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; + MI_U8 u8Strength; + MI_U8 u8StrengthByY[10]; + MI_U8 u8StrengthByMot[16]; + MI_U16 u16EdgeTh[8]; + MI_U32 u32EdgeGain[8]; + MI_U8 u8StrengthByType[2]; +} NRLUMA_Adv_PARAM_t; + +typedef struct NRLUMA_Adv_MANUAL_ATTR_s +{ + NRLUMA_Adv_PARAM_t stParaAPI; +} NRLUMA_Adv_MANUAL_ATTR_t; + +typedef struct NRLUMA_Adv_AUTO_ATTR_s +{ + NRLUMA_Adv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_Adv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLuma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_Adv_AUTO_ATTR_t stAuto; + NRLUMA_Adv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLuma_Adv_TYPE_t; + +typedef struct NRChroma_PARAM_s +{ + MI_U8 u8MatchRatio; //0 ~ 127 + MI_U16 u16UvTh; //0 ~ 1023 + MI_U16 u16StrengthByCEdge[6]; //0 ~ 1023 +} NRChroma_PARAM_t; + +typedef struct NRChroma_MANUAL_ATTR_s +{ + NRChroma_PARAM_t stParaAPI; +} NRChroma_MANUAL_ATTR_t; + +typedef struct NRChroma_AUTO_ATTR_s +{ + NRChroma_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_AUTO_ATTR_t stAuto; + NRChroma_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_TYPE_t; + +typedef struct NRChroma_Adv_PARAM_s +{ + MI_U8 u8StrengthByY[8]; //0 ~ 255 + MI_U8 u8StrengthByYEdge[8]; //0 ~ 63 + MI_U8 u8StrengthByCEdge[8]; //0 ~ 255 + MI_U8 u8MaxStrength; //0 ~ 255 + MI_U8 u8StaticLimitRatio; //0 ~ 63 + MI_U8 u8MotionClip; //0 ~ 255 + MI_U8 u8MotionColorReduce; //0 ~ 255 + MI_U8 u8MotionColorRecover; //0 ~ 255 + MI_U8 u8PreStrength; //0 ~ 128 +} NRChroma_Adv_PARAM_t; + +typedef struct NRChroma_Adv_MANUAL_ATTR_s +{ + NRChroma_Adv_PARAM_t stParaAPI; +} NRChroma_Adv_MANUAL_ATTR_t; + +typedef struct NRChroma_Adv_AUTO_ATTR_s +{ + NRChroma_Adv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_Adv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_Adv_AUTO_ATTR_t stAuto; + NRChroma_Adv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_Adv_TYPE_t; + +typedef struct MI_ISP_IQ_NRChroma_Pre_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NRChroma_Pre_TYPE_t; + +typedef struct SHARPNESS_PARAM_s +{ + MI_U8 u8OverShootGain; //0 ~ 255 + MI_U8 u8UnderShootGain; //0 ~ 255 + MI_U8 u8CorLUT[6]; //0 ~ 255 + MI_U8 u8SclLUT[6]; //0 ~ 255 + MI_U16 u16EdgeKillLUT[6]; //0 ~ 1023 + MI_U8 u8CornerReduce; //0 ~ 32 + MI_U8 u8DirTh; //0 ~ 255 + MI_U16 u16SharpnessUD[2]; //0 ~ 1023 + MI_U16 u16SharpnessD[2]; //0 ~ 1023 + MI_U8 u8PreCorUD[2]; //0 ~ 63 + MI_U8 u8PreCorD[2]; //0 ~ 63 + MI_U8 u8PreCorMotGain; //0 ~ 255 + MI_U8 u8LpfEdgeGainUD; //0 ~ 255 + MI_U8 u8LpfEdgeGainD; //0 ~ 255 + MI_U8 u8WeakDetailEnhance; //0 ~ 15 + MI_U16 u16DetailTh; //0 ~ 4095 + MI_U8 u8DetailMotOffset; //0 ~ 255 + MI_U8 u8DetailByY[6]; //0 ~ 255 + MI_U16 u16OverShootLimit; //0 ~ 1023 + MI_U16 u16UnderShootLimit; //0 ~ 1023 + MI_U8 u8MotGain[16]; //0 ~ 255 +} SHARPNESS_PARAM_t; + +typedef struct SHARPNESS_MANUAL_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI; +} SHARPNESS_MANUAL_ATTR_t; + +typedef struct SHARPNESS_AUTO_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SHARPNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SHARPNESS_AUTO_ATTR_t stAuto; + SHARPNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_TYPE_t; + +typedef struct SHARPNESS_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_U8 u8DirSel; //0 ~ 1 + MI_U8 u8DirOffA; //0 ~ 255 + MI_U8 u8MaxRatio; //0 ~ 255 + MI_U8 u8LpfY; //0 ~ 1 + MI_U8 u8SblLutY[6]; //0 ~ 255 + MI_U8 u8Sbl2LutY[6]; //0 ~ 255 + MI_U8 u8StrengthByHue[24]; //0 ~ 255 +} SHARPNESS_EX_PARAM_t; + +typedef struct SHARPNESS_EX_MANUAL_ATTR_s +{ + SHARPNESS_EX_PARAM_t stParaAPI; +} SHARPNESS_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + SHARPNESS_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_EX_TYPE_t; + +typedef struct CROSSTALK_PARAM_s +{ + MI_U8 u8Strength; //0 ~ 31 + MI_U8 u8StrengthByY[15]; //0 ~ 127 + MI_U8 u8Threshold; //0 ~ 255 + MI_U16 u16Offset; //0 ~ 4095 +} CROSSTALK_PARAM_t; + +typedef struct CROSSTALK_MANUAL_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI; +} CROSSTALK_MANUAL_ATTR_t; + +typedef struct CROSSTALK_AUTO_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CROSSTALK_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CROSSTALK_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + CROSSTALK_AUTO_ATTR_t stAuto; + CROSSTALK_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CROSSTALK_TYPE_t; + +typedef struct OBC_PARAM_s +{ + MI_U16 u16ValR; //0 ~ 255 + MI_U16 u16ValGr; //0 ~ 255 + MI_U16 u16ValGb; //0 ~ 255 + MI_U16 u16ValB; //0 ~ 255 +} OBC_PARAM_t; + +typedef struct OBC_MANUAL_ATTR_s +{ + OBC_PARAM_t stParaAPI; +} OBC_MANUAL_ATTR_t; + +typedef struct OBC_AUTO_ATTR_s +{ + OBC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} OBC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_OBC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + OBC_AUTO_ATTR_t stAuto; + OBC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_OBC_TYPE_t; + +typedef struct WDR_PARAM_s +{ + MI_U8 u8BoxNum; //1 ~ 4 + MI_U8 u8PreEnhance; //0 ~ 6 + MI_ISP_BOOL_e bAutoDetailEnhance; //0 ~ 1 + MI_U8 u8ManualDetailEnhance; //0~255; default:128 + MI_U8 u8GlobalDarkToneEnhance; //0 ~ 15 + MI_U8 u8WDRStrByY[33]; //0 ~ 255 + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8DarkLimit; //0 ~ 255 + MI_U8 u8BrightLimit; //0 ~ 255 + MI_ISP_BOOL_e bGammaSyncEn; //0 ~ 1 +} WDR_PARAM_t; + +typedef struct WDR_MANUAL_ATTR_s +{ + WDR_PARAM_t stParaAPI; +} WDR_MANUAL_ATTR_t; + +typedef struct WDR_AUTO_ATTR_s +{ + WDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDR_AUTO_ATTR_t stAuto; + WDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDR_TYPE_t; + +typedef struct WDRCurveFull_PARAM_s +{ + MI_U16 u16FCurve[256]; +} WDRCurveFull_PARAM_t; + +typedef struct WDRCurveFull_MANUAL_ATTR_s +{ + WDRCurveFull_PARAM_t stParaAPI; +} WDRCurveFull_MANUAL_ATTR_t; + +typedef struct WDRCurveFull_AUTO_ATTR_s +{ + WDRCurveFull_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveFull_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveFull_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveFull_AUTO_ATTR_t stAuto; + WDRCurveFull_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveFull_TYPE_t; + +typedef struct WDRCurveAdv_PARAM_s +{ + MI_U16 u16Slope; //1024~16384 + MI_U8 u8TransitionPoint0; //0~255 + MI_U8 u8TransitionPoint1; //0~255 + MI_U8 u8SaturatedPoint; //0~255 + MI_U8 u8CurveModeSel; //0~5 +} WDRCurveAdv_PARAM_t; + +typedef struct WDRCurveAdv_MANUAL_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI; +} WDRCurveAdv_MANUAL_ATTR_t; + +typedef struct WDRCurveAdv_AUTO_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveAdv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveAdv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveAdv_AUTO_ATTR_t stAuto; + WDRCurveAdv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveAdv_TYPE_t; + +typedef struct DYNAMIC_DP_PARAM_s +{ + MI_ISP_BOOL_e bHotPixEn; //0 ~ 1 + MI_U16 u16HotPixCompSlpoe; + MI_ISP_BOOL_e bDarkPixEn; //0 ~ 1 + MI_U16 u16DarkPixCompSlpoe; + MI_U16 u16DPCTH; + MI_ISP_BOOL_e bBlendEn; + MI_U16 u16DiffLut[6]; + MI_U16 u16YLut[6]; +} DYNAMIC_DP_PARAM_t; + +typedef struct DYNAMIC_DP_MANUAL_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI; +} DYNAMIC_DP_MANUAL_ATTR_t; + +typedef struct DYNAMIC_DP_AUTO_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_AUTO_ATTR_t stAuto; + DYNAMIC_DP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DYNAMIC_DP_TYPE_t; + +typedef struct DYNAMIC_DP_CLUSTER_ATTR_S +{ + MI_ISP_BOOL_e bEdgeMode; + MI_U16 u16NeiDeltaTh; + MI_U8 u8NeiSmooth; + MI_ISP_BOOL_e bSortEn; + MI_ISP_BOOL_e bSortRGGBEn[4]; + MI_ISP_BOOL_e bSort1x3ModeEn; + MI_U16 u16SortLumTblL[6]; + MI_U16 u16SortLumTblD[6]; + MI_U16 u16SortLumTblS[6]; +} DYNAMIC_DP_CLUSTER_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI; +} DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_CLUSTER_AUTO_ATTR_S; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_CLUSTER_AUTO_ATTR_S stAuto; + DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_t; + +typedef struct HSV_PARAM_s +{ + MI_S16 s16HueLut[24]; //-64 ~ 64 + MI_U16 u16SatLut[24]; // 0 ~ 255 (64->1X) + MI_S16 s16HueLut_ForUnitCCM[24]; //-64 ~ 64 + MI_U16 u16SatLut_ForUnitCCM[24]; // 0 ~ 255 (64->1X) + MI_U8 u8GlobalSat; // 0 ~ 255 (64->1x) +} HSV_PARAM_t; + +typedef struct HSV_MANUAL_ATTR_s +{ + HSV_PARAM_t stParaAPI; +} HSV_MANUAL_ATTR_t; + +typedef struct HSV_AUTO_ATTR_s +{ + HSV_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HSV_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HSV_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + HSV_AUTO_ATTR_t stAuto; + HSV_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HSV_TYPE_t; + +typedef struct RGBIR_PARAM_s +{ + MI_U8 u8IrPosType; //0 ~ 7, def : 0 + MI_ISP_BOOL_e bRemovelEn; //0 ~ 1, def : 1 + MI_U16 u16Ratio_R[6]; + MI_U16 u16Ratio_G[6]; + MI_U16 u16Ratio_B[6]; +} RGBIR_PARAM_t; + +typedef struct RGBIR_MANUAL_ATTR_s +{ + RGBIR_PARAM_t stParaAPI; +} RGBIR_MANUAL_ATTR_t; + +typedef struct RGBIR_AUTO_ATTR_s +{ + RGBIR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBIR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBIR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBIR_AUTO_ATTR_t stAuto; + RGBIR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBIR_TYPE_t; + +typedef struct MI_ISP_IQ_FPN_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_FPN_TYPE_t; + +typedef struct PFC_PARAM_s +{ + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8UStrength; //0 ~ 63 + MI_U8 u8VStrength; //0 ~ 63 + MI_U8 u8StrengthByY[8]; //0 ~ 255 + MI_U8 u8FlatProtect; //0 ~ 127 + MI_U8 u8SatByY[2]; //0 ~ 25 + MI_U8 u8SatSrcSel; //0 ~ 1 + MI_U8 u8StrengthByContrast[8]; //0 ~ 127 +} PFC_PARAM_t; + +typedef struct PFC_MANUAL_ATTR_s +{ + PFC_PARAM_t stParaAPI; +} PFC_MANUAL_ATTR_t; + +typedef struct PFC_AUTO_ATTR_s +{ + PFC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} PFC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_PFC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + PFC_AUTO_ATTR_t stAuto; + PFC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_PFC_TYPE_t; + +typedef struct PFC_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_ISP_BOOL_e bGSkipEn; //0 ~ 1 + MI_U8 u8SatMaskSel; //0 ~ 1 + MI_ISP_BOOL_e bSatAmpEn; //0 ~ 1 + MI_U8 u8StrengthByHue[12]; //0 ~ 255 +} PFC_EX_PARAM_t; + +typedef struct PFC_EX_MANUAL_ATTR_s +{ + PFC_EX_PARAM_t stParaAPI; +} PFC_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_PFC_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + PFC_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_PFC_EX_TYPE_t; + +typedef struct DEMOSAIC_PARAM_s +{ + MI_U8 u8DirThrd; //0~63 def:35 + MI_U8 u8EdgeSmoothThrdY; //0~255 def:230 + MI_U8 u8EdgeSmoothThrdC; //0~127 def:20 +} DEMOSAIC_PARAM_t; + +typedef struct DEMOSAIC_MANUAL_ATTR_s +{ + DEMOSAIC_PARAM_t stParaAPI; +} DEMOSAIC_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_DEMOSAIC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DEMOSAIC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEMOSAIC_TYPE_t; + +typedef struct COLORTRANS_PARAM_s +{ + MI_U16 u16Y_OFST; //0 ~ 2047 + MI_U16 u16U_OFST; //0 ~ 2047 + MI_U16 u16V_OFST; //0 ~ 2047 + MI_U16 u16Matrix[9]; //0 ~ 1023 +} COLORTRANS_PARAM_t; + +typedef struct COLORTRANS_MANUAL_ATTR_s +{ + COLORTRANS_PARAM_t stParaAPI; +} COLORTRANS_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_COLORTRANS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + COLORTRANS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_COLORTRANS_TYPE_t; + +typedef struct HDR_PARAM_s +{ + MI_ISP_BOOL_e bNrEn; + MI_U16 u16YwtTh1; + MI_U16 u16YwtTh2; + MI_U16 u16NoiseLevel[16]; + MI_U16 u16MotionTh; + MI_U16 u16MotionAdjLut[7]; +} HDR_PARAM_t; + +typedef struct HDR_MANUAL_ATTR_s +{ + HDR_PARAM_t stParaAPI; +} HDR_MANUAL_ATTR_t; + +typedef struct HDR_AUTO_ATTR_s +{ + HDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + HDR_AUTO_ATTR_t stAuto; + HDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_TYPE_t; + +typedef struct HDR_EX_PARAM_s +{ + MI_U16 u16SensorExpRatio; + MI_ISP_BOOL_e bDynRatioEn; + MI_U8 u8DynRatioSrcSel; + MI_U8 u8YSrcSel; + MI_U8 u8NoiseLevelSrcSel; + MI_U8 u8MotionMaxVal; + MI_U16 u16MotionLumaTh; + MI_U8 u8MotionAdjSft[6]; +} HDR_EX_PARAM_t; + +typedef struct HDR_EX_MANUAL_ATTR_s +{ + HDR_EX_PARAM_t stParaAPI; +} HDR_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + HDR_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_EX_TYPE_t; + +typedef struct MI_ISP_IQ_EFFECT_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_EFFECT_TYPE_t; + +typedef struct MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U16 u16CenterX; + MI_U16 u16CenterY; + MI_U8 u8Shift; + MI_U16 u16RGainTable[32*3]; + MI_U16 u16GGainTable[32*3]; + MI_U16 u16BGainTable[32*3]; +} MI_ISP_IQ_LSC_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_LSC_CTRL_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8GridX; + MI_U8 u8GridY; + MI_U16 u16CCTthr[3]; + MI_U8 u8DeltaMode; + MI_ISP_BOOL_e bDeltaModeAdvEn; + MI_U8 u8DeltaLutX[26]; + MI_U8 u8DeltaLutY[26]; + MI_U16 u16TableR[3][ALSC_TBL_MAX]; + MI_U16 u16TableG[3][ALSC_TBL_MAX]; + MI_U16 u16TableB[3][ALSC_TBL_MAX]; +} MI_ISP_IQ_ALSC_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_ALSC_CTRL_TYPE_t; + +typedef struct R2Y_PARAM_s +{ + MI_U16 u16Matrix[9]; + MI_U8 u8AddY16; +} R2Y_PARAM_t; + +typedef struct R2Y_MANUAL_ATTR_s +{ + R2Y_PARAM_t stParaAPI; +} R2Y_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_R2Y_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + R2Y_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_R2Y_TYPE_t; + +typedef struct DUMMY_ATTR_s +{ + MI_S16 s16Dummy0[256]; + MI_S16 s16Dummy1[256]; + MI_S16 s16Dummy2[256]; + MI_S16 s16Dummy3; + MI_S16 s16Dummy4; +} DUMMY_ATTR_t; + +typedef struct DUMMY_MANUAL_ATTR_s +{ + DUMMY_ATTR_t stParaAPI; +} DUMMY_MANUAL_ATTR_t; + +typedef struct DUMMY_AUTO_ATTR_s +{ + DUMMY_ATTR_t stParaAPI[MI_ISP_AUTO_NUM]; +} DUMMY_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DUMMY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + DUMMY_AUTO_ATTR_t stAuto; + DUMMY_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DUMMY_TYPE_t; + +typedef struct DUMMY_EX_ATTR_s +{ + MI_S16 s16DummyEx0[256]; + MI_S16 s16DummyEx1[256]; + MI_S16 s16DummyEx2[256]; + MI_S16 s16DummyEx3; + MI_S16 s16DummyEx4; +} DUMMY_EX_ATTR_t; + +typedef struct +{ + DUMMY_EX_ATTR_t stParaAPI; +} DUMMY_EX_MANUAL_ATTR_S; + +typedef struct MI_ISP_IQ_DUMMY_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DUMMY_EX_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DUMMY_EX_TYPE_t; + +#endif + +#if 1 // ISP IQ API +typedef struct IQ_VERSION_INFO_PARAM_s +{ + MI_U32 u32Vendor; + MI_U32 u32Major; + MI_U32 u32Minor; +} IQ_VERSION_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_VERSION_INFO_TYPE_s +{ + IQ_VERSION_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_VERSION_INFO_TYPE_t; + +typedef struct IQ_PARAM_INIT_INFO_PARAM_s +{ + MI_ISP_BOOL_e bFlag; +} IQ_PARAM_INIT_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_PARAM_INIT_INFO_TYPE_s +{ + IQ_PARAM_INIT_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_PARAM_INIT_INFO_TYPE_t; + +typedef struct FAST_MODE_PARAM_s +{ + MI_ISP_BOOL_e bFastMode; +} FAST_MODE_PARAM_t; + +typedef struct MI_ISP_IQ_FAST_MODE_TYPE_s +{ + FAST_MODE_PARAM_t stParaAPI; +} MI_ISP_IQ_FAST_MODE_TYPE_t; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_PARAM_MODE_NORMAL = 0, + SS_IQ_PARAM_MODE_NIGHT = 1, //Night Mode + SS_IQ_PARAM_MODE_MAX +} MI_ISP_IQ_PARAM_MODE_e; + +typedef struct MI_ISP_IQ_GAMMA_LUT_TYPE_s +{ + MI_U16 u16LutR[256]; + MI_U16 u16LutG[256]; + MI_U16 u16LutB[256]; +} MI_ISP_IQ_GAMMA_LUT_TYPE_t; + +typedef struct MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_U16 u16BTGamma[256]; + MI_U16 u16DTGamma[256]; +} MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_t; + +typedef struct MI_ISP_IQ_OBC4Ch_TYPE_s +{ + MI_U16 u16OBC4Ch[4]; +} MI_ISP_IQ_OBC4Ch_TYPE_t; +#endif + +typedef struct TEMP_PARAM_s +{ + MI_S16 s16ObcOffset; + MI_U8 u8DynamicDPRatio; + MI_U8 u8CrosstalkRatio; + MI_U8 u8NRDeSpikeRatio; + MI_U8 u8NR3DRatio[2]; + MI_U8 u8NRLumaRatio; + MI_U8 u8SharpnessRatio[2]; + MI_U8 u8SaturationRatio; + MI_U8 u8ColorToneRatio[3]; +} TEMP_PARAM_t; + +typedef struct TEMP_MANUAL_ATTR_s +{ + TEMP_PARAM_t stParaAPI; +} TEMP_MANUAL_ATTR_t; + +typedef struct TEMP_AUTO_ATTR_s +{ + TEMP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} TEMP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_TEMP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8TemperatureLut[16]; + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + TEMP_AUTO_ATTR_t stAuto; + TEMP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_TEMP_TYPE_t; + +typedef struct MI_ISP_IQ_TEMP_INFO_TYPE_s +{ + MI_U8 u8Temperature; +} MI_ISP_IQ_TEMP_INFO_TYPE_t; + +#if 1 // MAINTOOL API +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_INDEX_0 = 0, + SS_IQ_INDEX_1, + SS_IQ_INDEX_2, + SS_IQ_INDEX_3, + SS_IQ_INDEX_4, + SS_IQ_INDEX_5, + SS_IQ_INDEX_6, + SS_IQ_INDEX_7, + SS_IQ_INDEX_8, + SS_IQ_INDEX_9, + SS_IQ_INDEX_10, + SS_IQ_INDEX_11, + SS_IQ_INDEX_12, + SS_IQ_INDEX_13, + SS_IQ_INDEX_14, + SS_IQ_INDEX_15, + SS_IQ_INDEX_MAX +} MI_ISP_IQ_INDEX_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_BYPASS_OFF = 0, + SS_BYPASS_ON, + SS_BYPASS_MAX +} MI_ISP_BYPASS_MODE_e; + +typedef struct MI_ISP_API_BYPASS_TYPE_s +{ + MI_ISP_BYPASS_MODE_e bEnable; //0 ~ 1 + MI_ISP_API_ID_e eAPIIndex; +} MI_ISP_API_BYPASS_TYPE_t; +#endif + + +/************************************* IQ - Define the structure declaration - END *************************************/ + + +#endif /* _MI_ISP_IQ_DATATYPE_H_ */ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ispahan/mi_isp_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ispahan/mi_isp_datatype.h new file mode 100644 index 000000000..b058e1868 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ispahan/mi_isp_datatype.h @@ -0,0 +1,430 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp_datatype.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_ISP_DATATYPE_H_ +#define _MI_ISP_DATATYPE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mi_common.h" +#include "mi_sys_datatype.h" +#include "mi_isp_3a_datatype.h" +#include "mi_isp_iq_datatype.h" + +/************************************* AF - Define the structure declaration - START *************************************/ + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************** Cus3A ***********************/ + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; + MI_U8 uAvgY; +} MI_ISP_AE_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AE_AVGS nAvg[128*90]; +}MI_ISP_AE_HW_STATISTICS_t; + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; +} MI_ISP_AWB_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AWB_AVGS nAvg[128*90]; +} MI_ISP_AWB_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[128]; +} MI_ISP_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[256]; +} MI_ISP_RGBIR_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_BOOL bAE; + MI_BOOL bAWB; + MI_BOOL bAF; +}Cus3AEnable_t; + +typedef struct +{ + MI_U32 Size; /**< struct size*/ + char sensor_id[32]; /**< sensor module id*/ + MI_U32 shutter; /**< shutter Shutter in ns*/ + MI_U32 shutter_step; /**< shutter Shutter step ns*/ + MI_U32 shutter_min; /**< shutter Shutter min us*/ + MI_U32 shutter_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gain; /**< sensor_gain Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + MI_U32 isp_gain; /**< isp_gain Isp digital gain , 1X = 1024 */ + MI_U32 isp_gain_max; /**< isp_gain Maximum Isp digital gain , 1X = 1024 */ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 fps; /**< initial frame per second*/ + MI_U32 shutterHDRShort_step; /**< shutter Shutter step ns*/ + MI_U32 shutterHDRShort_min; /**< shutter Shutter min us*/ + MI_U32 shutterHDRShort_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gainHDRShort_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gainHDRShort_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + /*CUS3A v1.1*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ +}CusAEInitParam_t,CusAeInitParam_t; + +/*! @brief ISP report to AE, hardware statistic */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + void *hist1; /**< HW statistic histogram 1*/ + void *hist2; /**< HW statistic histogram 2*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ + void * avgs; /**< HW statistics average block data*/ + MI_U32 Shutter; /**< Current shutter in ns*/ + MI_U32 SensorGain; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< Current ISP gain, 1X = 1024*/ + MI_U32 ShutterHDRShort; /**< Current shutter in ns*/ + MI_U32 SensorGainHDRShort; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGainHDRShort; /**< Current ISP gain, 1X = 1024*/ + /*CUS3A V1.1*/ + MI_U32 PreAvgY; /**< Previous frame brightness*/ + MI_U8 HDRCtlMode; /**< 0 = HDR off; */ + /**< 1 = Separate shutter & Separate sensor gain settings */ + /**< 2 = Separate shutter & Share sensor gain settings */ + /**< 3 = Share shutter & Separate sensor gain settings */ + MI_U32 FNx10; /**< Aperture in FNx10*/ + MI_U32 CurFPS; /**Current sensor FPS */ + MI_U32 PreWeightY; /**< Previous frame brightness with ROI weight*/ +} __attribute__((packed, aligned(1))) CusAEInfo_t, CusAeInput_t; + +/*! @brief ISP ae algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 Shutter; /**< Shutter in ns */ + MI_U32 SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< ISP gain, 1X = 1024 */ + MI_U32 ShutterHdrShort; /**< Shutter in ns */ + MI_U32 SensorGainHdrShort; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGainHdrShort; /**< ISP gain, 1X = 1024 */ + MI_U32 u4BVx16384; /**< Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_U32 AvgY; /**< frame brightness */ + MI_U32 HdrRatio; /**< hdr ratio, 1X = 1024 */ + /*CUS3A V1.1*/ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 DebandFPS; /** Target fps when running auto debanding**/ + MI_U32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAEResult_t, CusAeOutput_t; + +/*! @brief AWB HW statistics data*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 AvgBlkX; + MI_U32 AvgBlkY; + MI_U32 CurRGain; + MI_U32 CurGGain; + MI_U32 CurBGain; + void *avgs; //ISP_AWB_SAMPLE + /*CUS3A V1.1*/ + MI_U8 HDRMode; /**< Noramal or HDR mode*/ + void* *pAwbStatisShort; /**< Short Shutter AWB statistic data */ + MI_U32 u4BVx16384; /**< From AE output, Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_S32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAWBInfo_t, CusAWBInput_t; + +/*! @brief AWB algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 R_gain; /**< AWB gain for R channel*/ + MI_U32 G_gain; /**< AWB gain for G channel*/ + MI_U32 B_gain; /**< AWB gain for B channel*/ + MI_U32 ColorTmp; /**< Return color temperature*/ +}CusAWBResult_t, CusAwbOutput_t;; + +typedef enum __attribute__ ((aligned (1))) +{ + SS_AE_16x24 = 0, + SS_AE_32x24, + SS_AE_64x48, + SS_AE_64x45, + SS_AE_128x80, + SS_AE_128x90, + SS_AE_32x32 +} MS_CUST_AE_WIN_BLOCK_NUM_TYPE_e; + +typedef struct { + MI_U16 u2Stawin_x_offset; + MI_U16 u2Stawin_x_size; + MI_U16 u2Stawin_y_offset; + MI_U16 u2Stawin_y_size; + MI_U16 u2WinIdx; +} CusAEHistWin_t; + +typedef struct +{ + MI_U32 SizeX; + MI_U32 SizeY; + MI_U32 IncRatio; +}CusAWBSample_t; + +typedef struct +{ + MI_U16 CropX; // 0~1023 + MI_U16 CropY; // 0~1023 + MI_U16 CropW; // 0~1023 + MI_U16 CropH; // 0~1023 +}CusAEAWBCropSize_t; + +typedef struct +{ + MI_U8 iir_1[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 iir_2[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 luma[4*16]; //[4]: luma 32bit, use 4*u8 datatype, [16]: 16wins + MI_U8 fir_v[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 fir_h[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 ysat[3*16]; //[3]: ysat 22bit, use 3*u8 datatype, [16]: 16wins +} AF_STATS_PARAM_t; + +typedef struct +{ + AF_STATS_PARAM_t stParaAPI[16]; +} CusAFStats_t; + +typedef struct AF_WINDOW_PARAM_s +{ + MI_U32 u32StartX; /*range : 0~1023*/ + MI_U32 u32StartY; /*range : 0~1023*/ + MI_U32 u32EndX; /*range : 0~1023*/ + MI_U32 u32EndY; /*range : 0~1023*/ +} AF_WINDOW_PARAM_t; + +typedef struct +{ + MI_U8 u8WindowIndex; + AF_WINDOW_PARAM_t stParaAPI; +} CusAFWin_t; + +typedef struct +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; + + MI_U16 u16IIR1_e1_en; + MI_U16 u16IIR1_e1_a0; + MI_U16 u16IIR1_e1_a1; + MI_U16 u16IIR1_e1_a2; + MI_U16 u16IIR1_e1_b1; + MI_U16 u16IIR1_e1_b2; + MI_U16 u16IIR1_e2_en; + MI_U16 u16IIR1_e2_a0; + MI_U16 u16IIR1_e2_a1; + MI_U16 u16IIR1_e2_a2; + MI_U16 u16IIR1_e2_b1; + MI_U16 u16IIR1_e2_b2; + + MI_U16 u16IIR2_e1_en; + MI_U16 u16IIR2_e1_a0; + MI_U16 u16IIR2_e1_a1; + MI_U16 u16IIR2_e1_a2; + MI_U16 u16IIR2_e1_b1; + MI_U16 u16IIR2_e1_b2; + MI_U16 u16IIR2_e2_en; + MI_U16 u16IIR2_e2_a0; + MI_U16 u16IIR2_e2_a1; + MI_U16 u16IIR2_e2_a2; + MI_U16 u16IIR2_e2_b1; + MI_U16 u16IIR2_e2_b2; +} CusAFFilter_t; + +typedef struct +{ + MI_U16 u16Coeff[70]; +} CusAFFilter_Geo_t; + +typedef struct +{ + MI_BOOL bSobelYSatEn; + MI_U16 u16SobelYThd; + + MI_BOOL bIIRSquareAccEn; + MI_BOOL bSobelSquareAccEn; + + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} CusAFFilterSq_t; + + +typedef enum __attribute__ ((aligned (1))) +{ + AF_ROI_MODE_NORMAL, + AF_ROI_MODE_MATRIX +} ISP_AF_ROI_MODE_e; + +typedef struct +{ + ISP_AF_ROI_MODE_e mode; + MI_U32 u32_vertical_block_number; +} CusAFRoiMode_t; + +/* Raw store control */ +typedef enum +{ + eRawStoreNode_P0HEAD = 0, /* Control by VIF, Do not use */ + eRawStoreNode_P1HEAD = 1, /* Control by VIF, Do not use */ + eRawStoreNode_P0TAIL = 2, + eRawStoreNode_P1TAIL = 3, + eRawStoreNode_ISPOUT = 4, + eRawStoreNode_VDOS = 5, + eRawStoreNode_ISPOUT_BEFORE_YEE = 6, + eRawStoreNode_RGBIR_IR_ONLY = 7 +}CameraRawStoreNode_e; + +typedef struct +{ + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusImageResolution_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; +} CusISPOutImage_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusHdrRawImage_t; + +typedef struct +{ + MI_U64 u64Pts; /** frame PTS */ + MI_U32 u32Shutter; /**< Shutter in us */ + MI_U32 u32SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 u32ColorTmp; /**< Return color temperature*/ +} IspFrameMetaInfo_t; + +/*! @brief ISP report to AF, hardware status */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 MinPos; /**< Maximum position of AF motor */ + MI_U32 MaxPos; /**< Minimum position of AF motor */ + MI_U32 CurPos; /**< Current position of AF motor */ +} __attribute__((packed, aligned(1))) CusAFInfo_t, CusAfInput_t; + +/*! @brief AF algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 NextPos; /**< Next absolute position of AF motor */ +}__attribute__((packed, aligned(1))) CusAfResult_t, CusAfOutput_t; + +typedef struct +{ + MI_U32 u32SlaveAddr; //sensor slave address + MI_U32 u32RegLen; //sensor register length , 1 or 2 bytes + MI_U32 u32DataLen; //sensor register data length, 1 or 2 bytes + MI_U32 u32I2cSpeed; //i2c speed , 100/200/300/400 KHz + MI_U32 u32Reg; //sensor register address + MI_U32 u32Data; //sensor register data +}CusSensorI2cParam_t; + +/***************************** end of Cus3A ****************************/ + +// COMMON API +typedef struct MI_ISP_API_CHANNEL_ID_TYPE_s +{ + MI_U32 u32ChannelID; +} MI_ISP_API_CHANNEL_ID_TYPE_t; + +typedef struct MI_ISP_API_USERSPACE3A_ATTR_s +{ + MI_SYS_PixelFormat_e ePixelFmt; + MI_U32 eSensorBindId; +} MI_ISP_API_USERSPACE3A_ATTR_t; + +typedef struct +{ + MI_S8 strIspRoot[64]; +} MI_ISP_ROOT_PATH_T; + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_MI_ISP_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ispahan/mi_isp_iq_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ispahan/mi_isp_iq_datatype.h new file mode 100644 index 000000000..ee9a9e7be --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/ispahan/mi_isp_iq_datatype.h @@ -0,0 +1,1347 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* + * iq_apiset.h + * + * Created on: 2016/8/16 + * Author: Elsa-cf.Lin + */ + +#ifndef _MI_ISP_IQ_DATATYPE_H_ +#define _MI_ISP_IQ_DATATYPE_H_ + +#include "mi_isp_3a_datatype.h" + +//put here temporarily, should add mi_isp_cali_datatype.h? + +typedef enum __attribute__ ((aligned (1))) +{ + SS_CALI_ITEM_AWB = 0, + SS_CALI_ITEM_OBC = 1, + SS_CALI_ITEM_SDC = 2, + SS_CALI_ITEM_ALSC = 3, + SS_CALI_ITEM_LSC = 4, + SS_CALI_ITEM_MAX, +} MI_ISP_CALI_ITEM_e; + +/************************************* AF - Define the structure declaration - START *************************************/ + +typedef struct MI_ISP_AF_HW_ROI_MODE_TYPE_s +{ + MI_U8 u8Mode; // 0: Normal, 1: Matrix + MI_U32 u32VerticalBlockNumber; +} MI_ISP_AF_HW_ROI_MODE_TYPE_t; + +typedef struct MI_ISP_AF_HW_WIN_TYPE_s +{ + MI_U16 u16Win[4*16]; +} MI_ISP_AF_HW_WIN_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTER_ATTR_TYPE_s +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; + + MI_U16 u16IIR1_e1_en; + MI_U16 u16IIR1_e1_a0; + MI_U16 u16IIR1_e1_a1; + MI_U16 u16IIR1_e1_a2; + MI_U16 u16IIR1_e1_b1; + MI_U16 u16IIR1_e1_b2; + MI_U16 u16IIR1_e2_en; + MI_U16 u16IIR1_e2_a0; + MI_U16 u16IIR1_e2_a1; + MI_U16 u16IIR1_e2_a2; + MI_U16 u16IIR1_e2_b1; + MI_U16 u16IIR1_e2_b2; + + MI_U16 u16IIR2_e1_en; + MI_U16 u16IIR2_e1_a0; + MI_U16 u16IIR2_e1_a1; + MI_U16 u16IIR2_e1_a2; + MI_U16 u16IIR2_e1_b1; + MI_U16 u16IIR2_e1_b2; + MI_U16 u16IIR2_e2_en; + MI_U16 u16IIR2_e2_a0; + MI_U16 u16IIR2_e2_a1; + MI_U16 u16IIR2_e2_a2; + MI_U16 u16IIR2_e2_b1; + MI_U16 u16IIR2_e2_b2; +} MI_ISP_AF_HW_FILTER_ATTR_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTERSQ_TYPE_s +{ + MI_U8 bSobelYSatEn; + MI_U16 u16SobelYThd; + MI_U8 bIIRSquareAccEn; + MI_U8 bSobelSquareAccEn; + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} MI_ISP_AF_HW_FILTERSQ_TYPE_t; + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************************* IQ - Define the structure declaration - START *************************************/ + +typedef struct +{ + MI_U16 u16NumOfPoints; + MI_S32 s32Y[16]; + MI_S32 s32X[16]; +} MI_INTP_LUT_IQ; + +#if 1 //API20 struct + +#define MI_ISP_AUTO_NUM (16) +#define ALSC_TBL_MAX 459 +#define ENABLE_CCM_COEFF_SUM_INFO 1 + +typedef enum __attribute__ ((aligned (4))) +{ + API20_AUTO = 0, //[00] + //API2.0 + API20_FPN, //[01] + API20_CCM, //[02] + API20_SAT, //[03] + API20_OBC, //[04] + API20_OBC_P1, //[05] + API20_FCOLOR, //[06] + API20_CR, //[07] + API20_NR_DeSpike, //[08] + API20_SHP, //[09] + API20_NR_3D, //[10] + API20_BRI, //[11] + API20_LIG, //[12] + API20_CST, //[13] + API20_GMA, //[14] + API20_CTG, //[15] + API20_NR_NLM, //[16] + API20_DEFOG, //[17] + API20_DRC, //[18] + API20_DPC, //[19] + API20_HSV, //[20] + API20_WDR_LOC, //[21] + API20_RGBIR, //[22] + API20_YUVGMA, //[23] + API20_HDR16to12, //[24] + API20_COLORTRANS, //[25] + API20_HDR, //[26] + API20_EFFECT, //[27] + API20_PFC, //[28] + API20_SIIR, //[29] + API20_DM, //[30] + API20_NR_3D_P1, //[31] + API20_WDRCurveAdv, //[32] + API20_MXNR, //[33] + API20_R2Y, //[34] + API20_LSC, //[35] + API20_LSC_CTRL, //[36] + API20_ALSC, //[37] + API20_ALSC_CTRL, //[38] + API20_DPC_CLUSTER, //[39] + API20_PFC_EX, //[40] + API20_HDR_EX, //[41] + API20_SHP_EX, //[42] + API20_NR_3D_EX, //[43] + API20_GNR, //[44] + API20_DUMMY, //[45] + API20_DUMMY_EX, //[46] + API20_WDRCurveFull, //[47] + API20_ADAPTIVE_GMA, //[48] + API20_XNR, //[49] + API20_TEMP, //[50] + API20_TEMP_INFO, //[51] + API20_MAX, //for para reset +} MI_ISP_API_ID_e; + +typedef struct MI_ISP_IQ_COLORTOGRAY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 +} MI_ISP_IQ_COLORTOGRAY_TYPE_t; + +typedef struct LEVEL_BASE_PARAM_s +{ + MI_U32 u32Lev; //0 ~ 100 +} LEVEL_BASE_PARAM_t; + +typedef struct LIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} LIGHTNESS_MANUAL_ATTR_t; + +typedef struct LIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} LIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_LIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + LIGHTNESS_AUTO_ATTR_t stAuto; + LIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_LIGHTNESS_TYPE_t; + +typedef struct CONTRAST_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} CONTRAST_MANUAL_ATTR_t; + +typedef struct CONTRAST_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CONTRAST_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CONTRAST_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + CONTRAST_AUTO_ATTR_t stAuto; + CONTRAST_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CONTRAST_TYPE_t; + +typedef struct BRIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} BRIGHTNESS_MANUAL_ATTR_t; + +typedef struct BRIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} BRIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_BRIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + BRIGHTNESS_AUTO_ATTR_t stAuto; + BRIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_BRIGHTNESS_TYPE_t; + + +typedef struct RGBGAMMA_PARAM_s +{ + MI_U16 u16LutR[256]; //0 ~ 4095 + MI_U16 u16LutG[256]; //0 ~ 4095 + MI_U16 u16LutB[256]; //0 ~ 4095 +} RGBGAMMA_PARAM_t; + +typedef struct RGBGAMMA_MANUAL_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI; +} RGBGAMMA_MANUAL_ATTR_t; + +typedef struct RGBGAMMA_AUTO_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBGAMMA_AUTO_ATTR_t stAuto; + RGBGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBGAMMA_TYPE_t; + +typedef struct YUVGAMMA_PAMAR_s +{ + MI_U16 u16LutY[256]; //0 ~ 1023 + MI_U16 u16LutU[128]; //0 ~ 511 + MI_U16 u16LutV[128]; //0 ~ 511 +} YUVGAMMA_PAMAR_t; + +typedef struct YUVGAMMA_MANUAL_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI; +} YUVGAMMA_MANUAL_ATTR_t; + +typedef struct YUVGAMMA_AUTO_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI[MI_ISP_AUTO_NUM]; +} YUVGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_YUVGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + YUVGAMMA_AUTO_ATTR_t stAuto; + YUVGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_YUVGAMMA_TYPE_t; + +typedef struct SATURATION_PARAM_s +{ + MI_U8 u8SatAllStr; //0 ~ 127 (32 = 1X) + MI_U8 u8SatByYSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatByYLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatBySSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatBySLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatCoring; +} SATURATION_PARAM_t; + +typedef struct SATURATION_MANUAL_ATTR_s +{ + SATURATION_PARAM_t stParaAPI; +} SATURATION_MANUAL_ATTR_t; + +typedef struct SATURATION_AUTO_ATTR_s +{ + SATURATION_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SATURATION_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SATURATION_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SATURATION_AUTO_ATTR_t stAuto; + SATURATION_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SATURATION_TYPE_t; + +typedef struct DEFOG_PARAM_s +{ + MI_U8 u8Strength; +} DEFOG_PARAM_t; + +typedef struct DEFOG_MANUAL_ATTR_s +{ + DEFOG_PARAM_t stParaAPI; +} DEFOG_MANUAL_ATTR_t; + +typedef struct DEFOG_AUTO_ATTR_s +{ + DEFOG_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DEFOG_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DEFOG_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DEFOG_AUTO_ATTR_t stAuto; + DEFOG_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEFOG_TYPE_t; + +typedef struct RGBMATRIX_PARAM_s +{ + MI_U16 u16CCTthr; +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_PARAM_t; + +typedef struct RGBMATRIX_MANUAL_ATTR_s +{ +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_MANUAL_ATTR_t; + +typedef struct RGBMATRIX_AUTO_ATTR_s +{ + MI_ISP_BOOL_e bISOActEn; //0 ~ 1 + RGBMATRIX_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBMATRIX_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBMATRIX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBMATRIX_AUTO_ATTR_t stAuto; + RGBMATRIX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBMATRIX_TYPE_t; + +typedef struct MI_ISP_IQ_CCM_INFO_TYPE_s +{ + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) + MI_U16 u16CCT; +} MI_ISP_IQ_CCM_INFO_TYPE_t; + +typedef struct FALSECOLOR_PARAM_s +{ + MI_U8 u8FreqThrd; //0~255 default:140 + MI_U8 u8EdgeScoreThrd; //0~255 default:31 + MI_U8 u8ChromaThrdOfStrengthMax; //0~127 default:10 + MI_U8 u8ChromaThrdOfStrengthMid; //0~127 default:40 + MI_U8 u8ChromaThrdOfStrengthMin; //0~127 default:80 + MI_U8 u8StrengthMid; //0~7 default:7 + MI_U8 u8StrengthMin; //0~7 default:7 +} FALSECOLOR_PARAM_t; + +typedef struct FALSECOLOR_MANUAL_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI; +} FALSECOLOR_MANUAL_ATTR_t; + +typedef struct FALSECOLOR_AUTO_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} FALSECOLOR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_FALSECOLOR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + FALSECOLOR_AUTO_ATTR_t stAuto; + FALSECOLOR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_FALSECOLOR_TYPE_t; + +typedef struct NR3D_PARAM_s +{ + MI_U8 u8MdThd; //0~255 + MI_U16 u16MdGain; //0~1023 + MI_U8 u8TfStr; //0~64 + MI_U8 u8TfStrEx; //0~64 + MI_U8 u8MdThdByY[16]; //0~255 + MI_U8 u8MdGainByY[16]; //0~255 + MI_U8 u8M2SLut[16]; //0~31 + MI_U16 u16TfLut[16]; //0~4095 + MI_U8 u8YSfBlendLut[16]; //0~16 + MI_U8 u8YSfBlendOffset; //0~16 +} NR3D_PARAM_t; + +typedef struct NR3D_MANUAL_ATTR_s +{ + NR3D_PARAM_t stParaAPI; +} NR3D_MANUAL_ATTR_t; + +typedef struct NR3D_AUTO_ATTR_s +{ + NR3D_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NR3D_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NR3D_AUTO_ATTR_t stAuto; + NR3D_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_TYPE_t; + +typedef struct NR3D_EX_PARAM_s +{ + MI_ISP_BOOL_e bAREn; //0~1 + MI_U8 u8ARLumaTh[2]; //0~255 + MI_U8 u8ARMotTh[2]; //0~255 + MI_ISP_BOOL_e bPREn; //0~1 + MI_U16 u16PRDiffTh; //0~4095 + MI_U8 u8PRRatioConf[4]; //0~16 + MI_U8 u8PRContrastTh[2]; //0~15 + MI_U8 u8PRMotTh[2]; //0~255 +} NR3D_EX_PARAM_t; + +typedef struct NR3D_EX_MANUAL_ATTR_s +{ + NR3D_EX_PARAM_t stParaAPI; +} NR3D_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + NR3D_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_EX_TYPE_t; + +typedef struct MI_ISP_IQ_NR3D_P1_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NR3D_P1_TYPE_t; + +typedef struct NRDESPIKE_PARAM_s +{ + MI_U8 u8BlendRatio; //0 ~ 15 + MI_U8 u8StrengthCenterNeighbor; //0 ~ 5 + MI_U8 u8StrengthMeanStd; //0 ~ 5 + MI_U8 u8StrengthCornerCross; //0 ~ 5 + MI_U8 u8DiffGainMeanStd; //0 ~ 31 + MI_U8 u8DiffGainCenterNeighbor; //0 ~ 255 + MI_U8 u8DiffThdCornerCross; //0 ~ 255 + MI_U16 u16BlendLut[5]; //0 ~ 2047 + MI_U8 u8StrengthByY[15]; //0 ~ 127 +} NRDESPIKE_PARAM_t; + +typedef struct NRDESPIKE_MANUAL_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI; +} NRDESPIKE_MANUAL_ATTR_t; + +typedef struct NRDESPIKE_AUTO_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRDESPIKE_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRDESPIKE_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRDESPIKE_AUTO_ATTR_t stAuto; + NRDESPIKE_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRDESPIKE_TYPE_t; + +typedef struct NRLUMA_PARAM_s +{ + MI_U8 u8Strength; + MI_U8 u8GMaskSel; + MI_U16 u16SpfBlendLut[2]; +} NRLUMA_PARAM_t; + +typedef struct NRLUMA_MANUAL_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI; +} NRLUMA_MANUAL_ATTR_t; + +typedef struct NRLUMA_AUTO_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLUMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_AUTO_ATTR_t stAuto; + NRLUMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLUMA_TYPE_t; + +typedef struct NRLUMA_Adv_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; + MI_U8 u8Strength; + MI_U8 u8StrengthByY[10]; + MI_U8 u8StrengthByMot[16]; + MI_U16 u16EdgeTh[8]; + MI_U32 u32EdgeGain[8]; + MI_U8 u8StrengthByType[2]; +} NRLUMA_Adv_PARAM_t; + +typedef struct NRLUMA_Adv_MANUAL_ATTR_s +{ + NRLUMA_Adv_PARAM_t stParaAPI; +} NRLUMA_Adv_MANUAL_ATTR_t; + +typedef struct NRLUMA_Adv_AUTO_ATTR_s +{ + NRLUMA_Adv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_Adv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLuma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_Adv_AUTO_ATTR_t stAuto; + NRLUMA_Adv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLuma_Adv_TYPE_t; + +typedef struct NRChroma_PARAM_s +{ + MI_U8 u8MatchRatio; //0 ~ 127 + MI_U16 u16UvTh; //0 ~ 1023 + MI_U16 u16StrengthByCEdge[6]; //0 ~ 1023 +} NRChroma_PARAM_t; + +typedef struct NRChroma_MANUAL_ATTR_s +{ + NRChroma_PARAM_t stParaAPI; +} NRChroma_MANUAL_ATTR_t; + +typedef struct NRChroma_AUTO_ATTR_s +{ + NRChroma_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_AUTO_ATTR_t stAuto; + NRChroma_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_TYPE_t; + +typedef struct NRChroma_Adv_PARAM_s +{ + MI_U8 u8StrengthByY[8]; //0 ~ 255 + MI_U8 u8StrengthByYEdge[8]; //0 ~ 63 + MI_U8 u8StrengthByCEdge[8]; //0 ~ 255 + MI_U8 u8MaxStrength; //0 ~ 255 + MI_U8 u8StaticLimitRatio; //0 ~ 63 + MI_U8 u8MotionClip; //0 ~ 255 + MI_U8 u8MotionColorReduce; //0 ~ 255 + MI_U8 u8MotionColorRecover; //0 ~ 255 + MI_U8 u8PreStrength; //0 ~ 128 +} NRChroma_Adv_PARAM_t; + +typedef struct NRChroma_Adv_MANUAL_ATTR_s +{ + NRChroma_Adv_PARAM_t stParaAPI; +} NRChroma_Adv_MANUAL_ATTR_t; + +typedef struct NRChroma_Adv_AUTO_ATTR_s +{ + NRChroma_Adv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_Adv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_Adv_AUTO_ATTR_t stAuto; + NRChroma_Adv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_Adv_TYPE_t; + +typedef struct MI_ISP_IQ_NRChroma_Pre_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NRChroma_Pre_TYPE_t; + +typedef struct SHARPNESS_PARAM_s +{ + MI_U8 u8OverShootGain; //0 ~ 255 + MI_U8 u8UnderShootGain; //0 ~ 255 + MI_U8 u8CorLUT[6]; //0 ~ 255 + MI_U8 u8SclLUT[6]; //0 ~ 255 + MI_U16 u16EdgeKillLUT[6]; //0 ~ 1023 + MI_U8 u8CornerReduce; //0 ~ 32 + MI_U8 u8DirTh; //0 ~ 255 + MI_U16 u16SharpnessUD[2]; //0 ~ 1023 + MI_U16 u16SharpnessD[2]; //0 ~ 1023 + MI_U8 u8PreCorUD[2]; //0 ~ 63 + MI_U8 u8PreCorD[2]; //0 ~ 63 + MI_U8 u8PreCorMotGain; //0 ~ 255 + MI_U8 u8LpfEdgeGainUD; //0 ~ 255 + MI_U8 u8LpfEdgeGainD; //0 ~ 255 + MI_U8 u8WeakDetailEnhance; //0 ~ 15 + MI_U16 u16DetailTh; //0 ~ 4095 + MI_U8 u8DetailMotOffset; //0 ~ 255 + MI_U8 u8DetailByY[6]; //0 ~ 255 + MI_U16 u16OverShootLimit; //0 ~ 1023 + MI_U16 u16UnderShootLimit; //0 ~ 1023 + MI_U8 u8MotGain[16]; //0 ~ 255 +} SHARPNESS_PARAM_t; + +typedef struct SHARPNESS_MANUAL_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI; +} SHARPNESS_MANUAL_ATTR_t; + +typedef struct SHARPNESS_AUTO_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SHARPNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SHARPNESS_AUTO_ATTR_t stAuto; + SHARPNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_TYPE_t; + +typedef struct SHARPNESS_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_U8 u8DirSel; //0 ~ 1 + MI_U8 u8DirOffA; //0 ~ 255 + MI_U8 u8MaxRatio; //0 ~ 255 + MI_U8 u8LpfY; //0 ~ 1 + MI_U8 u8SblLutY[6]; //0 ~ 255 + MI_U8 u8Sbl2LutY[6]; //0 ~ 255 + MI_U8 u8StrengthByHue[24]; //0 ~ 255 +} SHARPNESS_EX_PARAM_t; + +typedef struct SHARPNESS_EX_MANUAL_ATTR_s +{ + SHARPNESS_EX_PARAM_t stParaAPI; +} SHARPNESS_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + SHARPNESS_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_EX_TYPE_t; + +typedef struct CROSSTALK_PARAM_s +{ + MI_U8 u8Strength; //0 ~ 31 + MI_U8 u8StrengthByY[15]; //0 ~ 127 + MI_U8 u8Threshold; //0 ~ 255 + MI_U16 u16Offset; //0 ~ 4095 +} CROSSTALK_PARAM_t; + +typedef struct CROSSTALK_MANUAL_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI; +} CROSSTALK_MANUAL_ATTR_t; + +typedef struct CROSSTALK_AUTO_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CROSSTALK_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CROSSTALK_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + CROSSTALK_AUTO_ATTR_t stAuto; + CROSSTALK_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CROSSTALK_TYPE_t; + +typedef struct OBC_PARAM_s +{ + MI_U16 u16ValR; //0 ~ 255 + MI_U16 u16ValGr; //0 ~ 255 + MI_U16 u16ValGb; //0 ~ 255 + MI_U16 u16ValB; //0 ~ 255 +} OBC_PARAM_t; + +typedef struct OBC_MANUAL_ATTR_s +{ + OBC_PARAM_t stParaAPI; +} OBC_MANUAL_ATTR_t; + +typedef struct OBC_AUTO_ATTR_s +{ + OBC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} OBC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_OBC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + OBC_AUTO_ATTR_t stAuto; + OBC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_OBC_TYPE_t; + +typedef struct WDR_PARAM_s +{ + MI_U8 u8BoxNum; //1 ~ 4 + MI_U8 u8PreEnhance; //0 ~ 6 + MI_ISP_BOOL_e bAutoDetailEnhance; //0 ~ 1 + MI_U8 u8ManualDetailEnhance; //0~255; default:128 + MI_U8 u8GlobalDarkToneEnhance; //0 ~ 15 + MI_U8 u8WDRStrByY[33]; //0 ~ 255 + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8DarkLimit; //0 ~ 255 + MI_U8 u8BrightLimit; //0 ~ 255 + MI_ISP_BOOL_e bGammaSyncEn; //0 ~ 1 +} WDR_PARAM_t; + +typedef struct WDR_MANUAL_ATTR_s +{ + WDR_PARAM_t stParaAPI; +} WDR_MANUAL_ATTR_t; + +typedef struct WDR_AUTO_ATTR_s +{ + WDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDR_AUTO_ATTR_t stAuto; + WDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDR_TYPE_t; + +typedef struct WDRCurveFull_PARAM_s +{ + MI_U16 u16FCurve[256]; +} WDRCurveFull_PARAM_t; + +typedef struct WDRCurveFull_MANUAL_ATTR_s +{ + WDRCurveFull_PARAM_t stParaAPI; +} WDRCurveFull_MANUAL_ATTR_t; + +typedef struct WDRCurveFull_AUTO_ATTR_s +{ + WDRCurveFull_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveFull_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveFull_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveFull_AUTO_ATTR_t stAuto; + WDRCurveFull_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveFull_TYPE_t; + +typedef struct WDRCurveAdv_PARAM_s +{ + MI_U16 u16Slope; //1024~16384 + MI_U8 u8TransitionPoint0; //0~255 + MI_U8 u8TransitionPoint1; //0~255 + MI_U8 u8SaturatedPoint; //0~255 + MI_U8 u8CurveModeSel; //0~5 +} WDRCurveAdv_PARAM_t; + +typedef struct WDRCurveAdv_MANUAL_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI; +} WDRCurveAdv_MANUAL_ATTR_t; + +typedef struct WDRCurveAdv_AUTO_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveAdv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveAdv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveAdv_AUTO_ATTR_t stAuto; + WDRCurveAdv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveAdv_TYPE_t; + +typedef struct DYNAMIC_DP_PARAM_s +{ + MI_ISP_BOOL_e bHotPixEn; //0 ~ 1 + MI_U16 u16HotPixCompSlpoe; + MI_ISP_BOOL_e bDarkPixEn; //0 ~ 1 + MI_U16 u16DarkPixCompSlpoe; + MI_U16 u16DPCTH; + MI_ISP_BOOL_e bBlendEn; + MI_U16 u16DiffLut[6]; + MI_U16 u16YLut[6]; +} DYNAMIC_DP_PARAM_t; + +typedef struct DYNAMIC_DP_MANUAL_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI; +} DYNAMIC_DP_MANUAL_ATTR_t; + +typedef struct DYNAMIC_DP_AUTO_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_AUTO_ATTR_t stAuto; + DYNAMIC_DP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DYNAMIC_DP_TYPE_t; + +typedef struct DYNAMIC_DP_CLUSTER_ATTR_S +{ + MI_ISP_BOOL_e bEdgeMode; + MI_U16 u16NeiDeltaTh; + MI_U8 u8NeiSmooth; + MI_ISP_BOOL_e bSortEn; + MI_ISP_BOOL_e bSortRGGBEn[4]; + MI_ISP_BOOL_e bSort1x3ModeEn; + MI_U16 u16SortLumTblL[6]; + MI_U16 u16SortLumTblD[6]; + MI_U16 u16SortLumTblS[6]; +} DYNAMIC_DP_CLUSTER_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI; +} DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_CLUSTER_AUTO_ATTR_S; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_CLUSTER_AUTO_ATTR_S stAuto; + DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_t; + +typedef struct HSV_PARAM_s +{ + MI_S16 s16HueLut[24]; //-64 ~ 64 + MI_U16 u16SatLut[24]; // 0 ~ 255 (64->1X) + MI_S16 s16HueLut_ForUnitCCM[24]; //-64 ~ 64 + MI_U16 u16SatLut_ForUnitCCM[24]; // 0 ~ 255 (64->1X) + MI_U8 u8GlobalSat; // 0 ~ 255 (64->1x) +} HSV_PARAM_t; + +typedef struct HSV_MANUAL_ATTR_s +{ + HSV_PARAM_t stParaAPI; +} HSV_MANUAL_ATTR_t; + +typedef struct HSV_AUTO_ATTR_s +{ + HSV_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HSV_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HSV_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + HSV_AUTO_ATTR_t stAuto; + HSV_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HSV_TYPE_t; + +typedef struct RGBIR_PARAM_s +{ + MI_U8 u8IrPosType; //0 ~ 7, def : 0 + MI_ISP_BOOL_e bRemovelEn; //0 ~ 1, def : 1 + MI_U16 u16Ratio_R[6]; + MI_U16 u16Ratio_G[6]; + MI_U16 u16Ratio_B[6]; +} RGBIR_PARAM_t; + +typedef struct RGBIR_MANUAL_ATTR_s +{ + RGBIR_PARAM_t stParaAPI; +} RGBIR_MANUAL_ATTR_t; + +typedef struct RGBIR_AUTO_ATTR_s +{ + RGBIR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBIR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBIR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBIR_AUTO_ATTR_t stAuto; + RGBIR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBIR_TYPE_t; + +typedef struct MI_ISP_IQ_FPN_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_FPN_TYPE_t; + +typedef struct PFC_PARAM_s +{ + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8UStrength; //0 ~ 63 + MI_U8 u8VStrength; //0 ~ 63 + MI_U8 u8StrengthByY[8]; //0 ~ 255 + MI_U8 u8FlatProtect; //0 ~ 127 + MI_U8 u8SatByY[2]; //0 ~ 25 + MI_U8 u8SatSrcSel; //0 ~ 1 + MI_U8 u8StrengthByContrast[8]; //0 ~ 127 +} PFC_PARAM_t; + +typedef struct PFC_MANUAL_ATTR_s +{ + PFC_PARAM_t stParaAPI; +} PFC_MANUAL_ATTR_t; + +typedef struct PFC_AUTO_ATTR_s +{ + PFC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} PFC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_PFC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + PFC_AUTO_ATTR_t stAuto; + PFC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_PFC_TYPE_t; + +typedef struct PFC_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_ISP_BOOL_e bGSkipEn; //0 ~ 1 + MI_U8 u8SatMaskSel; //0 ~ 1 + MI_ISP_BOOL_e bSatAmpEn; //0 ~ 1 + MI_U8 u8StrengthByHue[12]; //0 ~ 255 +} PFC_EX_PARAM_t; + +typedef struct PFC_EX_MANUAL_ATTR_s +{ + PFC_EX_PARAM_t stParaAPI; +} PFC_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_PFC_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + PFC_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_PFC_EX_TYPE_t; + +typedef struct DEMOSAIC_PARAM_s +{ + MI_U8 u8DirThrd; //0~63 def:35 + MI_U8 u8EdgeSmoothThrdY; //0~255 def:230 + MI_U8 u8EdgeSmoothThrdC; //0~127 def:20 +} DEMOSAIC_PARAM_t; + +typedef struct DEMOSAIC_MANUAL_ATTR_s +{ + DEMOSAIC_PARAM_t stParaAPI; +} DEMOSAIC_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_DEMOSAIC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DEMOSAIC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEMOSAIC_TYPE_t; + +typedef struct COLORTRANS_PARAM_s +{ + MI_U16 u16Y_OFST; //0 ~ 2047 + MI_U16 u16U_OFST; //0 ~ 2047 + MI_U16 u16V_OFST; //0 ~ 2047 + MI_U16 u16Matrix[9]; //0 ~ 1023 +} COLORTRANS_PARAM_t; + +typedef struct COLORTRANS_MANUAL_ATTR_s +{ + COLORTRANS_PARAM_t stParaAPI; +} COLORTRANS_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_COLORTRANS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + COLORTRANS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_COLORTRANS_TYPE_t; + +typedef struct HDR_PARAM_s +{ + MI_ISP_BOOL_e bNrEn; + MI_U16 u16YwtTh1; + MI_U16 u16YwtTh2; + MI_U16 u16NoiseLevel[16]; + MI_U16 u16MotionTh; + MI_U16 u16MotionAdjLut[7]; +} HDR_PARAM_t; + +typedef struct HDR_MANUAL_ATTR_s +{ + HDR_PARAM_t stParaAPI; +} HDR_MANUAL_ATTR_t; + +typedef struct HDR_AUTO_ATTR_s +{ + HDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + HDR_AUTO_ATTR_t stAuto; + HDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_TYPE_t; + +typedef struct HDR_EX_PARAM_s +{ + MI_U16 u16SensorExpRatio; + MI_ISP_BOOL_e bDynRatioEn; + MI_U8 u8DynRatioSrcSel; + MI_U8 u8YSrcSel; + MI_U8 u8NoiseLevelSrcSel; + MI_U8 u8MotionMaxVal; + MI_U16 u16MotionLumaTh; + MI_U8 u8MotionAdjSft[6]; +} HDR_EX_PARAM_t; + +typedef struct HDR_EX_MANUAL_ATTR_s +{ + HDR_EX_PARAM_t stParaAPI; +} HDR_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + HDR_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_EX_TYPE_t; + +typedef struct MI_ISP_IQ_EFFECT_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_EFFECT_TYPE_t; + +typedef struct MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U16 u16CenterX; + MI_U16 u16CenterY; + MI_U8 u8Shift; + MI_U16 u16RGainTable[32*3]; + MI_U16 u16GGainTable[32*3]; + MI_U16 u16BGainTable[32*3]; +} MI_ISP_IQ_LSC_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_LSC_CTRL_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8GridX; + MI_U8 u8GridY; + MI_U16 u16CCTthr[3]; + MI_U8 u8DeltaMode; + MI_ISP_BOOL_e bDeltaModeAdvEn; + MI_U8 u8DeltaLutX[26]; + MI_U8 u8DeltaLutY[26]; + MI_U16 u16TableR[3][ALSC_TBL_MAX]; + MI_U16 u16TableG[3][ALSC_TBL_MAX]; + MI_U16 u16TableB[3][ALSC_TBL_MAX]; +} MI_ISP_IQ_ALSC_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_ALSC_CTRL_TYPE_t; + +typedef struct R2Y_PARAM_s +{ + MI_U16 u16Matrix[9]; + MI_U8 u8AddY16; +} R2Y_PARAM_t; + +typedef struct R2Y_MANUAL_ATTR_s +{ + R2Y_PARAM_t stParaAPI; +} R2Y_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_R2Y_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + R2Y_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_R2Y_TYPE_t; + +typedef struct DUMMY_ATTR_s +{ + MI_S16 s16Dummy0[256]; + MI_S16 s16Dummy1[256]; + MI_S16 s16Dummy2[256]; + MI_S16 s16Dummy3; + MI_S16 s16Dummy4; +} DUMMY_ATTR_t; + +typedef struct DUMMY_MANUAL_ATTR_s +{ + DUMMY_ATTR_t stParaAPI; +} DUMMY_MANUAL_ATTR_t; + +typedef struct DUMMY_AUTO_ATTR_s +{ + DUMMY_ATTR_t stParaAPI[MI_ISP_AUTO_NUM]; +} DUMMY_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DUMMY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + DUMMY_AUTO_ATTR_t stAuto; + DUMMY_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DUMMY_TYPE_t; + +typedef struct DUMMY_EX_ATTR_s +{ + MI_S16 s16DummyEx0[256]; + MI_S16 s16DummyEx1[256]; + MI_S16 s16DummyEx2[256]; + MI_S16 s16DummyEx3; + MI_S16 s16DummyEx4; +} DUMMY_EX_ATTR_t; + +typedef struct +{ + DUMMY_EX_ATTR_t stParaAPI; +} DUMMY_EX_MANUAL_ATTR_S; + +typedef struct MI_ISP_IQ_DUMMY_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DUMMY_EX_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DUMMY_EX_TYPE_t; + +#endif + +#if 1 // ISP IQ API +typedef struct IQ_VERSION_INFO_PARAM_s +{ + MI_U32 u32Vendor; + MI_U32 u32Major; + MI_U32 u32Minor; +} IQ_VERSION_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_VERSION_INFO_TYPE_s +{ + IQ_VERSION_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_VERSION_INFO_TYPE_t; + +typedef struct IQ_PARAM_INIT_INFO_PARAM_s +{ + MI_ISP_BOOL_e bFlag; +} IQ_PARAM_INIT_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_PARAM_INIT_INFO_TYPE_s +{ + IQ_PARAM_INIT_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_PARAM_INIT_INFO_TYPE_t; + +typedef struct FAST_MODE_PARAM_s +{ + MI_ISP_BOOL_e bFastMode; +} FAST_MODE_PARAM_t; + +typedef struct MI_ISP_IQ_FAST_MODE_TYPE_s +{ + FAST_MODE_PARAM_t stParaAPI; +} MI_ISP_IQ_FAST_MODE_TYPE_t; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_PARAM_MODE_NORMAL = 0, + SS_IQ_PARAM_MODE_NIGHT = 1, //Night Mode + SS_IQ_PARAM_MODE_MAX +} MI_ISP_IQ_PARAM_MODE_e; + +typedef struct MI_ISP_IQ_GAMMA_LUT_TYPE_s +{ + MI_U16 u16LutR[256]; + MI_U16 u16LutG[256]; + MI_U16 u16LutB[256]; +} MI_ISP_IQ_GAMMA_LUT_TYPE_t; + +typedef struct MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_U16 u16BTGamma[256]; + MI_U16 u16DTGamma[256]; +} MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_t; + +typedef struct MI_ISP_IQ_OBC4Ch_TYPE_s +{ + MI_U16 u16OBC4Ch[4]; +} MI_ISP_IQ_OBC4Ch_TYPE_t; +#endif + +typedef struct TEMP_PARAM_s +{ + MI_S16 s16ObcOffset; + MI_U8 u8DynamicDPRatio; + MI_U8 u8CrosstalkRatio; + MI_U8 u8NRDeSpikeRatio; + MI_U8 u8NR3DRatio[2]; + MI_U8 u8NRLumaRatio; + MI_U8 u8SharpnessRatio[2]; + MI_U8 u8SaturationRatio; + MI_U8 u8ColorToneRatio[3]; +} TEMP_PARAM_t; + +typedef struct TEMP_MANUAL_ATTR_s +{ + TEMP_PARAM_t stParaAPI; +} TEMP_MANUAL_ATTR_t; + +typedef struct TEMP_AUTO_ATTR_s +{ + TEMP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} TEMP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_TEMP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8TemperatureLut[16]; + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + TEMP_AUTO_ATTR_t stAuto; + TEMP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_TEMP_TYPE_t; + +typedef struct MI_ISP_IQ_TEMP_INFO_TYPE_s +{ + MI_U8 u8Temperature; +} MI_ISP_IQ_TEMP_INFO_TYPE_t; + +#if 1 // MAINTOOL API +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_INDEX_0 = 0, + SS_IQ_INDEX_1, + SS_IQ_INDEX_2, + SS_IQ_INDEX_3, + SS_IQ_INDEX_4, + SS_IQ_INDEX_5, + SS_IQ_INDEX_6, + SS_IQ_INDEX_7, + SS_IQ_INDEX_8, + SS_IQ_INDEX_9, + SS_IQ_INDEX_10, + SS_IQ_INDEX_11, + SS_IQ_INDEX_12, + SS_IQ_INDEX_13, + SS_IQ_INDEX_14, + SS_IQ_INDEX_15, + SS_IQ_INDEX_MAX +} MI_ISP_IQ_INDEX_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_BYPASS_OFF = 0, + SS_BYPASS_ON, + SS_BYPASS_MAX +} MI_ISP_BYPASS_MODE_e; + +typedef struct MI_ISP_API_BYPASS_TYPE_s +{ + MI_ISP_BYPASS_MODE_e bEnable; //0 ~ 1 + MI_ISP_API_ID_e eAPIIndex; +} MI_ISP_API_BYPASS_TYPE_t; +#endif + + +/************************************* IQ - Define the structure declaration - END *************************************/ + + +#endif /* _MI_ISP_IQ_DATATYPE_H_ */ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/macaron/mi_isp_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/macaron/mi_isp_datatype.h new file mode 100644 index 000000000..e1894bbe2 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/macaron/mi_isp_datatype.h @@ -0,0 +1,404 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp_datatype.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_ISP_DATATYPE_H_ +#define _MI_ISP_DATATYPE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mi_common.h" +#include "mi_sys_datatype.h" +#include "mi_isp_3a_datatype.h" +#include "mi_isp_iq_datatype.h" + +/************************************* AF - Define the structure declaration - START *************************************/ + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************** Cus3A ***********************/ + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; + MI_U8 uAvgY; +} MI_ISP_AE_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AE_AVGS nAvg[128*90]; +}MI_ISP_AE_HW_STATISTICS_t; + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; +} MI_ISP_AWB_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AWB_AVGS nAvg[128*90]; +} MI_ISP_AWB_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[128]; +} MI_ISP_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[256]; +} MI_ISP_RGBIR_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_BOOL bAE; + MI_BOOL bAWB; + MI_BOOL bAF; +}Cus3AEnable_t; + +typedef struct +{ + MI_U32 Size; /**< struct size*/ + char sensor_id[32]; /**< sensor module id*/ + MI_U32 shutter; /**< shutter Shutter in ns*/ + MI_U32 shutter_step; /**< shutter Shutter step ns*/ + MI_U32 shutter_min; /**< shutter Shutter min us*/ + MI_U32 shutter_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gain; /**< sensor_gain Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + MI_U32 isp_gain; /**< isp_gain Isp digital gain , 1X = 1024 */ + MI_U32 isp_gain_max; /**< isp_gain Maximum Isp digital gain , 1X = 1024 */ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 fps; /**< initial frame per second*/ + MI_U32 shutterHDRShort_step; /**< shutter Shutter step ns*/ + MI_U32 shutterHDRShort_min; /**< shutter Shutter min us*/ + MI_U32 shutterHDRShort_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gainHDRShort_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gainHDRShort_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + /*CUS3A v1.1*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ +}CusAEInitParam_t,CusAeInitParam_t; + +/*! @brief ISP report to AE, hardware statistic */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + void *hist1; /**< HW statistic histogram 1*/ + void *hist2; /**< HW statistic histogram 2*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ + void * avgs; /**< HW statistics average block data*/ + MI_U32 Shutter; /**< Current shutter in ns*/ + MI_U32 SensorGain; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< Current ISP gain, 1X = 1024*/ + MI_U32 ShutterHDRShort; /**< Current shutter in ns*/ + MI_U32 SensorGainHDRShort; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGainHDRShort; /**< Current ISP gain, 1X = 1024*/ + /*CUS3A V1.1*/ + MI_U32 PreAvgY; /**< Previous frame brightness*/ + MI_U8 HDRCtlMode; /**< 0 = HDR off; */ + /**< 1 = Separate shutter & Separate sensor gain settings */ + /**< 2 = Separate shutter & Share sensor gain settings */ + /**< 3 = Share shutter & Separate sensor gain settings */ + MI_U32 FNx10; /**< Aperture in FNx10*/ + MI_U32 CurFPS; /**Current sensor FPS */ + MI_U32 PreWeightY; /**< Previous frame brightness with ROI weight*/ +} __attribute__((packed, aligned(1))) CusAEInfo_t, CusAeInput_t; + +/*! @brief ISP ae algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 Shutter; /**< Shutter in ns */ + MI_U32 SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< ISP gain, 1X = 1024 */ + MI_U32 ShutterHdrShort; /**< Shutter in ns */ + MI_U32 SensorGainHdrShort; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGainHdrShort; /**< ISP gain, 1X = 1024 */ + MI_U32 u4BVx16384; /**< Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_U32 AvgY; /**< frame brightness */ + MI_U32 HdrRatio; /**< hdr ratio, 1X = 1024 */ + /*CUS3A V1.1*/ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 DebandFPS; /** Target fps when running auto debanding**/ + MI_U32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAEResult_t, CusAeOutput_t; + +/*! @brief AWB HW statistics data*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 AvgBlkX; + MI_U32 AvgBlkY; + MI_U32 CurRGain; + MI_U32 CurGGain; + MI_U32 CurBGain; + void *avgs; //ISP_AWB_SAMPLE + /*CUS3A V1.1*/ + MI_U8 HDRMode; /**< Noramal or HDR mode*/ + void* *pAwbStatisShort; /**< Short Shutter AWB statistic data */ + MI_U32 u4BVx16384; /**< From AE output, Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_S32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAWBInfo_t, CusAWBInput_t; + +/*! @brief AWB algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 R_gain; /**< AWB gain for R channel*/ + MI_U32 G_gain; /**< AWB gain for G channel*/ + MI_U32 B_gain; /**< AWB gain for B channel*/ + MI_U32 ColorTmp; /**< Return color temperature*/ +}CusAWBResult_t, CusAwbOutput_t;; + +typedef enum __attribute__ ((aligned (1))) +{ + SS_AE_16x24 = 0, + SS_AE_32x24, + SS_AE_64x48, + SS_AE_64x45, + SS_AE_128x80, + SS_AE_128x90, + SS_AE_32x32 +} MS_CUST_AE_WIN_BLOCK_NUM_TYPE_e; + +typedef struct { + MI_U16 u2Stawin_x_offset; + MI_U16 u2Stawin_x_size; + MI_U16 u2Stawin_y_offset; + MI_U16 u2Stawin_y_size; + MI_U16 u2WinIdx; +} CusAEHistWin_t; + +typedef struct +{ + MI_U32 SizeX; + MI_U32 SizeY; + MI_U32 IncRatio; +}CusAWBSample_t; + +typedef struct +{ + MI_U16 CropX; // 0~1023 + MI_U16 CropY; // 0~1023 + MI_U16 CropW; // 0~1023 + MI_U16 CropH; // 0~1023 +}CusAEAWBCropSize_t; + +typedef struct +{ + MI_U8 iir_1[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 iir_2[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 luma[4*16]; //[4]: luma 32bit, use 4*u8 datatype, [16]: 16wins + MI_U8 fir_v[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 fir_h[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 ysat[3*16]; //[3]: ysat 22bit, use 3*u8 datatype, [16]: 16wins +} AF_STATS_PARAM_t; + +typedef struct +{ + AF_STATS_PARAM_t stParaAPI[16]; +} CusAFStats_t; + +typedef struct AF_WINDOW_PARAM_s +{ + MI_U32 u32StartX; /*range : 0~1023*/ + MI_U32 u32StartY; /*range : 0~1023*/ + MI_U32 u32EndX; /*range : 0~1023*/ + MI_U32 u32EndY; /*range : 0~1023*/ +} AF_WINDOW_PARAM_t; + +typedef struct +{ + MI_U8 u8WindowIndex; + AF_WINDOW_PARAM_t stParaAPI; +} CusAFWin_t; + +typedef struct +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; +} CusAFFilter_t; + +typedef struct +{ + MI_U16 u16Coeff[70]; +} CusAFFilter_Geo_t; + +typedef struct +{ + MI_BOOL bSobelYSatEn; + MI_U16 u16SobelYThd; + + MI_BOOL bIIRSquareAccEn; + MI_BOOL bSobelSquareAccEn; + + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} CusAFFilterSq_t; + + +typedef enum __attribute__ ((aligned (1))) +{ + AF_ROI_MODE_NORMAL, + AF_ROI_MODE_MATRIX +} ISP_AF_ROI_MODE_e; + +typedef struct +{ + ISP_AF_ROI_MODE_e mode; + MI_U32 u32_vertical_block_number; +} CusAFRoiMode_t; + +/* Raw store control */ +typedef enum +{ + eRawStoreNode_P0HEAD = 0, /* Control by VIF, Do not use */ + eRawStoreNode_P1HEAD = 1, /* Control by VIF, Do not use */ + eRawStoreNode_P0TAIL = 2, + eRawStoreNode_P1TAIL = 3, + eRawStoreNode_ISPOUT = 4, + eRawStoreNode_VDOS = 5, + eRawStoreNode_ISPOUT_BEFORE_YEE = 6, + eRawStoreNode_RGBIR_IR_ONLY = 7 +}CameraRawStoreNode_e; + +typedef struct +{ + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusImageResolution_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; +} CusISPOutImage_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusHdrRawImage_t; + +typedef struct +{ + MI_U64 u64Pts; /** frame PTS */ + MI_U32 u32Shutter; /**< Shutter in us */ + MI_U32 u32SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 u32ColorTmp; /**< Return color temperature*/ +} IspFrameMetaInfo_t; + +/*! @brief ISP report to AF, hardware status */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 MinPos; /**< Maximum position of AF motor */ + MI_U32 MaxPos; /**< Minimum position of AF motor */ + MI_U32 CurPos; /**< Current position of AF motor */ +} __attribute__((packed, aligned(1))) CusAFInfo_t, CusAfInput_t; + +/*! @brief AF algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 NextPos; /**< Next absolute position of AF motor */ +}__attribute__((packed, aligned(1))) CusAfResult_t, CusAfOutput_t; + +typedef struct +{ + MI_U32 u32SlaveAddr; //sensor slave address + MI_U32 u32RegLen; //sensor register length , 1 or 2 bytes + MI_U32 u32DataLen; //sensor register data length, 1 or 2 bytes + MI_U32 u32I2cSpeed; //i2c speed , 100/200/300/400 KHz + MI_U32 u32Reg; //sensor register address + MI_U32 u32Data; //sensor register data +}CusSensorI2cParam_t; + +/***************************** end of Cus3A ****************************/ + +// COMMON API +typedef struct MI_ISP_API_CHANNEL_ID_TYPE_s +{ + MI_U32 u32ChannelID; +} MI_ISP_API_CHANNEL_ID_TYPE_t; + +typedef struct MI_ISP_API_USERSPACE3A_ATTR_s +{ + MI_SYS_PixelFormat_e ePixelFmt; + MI_U32 eSensorBindId; +} MI_ISP_API_USERSPACE3A_ATTR_t; + +typedef struct +{ + MI_S8 strIspRoot[64]; +} MI_ISP_ROOT_PATH_T; + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_MI_ISP_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/macaron/mi_isp_iq_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/macaron/mi_isp_iq_datatype.h new file mode 100644 index 000000000..e69e25825 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/macaron/mi_isp_iq_datatype.h @@ -0,0 +1,1166 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* + * iq_apiset.h + * + * Created on: 2016/8/16 + * Author: Elsa-cf.Lin + */ + +#ifndef _MI_ISP_IQ_DATATYPE_H_ +#define _MI_ISP_IQ_DATATYPE_H_ + +#include "mi_isp_3a_datatype.h" + +//put here temporarily, should add mi_isp_cali_datatype.h? + +typedef enum __attribute__ ((aligned (1))) +{ + SS_CALI_ITEM_AWB = 0, + SS_CALI_ITEM_OBC = 1, + SS_CALI_ITEM_SDC = 2, + SS_CALI_ITEM_ALSC = 3, + SS_CALI_ITEM_LSC = 4, + SS_CALI_ITEM_MAX, +} MI_ISP_CALI_ITEM_e; + +/************************************* AF - Define the structure declaration - START *************************************/ + +typedef struct MI_ISP_AF_HW_ROI_MODE_TYPE_s +{ + MI_U8 u8Mode; // 0: Normal, 1: Matrix + MI_U32 u32VerticalBlockNumber; +} MI_ISP_AF_HW_ROI_MODE_TYPE_t; + +typedef struct MI_ISP_AF_HW_WIN_TYPE_s +{ + MI_U16 u16Win[4*16]; +} MI_ISP_AF_HW_WIN_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTER_ATTR_TYPE_s +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; +} MI_ISP_AF_HW_FILTER_ATTR_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTERSQ_TYPE_s +{ + MI_U8 bSobelYSatEn; + MI_U16 u16SobelYThd; + MI_U8 bIIRSquareAccEn; + MI_U8 bSobelSquareAccEn; + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} MI_ISP_AF_HW_FILTERSQ_TYPE_t; + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************************* IQ - Define the structure declaration - START *************************************/ + +typedef struct +{ + MI_U16 u16NumOfPoints; + MI_S32 s32Y[16]; + MI_S32 s32X[16]; +} MI_INTP_LUT_IQ; + +#if 1 //API20 struct + +#define MI_ISP_AUTO_NUM (16) +#define ALSC_TBL_MAX 255 +#define ENABLE_CCM_COEFF_SUM_INFO 0 + +typedef enum __attribute__ ((aligned (4))) +{ + API20_AUTO = 0, //[00] + //API2.0 + API20_FPN, //[01] + API20_CCM, //[02] + API20_SAT, //[03] + API20_OBC, //[04] + API20_OBC_P1, //[05] + API20_FCOLOR, //[06] + API20_CR, //[07] + API20_NR_DeSpike, //[08] + API20_SHP, //[09] + API20_NR_3D, //[10] + API20_BRI, //[11] + API20_LIG, //[12] + API20_CST, //[13] + API20_GMA, //[14] + API20_CTG, //[15] + API20_NR_NLM, //[16] + API20_DEFOG, //[17] + API20_DRC, //[18] + API20_DPC, //[19] + API20_HSV, //[20] + API20_WDR_LOC, //[21] + API20_RGBIR, //[22] + API20_YUVGMA, //[23] + API20_HDR16to12, //[24] + API20_COLORTRANS, //[25] + API20_HDR, //[26] + API20_EFFECT, //[27] + API20_PFC, //[28] + API20_SIIR, //[29] + API20_DM, //[30] + API20_NR_3D_P1, //[31] + API20_WDRCurveAdv, //[32] + API20_MXNR, //[33] + API20_R2Y, //[34] + API20_LSC, //[35] + API20_LSC_CTRL, //[36] + API20_ALSC, //[37] + API20_ALSC_CTRL, //[38] + API20_DPC_CLUSTER, //[39] + API20_PFC_EX, //[40] + API20_HDR_EX, //[41] + API20_SHP_EX, //[42] + API20_NR_3D_EX, //[43] + API20_GNR, //[44] + API20_DUMMY, //[45] + API20_DUMMY_EX, //[46] + API20_WDRCurveFull, //[47] + API20_ADAPTIVE_GMA, //[48] + API20_XNR, //[49] + API20_TEMP, //[50] + API20_TEMP_INFO, //[51] + API20_MAX, //for para reset +} MI_ISP_API_ID_e; + +typedef struct MI_ISP_IQ_COLORTOGRAY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 +} MI_ISP_IQ_COLORTOGRAY_TYPE_t; + +typedef struct LEVEL_BASE_PARAM_s +{ + MI_U32 u32Lev; //0 ~ 100 +} LEVEL_BASE_PARAM_t; + +typedef struct LIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} LIGHTNESS_MANUAL_ATTR_t; + +typedef struct LIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} LIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_LIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + LIGHTNESS_AUTO_ATTR_t stAuto; + LIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_LIGHTNESS_TYPE_t; + +typedef struct CONTRAST_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} CONTRAST_MANUAL_ATTR_t; + +typedef struct CONTRAST_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CONTRAST_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CONTRAST_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + CONTRAST_AUTO_ATTR_t stAuto; + CONTRAST_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CONTRAST_TYPE_t; + +typedef struct BRIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} BRIGHTNESS_MANUAL_ATTR_t; + +typedef struct BRIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} BRIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_BRIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + BRIGHTNESS_AUTO_ATTR_t stAuto; + BRIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_BRIGHTNESS_TYPE_t; + + +typedef struct RGBGAMMA_PARAM_s +{ + MI_U16 u16LutR[256]; //0 ~ 4095 + MI_U16 u16LutG[256]; //0 ~ 4095 + MI_U16 u16LutB[256]; //0 ~ 4095 +} RGBGAMMA_PARAM_t; + +typedef struct RGBGAMMA_MANUAL_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI; +} RGBGAMMA_MANUAL_ATTR_t; + +typedef struct RGBGAMMA_AUTO_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBGAMMA_AUTO_ATTR_t stAuto; + RGBGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBGAMMA_TYPE_t; + +typedef struct YUVGAMMA_PAMAR_s +{ + MI_U16 u16LutY[256]; //0 ~ 1023 + MI_U16 u16LutU[128]; //0 ~ 511 + MI_U16 u16LutV[128]; //0 ~ 511 +} YUVGAMMA_PAMAR_t; + +typedef struct YUVGAMMA_MANUAL_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI; +} YUVGAMMA_MANUAL_ATTR_t; + +typedef struct YUVGAMMA_AUTO_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI[MI_ISP_AUTO_NUM]; +} YUVGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_YUVGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + YUVGAMMA_AUTO_ATTR_t stAuto; + YUVGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_YUVGAMMA_TYPE_t; + +typedef struct SATURATION_PARAM_s +{ + MI_U8 u8SatAllStr; //0 ~ 127 (32 = 1X) + MI_U8 u8SatByYSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatByYLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatBySSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatBySLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatCoring; +} SATURATION_PARAM_t; + +typedef struct SATURATION_MANUAL_ATTR_s +{ + SATURATION_PARAM_t stParaAPI; +} SATURATION_MANUAL_ATTR_t; + +typedef struct SATURATION_AUTO_ATTR_s +{ + SATURATION_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SATURATION_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SATURATION_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SATURATION_AUTO_ATTR_t stAuto; + SATURATION_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SATURATION_TYPE_t; + +typedef struct DEFOG_PARAM_s +{ + MI_U8 u8Strength; +} DEFOG_PARAM_t; + +typedef struct DEFOG_MANUAL_ATTR_s +{ + DEFOG_PARAM_t stParaAPI; +} DEFOG_MANUAL_ATTR_t; + +typedef struct DEFOG_AUTO_ATTR_s +{ + DEFOG_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DEFOG_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DEFOG_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DEFOG_AUTO_ATTR_t stAuto; + DEFOG_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEFOG_TYPE_t; + +typedef struct RGBMATRIX_PARAM_s +{ + MI_U16 u16CCTthr; +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_PARAM_t; + +typedef struct RGBMATRIX_MANUAL_ATTR_s +{ +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_MANUAL_ATTR_t; + +typedef struct RGBMATRIX_AUTO_ATTR_s +{ + MI_ISP_BOOL_e bISOActEn; //0 ~ 1 + RGBMATRIX_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBMATRIX_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBMATRIX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBMATRIX_AUTO_ATTR_t stAuto; + RGBMATRIX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBMATRIX_TYPE_t; + +typedef struct MI_ISP_IQ_CCM_INFO_TYPE_s +{ + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) + MI_U16 u16CCT; +} MI_ISP_IQ_CCM_INFO_TYPE_t; + +typedef struct FALSECOLOR_PARAM_s +{ + MI_U8 u8FreqThrd; //0~255 default:140 + MI_U8 u8EdgeScoreThrd; //0~255 default:31 + MI_U8 u8ChromaThrdOfStrengthMax; //0~127 default:10 + MI_U8 u8ChromaThrdOfStrengthMid; //0~127 default:40 + MI_U8 u8ChromaThrdOfStrengthMin; //0~127 default:80 + MI_U8 u8StrengthMid; //0~7 default:7 + MI_U8 u8StrengthMin; //0~7 default:7 +} FALSECOLOR_PARAM_t; + +typedef struct FALSECOLOR_MANUAL_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI; +} FALSECOLOR_MANUAL_ATTR_t; + +typedef struct FALSECOLOR_AUTO_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} FALSECOLOR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_FALSECOLOR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + FALSECOLOR_AUTO_ATTR_t stAuto; + FALSECOLOR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_FALSECOLOR_TYPE_t; + +typedef struct NR3D_PARAM_s +{ + //TF + MI_U16 u16MdThd; //0~2048 + MI_U16 u16MdGain; //0~2048 + MI_U8 u8TfStr; //0~64 + MI_U8 u8TfStrEx; //0~64 + MI_U8 u8MdThdByY[16]; //0~255 + MI_U8 u8MdGainByY[16]; //0~255 + MI_U8 u8M2SLut[16]; //0~31 + MI_U8 u8TfLut[16]; //0~63 + + //Y SF (BNR) + MI_U8 u8YSfStr; //0~31 + MI_U8 u8YSfBlendLut[16]; //0~16 +} NR3D_PARAM_t; + +typedef struct NR3D_MANUAL_ATTR_s +{ + NR3D_PARAM_t stParaAPI; +} NR3D_MANUAL_ATTR_t; + +typedef struct NR3D_AUTO_ATTR_s +{ + NR3D_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NR3D_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NR3D_AUTO_ATTR_t stAuto; + NR3D_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_TYPE_t; + +typedef struct MI_ISP_IQ_NR3D_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NR3D_EX_TYPE_t; + +typedef struct MI_ISP_IQ_NR3D_P1_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NR3D_P1_TYPE_t; + +typedef struct NRDESPIKE_PARAM_s +{ + MI_U8 u8BlendRatio; //0 ~ 15 + MI_U8 u8StrengthCenterNeighbor; //0 ~ 5 + MI_U8 u8StrengthMeanStd; //0 ~ 5 + MI_U8 u8StrengthCornerCross; //0 ~ 5 + MI_U8 u8DiffGainMeanStd; //0 ~ 31 + MI_U16 u16DiffGainCenterNeighbor; //0 ~ 255 + MI_U16 u16DiffThdCornerCross; //0 ~ 255 +} NRDESPIKE_PARAM_t; + +typedef struct NRDESPIKE_MANUAL_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI; +} NRDESPIKE_MANUAL_ATTR_t; + +typedef struct NRDESPIKE_AUTO_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRDESPIKE_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRDESPIKE_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRDESPIKE_AUTO_ATTR_t stAuto; + NRDESPIKE_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRDESPIKE_TYPE_t; + +typedef struct NRLUMA_PARAM_s +{ + MI_ISP_BOOL_e bLumaAdjEn; + MI_U8 u8LumaX[9]; + MI_U16 u16LumaStrByY[10]; + MI_U8 u8Wei[20]; +} NRLUMA_PARAM_t; + +typedef struct NRLUMA_MANUAL_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI; +} NRLUMA_MANUAL_ATTR_t; + +typedef struct NRLUMA_AUTO_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLUMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_AUTO_ATTR_t stAuto; + NRLUMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLUMA_TYPE_t; + +typedef struct MI_ISP_IQ_NRLuma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NRLuma_Adv_TYPE_t; + +typedef struct NRChroma_PARAM_s +{ + MI_U8 u8MatchRatio; //0 ~ 127 + MI_U16 u16UvTh; //0 ~ 1023 + MI_U16 u16StrengthByCEdge[6]; //0 ~ 1023 +} NRChroma_PARAM_t; + +typedef struct NRChroma_MANUAL_ATTR_s +{ + NRChroma_PARAM_t stParaAPI; +} NRChroma_MANUAL_ATTR_t; + +typedef struct NRChroma_AUTO_ATTR_s +{ + NRChroma_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_AUTO_ATTR_t stAuto; + NRChroma_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_TYPE_t; + +typedef struct MI_ISP_IQ_NRChroma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NRChroma_Adv_TYPE_t; + +typedef struct MI_ISP_IQ_NRChroma_Pre_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NRChroma_Pre_TYPE_t; + +typedef struct SHARPNESS_LOCAL_PARAM_s +{ + MI_U8 u8OverShootGain; //0 ~ 255, def: 128 + MI_U8 u8UnderShootGain; //0 ~ 255, def: 128 + MI_U8 u8CorLUT[6]; //0 ~ 255, def: 0 + MI_U8 u8SclLUT[6]; //0 ~ 255, def: 0 +} SHARPNESS_LOCAL_PARAM_t; + +typedef struct SHARPNESS_PARAM_s +{ + SHARPNESS_LOCAL_PARAM_t stEdgeCtrl; + SHARPNESS_LOCAL_PARAM_t stTextureCtrl; + MI_U8 u8EdgeKillLUT[6]; //0 ~ 255, def: 0 + MI_U8 u8CornerReduce; //0 ~ 32, def: 32 + MI_ISP_BOOL_e bDirEn; //0 ~ 1, def: 1 + MI_U16 u16SharpnessUD; //0 ~ 1023 + MI_U16 u16SharpnessD; //0 ~ 1023 + MI_U16 u16DetailTh; //0 ~ 4095 + MI_U8 u8DetailByY[6]; //0 ~ 255 + MI_U16 u16OverShootLimit; //0 ~ 1023 + MI_U16 u16UnderShootLimit; //0 ~ 1023 +} SHARPNESS_PARAM_t; + +typedef struct SHARPNESS_MANUAL_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI; +} SHARPNESS_MANUAL_ATTR_t; + +typedef struct SHARPNESS_AUTO_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SHARPNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SHARPNESS_AUTO_ATTR_t stAuto; + SHARPNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_TYPE_t; + +typedef struct MI_ISP_IQ_SHARPNESS_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_SHARPNESS_EX_TYPE_t; + +typedef struct CROSSTALK_PARAM_s +{ + MI_U8 u8StrengthV2; //0 ~ 31 + MI_U16 u16ThresholdV2; //0 ~ 255 + MI_U16 u16ThresholdOffsetV2; //0 ~ 4095 +} CROSSTALK_PARAM_t; + +typedef struct CROSSTALK_MANUAL_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI; +} CROSSTALK_MANUAL_ATTR_t; + +typedef struct CROSSTALK_AUTO_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CROSSTALK_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CROSSTALK_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + CROSSTALK_AUTO_ATTR_t stAuto; + CROSSTALK_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CROSSTALK_TYPE_t; + +typedef struct OBC_PARAM_s +{ + MI_U16 u16ValR; //0 ~ 255 + MI_U16 u16ValGr; //0 ~ 255 + MI_U16 u16ValGb; //0 ~ 255 + MI_U16 u16ValB; //0 ~ 255 +} OBC_PARAM_t; + +typedef struct OBC_MANUAL_ATTR_s +{ + OBC_PARAM_t stParaAPI; +} OBC_MANUAL_ATTR_t; + +typedef struct OBC_AUTO_ATTR_s +{ + OBC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} OBC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_OBC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + OBC_AUTO_ATTR_t stAuto; + OBC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_OBC_TYPE_t; + +typedef struct WDR_PARAM_s +{ + MI_U8 u8BoxNum; //1 ~ 4 + MI_U8 u8PreEnhance; //0 ~ 6 + MI_ISP_BOOL_e bAutoDetailEnhance; //0 ~ 1 + MI_U8 u8ManualDetailEnhance; //0~255; default:128 + MI_U8 u8GlobalDarkToneEnhance; //0 ~ 15 + MI_U8 u8WDRStrByY[33]; //0 ~ 255 + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8DarkLimit; //0 ~ 255 + MI_U8 u8BrightLimit; //0 ~ 255 + MI_ISP_BOOL_e bGammaSyncEn; //0 ~ 1 +} WDR_PARAM_t; + +typedef struct WDR_MANUAL_ATTR_s +{ + WDR_PARAM_t stParaAPI; +} WDR_MANUAL_ATTR_t; + +typedef struct WDR_AUTO_ATTR_s +{ + WDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDR_AUTO_ATTR_t stAuto; + WDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDR_TYPE_t; + +typedef struct WDRCurveFull_PARAM_s +{ + MI_U16 u16FCurve[256]; +} WDRCurveFull_PARAM_t; + +typedef struct WDRCurveFull_MANUAL_ATTR_s +{ + WDRCurveFull_PARAM_t stParaAPI; +} WDRCurveFull_MANUAL_ATTR_t; + +typedef struct WDRCurveFull_AUTO_ATTR_s +{ + WDRCurveFull_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveFull_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveFull_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveFull_AUTO_ATTR_t stAuto; + WDRCurveFull_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveFull_TYPE_t; + +typedef struct WDRCurveAdv_PARAM_s +{ + MI_U16 u16Slope; //1024~16384 + MI_U8 u8TransitionPoint0; //0~255 + MI_U8 u8TransitionPoint1; //0~255 + MI_U8 u8SaturatedPoint; //0~255 + MI_U8 u8CurveModeSel; //0~5 +} WDRCurveAdv_PARAM_t; + +typedef struct WDRCurveAdv_MANUAL_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI; +} WDRCurveAdv_MANUAL_ATTR_t; + +typedef struct WDRCurveAdv_AUTO_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveAdv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveAdv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveAdv_AUTO_ATTR_t stAuto; + WDRCurveAdv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveAdv_TYPE_t; + +typedef struct DYNAMIC_DP_PARAM_s +{ + MI_ISP_BOOL_e bHotPixEn; //0 ~ 1 + MI_U16 u16HotPixCompSlpoe; + MI_ISP_BOOL_e bDarkPixEn; //0 ~ 1 + MI_U16 u16DarkPixCompSlpoe; + MI_U16 u16DPCTH; + MI_ISP_BOOL_e bBlendEn; + MI_U16 u16DiffLut[6]; + MI_U16 u16YLut[6]; +} DYNAMIC_DP_PARAM_t; + +typedef struct DYNAMIC_DP_MANUAL_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI; +} DYNAMIC_DP_MANUAL_ATTR_t; + +typedef struct DYNAMIC_DP_AUTO_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_AUTO_ATTR_t stAuto; + DYNAMIC_DP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DYNAMIC_DP_TYPE_t; + +typedef struct DYNAMIC_DP_CLUSTER_ATTR_S +{ + MI_ISP_BOOL_e bEdgeMode; + MI_U16 u16NeiDeltaTh; + MI_U8 u8NeiSmooth; + MI_ISP_BOOL_e bSortEn; + MI_ISP_BOOL_e bSortRGGBEn[4]; + MI_ISP_BOOL_e bSort1x3ModeEn; + MI_U16 u16SortLumTblL[6]; + MI_U16 u16SortLumTblD[6]; + MI_U16 u16SortLumTblS[6]; +} DYNAMIC_DP_CLUSTER_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI; +} DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_CLUSTER_AUTO_ATTR_S; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_CLUSTER_AUTO_ATTR_S stAuto; + DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_t; + +typedef struct HSV_PARAM_s +{ + MI_S16 s16HueLut[24]; //-64 ~ 64 + MI_U16 u16SatLut[24]; // 0 ~ 255 (64->1X) + MI_S16 s16HueLut_ForUnitCCM[24]; //-64 ~ 64 + MI_U16 u16SatLut_ForUnitCCM[24]; // 0 ~ 255 (64->1X) + MI_U8 u8GlobalSat; // 0 ~ 255 (64->1x) +} HSV_PARAM_t; + +typedef struct HSV_MANUAL_ATTR_s +{ + HSV_PARAM_t stParaAPI; +} HSV_MANUAL_ATTR_t; + +typedef struct HSV_AUTO_ATTR_s +{ + HSV_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HSV_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HSV_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + HSV_AUTO_ATTR_t stAuto; + HSV_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HSV_TYPE_t; + +typedef struct RGBIR_PARAM_s +{ + MI_U8 u8IrPosType; //0 ~ 7, def : 0 + MI_ISP_BOOL_e bRemovelEn; //0 ~ 1, def : 1 + MI_U16 u16Ratio_R[6]; + MI_U16 u16Ratio_G[6]; + MI_U16 u16Ratio_B[6]; +} RGBIR_PARAM_t; + +typedef struct RGBIR_MANUAL_ATTR_s +{ + RGBIR_PARAM_t stParaAPI; +} RGBIR_MANUAL_ATTR_t; + +typedef struct RGBIR_AUTO_ATTR_s +{ + RGBIR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBIR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBIR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBIR_AUTO_ATTR_t stAuto; + RGBIR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBIR_TYPE_t; + +typedef struct MI_ISP_IQ_FPN_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_FPN_TYPE_t; + +typedef struct MI_ISP_IQ_PFC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_PFC_TYPE_t; + +typedef struct MI_ISP_IQ_PFC_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_PFC_EX_TYPE_t; + +typedef struct DEMOSAIC_PARAM_s +{ + MI_U8 u8DirThrd; //0~63 def:35 + MI_U8 u8EdgeSmoothThrdY; //0~255 def:230 + MI_U8 u8EdgeSmoothThrdC; //0~127 def:20 +} DEMOSAIC_PARAM_t; + +typedef struct DEMOSAIC_MANUAL_ATTR_s +{ + DEMOSAIC_PARAM_t stParaAPI; +} DEMOSAIC_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_DEMOSAIC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DEMOSAIC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEMOSAIC_TYPE_t; + +typedef struct COLORTRANS_PARAM_s +{ + MI_U16 u16Y_OFST; //0 ~ 2047 + MI_U16 u16U_OFST; //0 ~ 2047 + MI_U16 u16V_OFST; //0 ~ 2047 + MI_U16 u16Matrix[9]; //0 ~ 1023 +} COLORTRANS_PARAM_t; + +typedef struct COLORTRANS_MANUAL_ATTR_s +{ + COLORTRANS_PARAM_t stParaAPI; +} COLORTRANS_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_COLORTRANS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + COLORTRANS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_COLORTRANS_TYPE_t; + +typedef struct HDR_PARAM_s +{ + MI_U16 u16SensorExpRatio; + MI_ISP_BOOL_e bNrEn; + MI_ISP_BOOL_e bDynRatioEn; + MI_U8 u8CRefSel; + MI_U16 u16YwtTh1; + MI_U16 u16YwtTh2; +} HDR_PARAM_t; + +typedef struct HDR_MANUAL_ATTR_s +{ + HDR_PARAM_t stParaAPI; +} HDR_MANUAL_ATTR_t; + +typedef struct HDR_AUTO_ATTR_s +{ + HDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + HDR_AUTO_ATTR_t stAuto; + HDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_TYPE_t; + +typedef struct MI_ISP_IQ_HDR_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_HDR_EX_TYPE_t; + +typedef struct MI_ISP_IQ_EFFECT_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_EFFECT_TYPE_t; + +typedef struct MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RGainTable[32*3]; + MI_U8 u8GGainTable[32*3]; + MI_U8 u8BGainTable[32*3]; +} MI_ISP_IQ_LSC_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_LSC_CTRL_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U16 u16TableR[3][ALSC_TBL_MAX]; + MI_U16 u16TableG[3][ALSC_TBL_MAX]; + MI_U16 u16TableB[3][ALSC_TBL_MAX]; +} MI_ISP_IQ_ALSC_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_ALSC_CTRL_TYPE_t; + +typedef struct R2Y_PARAM_s +{ + MI_U16 u16Matrix[9]; + MI_U8 u8AddY16; +} R2Y_PARAM_t; + +typedef struct R2Y_MANUAL_ATTR_s +{ + R2Y_PARAM_t stParaAPI; +} R2Y_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_R2Y_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + R2Y_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_R2Y_TYPE_t; + +typedef struct DUMMY_ATTR_s +{ + MI_S16 s16Dummy0[256]; + MI_S16 s16Dummy1[256]; + MI_S16 s16Dummy2[256]; + MI_S16 s16Dummy3; + MI_S16 s16Dummy4; +} DUMMY_ATTR_t; + +typedef struct DUMMY_MANUAL_ATTR_s +{ + DUMMY_ATTR_t stParaAPI; +} DUMMY_MANUAL_ATTR_t; + +typedef struct DUMMY_AUTO_ATTR_s +{ + DUMMY_ATTR_t stParaAPI[MI_ISP_AUTO_NUM]; +} DUMMY_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DUMMY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + DUMMY_AUTO_ATTR_t stAuto; + DUMMY_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DUMMY_TYPE_t; + +typedef struct DUMMY_EX_ATTR_s +{ + MI_S16 s16DummyEx0[256]; + MI_S16 s16DummyEx1[256]; + MI_S16 s16DummyEx2[256]; + MI_S16 s16DummyEx3; + MI_S16 s16DummyEx4; +} DUMMY_EX_ATTR_t; + +typedef struct +{ + DUMMY_EX_ATTR_t stParaAPI; +} DUMMY_EX_MANUAL_ATTR_S; + +typedef struct MI_ISP_IQ_DUMMY_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DUMMY_EX_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DUMMY_EX_TYPE_t; + +#endif + +#if 1 // ISP IQ API +typedef struct IQ_VERSION_INFO_PARAM_s +{ + MI_U32 u32Vendor; + MI_U32 u32Major; + MI_U32 u32Minor; +} IQ_VERSION_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_VERSION_INFO_TYPE_s +{ + IQ_VERSION_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_VERSION_INFO_TYPE_t; + +typedef struct IQ_PARAM_INIT_INFO_PARAM_s +{ + MI_ISP_BOOL_e bFlag; +} IQ_PARAM_INIT_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_PARAM_INIT_INFO_TYPE_s +{ + IQ_PARAM_INIT_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_PARAM_INIT_INFO_TYPE_t; + +typedef struct FAST_MODE_PARAM_s +{ + MI_ISP_BOOL_e bFastMode; +} FAST_MODE_PARAM_t; + +typedef struct MI_ISP_IQ_FAST_MODE_TYPE_s +{ + FAST_MODE_PARAM_t stParaAPI; +} MI_ISP_IQ_FAST_MODE_TYPE_t; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_PARAM_MODE_NORMAL = 0, + SS_IQ_PARAM_MODE_NIGHT = 1, //Night Mode + SS_IQ_PARAM_MODE_MAX +} MI_ISP_IQ_PARAM_MODE_e; + +typedef struct MI_ISP_IQ_GAMMA_LUT_TYPE_s +{ + MI_U16 u16LutR[256]; + MI_U16 u16LutG[256]; + MI_U16 u16LutB[256]; +} MI_ISP_IQ_GAMMA_LUT_TYPE_t; + +typedef struct MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_U16 u16BTGamma[256]; + MI_U16 u16DTGamma[256]; +} MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_t; + +typedef struct MI_ISP_IQ_OBC4Ch_TYPE_s +{ + MI_U16 u16OBC4Ch[4]; +} MI_ISP_IQ_OBC4Ch_TYPE_t; +#endif + +typedef struct TEMP_PARAM_s +{ + MI_S16 s16ObcOffset; + MI_U8 u8DynamicDPRatio; + MI_U8 u8CrosstalkRatio; + MI_U8 u8NRDeSpikeRatio; + MI_U8 u8NR3DRatio[2]; + MI_U8 u8NRLumaRatio; + MI_U8 u8SharpnessRatio[2]; + MI_U8 u8SaturationRatio; + MI_U8 u8ColorToneRatio[3]; +} TEMP_PARAM_t; + +typedef struct TEMP_MANUAL_ATTR_s +{ + TEMP_PARAM_t stParaAPI; +} TEMP_MANUAL_ATTR_t; + +typedef struct TEMP_AUTO_ATTR_s +{ + TEMP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} TEMP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_TEMP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8TemperatureLut[16]; + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + TEMP_AUTO_ATTR_t stAuto; + TEMP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_TEMP_TYPE_t; + +typedef struct MI_ISP_IQ_TEMP_INFO_TYPE_s +{ + MI_U8 u8Temperature; +} MI_ISP_IQ_TEMP_INFO_TYPE_t; + +#if 1 // MAINTOOL API +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_INDEX_0 = 0, + SS_IQ_INDEX_1, + SS_IQ_INDEX_2, + SS_IQ_INDEX_3, + SS_IQ_INDEX_4, + SS_IQ_INDEX_5, + SS_IQ_INDEX_6, + SS_IQ_INDEX_7, + SS_IQ_INDEX_8, + SS_IQ_INDEX_9, + SS_IQ_INDEX_10, + SS_IQ_INDEX_11, + SS_IQ_INDEX_12, + SS_IQ_INDEX_13, + SS_IQ_INDEX_14, + SS_IQ_INDEX_15, + SS_IQ_INDEX_MAX +} MI_ISP_IQ_INDEX_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_BYPASS_OFF = 0, + SS_BYPASS_ON, + SS_BYPASS_MAX +} MI_ISP_BYPASS_MODE_e; + +typedef struct MI_ISP_API_BYPASS_TYPE_s +{ + MI_ISP_BYPASS_MODE_e bEnable; //0 ~ 1 + MI_ISP_API_ID_e eAPIIndex; +} MI_ISP_API_BYPASS_TYPE_t; +#endif + + +/************************************* IQ - Define the structure declaration - END *************************************/ + + +#endif /* _MI_ISP_IQ_DATATYPE_H_ */ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp.h new file mode 100644 index 000000000..ff5b76153 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp.h @@ -0,0 +1,116 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_ISP_H_ +#define _MI_ISP_H_ +//#include + +#include "mi_common.h" +#include "mi_isp_datatype.h" +#include "mi_vpe_datatype.h" +#include "mi_isp_iq.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MI_ISP_OK (0) +#define MI_ISP_NOT_SUPPORT (1) +#define MI_ISP_FAILURE (-1) +#define MI_ISP_API_MAX_PARM_NUMBRE (6) +#define MI_ISP_API_ISPMID_NOT_SUPPORT (5) + + /************************************* Customer 3A API ***********************************/ + MI_S32 MI_ISP_AE_GetAeHwAvgStats(MI_U32 Channel, MI_ISP_AE_HW_STATISTICS_t *data); + MI_S32 MI_ISP_AWB_GetAwbHwAvgStats(MI_U32 Channel, MI_ISP_AWB_HW_STATISTICS_t *data); + MI_S32 MI_ISP_AWB_GetAwbHwAvgStatsShort(MI_U32 Channel, MI_ISP_AWB_HW_STATISTICS_t *data); + MI_S32 MI_ISP_AE_GetHisto0HwStats(MI_U32 Channel, MI_ISP_HISTO_HW_STATISTICS_t *data); + MI_S32 MI_ISP_AE_GetHisto1HwStats(MI_U32 Channel, MI_ISP_HISTO_HW_STATISTICS_t *data); + MI_S32 MI_ISP_AE_GetRgbIrHistoHwStats(MI_U32 Channel, MI_ISP_RGBIR_HISTO_HW_STATISTICS_t *data); + MI_S32 MI_ISP_CUS3A_Enable(MI_U32 Channel, Cus3AEnable_t *data); + MI_S32 MI_ISP_CUS3A_GetAeInitStatus(MI_U32 Channel, CusAEInitParam_t *data); + MI_S32 MI_ISP_CUS3A_GetAeStatus(MI_U32 Channel, CusAEInfo_t *data); + MI_S32 MI_ISP_CUS3A_SetAeParam(MI_U32 Channel, CusAEResult_t *data); + MI_S32 MI_ISP_CUS3A_GetAwbStatus(MI_U32 Channel, CusAWBInfo_t *data); + MI_S32 MI_ISP_CUS3A_SetAwbParam(MI_U32 Channel, CusAWBResult_t *data); + MI_S32 MI_ISP_CUS3A_SetAEWindowBlockNumber(MI_U32 Channel, MS_CUST_AE_WIN_BLOCK_NUM_TYPE_e *data); + MI_S32 MI_ISP_CUS3A_SetAEHistogramWindow(MI_U32 Channel, CusAEHistWin_t*data); + MI_S32 MI_ISP_CUS3A_SetAWBSampling(MI_U32 Channel, CusAWBSample_t *data); + MI_S32 MI_ISP_CUS3A_SetAECropSize(MI_U32 Channel, CusAEAWBCropSize_t *data); + MI_S32 MI_ISP_CUS3A_SetAWBCropSize(MI_U32 Channel, CusAEAWBCropSize_t *data); + + MI_S32 MI_ISP_CUS3A_GetAFStats(MI_U32 Channel, CusAFStats_t *data); + MI_S32 MI_ISP_CUS3A_SetAFWindow(MI_U32 Channel, CusAFWin_t *data); + MI_S32 MI_ISP_CUS3A_GetAFWindow(MI_U32 Channel, CusAFWin_t *data); + MI_S32 MI_ISP_CUS3A_SetAFFilter(MI_U32 Channel, CusAFFilter_t *data); + MI_S32 MI_ISP_CUS3A_GetAFFilter(MI_U32 Channel, CusAFFilter_t *data); + MI_S32 MI_ISP_CUS3A_SetAFFilter_Geo(MI_U32 Channel, CusAFFilter_Geo_t *data); + MI_S32 MI_ISP_CUS3A_GetAFFilter_Geo(MI_U32 Channel, CusAFFilter_Geo_t *data); + MI_S32 MI_ISP_CUS3A_SetAFFilterSq(MI_U32 Channel, CusAFFilterSq_t *data); + MI_S32 MI_ISP_CUS3A_GetAFFilterSq(MI_U32 Channel, CusAFFilterSq_t *data); + MI_S32 MI_ISP_CUS3A_SetAFRoiMode(MI_U32 Channel, CusAFRoiMode_t *data); + MI_S32 MI_ISP_CUS3A_GetAFRoiMode(MI_U32 Channel, CusAFRoiMode_t *data); + MI_S32 MI_ISP_CUS3A_GetAfStatus(MI_U32 Channel, CusAFInfo_t *data); + MI_S32 MI_ISP_CUS3A_SetAfParam(MI_U32 Channel, CusAfResult_t *data); + + MI_S32 MI_ISP_CUS3A_GetImageResolution(MI_U32 Channel, CusImageResolution_t *data); + MI_S32 MI_ISP_CUS3A_EnableISPOutImage(MI_U32 Channel, CusISPOutImage_t *data); + MI_S32 MI_ISP_CUS3A_GetISPOutImageCount(MI_U32 Channel, MI_U32 *data); + MI_S32 MI_ISP_CUS3A_CaptureHdrRawImage(MI_U32 Channel, CusHdrRawImage_t *data); + MI_S32 MI_ISP_GetFrameMetaInfo(MI_U32 Channel, IspFrameMetaInfo_t *data); + MI_S32 MI_ISP_ReadSensorData(MI_U32 Channel, CusSensorI2cParam_t *data); + MI_S32 MI_ISP_WriteSensorData(MI_U32 Channel, CusSensorI2cParam_t *data); + /************************************* Customer 3A API END********************************/ + /************************************* Debug API ***********************************/ + MI_S32 MI_ISP_SetDebugLevel_AE(MI_U32 Channel, MI_S32 *data); + MI_S32 MI_ISP_GetDebugLevel_AE(MI_U32 Channel, MI_S32 *data); + MI_S32 MI_ISP_SetDebugLevel_AWB(MI_U32 Channel, MI_S32 *data); + MI_S32 MI_ISP_GetDebugLevel_AWB(MI_U32 Channel, MI_S32 *data); + /************************************* Debug API END********************************/ + + MI_S32 MI_ISP_SET_ALL(int Channel, MI_U16 ApiId, MI_U32 ApiLen, MI_U8* pApiBuf); + MI_S32 MI_ISP_GET_ALL(int Channel, MI_U16 ApiId, MI_U32* ApiLen, MI_U8* pApiBuf); + + MI_S32 MI_ISP_API_CmdLoadBinFile(MI_U32 Channel, char* filepath, MI_U32 user_key); + MI_S32 MI_ISP_API_CmdLoadCaliData(MI_U32 Channel, MI_ISP_CALI_ITEM_e eCaliItem, char* filepath); + + typedef MI_S32 (*MI_ISP_ApiAgent_fp)(MI_VPE_IspApiHeader_t *pstData, void* pData); + + /*Api agent for SigmaStar user space 3A library*/ + MI_S32 MI_ISP_RegisterIspApiAgent(MI_U32 Channel, MI_ISP_ApiAgent_fp fpApiSet, MI_ISP_ApiAgent_fp fpApiGet); +#if !defined(DUAL_OS) && !defined(__RTOS__) //for pure linux + MI_S32 MI_ISP_EnableUserspace3A(MI_U32 Channel,MI_ISP_API_USERSPACE3A_ATTR_t *pAttr); + MI_S32 MI_ISP_DisableUserspace3A(MI_U32 Channel); +#else //for DualOS-Linux , RTK + inline MI_S32 MI_ISP_EnableUserspace3A(MI_U32 Channel,MI_ISP_API_USERSPACE3A_ATTR_t *pAttr) {return 0;} + inline MI_S32 MI_ISP_DisableUserspace3A(MI_U32 Channel) {return 0;} +#endif + + /*Common API, get isp root path*/ + MI_S32 MI_ISP_GetIspRoot(MI_U32 Channel, MI_ISP_ROOT_PATH_T *data); + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_MI_ISP_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_3a_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_3a_datatype.h new file mode 100644 index 000000000..74d29bae6 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_3a_datatype.h @@ -0,0 +1,532 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_ISP_3A_DATATYPE_H_ +#define _MI_ISP_3A_DATATYPE_H_ + +typedef enum __attribute__ ((aligned (4))) +{ + SS_FALSE = 0, + SS_TRUE = !SS_FALSE, + SS_BOOL_MAX +} MI_ISP_BOOL_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_OP_TYP_AUTO = 0, + SS_OP_TYP_MANUAL = !SS_OP_TYP_AUTO, + SS_OP_TYP_MODE_MAX +} MI_ISP_OP_TYPE_e; + +/************************************* AE - Define the structure declaration - START *************************************/ + +typedef enum __attribute__ ((aligned (4))) +{ + SS_ISP_STATE_NORMAL = 0, + SS_ISP_STATE_PAUSE = 1, + SS_ISP_STATE_MAX +} MI_ISP_SM_STATE_TYPE_e; + + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AE_MODE_A, // auto + SS_AE_MODE_AV, // aperture priority + SS_AE_MODE_SV, + SS_AE_MODE_TV, // shutter priority + SS_AE_MODE_M, // manual mode + SS_AE_MODE_MAX +} MI_ISP_AE_MODE_TYPE_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AE_WEIGHT_AVERAGE = 0, + SS_AE_WEIGHT_CENTER, + SS_AE_WEIGHT_SPOT, + SS_AE_WEIGHT_MAX +} MI_ISP_AE_WIN_WEIGHT_MODE_TYPE_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AE_FLICKER_TYPE_DISABLE = 0, + SS_AE_FLICKER_TYPE_60HZ = 1, + SS_AE_FLICKER_TYPE_50HZ = 2, + SS_AE_FLICKER_TYPE_AUTO = 3, + //SS_AE_FLICKER_TYPE_DETECT_60HZ = 4, + //SS_AE_FLICKER_TYPE_DETECT_50HZ = 5, + SS_AE_FLICKER_TYPE_MAX +} MI_ISP_AE_FLICKER_TYPE_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AE_FLICKER_TYPE_DETECT_60HZ = 0, + SS_AE_FLICKER_TYPE_DETECT_50HZ = 1, + SS_AE_FLICKER_TYPE_DETECT_MAX +} MI_ISP_AE_FLICKER_DETECT_TYPE_e; + +//typedef struct MI_ISP_AE_FLICKER_INFO_TYPE_s +//{ +// MI_ISP_BOOL_e bIsEffective; +// MI_ISP_AE_FLICKER_TYPE_e eFlickerType; +// MI_U16 u16Score; +//} MI_ISP_AE_FLICKER_INFO_TYPE_t; + +typedef struct MI_ISP_AE_FLICKER_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + MI_U8 u8AmpSensitivity; // 1 ~ 100 + MI_U8 u8ScoreThd; // 1 ~ 100 + MI_U8 uRefreshCycles; // 1 ~ 10 + MI_U8 u8ValidTimesThd; // 1 ~ 10 + MI_ISP_AE_FLICKER_DETECT_TYPE_e eFlickerType; // 60Hz = 0, 50Hz = 1 +} MI_ISP_AE_FLICKER_EX_TYPE_t; + +typedef struct MI_ISP_AE_FLICKER_EX_INFO_TYPE_s +{ + MI_ISP_BOOL_e bIsEffective; + MI_ISP_AE_FLICKER_DETECT_TYPE_e eFlickerType; + MI_U16 u16Score; +} MI_ISP_AE_FLICKER_EX_INFO_TYPE_t; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AE_STRATEGY_BRIGHTTONE, + SS_AE_STRATEGY_DARKTONE, + SS_AE_STRATEGY_AUTO, + SS_AE_STRATEGY_MAX +} MI_ISP_AE_STRATEGY_TYPE_e; + +typedef struct MI_ISP_AE_HIST_WEIGHT_Y_TYPE_s +{ + MI_U32 u32LumY; + MI_U32 u32AvgY; + MI_U32 u32Hits[128]; +} MI_ISP_AE_HIST_WEIGHT_Y_TYPE_t; + +typedef struct MI_ISP_AE_EXPO_VALUE_TYPE_s +{ + MI_U32 u32FNx10; + MI_U32 u32SensorGain; + MI_U32 u32ISPGain; + MI_U32 u32US; +} MI_ISP_AE_EXPO_VALUE_TYPE_t; + +typedef struct MI_ISP_AE_EXPO_INFO_TYPE_s +{ + MI_ISP_BOOL_e bIsStable; + MI_ISP_BOOL_e bIsReachBoundary; + MI_ISP_AE_EXPO_VALUE_TYPE_t stExpoValueLong; + MI_ISP_AE_EXPO_VALUE_TYPE_t stExpoValueShort; + MI_ISP_AE_HIST_WEIGHT_Y_TYPE_t stHistWeightY; + MI_U32 u32LVx10; + MI_S32 s32BV; + MI_U32 u32SceneTarget; +} MI_ISP_AE_EXPO_INFO_TYPE_t; + +typedef struct MI_ISP_AE_EV_COMP_TYPE_s +{ + MI_S32 s32EV; + MI_U32 u32Grad; +} MI_ISP_AE_EV_COMP_TYPE_t; + +typedef struct MI_ISP_AE_INTP_LUT_TYPE_s +{ + MI_U16 u16NumOfPoints; + MI_U32 u32Y[16]; + MI_U32 u32X[16]; +} MI_ISP_AE_INTP_LUT_TYPE_t; + +typedef struct CONV_SPEED_PARAM_s +{ + MI_U32 u32SpeedX[4]; + MI_U32 u32SpeedY[4]; +} CONV_SPEED_PARAM_t; + +typedef struct CONV_THD_PARAM_s +{ + MI_U32 u32InThd; + MI_U32 u32OutThd; +} CONV_THD_PARAM_t; + +typedef struct MI_ISP_AE_CONV_CONDITON_TYPE_s +{ + CONV_THD_PARAM_t stConvThrd; + CONV_SPEED_PARAM_t stConvSpeed; +} MI_ISP_AE_CONV_CONDITON_TYPE_t; + +typedef struct MI_ISP_AE_EXPO_LIMIT_TYPE_s +{ + MI_U32 u32MinShutterUS; + MI_U32 u32MaxShutterUS; + MI_U32 u32MinFNx10; + MI_U32 u32MaxFNx10; + MI_U32 u32MinSensorGain; + MI_U32 u32MinISPGain; + MI_U32 u32MaxSensorGain; + MI_U32 u32MaxISPGain; +} MI_ISP_AE_EXPO_LIMIT_TYPE_t; + +typedef struct EXPO_POINT_PARAM_s +{ + MI_U32 u32FNumx10; + MI_U32 u32Shutter; + MI_U32 u32TotalGain; + MI_U32 u32SensorGain; +} EXPO_POINT_PARAM_t; + +typedef struct MI_ISP_AE_EXPO_TABLE_TYPE_s +{ + MI_U32 u32NumPoints; + EXPO_POINT_PARAM_t stExpoTbl[16]; // LV from High to Low +} MI_ISP_AE_EXPO_TABLE_TYPE_t; + +typedef struct WIN_WEIGHT_PARAM_s +{ + MI_U8 u8AverageTbl[32*32]; + MI_U8 u8CenterTbl[32*32]; + MI_U8 u8SpotTbl[32*32]; +} WIN_WEIGHT_PARAM_t; + +typedef struct MI_ISP_AE_WIN_WEIGHT_TYPE_s +{ + MI_ISP_AE_WIN_WEIGHT_MODE_TYPE_e eTypeID; + WIN_WEIGHT_PARAM_t stParaAPI; +} MI_ISP_AE_WIN_WEIGHT_TYPE_t; + +typedef struct MI_ISP_AE_STRATEGY_TYPE_s +{ + MI_ISP_AE_STRATEGY_TYPE_e eAEStrategyMode; + MI_U32 u32Weighting; + MI_ISP_AE_INTP_LUT_TYPE_t stUpperOffset; + MI_ISP_AE_INTP_LUT_TYPE_t stLowerOffset; + MI_U32 u32BrightToneStrength; + MI_U32 u32BrightToneSensitivity; + MI_U32 u32DarkToneStrength; + MI_U32 u32DarkToneSensitivity; + MI_U32 u32AutoStrength; + MI_U32 u32AutoSensitivity; +} MI_ISP_AE_STRATEGY_TYPE_t; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AE_STRATEGY_EX_BRIGHTTONE, + SS_AE_STRATEGY_EX_DARKTONE, +} MI_ISP_AE_STRATEGY_EX_PRIORITY_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AE_STRATEGY_EX_COUNT, + SS_AE_STRATEGY_EX_TARGET, +} MI_ISP_AE_STRATEGY_EX_MODE_e; + +typedef struct MI_ISP_AE_STRATEGY_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_ISP_AE_STRATEGY_EX_MODE_e eMode; + MI_ISP_AE_STRATEGY_EX_PRIORITY_e ePriority; + MI_U16 u16BT_NodeNum; + MI_S32 u32BT_NodeBV[16]; + MI_U32 u32BT_ThdY[16]; + MI_U32 u32BT_Percentx10[16]; + MI_U32 u32BT_TargetYx10[16]; + MI_U32 u32BT_MaxOffsetDown[16]; + MI_U16 u16DT_NodeNum; + MI_S32 u32DT_NodeBV[16]; + MI_U32 u32DT_ThdY[16]; + MI_U32 u32DT_Percentx10[16]; + MI_U32 u32DT_TargetYx10[16]; + MI_U32 u32DT_MaxOffsetUp[16]; +} MI_ISP_AE_STRATEGY_EX_TYPE_t; + +typedef struct MI_ISP_AE_STRATEGY_EX_INFO_TYPE_s +{ + MI_U16 u16GMBlendRatio; + MI_U16 u16UpperLimitTargetx10; + MI_U16 u16LowerLimitTargetx10; + MI_U16 u16BTCntPcntx10; + MI_U16 u16DTCntPcntx10; + MI_U16 u16BTYx10; + MI_U16 u16DTYx10; +} MI_ISP_AE_STRATEGY_EX_INFO_TYPE_t; + +typedef struct MI_ISP_AE_RGBIR_AE_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_U16 u16MaxYWithIR; + MI_U16 u16MinISPGainCompRatio; +} MI_ISP_AE_RGBIR_AE_TYPE_t; + +typedef struct MI_ISP_AE_HDR_TYPE_s +{ + MI_ISP_AE_INTP_LUT_TYPE_t stAeHdrRatio; +} MI_ISP_AE_HDR_TYPE_t; + +typedef struct MI_ISP_AE_STABILIZER_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_U16 u16DiffThd; + MI_U16 u16Percent; +} MI_ISP_AE_STABILIZER_TYPE_t; + +/************************************* AE - Define the structure declaration - END *************************************/ + +/************************************* AWB - Define the structure declaration - START *************************************/ + +#define MI_ISP_AWB_LV_CT_TBL_NUM (18) +#define MI_ISP_AWB_CT_TBL_NUM (10) +#define MI_ISP_AWB_WEIGHT_WIN_NUM (81) + +typedef struct MI_ISP_AWB_QUERY_INFO_TYPE_s +{ + MI_ISP_BOOL_e bIsStable; + MI_U16 u16Rgain; + MI_U16 u16Grgain; + MI_U16 u16Gbgain; + MI_U16 u16Bgain; + MI_U16 u16ColorTemp; + MI_U8 u8WPInd; + MI_ISP_BOOL_e bMultiLSDetected; + MI_U8 u8FirstLSInd; + MI_U8 u8SecondLSInd; +} MI_ISP_AWB_QUERY_INFO_TYPE_t; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AWB_MODE_AUTO, + SS_AWB_MODE_MANUAL, + SS_AWB_MODE_CTMANUAL, + SS_AWB_MODE_MAX +} MI_ISP_AWB_MODE_TYPE_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AWB_ALG_GRAYWORLD = 0, + SS_AWB_ALG_NORMAL = 1, + SS_AWB_ALG_BALANCE = 2, + SS_AWB_ALG_FOCUS = 3, + SS_AWB_ALG_MAX = 0xffffffff +} MI_ISP_AWB_ALG_TYPE_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AWB_ADV_DEFAULT = 0, + SS_AWB_ADV_ADVANCE = 1, + SS_AWB_ADV_MAX = 0xffffffff +} MI_ISP_AWB_ADV_TYPE_e; + +typedef struct CT_LIMIT_PARAM_s +{ + MI_U16 u16MaxRgain; //RW, Maximum RGain, Range: [0, 8191] + MI_U16 u16MinRgain; //RW, Miniimum RGain, Range: [0, 8191] + MI_U16 u16MaxBgain; //RW, Maximum BGain, Range: [0, 8191] + MI_U16 u16MinBgain; //RW, Miniimum BGain, Range: [0, 8191] +} CT_LIMIT_PARAM_t; + +typedef struct CT_WEIGHT_PARAM_s +{ + MI_U16 u16Weight[MI_ISP_AWB_CT_TBL_NUM]; //RW, Light CT Weight, Range: [1, 255] +} CT_WEIGHT_PARAM_t; + +typedef struct CT_RATIO_PARAM_s +{ + MI_U16 u16Ratio[MI_ISP_AWB_CT_TBL_NUM]; //RW, CT Prefer Ratio, Range: [1, 255] +} CT_RATIO_PARAM_t; + +typedef struct AWB_ATTR_PARAM_s +{ + MI_U8 u8Speed; //RW, AWB converging speed, Range: [0x1, 0x64] + MI_U8 u8ConvInThd; //RW, AWB converging threshold, Range:[0, 255], Recommended: [32] + MI_U8 u8ConvOutThd; //RW, AWB converging threshold, Range:[0, 255], Recommended: [64] + MI_ISP_AWB_ALG_TYPE_e eAlgType; //RW, AWB 0:GrayWorld, 1:Normal, 2:Balance 3,Focus + MI_ISP_AWB_ADV_TYPE_e eAdvType; //RW, AWB advance mode type + MI_U8 u8RGStrength; //RW, AWB adjust RG ratio, Range:[0, 255] + MI_U8 u8BGStrength; //RW, AWB adjust BG ratio, Range:[0, 255] + CT_LIMIT_PARAM_t stCTLimit; //RW, AWB limitation when envirnoment ct is out of boundary + CT_WEIGHT_PARAM_t stLvWeight[MI_ISP_AWB_LV_CT_TBL_NUM]; //RW, AWB Lv Ct Weight, Range: [0, 255] + CT_RATIO_PARAM_t stPreferRRatio[MI_ISP_AWB_LV_CT_TBL_NUM]; //RW, AWB prefer R gain, Range: [0, 255] + CT_RATIO_PARAM_t stPreferBRatio[MI_ISP_AWB_LV_CT_TBL_NUM]; //RW, AWB prefer B gain, Range: [0, 255] + MI_U16 u16WpWeight[MI_ISP_AWB_CT_TBL_NUM]; + MI_U32 u32WeightWin[MI_ISP_AWB_WEIGHT_WIN_NUM]; //RW, AWB region gain, Range: [0, 16] +} AWB_ATTR_PARAM_t; + +typedef struct MWB_ATTR_PARAM_s +{ + MI_U16 u16Rgain; //RW, Multiplier for R color channel, Range: [0, 0x2000] + MI_U16 u16Grgain; //RW, Multiplier for Gr color channel, Range: [0, 0x2000] + MI_U16 u16Gbgain; //RW, Multiplier for Gb color channel, Range: [0, 0x2000] + MI_U16 u16Bgain; //RW, Multiplier for B color channel, Range: [0, 0x2000] +} MWB_ATTR_PARAM_t; + +typedef struct MI_ISP_AWB_ATTR_TYPE_s +{ + MI_ISP_SM_STATE_TYPE_e eState; + MI_ISP_AWB_MODE_TYPE_e eOpType; + MWB_ATTR_PARAM_t stManualParaAPI; + AWB_ATTR_PARAM_t stAutoParaAPI; +} MI_ISP_AWB_ATTR_TYPE_t; + +typedef struct AWB_ATTR_EXTRA_LIGHTSOURCE_PARAM_s +{ + MI_U16 u16WhiteRgain; //RW, RGain of white Point Location , Range: [256, 4095] + MI_U16 u16WhiteBgain; //RW, RGain of white Point Location , Range: [256, 4095] + MI_U8 u8AreaSize; //RW, Light Area Size , Range: [1, 32] + MI_ISP_BOOL_e bExclude; //RW, Include or exclude Uaer light Area, 0: include, 1:exclude +} AWB_ATTR_EXTRA_LIGHTSOURCE_PARAM_t; + +typedef struct MI_ISP_AWB_ATTR_EX_TYPE_s +{ + MI_ISP_BOOL_e bExtraLightEn; + AWB_ATTR_EXTRA_LIGHTSOURCE_PARAM_t stLightInfo[4]; +} MI_ISP_AWB_ATTR_EX_TYPE_t; + +typedef struct MI_ISP_AWB_MULTILS_LS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_U8 u8Sensitive; + MI_U8 u8CaliStrength; + MI_U16 u16CcmForLow[9]; + MI_U16 u16CcmForHigh[9]; +} MI_ISP_AWB_MULTILS_LS_TYPE_t; + +typedef struct MI_ISP_AWB_CT_WEIGHT_TYPE_s +{ + MI_U16 u16LvIndex; + CT_WEIGHT_PARAM_t stParaAPI; +} MI_ISP_AWB_CT_WEIGHT_TYPE_t; + +typedef struct MI_ISP_AWB_CT_CALI_TYPE_s +{ + MI_U16 u16StartIdx; //RW, Light area start index, Range: [0, u2EndIdx] + MI_U16 u16EndIdx; //RW, Light area end index, Range: [u2StartIdx, 9] + MI_U16 u16CtParams[40]; //RW, Color temperature of calibration paramters , Range: [1, 1000] +} MI_ISP_AWB_CT_CALI_TYPE_t; + +typedef struct MI_ISP_AWB_CUR_CT_CALI_TYPE_s +{ + MI_U16 u16CtParams[40]; //RW, Color temperature of calibration paramters , Range: [1, 1000] +} MI_ISP_AWB_CUR_CT_CALI_TYPE_t; + +typedef struct MI_ISP_AWB_CT_STATISTICS_TYPE_s +{ + MI_U16 u16Width; //RW, Effective range + MI_U16 u16Height; //RW, Effective range + MI_U16 u16StatisX[5760]; //RW, Color Temperature Curve Domain Statistics X, max is 64x90 + MI_U16 u16StatisY[5760]; //RW, Color Temperature Curve Domain Statistics Y, max is 64x90 +} MI_ISP_AWB_CT_STATISTICS_TYPE_t; + +typedef struct MI_ISP_AWB_HW_STATISTICS_TYPE_s +{ + MI_U8 u8AwbBuffer[34560]; // 128 * 90 * 3 +} MI_ISP_AWB_HW_STATISTICS_TYPE_t; + +typedef struct MI_ISP_AWB_CTMWB_PARAM_s +{ + MI_U32 u32CT; +} MI_ISP_AWB_CTMWB_PARAM_t; + +/************************************* AWB - Define the structure declaration - END *************************************/ + +/************************************* AF - Define the structure declaration - START *************************************/ + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AF_ALGO_ONESHOT = 0, + SS_AF_ALGO_CONTINUOUS = 1 +} MI_ISP_AF_ALGO_TYPE_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_AF_ACC_IIRH = 0, + SS_AF_ACC_IIRL = 1, + SS_AF_ACC_SBLV = 2, + SS_AF_ACC_SBLH = 3, + SS_AF_ACC_LUMA = 4, + SS_AF_ACC_MAX = 0xffffffff +} MI_ISP_AF_ACC_SEL_TYPE_e; + +typedef struct MI_ISP_AF_ATTR_TYPE_s +{ + MI_ISP_SM_STATE_TYPE_e eState; // 0~1 + MI_ISP_OP_TYPE_e eType; // 0~1 + MI_U16 u16ManualMotorPos; // 0~1023? + MI_ISP_AF_ALGO_TYPE_e eAlgo; // 0~1 +} MI_ISP_AF_ATTR_TYPE_t; + +typedef struct MI_ISP_AF_MOTOR_TYPE_s +{ + MI_U16 u16MinMotorPos; // 0~1023? + MI_U16 u16MaxMotorPos; // 0~1023? + MI_U16 u16MinMotorStep; // 0~1023? + MI_U16 u16MaxMotorStep; // 0~1023? +} MI_ISP_AF_MOTOR_TYPE_t; + +typedef struct MI_ISP_AF_ACC_WEIGHT_TYPE_s +{ + MI_U8 u8WinNumX; // 1~16 + MI_U8 u8WinNumY; // 1~16 + MI_ISP_BOOL_e bEqualWinWgt; // 0~1 + MI_U8 u8WinWgt[256]; // 0~255 + MI_ISP_BOOL_e bIIRHBlendEn; // 0~1 + MI_U8 u8IIRHWgt_FirstBlendIIRL; // 0~255 + MI_U8 u8IIRHWgt_SecondBlendSBLV; // 0~255 + MI_U8 u8IIRHWgt_ThirdBlendSBLH; // 0~255 +} MI_ISP_AF_ACC_WEIGHT_TYPE_t; + +typedef struct MI_ISP_AF_ONESHOT_TYPE_s +{ + MI_ISP_AF_ACC_SEL_TYPE_e eAccSel; // 0~3 + MI_U16 u16MotorStep; // 0~1023? +} MI_ISP_AF_ONESHOT_TYPE_t; + +typedef struct MI_ISP_AF_SCENE_CHANGE_TYPE_s +{ + MI_ISP_AF_ACC_SEL_TYPE_e ePreAfAccSel; // 0~3 + MI_U8 u8PreAeAccDiffThOft; // 0~100, unit: % + MI_U8 u8PreAeAccDiffThSlp; // 0~100, unit: % + MI_U8 u8PreAeAccCntThOft; // 0~100, unit: % + MI_U8 u8PreAeAccCntThSlp; // 0~100, unit: % + MI_U8 u8PreAfAccDiffThOft; // 0~100, unit: % + MI_U8 u8PreAfAccDiffThSlp; // 0~100, unit: % + MI_U8 u8PreAfAccCntThOft; // 0~100, unit: % + MI_U8 u8PreAfAccCntThSlp; // 0~100, unit: % + MI_ISP_AF_ACC_SEL_TYPE_e eFocusAfAccSel; // 0~3 + MI_U8 u8FocusAeAccDiffTh; // 0~100, unit: % + MI_U8 u8FocusAeAccCntTh; // 0~100, unit: % + MI_U8 u8FocusAfAccDiffTh; // 0~100, unit: % + MI_U8 u8FocusAfAccCntTh; // 0~100, unit: % + MI_U8 u8StableCntTh; // 0~255 +} MI_ISP_AF_SCENE_CHANGE_TYPE_t; + +typedef struct MI_ISP_AF_SEARCH_START_TYPE_s +{ + MI_U16 u16SearchMotorStep; // 0~1023? + MI_U16 u16SearchMotorDirByPosTh; // 0~1023? + MI_ISP_AF_ACC_SEL_TYPE_e eSearchAccSel; // 0~3 +} MI_ISP_AF_SEARCH_START_TYPE_t; + +typedef struct MI_ISP_AF_SEARCH_TYPE_s +{ + MI_U8 u8MinMaxAccRatioPeakThOft; // 0~100, unit: % + MI_U8 u8MinMaxAccRatioPeakThSlp; // 0~100, unit: % + MI_U8 u8AccDecCntPeakTh; // 0~255 + MI_U8 u8NowFakeMaxAccRatioPeakTh; // 0~100, unit: % + MI_U8 u8AccDecCntWrongDirTh; // 0~255 + MI_U8 u8NowFakeMaxAccRatioWrongDirTh; // 0~100, unit: % +} MI_ISP_AF_SEARCH_TYPE_t; + +/************************************* AF - Define the structure declaration - END *************************************/ + +#endif //_MI_ISP_3A_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_api_id.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_api_id.h new file mode 100644 index 000000000..dfd3aee4b --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_api_id.h @@ -0,0 +1,333 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp_api_id.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _TUNINGSERVER_API_ID_H_ +#define _TUNINGSERVER_API_ID_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif +#define ID_API_COMMON_BASE (0x0000) +#define ID_API_COMMON_END (0x0FFF) + +#if 0 +#define ID_API_ISP_BASE (0x1000) +#define ID_API_ISP_END (0x1FFF) + +#define ID_API_CALIBRATION_20_BASE (0x2000) +#define ID_API_CALIBRATION_20_END (0x22FF) + +#define ID_API_MAINTOOL_BASE (0x2300) +#define ID_API_MAINTOOL_END (0x25FF) + +#define ID_API_PLUGIN_BASE (0x2600) +#define ID_API_PLUGIN_END (0x28FF) +#else +#define ID_API_ISP_IQ_BASE (0x1000) +#define ID_API_ISP_IQ_END (0x13FF) + +#define ID_API_ISP_AE_BASE (0x1400) +#define ID_API_ISP_AE_END (0x17FF) + +#define ID_API_ISP_AWB_BASE (0x1800) +#define ID_API_ISP_AWB_END (0x1BFF) + +#define ID_API_ISP_AF_BASE (0x1C00) +#define ID_API_ISP_AF_END (0x1FFF) + +#define ID_API_ISP_OTHER_BASE (0x2000) +#define ID_API_ISP_OTHER_END (0x23FF) + +#define ID_API_CALIBRATION_20_BASE (0x2400) +#define ID_API_CALIBRATION_20_END (0x27FF) + +#define ID_API_MAINTOOL_BASE (0x2800) +#define ID_API_MAINTOOL_END (0x2BFF) + +#define ID_API_PLUGIN_BASE (0x2C00) +#define ID_API_PLUGIN_END (0x2DFF) + +#define ID_API_CUS3A_BASE (0x2E00) +#define ID_API_CUS3A_END (0x2FFF) + +#define ID_API_DEBUG_LEVEL_BASE (0x2FFF) +#define ID_API_DEBUG_LEVEL_END (0x3100) + +#define ID_API_VIDEO_ENCODE_BASE (0x3101) +#define ID_API_VIDEO_ENCODE_END (0x31FF) + +#define ID_API_RESERVED_BASE (0x3200) +#define ID_API_RESERVED_END (0x3FFF) + +#endif + +#define ID_CHIP_I1 (0x6d65031B) +#define ID_CHIP_I3 (0x6d65031C) +#define ID_CHIP_I2 (0x6d65031D) +#define ID_CHIP_I5 (0x6d65031E) +#define ID_CHIP_I6 (0x6d650320) +#define ID_CHIP_I6E (0x6d650321) +#define ID_CHIP_I6B0 (0x6d650322) +#define ID_CHIP_M6 (0x6d650323) +#define ID_CHIP_P3 (0x6d650324) + +//================================================================ +// ID Defined : Common API +//================================================================ +#define ID_API_COMMON_I2C_ACCESS ( ID_API_COMMON_BASE + 32 ) //SET_API_ID_MI_ISP_WriteI2C +//#define ID_API_COMMON_QuerySensorInfo ( ID_API_COMMON_BASE + 33 ) //GET_API_ID_MI_ISP_QuerySensorInfo +#define ID_API_COMMON_MIRROR ( ID_API_COMMON_BASE + 34 ) +#define ID_API_COMMON_ROTATE ( ID_API_COMMON_BASE + 35 ) +#define ID_API_COMMON_SENSOR_ID ( ID_API_COMMON_BASE + 36 ) + +#define ID_API_COMMON_FileID ( ID_API_COMMON_BASE + 100 ) //I1 or I3 or I2 or I5 ... +#define ID_API_COMMON_CHANNEL_ID ( ID_API_COMMON_BASE + 101 ) +#define ID_API_COMMON_ISPROOT ( ID_API_COMMON_BASE + 102 ) + +//#define ID_API_COMMON_AVAILABLE_MEMINFO ( ID_API_COMMON_BASE + 103 ) +//#define ID_API_COMMON_DEVICE_ID ( ID_API_COMMON_BASE + 104 ) +#define ID_API_COMMON_REOPEN ( ID_API_COMMON_BASE + 105 )//Ispmid reopen + +//================================================================ +// ID Defined : ISP API +//================================================================ +#define ID_API_ISP_IQ_VERSION_INFO ( ID_API_ISP_IQ_BASE + 1 ) // 1. 4097 +#define ID_API_ISP_IQ_PARAM_INIT_STATUS ( ID_API_ISP_IQ_BASE + 2 ) // 2. 4098 +#define ID_API_ISP_IQ_FAST_MODE ( ID_API_ISP_IQ_BASE + 3 ) // 3. 4099 +#define ID_API_ISP_IQ_COLORTOGRAY ( ID_API_ISP_IQ_BASE + 4 ) // 4. 4100 +#define ID_API_ISP_IQ_CONTRAST ( ID_API_ISP_IQ_BASE + 5 ) // 5. 4101 +#define ID_API_ISP_IQ_BRIGHTNESS ( ID_API_ISP_IQ_BASE + 6 ) // 6. 4102 +#define ID_API_ISP_IQ_LIGHTNESS ( ID_API_ISP_IQ_BASE + 7 ) // 7. 4103 +#define ID_API_ISP_IQ_RGBGAMMA ( ID_API_ISP_IQ_BASE + 8 ) // 8. 4104 +#define ID_API_ISP_IQ_YUVGAMMA ( ID_API_ISP_IQ_BASE + 9 ) // 9. 4105 +#define ID_API_ISP_IQ_SATURATION ( ID_API_ISP_IQ_BASE + 10 ) // 10. 4106 +#define ID_API_ISP_IQ_DEFOG ( ID_API_ISP_IQ_BASE + 11 ) // 11. 4107 +#define ID_API_ISP_IQ_CCM ( ID_API_ISP_IQ_BASE + 12 ) // 12. 4108 +#define ID_API_ISP_IQ_ANTI_FALSE_COLOR ( ID_API_ISP_IQ_BASE + 13 ) // 13. 4109 +#define ID_API_ISP_IQ_NR3D ( ID_API_ISP_IQ_BASE + 14 ) // 14. 4110 +#define ID_API_ISP_IQ_NR2D_DESPIKE ( ID_API_ISP_IQ_BASE + 15 ) // 15. 4111 +#define ID_API_ISP_IQ_NR2D_LUMA ( ID_API_ISP_IQ_BASE + 16 ) // 16. 4112 +#define ID_API_ISP_IQ_NR2D_CHROMA ( ID_API_ISP_IQ_BASE + 17 ) // 17. 4113 +#define ID_API_ISP_IQ_SHARPNESS ( ID_API_ISP_IQ_BASE + 18 ) // 18. 4114 +#define ID_API_ISP_IQ_CROSSTALK ( ID_API_ISP_IQ_BASE + 19 ) // 19. 4115 +#define ID_API_ISP_IQ_BLACK_LEVEL ( ID_API_ISP_IQ_BASE + 20 ) // 20. 4116 +#define ID_API_ISP_IQ_BLACK_LEVEL_P1 ( ID_API_ISP_IQ_BASE + 21 ) // 21. 4117 +#define ID_API_ISP_IQ_WDR ( ID_API_ISP_IQ_BASE + 22 ) // 22. 4118 +#define ID_API_ISP_IQ_DEFECT_PIXEL ( ID_API_ISP_IQ_BASE + 23 ) // 23. 4119 +#define ID_API_ISP_IQ_HSV ( ID_API_ISP_IQ_BASE + 24 ) // 24. 4120 +#define ID_API_ISP_IQ_RGBIR ( ID_API_ISP_IQ_BASE + 25 ) // 25. 4121 +#define ID_API_ISP_IQ_FPN ( ID_API_ISP_IQ_BASE + 26 ) // 26. 4122 +#define ID_API_ISP_IQ_PFC ( ID_API_ISP_IQ_BASE + 27 ) // 27. 4123 +#define ID_API_ISP_IQ_DM ( ID_API_ISP_IQ_BASE + 28 ) // 28. 4124 +#define ID_API_ISP_IQ_COLOR_TRANSFORM ( ID_API_ISP_IQ_BASE + 29 ) // 29. 4125 +#define ID_API_ISP_IQ_HDR ( ID_API_ISP_IQ_BASE + 30 ) // 30. 4126 +#define ID_API_ISP_IQ_EFFECT ( ID_API_ISP_IQ_BASE + 31 ) // 31. 4127 +#define ID_API_ISP_IQ_SYS_MCNR_MEMORY ( ID_API_ISP_IQ_BASE + 32 ) // 32. 4128 +#define ID_API_ISP_IQ_LSC ( ID_API_ISP_IQ_BASE + 33 ) // 33. 4129 +#define ID_API_ISP_IQ_PARAM_MODE ( ID_API_ISP_IQ_BASE + 34 ) // 34. 4130 +#define ID_API_ISP_IQ_LinearityLUT ( ID_API_ISP_IQ_BASE + 35 ) // 35. 4131 //Get Gamma data for CCM calibration +#define ID_API_ISP_IQ_OBCCALIB ( ID_API_ISP_IQ_BASE + 36 ) // 36. 4132 //Get OB data for Gamma or CCM calibration +#define ID_API_ISP_IQ_NR3D_P1 ( ID_API_ISP_IQ_BASE + 37 ) // 37. 4133 +#define ID_API_ISP_IQ_WDR_FC_CURVE ( ID_API_ISP_IQ_BASE + 38 ) // 38. 4134 +#define ID_API_ISP_IQ_R2Y ( ID_API_ISP_IQ_BASE + 39 ) // 39. 4135 +#define ID_API_ISP_IQ_ALSC ( ID_API_ISP_IQ_BASE + 40 ) // 40. 4136 +#define ID_API_ISP_IQ_LSC_CTRL ( ID_API_ISP_IQ_BASE + 41 ) // 41. 4137 +#define ID_API_ISP_IQ_ALSC_CTRL ( ID_API_ISP_IQ_BASE + 42 ) // 42. 4138 +#define ID_API_ISP_IQ_DEFECT_PIXEL_CLUSTER ( ID_API_ISP_IQ_BASE + 43 ) // 43. 4139 +#define ID_API_ISP_IQ_QUERY_CCM_INFO ( ID_API_ISP_IQ_BASE + 44 ) // 44. 4140 +#define ID_API_ISP_IQ_NR2D_LUMA_ADV ( ID_API_ISP_IQ_BASE + 45 ) // 45. 4141 +#define ID_API_ISP_IQ_NR2D_CHROMA_ADV ( ID_API_ISP_IQ_BASE + 46 ) // 46. 4142 +#define ID_API_ISP_IQ_PFC_EX ( ID_API_ISP_IQ_BASE + 47 ) // 47. 4143 +#define ID_API_ISP_IQ_HDR_EX ( ID_API_ISP_IQ_BASE + 48 ) // 48. 4144 +#define ID_API_ISP_IQ_SHP_EX ( ID_API_ISP_IQ_BASE + 49 ) // 49. 4145 +#define ID_API_ISP_IQ_NR_3D_EX ( ID_API_ISP_IQ_BASE + 50 ) // 50. 4146 +#define ID_API_ISP_IQ_DUMMY ( ID_API_ISP_IQ_BASE + 51 ) // 51. 4147 +#define ID_API_ISP_IQ_DUMMY_EX ( ID_API_ISP_IQ_BASE + 52 ) // 52. 4148 +#define ID_API_ISP_IQ_WDR_FC_CURVE_FULL ( ID_API_ISP_IQ_BASE + 53 ) // 53. 4149 +#define ID_API_ISP_IQ_ADAPTIVE_GAMMA ( ID_API_ISP_IQ_BASE + 54 ) // 54. 4150 +#define ID_API_ISP_IQ_NR2D_CHROMA_PRE ( ID_API_ISP_IQ_BASE + 55 ) // 55. 4151 +#define ID_API_ISP_IQ_TEMP ( ID_API_ISP_IQ_BASE + 56 ) // 56. 4152 +#define ID_API_ISP_IQ_TEMP_INFO ( ID_API_ISP_IQ_BASE + 57 ) // 57. 4153 + +#define ID_API_ISP_AE_HIST_WEIGHT_Y ( ID_API_ISP_AE_BASE + 1 ) // 1. 5121 +#define ID_API_ISP_AE_QUERY_EXPOSURE_INFO ( ID_API_ISP_AE_BASE + 2 ) // 2. 5122 +#define ID_API_ISP_AE_EV_COMP ( ID_API_ISP_AE_BASE + 3 ) // 3. 5123 +#define ID_API_ISP_AE_EXPO_MODE ( ID_API_ISP_AE_BASE + 4 ) // 4. 5124 +#define ID_API_ISP_AE_MANUAL_EXPO ( ID_API_ISP_AE_BASE + 5 ) // 5. 5125 +#define ID_API_ISP_AE_STATE ( ID_API_ISP_AE_BASE + 6 ) // 6. 5126 +#define ID_API_ISP_AE_TARGET ( ID_API_ISP_AE_BASE + 7 ) // 7. 5127 +#define ID_API_ISP_AE_CONVERGE ( ID_API_ISP_AE_BASE + 8 ) // 8. 5128 +#define ID_API_ISP_AE_EXPOSURE_LIMIT ( ID_API_ISP_AE_BASE + 9 ) // 9. 5129 +#define ID_API_ISP_AE_PLAIN_LONG_EXPO_TABLE ( ID_API_ISP_AE_BASE + 10 ) // 10. 5130 +#define ID_API_ISP_AE_PLAIN_SHORT_EXPO_TABLE ( ID_API_ISP_AE_BASE + 11 ) // 11. 5131 +#define ID_API_ISP_AE_WINDOW_WGT_MODE ( ID_API_ISP_AE_BASE + 12 ) // 12. 5132 +#define ID_API_ISP_AE_WINDOW_WGT ( ID_API_ISP_AE_BASE + 13 ) // 13. 5133 +#define ID_API_ISP_AE_FLICKER ( ID_API_ISP_AE_BASE + 14 ) // 14. 5134 +#define ID_API_ISP_AE_STRATEGY ( ID_API_ISP_AE_BASE + 15 ) // 15. 5135 +#define ID_API_ISP_AE_RGBIRExposureAttr ( ID_API_ISP_AE_BASE + 16 ) // 16. 5136 +#define ID_API_ISP_AE_HDR ( ID_API_ISP_AE_BASE + 17 ) // 17. 5137 +#define ID_API_ISP_AE_MANUAL_EXPO_SHORT ( ID_API_ISP_AE_BASE + 18 ) // 18. 5138 +#define ID_API_ISP_AE_FLICKER_EX ( ID_API_ISP_AE_BASE + 19 ) // 19. 5139 +#define ID_API_ISP_AE_QUERY_FLICKER_EX_INFO ( ID_API_ISP_AE_BASE + 20 ) // 20. 5140 +#define ID_API_ISP_AE_STABILIZER ( ID_API_ISP_AE_BASE + 21 ) // 21. 5141 +#define ID_API_ISP_AE_STRATEGY_EX ( ID_API_ISP_AE_BASE + 22 ) // 22. 5142 +#define ID_API_ISP_AE_QUERY_STRATEGY_EX_INFO ( ID_API_ISP_AE_BASE + 23 ) // 24. 5143 + +#define ID_API_ISP_AWB_QUERY_WHITE_BALANCE_INFO ( ID_API_ISP_AWB_BASE + 1 ) // 1. 6145 +#define ID_API_ISP_AWB_ATTR ( ID_API_ISP_AWB_BASE + 2 ) // 2. 6146 +#define ID_API_ISP_AWB_ATTR_EX ( ID_API_ISP_AWB_BASE + 3 ) // 3. 6147 +#define ID_API_ISP_AWB_MULTI_LS_ATTR ( ID_API_ISP_AWB_BASE + 4 ) // 4. 6148 +#define ID_API_ISP_AWB_CT_WEIGHT ( ID_API_ISP_AWB_BASE + 5 ) // 5. 6149 +#define ID_API_ISP_AWB_CTMWB ( ID_API_ISP_AWB_BASE + 6 ) // 5. 6150 + +#define ID_API_ISP_AF_HW_ROI_MODE ( ID_API_ISP_AF_BASE + 1 ) // 1. 7169 +#define ID_API_ISP_AF_HW_WIN ( ID_API_ISP_AF_BASE + 2 ) // 2. 7170 +#define ID_API_ISP_AF_HW_FILTER_ATTR ( ID_API_ISP_AF_BASE + 3 ) // 3. 7171 +#define ID_API_ISP_AF_HW_FILTERSQ ( ID_API_ISP_AF_BASE + 4 ) // 4. 7172 +#define ID_API_ISP_AF_ATTR ( ID_API_ISP_AF_BASE + 41 ) // 41. 7209 +#define ID_API_ISP_AF_MOTOR ( ID_API_ISP_AF_BASE + 42 ) // 42. 7210 +#define ID_API_ISP_AF_ACC_WEIGHT ( ID_API_ISP_AF_BASE + 43 ) // 43. 7211 +#define ID_API_ISP_AF_ONESHOT ( ID_API_ISP_AF_BASE + 44 ) // 44. 7212 +#define ID_API_ISP_AF_SCENE_CHANGE ( ID_API_ISP_AF_BASE + 45 ) // 45. 7213 +#define ID_API_ISP_AF_SEARCH_START ( ID_API_ISP_AF_BASE + 46 ) // 46. 7214 +#define ID_API_ISP_AF_SEARCH ( ID_API_ISP_AF_BASE + 47 ) // 47. 7215 + +//#define ID_API_VENC_RcParamEx ( ID_API_ISP_OTHER_BASE + 1 ) // 1. 8193 --> old ( ID_API_ISP_BASE + 35 ) //35. 4131 +//#define ID_API_VI_SensorFrameRate ( ID_API_ISP_OTHER_BASE + 2 ) // 2. 8194 --> old ( ID_API_ISP_BASE + 36 ) //36. 4132 +//#define ID_API_VENC_Resolution ( ID_API_ISP_OTHER_BASE + 3 ) // 3. 8195 --> old ( ID_API_ISP_BASE + 37 ) //37. 4133 + +//================================================================ +// ID Defined : Calibration 2.0 API +//================================================================ +#define ID_API_CALIBRATION_20_CaliBVAV ( ID_API_CALIBRATION_20_BASE + 1) // 1. 9217 //SET_API_ID_CALIBRATION_CaliBVAV = 61, +#define ID_API_CALIBRATION_20_Apply ( ID_API_CALIBRATION_20_BASE + 2) // 2. 9218 //SET_API_ID_CALIBRATION_ApplyBVAV = 62, +#define ID_API_CALIBRATION_20_CaliData ( ID_API_CALIBRATION_20_BASE + 3) // 3. 9219 //SET_API_ID_CALIBRATION_SetCaliData = 63, +#define ID_API_CALIBRATION_20_CaliPath ( ID_API_CALIBRATION_20_BASE + 4) // 4. 9220 //SET_API_ID_CALIBRATION_SetCaliPath = 64, +#define ID_API_CALIBRATION_20_CaliDBPath ( ID_API_CALIBRATION_20_BASE + 5) // 5. 9221 //SET_API_ID_CALIBRATION_SetCaliDBPath +#define ID_API_CALIBRATION_20_CaliInfo ( ID_API_CALIBRATION_20_BASE + 6) // 6. 9222 //GET_API_ID_CALIBRATION_GetCaliInfo + +#define ID_API_CALIBRATION_20_CaliAWB ( ID_API_CALIBRATION_20_BASE + 7) // 7. 9223 +#define ID_API_CALIBRATION_20_CaliOB ( ID_API_CALIBRATION_20_BASE + 8) // 8. 9224 +#define ID_API_CALIBRATION_20_CaliMinGain ( ID_API_CALIBRATION_20_BASE + 9) // 9. 9225 +#define ID_API_CALIBRATION_20_CaliShutterLinearity ( ID_API_CALIBRATION_20_BASE + 10) // 10. 9226 +#define ID_API_CALIBRATION_20_CaliGainLinearity ( ID_API_CALIBRATION_20_BASE + 11) // 11 9227 +#define ID_API_CALIBRATION_20_CaliDPC ( ID_API_CALIBRATION_20_BASE + 12) // 12. 9228 +#define ID_API_CALIBRATION_20_CaliALSC ( ID_API_CALIBRATION_20_BASE + 13) // 13. 9229 +#define ID_API_CALIBRATION_20_CaliFPN ( ID_API_CALIBRATION_20_BASE + 14) // 14. 9230 + +#define ID_API_CALIBRATION_30_ApplyAWB ( ID_API_CALIBRATION_20_BASE + 15) // 15. 9231 +#define ID_API_CALIBRATION_30_ApplyOBC ( ID_API_CALIBRATION_20_BASE + 16) // 16. 9232 +#define ID_API_CALIBRATION_30_ApplyMinGain ( ID_API_CALIBRATION_20_BASE + 17) // 17. 9233 +#define ID_API_CALIBRATION_30_ApplyShutterLinearity ( ID_API_CALIBRATION_20_BASE + 18) // 18. 9234 +#define ID_API_CALIBRATION_30_ApplyGainLinearity ( ID_API_CALIBRATION_20_BASE + 19) // 19 9235 +#define ID_API_CALIBRATION_30_ApplySDC ( ID_API_CALIBRATION_20_BASE + 20) // 20. 9236 +#define ID_API_CALIBRATION_30_ApplyALSC ( ID_API_CALIBRATION_20_BASE + 21) // 21. 9237 +#define ID_API_CALIBRATION_30_ApplyFPN ( ID_API_CALIBRATION_20_BASE + 22) // 22. 9238 +#define ID_API_CALIBRATION_30_ApplyLSC ( ID_API_CALIBRATION_20_BASE + 23) // 21. 9239 + +//================================================================ +// ID Defined : MainTool API +//================================================================ +#define ID_API_MAINTOOL_QUERY_SENSOR_INFO ( ID_API_MAINTOOL_BASE + 1 ) // 1. 10241 +#define ID_API_MAINTOOL_IQ_INDEX ( ID_API_MAINTOOL_BASE + 2 ) // 2. 10242 +#define ID_API_MAINTOOL_BYPASS ( ID_API_MAINTOOL_BASE + 3 ) // 3. 10243 + +//================================================================ +// ID Defined : Plugin API +//================================================================ +#define ID_API_PLUGIN_I2C_ACCESS ( ID_API_PLUGIN_BASE + 1 ) // 1. 11265 //SET_API_ID_MI_ISP_WriteI2C +#define ID_API_PLUGIN_WBCT ( ID_API_PLUGIN_BASE + 3 ) // 3. 11267 //SetWBCTCaliAttr +#define ID_API_PLUGIN_AWBCTStats ( ID_API_PLUGIN_BASE + 4 ) // 4. 11268 +#define ID_API_PLUGIN_AWBHWStats ( ID_API_PLUGIN_BASE + 5 ) // 5. 11269 +#define ID_API_PLUGIN_CUR_WBCT ( ID_API_PLUGIN_BASE + 6 ) // 6. 11270 //GetCurCTCaliAttr + +//================================================================ +// ID Defined : Cus3A API +//================================================================ +#define ID_API_CUS_AE_HW_AVG_STATS ( ID_API_CUS3A_BASE + 1 ) // 1. 11777 +#define ID_API_CUS_AE_HW_HISTO_0_STATS ( ID_API_CUS3A_BASE + 2 ) // 2. 11778 +#define ID_API_CUS_AE_HW_HISTO_1_STATS ( ID_API_CUS3A_BASE + 3 ) // 3. 11779 +#define ID_API_CUS_AE_GET_INIT_STATUS ( ID_API_CUS3A_BASE + 4 ) // 4. 11780 +#define ID_API_CUS_AE_GET_CUR_STATUS ( ID_API_CUS3A_BASE + 5 ) // 5. 11781 +#define ID_API_CUS_AE_SET_PARAM ( ID_API_CUS3A_BASE + 6 ) // 6. 11782 +#define ID_API_CUS_AWB_HW_AVG_STATS ( ID_API_CUS3A_BASE + 7 ) // 7. 11783 +#define ID_API_CUS_3A_ENABLE ( ID_API_CUS3A_BASE + 8 ) // 8. 11784 +#define ID_API_CUS_AWB_GET_CUR_STATUS ( ID_API_CUS3A_BASE + 9 ) // 9. 11785 +#define ID_API_CUS_AWB_SET_PARAM ( ID_API_CUS3A_BASE + 10) //10. 11786 +#define ID_API_CUS_AE_WINDOW_BLOCK_NUMBER ( ID_API_CUS3A_BASE + 11 )//11. 11787 +#define ID_API_CUS_AWB_SAMPLING ( ID_API_CUS3A_BASE + 12 )//12. 11788 +#define ID_API_CUS_AF_STATS ( ID_API_CUS3A_BASE + 13 )//13. 11789 +#define ID_API_CUS_AF_WINDOW ( ID_API_CUS3A_BASE + 14 )//14. 11790 +#define ID_API_CUS_AF_FILTER ( ID_API_CUS3A_BASE + 15 )//15. 11791 +#define ID_API_CUS_AF_FILTER_SQUARE ( ID_API_CUS3A_BASE + 16 )//16. 11792 +#define ID_API_CUS_AF_MODE ( ID_API_CUS3A_BASE + 17 )//17. 11793 +#define ID_API_CUS_AE_HISTOGRAM_WINDOW ( ID_API_CUS3A_BASE + 18 )//18. 11794 +#define ID_API_CUS_GET_IMAGE_RESOLUTION ( ID_API_CUS3A_BASE + 19 )//19. 11795 +#define ID_API_CUS_ENABLE_ISP_OUT_IMAGE ( ID_API_CUS3A_BASE + 20 )//20. 11796 +#define ID_API_CUS_GET_ISP_OUT_IMAGE_COUNT ( ID_API_CUS3A_BASE + 21 )//21. 11797 +#define ID_API_CUS_CAPTURE_HDR_RAW_IMAGE ( ID_API_CUS3A_BASE + 22 )//22. 11798 +#define ID_API_CUS_FRAME_META_INFO ( ID_API_CUS3A_BASE + 23 )//23. 11799 +#define ID_API_CUS_I2C_ACCESS ( ID_API_CUS3A_BASE + 24 )//24. 11800 +#define ID_API_CUS_AWB_HW_AVG_STATS_SHORT ( ID_API_CUS3A_BASE + 25 ) // 25. 11801 +#define ID_API_CUS_CAPTURE_RAW_IMAGE ( ID_API_CUS3A_BASE + 26 )//26. 11802 +#define ID_API_CUS_CUSTOMER_AE_CTRL ( ID_API_CUS3A_BASE + 27 )//27. 11803 , Customer defined AE control only +#define ID_API_CUS_CUSTOMER_AWB_CTRL ( ID_API_CUS3A_BASE + 28 )//28. 11804 , Customer defined AWB control only +#define ID_API_CUS_CUSTOMER_AF_CTRL ( ID_API_CUS3A_BASE + 29 )//29. 11805 , Customer defined AF control only +#define ID_API_CUS_AE_HW_RGBIR_HISTO_STATS ( ID_API_CUS3A_BASE + 30 ) // 30. 11806 +#ifdef ENABLE_EARLY_AE_DONE +#define ID_API_CUS_AE_DONE_RATIO ( ID_API_CUS3A_BASE + 31 )//31. 11807 +#endif +#define ID_API_CUS_AF_GET_CUR_STATUS ( ID_API_CUS3A_BASE + 32 )//32. 11808 , Customer defined AF control only +#define ID_API_CUS_AF_SET_PARAM ( ID_API_CUS3A_BASE + 33 )//33. 11809 , Customer defined AF control only +#define ID_API_CUS_AE_CROP_SIZE ( ID_API_CUS3A_BASE + 34 )//34. 11810 +#define ID_API_CUS_AWB_CROP_SIZE ( ID_API_CUS3A_BASE + 35 )//35. 11811 +//#define ID_API_CUS_AF_YPARAM ( ID_API_CUS3A_BASE + 36 )//36. 11812 +//#define ID_API_CUS_AF_SOURCE ( ID_API_CUS3A_BASE + 37 )//37. 11813 +//#define ID_API_CUS_AF_PRE_FILTER ( ID_API_CUS3A_BASE + 38 )//38. 11814 +//#define ID_API_CUS_AF_YMAP ( ID_API_CUS3A_BASE + 39 )//39. 11815 +//#define ID_API_CUS_AF_LDG ( ID_API_CUS3A_BASE + 40 )//40. 11816 + +//================================================================ +// ID Defined : Debug Level API +//================================================================ +#define ID_API_ISP_DeBugLevel_AE ( ID_API_DEBUG_LEVEL_BASE + 1 ) // 1. 12288 +#define ID_API_ISP_DeBugLevel_AWB ( ID_API_DEBUG_LEVEL_BASE + 2 ) // 2. 12289 +#define ID_API_ISP_DeBugLevel_AWB_PERIOD ( ID_API_DEBUG_LEVEL_BASE + 3 ) // 3. 12290 +#define ID_API_ISP_DeBugLevel_AF ( ID_API_DEBUG_LEVEL_BASE + 4 ) // 4. 12291 + + +//================================================================ +// ID Defined : ENCODE API +//================================================================ +#define ID_API_VIDEO_CHANNEL_ID ( ID_API_VIDEO_ENCODE_BASE + 1 ) // 1. 12546 +#define ID_API_VIDEO_RATE_CONTROL_ATTR ( ID_API_VIDEO_ENCODE_BASE + 2 ) // 2. 12547 +#define ID_API_VIDEO_RATE_CONTROL_PARAM ( ID_API_VIDEO_ENCODE_BASE + 3 ) // 2. 12548 + +#define ID_API_REGISTER_API_SET_CB ( ID_API_RESERVED_BASE + 1) //1. register API_SET callback +#define ID_API_REGISTER_API_GET_CB ( ID_API_RESERVED_BASE + 2) //2. register API_GET callback + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_TUNINGSERVER_API_ID_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_general.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_general.h new file mode 100644 index 000000000..c14a62fdb --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_general.h @@ -0,0 +1,188 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_ISP_GENERAL_H_ +#define _MI_ISP_GENERAL_H_ + +#include "mi_syscall.h" +#include "mi_vpe_datatype.h" +#include "mi_common.h" +#include "mi_isp.h" +#include "mi_isp_datatype.h" + +#ifdef CAM_OS_LINUX_USER +#include +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef LINUX_FLOW_ON_DUAL_OS +#define DUAL_OS_RUN_ON_LINUX 1 +#define DUAL_OS_RUN_ON_RTOS 0 +#else +#ifdef __RTOS__ +#define DUAL_OS_RUN_ON_LINUX 0 +#define DUAL_OS_RUN_ON_RTOS 1 +#else +#define DUAL_OS_RUN_ON_LINUX 0 +#define DUAL_OS_RUN_ON_RTOS 0 +#endif +#endif + +#define MI_ISP_MSG(args...) printf(args) +#define MI_ISP_DMSG(args...) do{}while(0) +#define MI_ISP_EMSG(args...) printf(args) +#define MI_ISP_VMSG(args...) do{}while(0) + +#define MI_ISP_CALLOC calloc +#define MI_ISP_FREE free + +extern MI_S32 MI_VPE_GetIspApiData(MI_VPE_IspApiHeader_t *pstIspDataHeader, void *pVirData); +extern MI_S32 MI_VPE_SetIspApiData(MI_VPE_IspApiHeader_t *pstIspDataHeader, void *pVirData); + +MI_S32 _MI_ISP_SetIspApiData(MI_VPE_IspApiHeader_t *pstIspDataHeader, void *pVirData); +MI_S32 _MI_ISP_GetIspApiData(MI_VPE_IspApiHeader_t *pstIspDataHeader, void *pVirData); + +#if (DUAL_OS_RUN_ON_LINUX) +#define MI_GETAPI(Channel, APIFuncID, PARAM_t, PtrData)\ + MI_S32 s32Ret = MI_ISP_OK;\ + MI_VPE_IspApiHeader_t stIspApiHeader;\ + PARAM_t *pIspBuffer = NULL;\ + MI_VPE_Alloc_IspDataBuf(sizeof(PARAM_t), &pIspBuffer);\ + memcpy(pIspBuffer, PtrData, sizeof(PARAM_t));\ + stIspApiHeader.u32HeadSize = sizeof(MI_VPE_IspApiHeader_t);\ + stIspApiHeader.u32DataLen = sizeof(PARAM_t);\ + stIspApiHeader.u32CtrlID = APIFuncID;\ + stIspApiHeader.u32Channel = Channel;\ + stIspApiHeader.s32Ret = 0;\ + MI_SYS_FlushInvCache((void *)pIspBuffer, sizeof(PARAM_t));\ + s32Ret = stIspApiHeader.s32Ret = MI_VPE_GetIspApiData(&stIspApiHeader, pIspBuffer);\ + memcpy(PtrData, pIspBuffer, sizeof(PARAM_t));\ + MI_VPE_Free_IspDataBuf(pIspBuffer);\ + return s32Ret;\ + +#define MI_SETAPI(Channel, APIFuncID, PARAM_t, PtrData)\ + MI_S32 s32Ret = MI_ISP_OK;\ + MI_VPE_IspApiHeader_t stIspApiHeader;\ + PARAM_t *pIspBuffer = NULL;\ + MI_VPE_Alloc_IspDataBuf(sizeof(PARAM_t), &pIspBuffer);\ + stIspApiHeader.u32HeadSize = sizeof(MI_VPE_IspApiHeader_t);\ + stIspApiHeader.u32DataLen = sizeof(PARAM_t);\ + stIspApiHeader.u32CtrlID = APIFuncID;\ + stIspApiHeader.u32Channel = Channel;\ + stIspApiHeader.s32Ret = 0;\ + memcpy(pIspBuffer, PtrData, sizeof(PARAM_t));\ + MI_SYS_FlushInvCache((void *)pIspBuffer, sizeof(PARAM_t));\ + s32Ret = stIspApiHeader.s32Ret = MI_VPE_SetIspApiData(&stIspApiHeader, pIspBuffer);\ + MI_VPE_Free_IspDataBuf(pIspBuffer);\ + return s32Ret;\ + +#define MI_CALI_SETAPI(Channel, APIFuncID, PARAM_t, DataSize, PtrData)\ + MI_VPE_IspApiHeader_t stIspApiHeader;\ + char *pIspBuffer = NULL;\ + MI_VPE_Alloc_IspDataBuf(DataSize, &pIspBuffer);\ + stIspApiHeader.u32HeadSize = sizeof(MI_VPE_IspApiHeader_t);\ + stIspApiHeader.u32DataLen = DataSize;\ + stIspApiHeader.u32CtrlID = APIFuncID;\ + stIspApiHeader.u32Channel = Channel;\ + stIspApiHeader.s32Ret = 0;\ + memcpy(pIspBuffer, PtrData, DataSize);\ + MI_SYS_FlushInvCache((void *)pIspBuffer, DataSize);\ + stIspApiHeader.s32Ret = MI_VPE_SetIspApiData(&stIspApiHeader, pIspBuffer);\ + MI_VPE_Free_IspDataBuf(pIspBuffer);\ + +#else +#define MI_GETAPI(Channel, APIFuncID, PARAM_t, PtrData)\ + MI_S32 s32Ret = MI_ISP_OK;\ + MI_VPE_IspApiHeader_t stIspApiHeader;\ + stIspApiHeader.u32HeadSize = sizeof(MI_VPE_IspApiHeader_t);\ + stIspApiHeader.u32DataLen = sizeof(PARAM_t);\ + stIspApiHeader.u32CtrlID = APIFuncID;\ + stIspApiHeader.u32Channel = Channel;\ + stIspApiHeader.s32Ret = 0;\ + /*s32Ret = stIspApiHeader.s32Ret = MI_VPE_GetIspApiData(&stIspApiHeader, PtrData);*/\ + s32Ret = stIspApiHeader.s32Ret = _MI_ISP_GetIspApiData(&stIspApiHeader, PtrData);\ + MI_ISP_DMSG("[%s] - (Channel,CtrlID, DataLenght, HeadSize) = (%d,%d,%d,%d)\n", __FUNCTION__, stIspApiHeader.u32Channel, stIspApiHeader.u32CtrlID, stIspApiHeader.u32DataLen, stIspApiHeader.u32HeadSize);\ + return s32Ret;\ + +#define MI_SETAPI(Channel, APIFuncID, PARAM_t, PtrData)\ + MI_S32 s32Ret = MI_ISP_OK;\ + MI_VPE_IspApiHeader_t stIspApiHeader;\ + stIspApiHeader.u32HeadSize = sizeof(MI_VPE_IspApiHeader_t);\ + stIspApiHeader.u32DataLen = sizeof(PARAM_t);\ + stIspApiHeader.u32CtrlID = APIFuncID;\ + stIspApiHeader.u32Channel = Channel;\ + stIspApiHeader.s32Ret = 0;\ + /*s32Ret = stIspApiHeader.s32Ret = MI_VPE_SetIspApiData(&stIspApiHeader, PtrData);*/\ + s32Ret = stIspApiHeader.s32Ret = _MI_ISP_SetIspApiData(&stIspApiHeader, PtrData);\ + MI_ISP_DMSG("[%s] - (Channel,CtrlID, DataLenght, HeadSize) = (%d,%d,%d,%d)\n", __FUNCTION__, stIspApiHeader.u32Channel, stIspApiHeader.u32CtrlID, stIspApiHeader.u32DataLen, stIspApiHeader.u32HeadSize);\ + return s32Ret;\ + +#define MI_CALI_SETAPI(Channel, APIFuncID, PARAM_t, DataSize, PtrData)\ + MI_VPE_IspApiHeader_t stIspApiHeader;\ + stIspApiHeader.u32HeadSize = sizeof(MI_VPE_IspApiHeader_t);\ + stIspApiHeader.u32DataLen = DataSize;\ + stIspApiHeader.u32CtrlID = APIFuncID;\ + stIspApiHeader.u32Channel = Channel;\ + stIspApiHeader.s32Ret = 0;\ + s32Ret = stIspApiHeader.s32Ret = MI_VPE_SetIspApiData(&stIspApiHeader, PtrData);\ + MI_ISP_DMSG("[%s] - (Channel,CtrlID, DataLenght, HeadSize) = (%d,%d,%d,%d)\n", __FUNCTION__, stIspApiHeader->u32Channel, stIspApiHeader->u32CtrlID, stIspApiHeader->u32DataLen, stIspApiHeader->u32HeadSize);\ + +#endif + +#define MI_ISP_SET(APIFunc, PARAM_t) \ + if(ApiLen != sizeof(PARAM_t)) \ + { \ + MI_ISP_MSG("[%s][%s] APIID:%d error param \n", __FILE__, __func__, ApiId); \ + break; \ + } \ + ret = APIFunc(Channel, (PARAM_t*)pApiBuf); \ + +#define MI_ISP_GET(APIFunc, PARAM_t) \ + *ApiLen = sizeof(PARAM_t); \ + ret = APIFunc(Channel, (PARAM_t*)pApiBuf); \ + +#define MI_CALL_SETAPI(Channel, APIFunc, PARAM_t)\ + MI_S32 s32Ret = MI_ISP_OK;\ + PARAM_t *stParam = MI_ISP_CALLOC(1, sizeof(PARAM_t));\ + memcpy(stParam, param_ary[0], sizeof(PARAM_t));\ + s32Ret = APIFunc(Channel, stParam);\ + MI_ISP_DMSG("[%s][%s] param_num = %d\n", __FILE__, __FUNCTION__, param_num);\ + MI_ISP_FREE(stParam);\ + return s32Ret;\ + +#define MI_RESET_API(Channel, APIFunc, PARAM_t)\ + PARAM_t *stParam = MI_ISP_CALLOC(1, sizeof(PARAM_t));\ + memset(stParam, 0x00, sizeof(PARAM_t));\ + s32Ret = APIFunc(Channel, stParam);\ + MI_ISP_DMSG("[%s][%s] param_num = %d\n", __FILE__, __FUNCTION__, param_num);\ + MI_ISP_FREE(stParam);\ + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_MI_ISP_GENERAL_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_iq.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_iq.h new file mode 100644 index 000000000..ed08f07bc --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/mi_isp_iq.h @@ -0,0 +1,298 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_ISP_IQ_H_ +#define _MI_ISP_IQ_H_ + +#include "mi_isp_3a_datatype.h" +#include "mi_isp_iq_datatype.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if 1 + /************************************* IQ API START *************************************/ + MI_S32 MI_ISP_IQ_GetVersionInfo(MI_U32 Channel, MI_ISP_IQ_VERSION_INFO_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetVersionInfo(MI_U32 Channel, MI_ISP_IQ_VERSION_INFO_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetParaInitStatus(MI_U32 Channel, MI_ISP_IQ_PARAM_INIT_INFO_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetColorToGray(MI_U32 Channel, MI_ISP_IQ_COLORTOGRAY_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetColorToGray(MI_U32 Channel, MI_ISP_IQ_COLORTOGRAY_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetContrast(MI_U32 Channel, MI_ISP_IQ_CONTRAST_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetContrast(MI_U32 Channel, MI_ISP_IQ_CONTRAST_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetBrightness(MI_U32 Channel, MI_ISP_IQ_BRIGHTNESS_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetBrightness(MI_U32 Channel, MI_ISP_IQ_BRIGHTNESS_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetLightness(MI_U32 Channel, MI_ISP_IQ_LIGHTNESS_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetLightness(MI_U32 Channel, MI_ISP_IQ_LIGHTNESS_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetRGBGamma(MI_U32 Channel, MI_ISP_IQ_RGBGAMMA_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetRGBGamma(MI_U32 Channel, MI_ISP_IQ_RGBGAMMA_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetYUVGamma(MI_U32 Channel, MI_ISP_IQ_YUVGAMMA_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetYUVGamma(MI_U32 Channel, MI_ISP_IQ_YUVGAMMA_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetSaturation(MI_U32 Channel, MI_ISP_IQ_SATURATION_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetSaturation(MI_U32 Channel, MI_ISP_IQ_SATURATION_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetDefog(MI_U32 Channel, MI_ISP_IQ_DEFOG_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetDefog(MI_U32 Channel, MI_ISP_IQ_DEFOG_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetRGBMatrix(MI_U32 Channel, MI_ISP_IQ_RGBMATRIX_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetRGBMatrix(MI_U32 Channel, MI_ISP_IQ_RGBMATRIX_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetFalseColor(MI_U32 Channel, MI_ISP_IQ_FALSECOLOR_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetFalseColor(MI_U32 Channel, MI_ISP_IQ_FALSECOLOR_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetNR3D(MI_U32 Channel, MI_ISP_IQ_NR3D_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetNR3D(MI_U32 Channel, MI_ISP_IQ_NR3D_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetNR3D_P1(MI_U32 Channel, MI_ISP_IQ_NR3D_P1_TYPE_t *data); //[not support chip] macaron, pudding, ispahan, tiramisu, ikayaki + MI_S32 MI_ISP_IQ_GetNR3D_P1(MI_U32 Channel, MI_ISP_IQ_NR3D_P1_TYPE_t *data); //[not support chip] macaron, pudding, ispahan, tiramisu, ikayaki + MI_S32 MI_ISP_IQ_SetNRDeSpike(MI_U32 Channel, MI_ISP_IQ_NRDESPIKE_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetNRDeSpike(MI_U32 Channel, MI_ISP_IQ_NRDESPIKE_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetNRLuma(MI_U32 Channel, MI_ISP_IQ_NRLUMA_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetNRLuma(MI_U32 Channel, MI_ISP_IQ_NRLUMA_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetNRChroma(MI_U32 Channel, MI_ISP_IQ_NRChroma_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetNRChroma(MI_U32 Channel, MI_ISP_IQ_NRChroma_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetSharpness(MI_U32 Channel, MI_ISP_IQ_SHARPNESS_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetSharpness(MI_U32 Channel, MI_ISP_IQ_SHARPNESS_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetCrossTalk(MI_U32 Channel, MI_ISP_IQ_CROSSTALK_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetCrossTalk(MI_U32 Channel, MI_ISP_IQ_CROSSTALK_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetOBC(MI_U32 Channel, MI_ISP_IQ_OBC_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetOBC(MI_U32 Channel, MI_ISP_IQ_OBC_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetOBC_P1(MI_U32 Channel, MI_ISP_IQ_OBC_TYPE_t *data); //[not support chip] ikayaki + MI_S32 MI_ISP_IQ_GetOBC_P1(MI_U32 Channel, MI_ISP_IQ_OBC_TYPE_t *data); //[not support chip] ikayaki + MI_S32 MI_ISP_IQ_SetWDR(MI_U32 Channel, MI_ISP_IQ_WDR_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetWDR(MI_U32 Channel, MI_ISP_IQ_WDR_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetWDRCurveAdv(MI_U32 Channel, MI_ISP_IQ_WDRCurveAdv_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetWDRCurveAdv(MI_U32 Channel, MI_ISP_IQ_WDRCurveAdv_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetWDRCurveFull(MI_U32 Channel, MI_ISP_IQ_WDRCurveFull_TYPE_t *data); //[not support chip] tiramisu + MI_S32 MI_ISP_IQ_GetWDRCurveFull(MI_U32 Channel, MI_ISP_IQ_WDRCurveFull_TYPE_t *data); //[not support chip] tiramisu + MI_S32 MI_ISP_IQ_SetDynamicDP(MI_U32 Channel, MI_ISP_IQ_DYNAMIC_DP_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetDynamicDP(MI_U32 Channel, MI_ISP_IQ_DYNAMIC_DP_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetDynamicDP_CLUSTER(MI_U32 Channel, MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetDynamicDP_CLUSTER(MI_U32 Channel, MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetHSV(MI_U32 Channel, MI_ISP_IQ_HSV_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetHSV(MI_U32 Channel, MI_ISP_IQ_HSV_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetRGBIR(MI_U32 Channel, MI_ISP_IQ_RGBIR_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetRGBIR(MI_U32 Channel, MI_ISP_IQ_RGBIR_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetFPN(MI_U32 Channel, MI_ISP_IQ_FPN_TYPE_t *data); //[not support chip] macaron, pudding, ispahan, tiramisu, ikayaki + MI_S32 MI_ISP_IQ_GetFPN(MI_U32 Channel, MI_ISP_IQ_FPN_TYPE_t *data); //[not support chip] macaron, pudding, ispahan, tiramisu, ikayaki + MI_S32 MI_ISP_IQ_SetPFC(MI_U32 Channel, MI_ISP_IQ_PFC_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_GetPFC(MI_U32 Channel, MI_ISP_IQ_PFC_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_SetDEMOSAIC(MI_U32 Channel, MI_ISP_IQ_DEMOSAIC_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetDEMOSAIC(MI_U32 Channel, MI_ISP_IQ_DEMOSAIC_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetR2Y(MI_U32 Channel, MI_ISP_IQ_R2Y_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetR2Y(MI_U32 Channel, MI_ISP_IQ_R2Y_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetCOLORTRANS(MI_U32 Channel, MI_ISP_IQ_COLORTRANS_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetCOLORTRANS(MI_U32 Channel, MI_ISP_IQ_COLORTRANS_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetHDR(MI_U32 Channel, MI_ISP_IQ_HDR_TYPE_t *data); //[not support chip] ikayaki + MI_S32 MI_ISP_IQ_GetHDR(MI_U32 Channel, MI_ISP_IQ_HDR_TYPE_t *data); //[not support chip] ikayaki + MI_S32 MI_ISP_IQ_SetLSC(MI_U32 Channel, MI_ISP_IQ_LSC_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetLSC(MI_U32 Channel, MI_ISP_IQ_LSC_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetLSC_CTRL(MI_U32 Channel, MI_ISP_IQ_LSC_CTRL_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetLSC_CTRL(MI_U32 Channel, MI_ISP_IQ_LSC_CTRL_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetALSC(MI_U32 Channel, MI_ISP_IQ_ALSC_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetALSC(MI_U32 Channel, MI_ISP_IQ_ALSC_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetALSC_CTRL(MI_U32 Channel, MI_ISP_IQ_ALSC_CTRL_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetALSC_CTRL(MI_U32 Channel, MI_ISP_IQ_ALSC_CTRL_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetNRLuma_Adv(MI_U32 Channel, MI_ISP_IQ_NRLuma_Adv_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_GetNRLuma_Adv(MI_U32 Channel, MI_ISP_IQ_NRLuma_Adv_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_SetNRChroma_Adv(MI_U32 Channel, MI_ISP_IQ_NRChroma_Adv_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_GetNRChroma_Adv(MI_U32 Channel, MI_ISP_IQ_NRChroma_Adv_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_SetNRChroma_Pre(MI_U32 Channel, MI_ISP_IQ_NRChroma_Pre_TYPE_t *data); //[not support chip] macaron, pudding, ispahan, ikayaki + MI_S32 MI_ISP_IQ_GetNRChroma_Pre(MI_U32 Channel, MI_ISP_IQ_NRChroma_Pre_TYPE_t *data); //[not support chip] macaron, pudding, ispahan, ikayaki + MI_S32 MI_ISP_IQ_SetPFC_EX(MI_U32 Channel, MI_ISP_IQ_PFC_EX_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_GetPFC_EX(MI_U32 Channel, MI_ISP_IQ_PFC_EX_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_SetHDR_EX(MI_U32 Channel, MI_ISP_IQ_HDR_EX_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_GetHDR_EX(MI_U32 Channel, MI_ISP_IQ_HDR_EX_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_SetSHP_EX(MI_U32 Channel, MI_ISP_IQ_SHARPNESS_EX_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_GetSHP_EX(MI_U32 Channel, MI_ISP_IQ_SHARPNESS_EX_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_SetNR3D_EX(MI_U32 Channel, MI_ISP_IQ_NR3D_EX_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_GetNR3D_EX(MI_U32 Channel, MI_ISP_IQ_NR3D_EX_TYPE_t *data); //[not support chip] macaron + MI_S32 MI_ISP_IQ_SetDUMMY(MI_U32 Channel, MI_ISP_IQ_DUMMY_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetDUMMY(MI_U32 Channel, MI_ISP_IQ_DUMMY_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetDUMMY_EX(MI_U32 Channel, MI_ISP_IQ_DUMMY_EX_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetDUMMY_EX(MI_U32 Channel, MI_ISP_IQ_DUMMY_EX_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetIQMode(MI_U32 Channel, MI_ISP_IQ_PARAM_MODE_e *data); + MI_S32 MI_ISP_IQ_GetIQMode(MI_U32 Channel, MI_ISP_IQ_PARAM_MODE_e *data); + MI_S32 MI_ISP_IQ_GetIQind(MI_U32 Channel, MI_ISP_IQ_INDEX_e *data); + MI_S32 MI_ISP_IQ_SetAPIBypassMode(MI_U32 Channel, MI_ISP_API_BYPASS_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetAPIBypassMode(MI_U32 Channel, MI_ISP_API_BYPASS_TYPE_t *data); + MI_S32 MI_ISP_IQ_QueryCCMInfo(MI_U32 Channel, MI_ISP_IQ_CCM_INFO_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetAdaptiveGamma(MI_U32 Channel, MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetAdaptiveGamma(MI_U32 Channel, MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_t *data); + MI_S32 MI_ISP_IQ_SetTEMP(MI_U32 Channel, MI_ISP_IQ_TEMP_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetTEMP(MI_U32 Channel, MI_ISP_IQ_TEMP_TYPE_t *data); + MI_S32 MI_ISP_IQ_GetTEMP_INFO(MI_U32 Channel, MI_ISP_IQ_TEMP_INFO_TYPE_t *data); + /************************************* IQ API END *************************************/ + + /************************************* AE API START *************************************/ + MI_S32 MI_ISP_AE_GetHistoWghtY(MI_U32 Channel, MI_ISP_AE_HIST_WEIGHT_Y_TYPE_t *data); + MI_S32 MI_ISP_AE_QueryExposureInfo(MI_U32 Channel, MI_ISP_AE_EXPO_INFO_TYPE_t *data); + MI_S32 MI_ISP_AE_SetEVComp(MI_U32 Channel, MI_ISP_AE_EV_COMP_TYPE_t *data); + MI_S32 MI_ISP_AE_GetEVComp(MI_U32 Channel, MI_ISP_AE_EV_COMP_TYPE_t *data); + MI_S32 MI_ISP_AE_SetExpoMode(MI_U32 Channel, MI_ISP_AE_MODE_TYPE_e *data); + MI_S32 MI_ISP_AE_GetExpoMode(MI_U32 Channel, MI_ISP_AE_MODE_TYPE_e *data); + MI_S32 MI_ISP_AE_SetManualExpo(MI_U32 Channel, MI_ISP_AE_EXPO_VALUE_TYPE_t *data); + MI_S32 MI_ISP_AE_GetManualExpo(MI_U32 Channel, MI_ISP_AE_EXPO_VALUE_TYPE_t *data); + MI_S32 MI_ISP_AE_SetManualShortExpo(MI_U32 Channel, MI_ISP_AE_EXPO_VALUE_TYPE_t *data); + MI_S32 MI_ISP_AE_GetManualShortExpo(MI_U32 Channel, MI_ISP_AE_EXPO_VALUE_TYPE_t *data); + MI_S32 MI_ISP_AE_SetState(MI_U32 Channel, MI_ISP_SM_STATE_TYPE_e *data); // Pause, Resume + MI_S32 MI_ISP_AE_GetState(MI_U32 Channel, MI_ISP_SM_STATE_TYPE_e *data); + MI_S32 MI_ISP_AE_SetTarget(MI_U32 Channel, MI_ISP_AE_INTP_LUT_TYPE_t *data); + MI_S32 MI_ISP_AE_GetTarget(MI_U32 Channel, MI_ISP_AE_INTP_LUT_TYPE_t *data); + MI_S32 MI_ISP_AE_SetConverge(MI_U32 Channel, MI_ISP_AE_CONV_CONDITON_TYPE_t *data); + MI_S32 MI_ISP_AE_GetConverge(MI_U32 Channel, MI_ISP_AE_CONV_CONDITON_TYPE_t *data); + MI_S32 MI_ISP_AE_SetExposureLimit(MI_U32 Channel, MI_ISP_AE_EXPO_LIMIT_TYPE_t *data); + MI_S32 MI_ISP_AE_GetExposureLimit(MI_U32 Channel, MI_ISP_AE_EXPO_LIMIT_TYPE_t *data); + MI_S32 MI_ISP_AE_SetPlainLongExpoTable(MI_U32 Channel, MI_ISP_AE_EXPO_TABLE_TYPE_t *data); + MI_S32 MI_ISP_AE_GetPlainLongExpoTable(MI_U32 Channel, MI_ISP_AE_EXPO_TABLE_TYPE_t *data); + MI_S32 MI_ISP_AE_SetPlainShortExpoTable(MI_U32 Channel, MI_ISP_AE_EXPO_TABLE_TYPE_t *data); + MI_S32 MI_ISP_AE_GetPlainShortExpoTable(MI_U32 Channel, MI_ISP_AE_EXPO_TABLE_TYPE_t *data); + MI_S32 MI_ISP_AE_SetWinWgtType(MI_U32 Channel, MI_ISP_AE_WIN_WEIGHT_MODE_TYPE_e *data); + MI_S32 MI_ISP_AE_GetWinWgtType(MI_U32 Channel, MI_ISP_AE_WIN_WEIGHT_MODE_TYPE_e *data); + MI_S32 MI_ISP_AE_SetWinWgt(MI_U32 Channel, MI_ISP_AE_WIN_WEIGHT_TYPE_t *data); + MI_S32 MI_ISP_AE_GetWinWgt(MI_U32 Channel, MI_ISP_AE_WIN_WEIGHT_TYPE_t *data); + MI_S32 MI_ISP_AE_SetFlicker(MI_U32 Channel, MI_ISP_AE_FLICKER_TYPE_e *data); + MI_S32 MI_ISP_AE_GetFlicker(MI_U32 Channel, MI_ISP_AE_FLICKER_TYPE_e *data); + MI_S32 MI_ISP_AE_SetFlickerEX(MI_U32 Channel, MI_ISP_AE_FLICKER_EX_TYPE_t *data); + MI_S32 MI_ISP_AE_GetFlickerEX(MI_U32 Channel, MI_ISP_AE_FLICKER_EX_TYPE_t *data); + MI_S32 MI_ISP_AE_SetStrategy(MI_U32 Channel, MI_ISP_AE_STRATEGY_TYPE_t *data); + MI_S32 MI_ISP_AE_GetStrategy(MI_U32 Channel, MI_ISP_AE_STRATEGY_TYPE_t *data); + MI_S32 MI_ISP_AE_SetStrategyEX(MI_U32 Channel, MI_ISP_AE_STRATEGY_EX_TYPE_t *data); + MI_S32 MI_ISP_AE_GetStrategyEX(MI_U32 Channel, MI_ISP_AE_STRATEGY_EX_TYPE_t *data); + MI_S32 MI_ISP_AE_SetRGBIRAE(MI_U32 Channel, MI_ISP_AE_RGBIR_AE_TYPE_t *data); + MI_S32 MI_ISP_AE_GetRGBIRAE(MI_U32 Channel, MI_ISP_AE_RGBIR_AE_TYPE_t *data); + MI_S32 MI_ISP_AE_SetHDR(MI_U32 Channel, MI_ISP_AE_HDR_TYPE_t *data); + MI_S32 MI_ISP_AE_GetHDR(MI_U32 Channel, MI_ISP_AE_HDR_TYPE_t *data); + MI_S32 MI_ISP_AE_SetStabilizer(MI_U32 Channel, MI_ISP_AE_STABILIZER_TYPE_t *data); + MI_S32 MI_ISP_AE_GetStabilizer(MI_U32 Channel, MI_ISP_AE_STABILIZER_TYPE_t *data); + /************************************* AE API END *************************************/ + + /************************************* AWB API START *************************************/ + MI_S32 MI_ISP_AWB_QueryInfo(MI_U32 Channel, MI_ISP_AWB_QUERY_INFO_TYPE_t *data); + MI_S32 MI_ISP_AWB_SetAttr(MI_U32 Channel, MI_ISP_AWB_ATTR_TYPE_t *data); + MI_S32 MI_ISP_AWB_GetAttr(MI_U32 Channel, MI_ISP_AWB_ATTR_TYPE_t *data); + MI_S32 MI_ISP_AWB_SetAttrEx(MI_U32 Channel, MI_ISP_AWB_ATTR_EX_TYPE_t *data); + MI_S32 MI_ISP_AWB_GetAttrEx(MI_U32 Channel, MI_ISP_AWB_ATTR_EX_TYPE_t *data); + MI_S32 MI_ISP_AWB_SetMultiLSAttr(MI_U32 Channel, MI_ISP_AWB_MULTILS_LS_TYPE_t *data); + MI_S32 MI_ISP_AWB_GetMultiLSAttr(MI_U32 Channel, MI_ISP_AWB_MULTILS_LS_TYPE_t *data); + MI_S32 MI_ISP_AWB_SetCTWeight(MI_U32 Channel, MI_ISP_AWB_CT_WEIGHT_TYPE_t *data); //Not works now, please use MI_ISP_AWB_SetAttr to set LvWeight indstead. + MI_S32 MI_ISP_AWB_GetCTWeight(MI_U32 Channel, MI_ISP_AWB_CT_WEIGHT_TYPE_t *data); //Not works now, please use MI_ISP_AWB_GetAttr to set LvWeight indstead. + + MI_S32 MI_ISP_AWB_SetCTCaliAttr(MI_U32 Channel, MI_ISP_AWB_CT_CALI_TYPE_t *data); + MI_S32 MI_ISP_AWB_GetCTCaliAttr(MI_U32 Channel, MI_ISP_AWB_CT_CALI_TYPE_t *data); + MI_S32 MI_ISP_AWB_GetCurCTCaliAttr(MI_U32 Channel, MI_ISP_AWB_CUR_CT_CALI_TYPE_t *data); + MI_S32 MI_ISP_AWB_GetCTStats(MI_U32 Channel, MI_ISP_AWB_CT_STATISTICS_TYPE_t *data); + MI_S32 MI_ISP_AWB_GetHWStats(MI_U32 Channel, MI_ISP_AWB_HW_STATISTICS_TYPE_t *data);//Not works now, please use MI_ISP_AWB_GetAwbHwAvgStats in mi_isp.h + MI_S32 MI_ISP_AWB_SetCTMwbAttr(MI_U32 Channel, MI_ISP_AWB_CTMWB_PARAM_t *data); + MI_S32 MI_ISP_AWB_GetCTMwbAttr(MI_U32 Channel, MI_ISP_AWB_CTMWB_PARAM_t *data); + + /************************************* AF API START *************************************/ + MI_S32 MI_ISP_AF_SetHWRoiMode(MI_U32 Channel, MI_ISP_AF_HW_ROI_MODE_TYPE_t *data); + MI_S32 MI_ISP_AF_GetHWRoiMode(MI_U32 Channel, MI_ISP_AF_HW_ROI_MODE_TYPE_t *data); + MI_S32 MI_ISP_AF_SetHWWin(MI_U32 Channel, MI_ISP_AF_HW_WIN_TYPE_t *data); + MI_S32 MI_ISP_AF_GetHWWin(MI_U32 Channel, MI_ISP_AF_HW_WIN_TYPE_t *data); + MI_S32 MI_ISP_AF_SetHWFilterAttr(MI_U32 Channel, MI_ISP_AF_HW_FILTER_ATTR_TYPE_t *data); + MI_S32 MI_ISP_AF_GetHWFilterAttr(MI_U32 Channel, MI_ISP_AF_HW_FILTER_ATTR_TYPE_t *data); + MI_S32 MI_ISP_AF_SetHWFilterSq(MI_U32 Channel, MI_ISP_AF_HW_FILTERSQ_TYPE_t *data); + MI_S32 MI_ISP_AF_GetHWFilterSq(MI_U32 Channel, MI_ISP_AF_HW_FILTERSQ_TYPE_t *data); + MI_S32 MI_ISP_AF_SetAttr(MI_U32 Channel, MI_ISP_AF_ATTR_TYPE_t *data); + MI_S32 MI_ISP_AF_GetAttr(MI_U32 Channel, MI_ISP_AF_ATTR_TYPE_t *data); + MI_S32 MI_ISP_AF_SetMotor(MI_U32 Channel, MI_ISP_AF_MOTOR_TYPE_t *data); + MI_S32 MI_ISP_AF_GetMotor(MI_U32 Channel, MI_ISP_AF_MOTOR_TYPE_t *data); + MI_S32 MI_ISP_AF_SetAccWeight(MI_U32 Channel, MI_ISP_AF_ACC_WEIGHT_TYPE_t *data); + MI_S32 MI_ISP_AF_GetAccWeight(MI_U32 Channel, MI_ISP_AF_ACC_WEIGHT_TYPE_t *data); + MI_S32 MI_ISP_AF_SetOneShot(MI_U32 Channel, MI_ISP_AF_ONESHOT_TYPE_t *data); + MI_S32 MI_ISP_AF_GetOneShot(MI_U32 Channel, MI_ISP_AF_ONESHOT_TYPE_t *data); + MI_S32 MI_ISP_AF_SetSceneChange(MI_U32 Channel, MI_ISP_AF_SCENE_CHANGE_TYPE_t *data); + MI_S32 MI_ISP_AF_GetSceneChange(MI_U32 Channel, MI_ISP_AF_SCENE_CHANGE_TYPE_t *data); + MI_S32 MI_ISP_AF_SetSearchStart(MI_U32 Channel, MI_ISP_AF_SEARCH_START_TYPE_t *data); + MI_S32 MI_ISP_AF_GetSearchStart(MI_U32 Channel, MI_ISP_AF_SEARCH_START_TYPE_t *data); + MI_S32 MI_ISP_AF_SetSearch(MI_U32 Channel, MI_ISP_AF_SEARCH_TYPE_t *data); + MI_S32 MI_ISP_AF_GetSearch(MI_U32 Channel, MI_ISP_AF_SEARCH_TYPE_t *data); + /************************************* AF API END *************************************/ + + MI_S32 MI_ISP_ALGO_SET_ALL(int Channel, MI_U16 ApiId, MI_U32 ApiLen, MI_U8* pApiBuf); + MI_S32 MI_ISP_ALGO_GET_ALL(int Channel, MI_U16 ApiId, MI_U32* ApiLen, MI_U8* pApiBuf); + +#endif + +#if 1 + +typedef struct MI_ISP_EXCUTE_CMD_ARRAY_s +{ + MI_U32 u32CmdType; + MI_U16 u16APIID; + MI_S32 (*callback)(MI_U32 Channel, MI_U8 *param_ary[], MI_U8 param_num); +} MI_ISP_EXCUTE_CMD_ARRAY_t; + +typedef enum __attribute__ ((aligned (1))) +{ + MI_ISP_CAMERA_CMD_SET = 0, + MI_ISP_CAMERA_CMD_GET, + MI_ISP_CAMERA_CMD_SET_MODE , + MI_ISP_CAMERA_CMD_GET_MODE, + MI_ISP_CAMERA_CMD_GET_PIC, + MI_ISP_CAMERA_CMD_SET_API, + MI_ISP_CAMERA_CMD_GET_API, + MI_ISP_CAMERA_CMD_UPLOAD_FILE, /* client upload file to server */ + MI_ISP_CAMERA_CMD_DOWNLOAD_FILE, /* client download file from server*/ +} MI_ISP_CAMERA_EXT_CMD_TYPE_e; + +typedef struct MI_ISP_CMD_HEADER_s +{ + MI_ISP_CAMERA_EXT_CMD_TYPE_e CmdType; + MI_S32 CmdLen; +} MI_ISP_CMD_HEADER_t; + +typedef struct MI_ISP_API_PARAM_s +{ + MI_U32 u32MagicKey; + MI_ISP_CMD_HEADER_t sCmdheader; + MI_U16 u16APIID; + MI_U16 u16ParamNum; +} MI_ISP_API_PARAM_t; + +typedef struct MI_ISP_API_BIN_FILE_s +{ + MI_U32 u32FileID; + MI_U32 u32ISPVer; + MI_U32 u32DataLen; + MI_U32 u32Checksum; + MI_U32 u32MagicKey; + MI_U32 u32Reserved[3]; +} MI_ISP_API_BIN_FILE_t; + +typedef struct MI_ISP_API_CALI_FILE_s +{ + MI_U32 u32CaliVer; + MI_U32 u32DataSize; + MI_U32 u32Checksum; + MI_U32 u32Reserved[2]; +} MI_ISP_API_CALI_FILE_t; + + MI_S32 MI_ISP_ALGO_API_DisableAllApi(MI_U32 Channel); + MI_S32 MI_ISP_ALGO_API_CmdLoadBinFile(MI_U32 Channel, MI_U8 *bindata_buf, MI_U32 user_key); + MI_S32 MI_ISP_ALGO_API_CmdLoadCaliData(MI_U32 Channel, MI_U8 *bindata_buf, MI_U32 BIN_BUF_MAX_LEN, MI_ISP_CALI_ITEM_e eCaliItem); + +#endif + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_MI_ISP_IQ_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/pudding/mi_isp_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/pudding/mi_isp_datatype.h new file mode 100644 index 000000000..b058e1868 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/pudding/mi_isp_datatype.h @@ -0,0 +1,430 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp_datatype.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_ISP_DATATYPE_H_ +#define _MI_ISP_DATATYPE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mi_common.h" +#include "mi_sys_datatype.h" +#include "mi_isp_3a_datatype.h" +#include "mi_isp_iq_datatype.h" + +/************************************* AF - Define the structure declaration - START *************************************/ + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************** Cus3A ***********************/ + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; + MI_U8 uAvgY; +} MI_ISP_AE_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AE_AVGS nAvg[128*90]; +}MI_ISP_AE_HW_STATISTICS_t; + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; +} MI_ISP_AWB_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AWB_AVGS nAvg[128*90]; +} MI_ISP_AWB_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[128]; +} MI_ISP_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[256]; +} MI_ISP_RGBIR_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_BOOL bAE; + MI_BOOL bAWB; + MI_BOOL bAF; +}Cus3AEnable_t; + +typedef struct +{ + MI_U32 Size; /**< struct size*/ + char sensor_id[32]; /**< sensor module id*/ + MI_U32 shutter; /**< shutter Shutter in ns*/ + MI_U32 shutter_step; /**< shutter Shutter step ns*/ + MI_U32 shutter_min; /**< shutter Shutter min us*/ + MI_U32 shutter_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gain; /**< sensor_gain Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + MI_U32 isp_gain; /**< isp_gain Isp digital gain , 1X = 1024 */ + MI_U32 isp_gain_max; /**< isp_gain Maximum Isp digital gain , 1X = 1024 */ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 fps; /**< initial frame per second*/ + MI_U32 shutterHDRShort_step; /**< shutter Shutter step ns*/ + MI_U32 shutterHDRShort_min; /**< shutter Shutter min us*/ + MI_U32 shutterHDRShort_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gainHDRShort_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gainHDRShort_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + /*CUS3A v1.1*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ +}CusAEInitParam_t,CusAeInitParam_t; + +/*! @brief ISP report to AE, hardware statistic */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + void *hist1; /**< HW statistic histogram 1*/ + void *hist2; /**< HW statistic histogram 2*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ + void * avgs; /**< HW statistics average block data*/ + MI_U32 Shutter; /**< Current shutter in ns*/ + MI_U32 SensorGain; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< Current ISP gain, 1X = 1024*/ + MI_U32 ShutterHDRShort; /**< Current shutter in ns*/ + MI_U32 SensorGainHDRShort; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGainHDRShort; /**< Current ISP gain, 1X = 1024*/ + /*CUS3A V1.1*/ + MI_U32 PreAvgY; /**< Previous frame brightness*/ + MI_U8 HDRCtlMode; /**< 0 = HDR off; */ + /**< 1 = Separate shutter & Separate sensor gain settings */ + /**< 2 = Separate shutter & Share sensor gain settings */ + /**< 3 = Share shutter & Separate sensor gain settings */ + MI_U32 FNx10; /**< Aperture in FNx10*/ + MI_U32 CurFPS; /**Current sensor FPS */ + MI_U32 PreWeightY; /**< Previous frame brightness with ROI weight*/ +} __attribute__((packed, aligned(1))) CusAEInfo_t, CusAeInput_t; + +/*! @brief ISP ae algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 Shutter; /**< Shutter in ns */ + MI_U32 SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< ISP gain, 1X = 1024 */ + MI_U32 ShutterHdrShort; /**< Shutter in ns */ + MI_U32 SensorGainHdrShort; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGainHdrShort; /**< ISP gain, 1X = 1024 */ + MI_U32 u4BVx16384; /**< Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_U32 AvgY; /**< frame brightness */ + MI_U32 HdrRatio; /**< hdr ratio, 1X = 1024 */ + /*CUS3A V1.1*/ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 DebandFPS; /** Target fps when running auto debanding**/ + MI_U32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAEResult_t, CusAeOutput_t; + +/*! @brief AWB HW statistics data*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 AvgBlkX; + MI_U32 AvgBlkY; + MI_U32 CurRGain; + MI_U32 CurGGain; + MI_U32 CurBGain; + void *avgs; //ISP_AWB_SAMPLE + /*CUS3A V1.1*/ + MI_U8 HDRMode; /**< Noramal or HDR mode*/ + void* *pAwbStatisShort; /**< Short Shutter AWB statistic data */ + MI_U32 u4BVx16384; /**< From AE output, Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_S32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAWBInfo_t, CusAWBInput_t; + +/*! @brief AWB algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 R_gain; /**< AWB gain for R channel*/ + MI_U32 G_gain; /**< AWB gain for G channel*/ + MI_U32 B_gain; /**< AWB gain for B channel*/ + MI_U32 ColorTmp; /**< Return color temperature*/ +}CusAWBResult_t, CusAwbOutput_t;; + +typedef enum __attribute__ ((aligned (1))) +{ + SS_AE_16x24 = 0, + SS_AE_32x24, + SS_AE_64x48, + SS_AE_64x45, + SS_AE_128x80, + SS_AE_128x90, + SS_AE_32x32 +} MS_CUST_AE_WIN_BLOCK_NUM_TYPE_e; + +typedef struct { + MI_U16 u2Stawin_x_offset; + MI_U16 u2Stawin_x_size; + MI_U16 u2Stawin_y_offset; + MI_U16 u2Stawin_y_size; + MI_U16 u2WinIdx; +} CusAEHistWin_t; + +typedef struct +{ + MI_U32 SizeX; + MI_U32 SizeY; + MI_U32 IncRatio; +}CusAWBSample_t; + +typedef struct +{ + MI_U16 CropX; // 0~1023 + MI_U16 CropY; // 0~1023 + MI_U16 CropW; // 0~1023 + MI_U16 CropH; // 0~1023 +}CusAEAWBCropSize_t; + +typedef struct +{ + MI_U8 iir_1[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 iir_2[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 luma[4*16]; //[4]: luma 32bit, use 4*u8 datatype, [16]: 16wins + MI_U8 fir_v[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 fir_h[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 ysat[3*16]; //[3]: ysat 22bit, use 3*u8 datatype, [16]: 16wins +} AF_STATS_PARAM_t; + +typedef struct +{ + AF_STATS_PARAM_t stParaAPI[16]; +} CusAFStats_t; + +typedef struct AF_WINDOW_PARAM_s +{ + MI_U32 u32StartX; /*range : 0~1023*/ + MI_U32 u32StartY; /*range : 0~1023*/ + MI_U32 u32EndX; /*range : 0~1023*/ + MI_U32 u32EndY; /*range : 0~1023*/ +} AF_WINDOW_PARAM_t; + +typedef struct +{ + MI_U8 u8WindowIndex; + AF_WINDOW_PARAM_t stParaAPI; +} CusAFWin_t; + +typedef struct +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; + + MI_U16 u16IIR1_e1_en; + MI_U16 u16IIR1_e1_a0; + MI_U16 u16IIR1_e1_a1; + MI_U16 u16IIR1_e1_a2; + MI_U16 u16IIR1_e1_b1; + MI_U16 u16IIR1_e1_b2; + MI_U16 u16IIR1_e2_en; + MI_U16 u16IIR1_e2_a0; + MI_U16 u16IIR1_e2_a1; + MI_U16 u16IIR1_e2_a2; + MI_U16 u16IIR1_e2_b1; + MI_U16 u16IIR1_e2_b2; + + MI_U16 u16IIR2_e1_en; + MI_U16 u16IIR2_e1_a0; + MI_U16 u16IIR2_e1_a1; + MI_U16 u16IIR2_e1_a2; + MI_U16 u16IIR2_e1_b1; + MI_U16 u16IIR2_e1_b2; + MI_U16 u16IIR2_e2_en; + MI_U16 u16IIR2_e2_a0; + MI_U16 u16IIR2_e2_a1; + MI_U16 u16IIR2_e2_a2; + MI_U16 u16IIR2_e2_b1; + MI_U16 u16IIR2_e2_b2; +} CusAFFilter_t; + +typedef struct +{ + MI_U16 u16Coeff[70]; +} CusAFFilter_Geo_t; + +typedef struct +{ + MI_BOOL bSobelYSatEn; + MI_U16 u16SobelYThd; + + MI_BOOL bIIRSquareAccEn; + MI_BOOL bSobelSquareAccEn; + + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} CusAFFilterSq_t; + + +typedef enum __attribute__ ((aligned (1))) +{ + AF_ROI_MODE_NORMAL, + AF_ROI_MODE_MATRIX +} ISP_AF_ROI_MODE_e; + +typedef struct +{ + ISP_AF_ROI_MODE_e mode; + MI_U32 u32_vertical_block_number; +} CusAFRoiMode_t; + +/* Raw store control */ +typedef enum +{ + eRawStoreNode_P0HEAD = 0, /* Control by VIF, Do not use */ + eRawStoreNode_P1HEAD = 1, /* Control by VIF, Do not use */ + eRawStoreNode_P0TAIL = 2, + eRawStoreNode_P1TAIL = 3, + eRawStoreNode_ISPOUT = 4, + eRawStoreNode_VDOS = 5, + eRawStoreNode_ISPOUT_BEFORE_YEE = 6, + eRawStoreNode_RGBIR_IR_ONLY = 7 +}CameraRawStoreNode_e; + +typedef struct +{ + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusImageResolution_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; +} CusISPOutImage_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusHdrRawImage_t; + +typedef struct +{ + MI_U64 u64Pts; /** frame PTS */ + MI_U32 u32Shutter; /**< Shutter in us */ + MI_U32 u32SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 u32ColorTmp; /**< Return color temperature*/ +} IspFrameMetaInfo_t; + +/*! @brief ISP report to AF, hardware status */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 MinPos; /**< Maximum position of AF motor */ + MI_U32 MaxPos; /**< Minimum position of AF motor */ + MI_U32 CurPos; /**< Current position of AF motor */ +} __attribute__((packed, aligned(1))) CusAFInfo_t, CusAfInput_t; + +/*! @brief AF algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 NextPos; /**< Next absolute position of AF motor */ +}__attribute__((packed, aligned(1))) CusAfResult_t, CusAfOutput_t; + +typedef struct +{ + MI_U32 u32SlaveAddr; //sensor slave address + MI_U32 u32RegLen; //sensor register length , 1 or 2 bytes + MI_U32 u32DataLen; //sensor register data length, 1 or 2 bytes + MI_U32 u32I2cSpeed; //i2c speed , 100/200/300/400 KHz + MI_U32 u32Reg; //sensor register address + MI_U32 u32Data; //sensor register data +}CusSensorI2cParam_t; + +/***************************** end of Cus3A ****************************/ + +// COMMON API +typedef struct MI_ISP_API_CHANNEL_ID_TYPE_s +{ + MI_U32 u32ChannelID; +} MI_ISP_API_CHANNEL_ID_TYPE_t; + +typedef struct MI_ISP_API_USERSPACE3A_ATTR_s +{ + MI_SYS_PixelFormat_e ePixelFmt; + MI_U32 eSensorBindId; +} MI_ISP_API_USERSPACE3A_ATTR_t; + +typedef struct +{ + MI_S8 strIspRoot[64]; +} MI_ISP_ROOT_PATH_T; + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_MI_ISP_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/pudding/mi_isp_iq_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/pudding/mi_isp_iq_datatype.h new file mode 100644 index 000000000..ee9a9e7be --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/pudding/mi_isp_iq_datatype.h @@ -0,0 +1,1347 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* + * iq_apiset.h + * + * Created on: 2016/8/16 + * Author: Elsa-cf.Lin + */ + +#ifndef _MI_ISP_IQ_DATATYPE_H_ +#define _MI_ISP_IQ_DATATYPE_H_ + +#include "mi_isp_3a_datatype.h" + +//put here temporarily, should add mi_isp_cali_datatype.h? + +typedef enum __attribute__ ((aligned (1))) +{ + SS_CALI_ITEM_AWB = 0, + SS_CALI_ITEM_OBC = 1, + SS_CALI_ITEM_SDC = 2, + SS_CALI_ITEM_ALSC = 3, + SS_CALI_ITEM_LSC = 4, + SS_CALI_ITEM_MAX, +} MI_ISP_CALI_ITEM_e; + +/************************************* AF - Define the structure declaration - START *************************************/ + +typedef struct MI_ISP_AF_HW_ROI_MODE_TYPE_s +{ + MI_U8 u8Mode; // 0: Normal, 1: Matrix + MI_U32 u32VerticalBlockNumber; +} MI_ISP_AF_HW_ROI_MODE_TYPE_t; + +typedef struct MI_ISP_AF_HW_WIN_TYPE_s +{ + MI_U16 u16Win[4*16]; +} MI_ISP_AF_HW_WIN_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTER_ATTR_TYPE_s +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; + + MI_U16 u16IIR1_e1_en; + MI_U16 u16IIR1_e1_a0; + MI_U16 u16IIR1_e1_a1; + MI_U16 u16IIR1_e1_a2; + MI_U16 u16IIR1_e1_b1; + MI_U16 u16IIR1_e1_b2; + MI_U16 u16IIR1_e2_en; + MI_U16 u16IIR1_e2_a0; + MI_U16 u16IIR1_e2_a1; + MI_U16 u16IIR1_e2_a2; + MI_U16 u16IIR1_e2_b1; + MI_U16 u16IIR1_e2_b2; + + MI_U16 u16IIR2_e1_en; + MI_U16 u16IIR2_e1_a0; + MI_U16 u16IIR2_e1_a1; + MI_U16 u16IIR2_e1_a2; + MI_U16 u16IIR2_e1_b1; + MI_U16 u16IIR2_e1_b2; + MI_U16 u16IIR2_e2_en; + MI_U16 u16IIR2_e2_a0; + MI_U16 u16IIR2_e2_a1; + MI_U16 u16IIR2_e2_a2; + MI_U16 u16IIR2_e2_b1; + MI_U16 u16IIR2_e2_b2; +} MI_ISP_AF_HW_FILTER_ATTR_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTERSQ_TYPE_s +{ + MI_U8 bSobelYSatEn; + MI_U16 u16SobelYThd; + MI_U8 bIIRSquareAccEn; + MI_U8 bSobelSquareAccEn; + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} MI_ISP_AF_HW_FILTERSQ_TYPE_t; + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************************* IQ - Define the structure declaration - START *************************************/ + +typedef struct +{ + MI_U16 u16NumOfPoints; + MI_S32 s32Y[16]; + MI_S32 s32X[16]; +} MI_INTP_LUT_IQ; + +#if 1 //API20 struct + +#define MI_ISP_AUTO_NUM (16) +#define ALSC_TBL_MAX 459 +#define ENABLE_CCM_COEFF_SUM_INFO 1 + +typedef enum __attribute__ ((aligned (4))) +{ + API20_AUTO = 0, //[00] + //API2.0 + API20_FPN, //[01] + API20_CCM, //[02] + API20_SAT, //[03] + API20_OBC, //[04] + API20_OBC_P1, //[05] + API20_FCOLOR, //[06] + API20_CR, //[07] + API20_NR_DeSpike, //[08] + API20_SHP, //[09] + API20_NR_3D, //[10] + API20_BRI, //[11] + API20_LIG, //[12] + API20_CST, //[13] + API20_GMA, //[14] + API20_CTG, //[15] + API20_NR_NLM, //[16] + API20_DEFOG, //[17] + API20_DRC, //[18] + API20_DPC, //[19] + API20_HSV, //[20] + API20_WDR_LOC, //[21] + API20_RGBIR, //[22] + API20_YUVGMA, //[23] + API20_HDR16to12, //[24] + API20_COLORTRANS, //[25] + API20_HDR, //[26] + API20_EFFECT, //[27] + API20_PFC, //[28] + API20_SIIR, //[29] + API20_DM, //[30] + API20_NR_3D_P1, //[31] + API20_WDRCurveAdv, //[32] + API20_MXNR, //[33] + API20_R2Y, //[34] + API20_LSC, //[35] + API20_LSC_CTRL, //[36] + API20_ALSC, //[37] + API20_ALSC_CTRL, //[38] + API20_DPC_CLUSTER, //[39] + API20_PFC_EX, //[40] + API20_HDR_EX, //[41] + API20_SHP_EX, //[42] + API20_NR_3D_EX, //[43] + API20_GNR, //[44] + API20_DUMMY, //[45] + API20_DUMMY_EX, //[46] + API20_WDRCurveFull, //[47] + API20_ADAPTIVE_GMA, //[48] + API20_XNR, //[49] + API20_TEMP, //[50] + API20_TEMP_INFO, //[51] + API20_MAX, //for para reset +} MI_ISP_API_ID_e; + +typedef struct MI_ISP_IQ_COLORTOGRAY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 +} MI_ISP_IQ_COLORTOGRAY_TYPE_t; + +typedef struct LEVEL_BASE_PARAM_s +{ + MI_U32 u32Lev; //0 ~ 100 +} LEVEL_BASE_PARAM_t; + +typedef struct LIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} LIGHTNESS_MANUAL_ATTR_t; + +typedef struct LIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} LIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_LIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + LIGHTNESS_AUTO_ATTR_t stAuto; + LIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_LIGHTNESS_TYPE_t; + +typedef struct CONTRAST_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} CONTRAST_MANUAL_ATTR_t; + +typedef struct CONTRAST_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CONTRAST_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CONTRAST_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + CONTRAST_AUTO_ATTR_t stAuto; + CONTRAST_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CONTRAST_TYPE_t; + +typedef struct BRIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} BRIGHTNESS_MANUAL_ATTR_t; + +typedef struct BRIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} BRIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_BRIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + BRIGHTNESS_AUTO_ATTR_t stAuto; + BRIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_BRIGHTNESS_TYPE_t; + + +typedef struct RGBGAMMA_PARAM_s +{ + MI_U16 u16LutR[256]; //0 ~ 4095 + MI_U16 u16LutG[256]; //0 ~ 4095 + MI_U16 u16LutB[256]; //0 ~ 4095 +} RGBGAMMA_PARAM_t; + +typedef struct RGBGAMMA_MANUAL_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI; +} RGBGAMMA_MANUAL_ATTR_t; + +typedef struct RGBGAMMA_AUTO_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBGAMMA_AUTO_ATTR_t stAuto; + RGBGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBGAMMA_TYPE_t; + +typedef struct YUVGAMMA_PAMAR_s +{ + MI_U16 u16LutY[256]; //0 ~ 1023 + MI_U16 u16LutU[128]; //0 ~ 511 + MI_U16 u16LutV[128]; //0 ~ 511 +} YUVGAMMA_PAMAR_t; + +typedef struct YUVGAMMA_MANUAL_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI; +} YUVGAMMA_MANUAL_ATTR_t; + +typedef struct YUVGAMMA_AUTO_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI[MI_ISP_AUTO_NUM]; +} YUVGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_YUVGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + YUVGAMMA_AUTO_ATTR_t stAuto; + YUVGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_YUVGAMMA_TYPE_t; + +typedef struct SATURATION_PARAM_s +{ + MI_U8 u8SatAllStr; //0 ~ 127 (32 = 1X) + MI_U8 u8SatByYSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatByYLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatBySSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatBySLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatCoring; +} SATURATION_PARAM_t; + +typedef struct SATURATION_MANUAL_ATTR_s +{ + SATURATION_PARAM_t stParaAPI; +} SATURATION_MANUAL_ATTR_t; + +typedef struct SATURATION_AUTO_ATTR_s +{ + SATURATION_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SATURATION_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SATURATION_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SATURATION_AUTO_ATTR_t stAuto; + SATURATION_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SATURATION_TYPE_t; + +typedef struct DEFOG_PARAM_s +{ + MI_U8 u8Strength; +} DEFOG_PARAM_t; + +typedef struct DEFOG_MANUAL_ATTR_s +{ + DEFOG_PARAM_t stParaAPI; +} DEFOG_MANUAL_ATTR_t; + +typedef struct DEFOG_AUTO_ATTR_s +{ + DEFOG_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DEFOG_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DEFOG_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DEFOG_AUTO_ATTR_t stAuto; + DEFOG_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEFOG_TYPE_t; + +typedef struct RGBMATRIX_PARAM_s +{ + MI_U16 u16CCTthr; +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_PARAM_t; + +typedef struct RGBMATRIX_MANUAL_ATTR_s +{ +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_MANUAL_ATTR_t; + +typedef struct RGBMATRIX_AUTO_ATTR_s +{ + MI_ISP_BOOL_e bISOActEn; //0 ~ 1 + RGBMATRIX_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBMATRIX_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBMATRIX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBMATRIX_AUTO_ATTR_t stAuto; + RGBMATRIX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBMATRIX_TYPE_t; + +typedef struct MI_ISP_IQ_CCM_INFO_TYPE_s +{ + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) + MI_U16 u16CCT; +} MI_ISP_IQ_CCM_INFO_TYPE_t; + +typedef struct FALSECOLOR_PARAM_s +{ + MI_U8 u8FreqThrd; //0~255 default:140 + MI_U8 u8EdgeScoreThrd; //0~255 default:31 + MI_U8 u8ChromaThrdOfStrengthMax; //0~127 default:10 + MI_U8 u8ChromaThrdOfStrengthMid; //0~127 default:40 + MI_U8 u8ChromaThrdOfStrengthMin; //0~127 default:80 + MI_U8 u8StrengthMid; //0~7 default:7 + MI_U8 u8StrengthMin; //0~7 default:7 +} FALSECOLOR_PARAM_t; + +typedef struct FALSECOLOR_MANUAL_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI; +} FALSECOLOR_MANUAL_ATTR_t; + +typedef struct FALSECOLOR_AUTO_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} FALSECOLOR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_FALSECOLOR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + FALSECOLOR_AUTO_ATTR_t stAuto; + FALSECOLOR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_FALSECOLOR_TYPE_t; + +typedef struct NR3D_PARAM_s +{ + MI_U8 u8MdThd; //0~255 + MI_U16 u16MdGain; //0~1023 + MI_U8 u8TfStr; //0~64 + MI_U8 u8TfStrEx; //0~64 + MI_U8 u8MdThdByY[16]; //0~255 + MI_U8 u8MdGainByY[16]; //0~255 + MI_U8 u8M2SLut[16]; //0~31 + MI_U16 u16TfLut[16]; //0~4095 + MI_U8 u8YSfBlendLut[16]; //0~16 + MI_U8 u8YSfBlendOffset; //0~16 +} NR3D_PARAM_t; + +typedef struct NR3D_MANUAL_ATTR_s +{ + NR3D_PARAM_t stParaAPI; +} NR3D_MANUAL_ATTR_t; + +typedef struct NR3D_AUTO_ATTR_s +{ + NR3D_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NR3D_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NR3D_AUTO_ATTR_t stAuto; + NR3D_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_TYPE_t; + +typedef struct NR3D_EX_PARAM_s +{ + MI_ISP_BOOL_e bAREn; //0~1 + MI_U8 u8ARLumaTh[2]; //0~255 + MI_U8 u8ARMotTh[2]; //0~255 + MI_ISP_BOOL_e bPREn; //0~1 + MI_U16 u16PRDiffTh; //0~4095 + MI_U8 u8PRRatioConf[4]; //0~16 + MI_U8 u8PRContrastTh[2]; //0~15 + MI_U8 u8PRMotTh[2]; //0~255 +} NR3D_EX_PARAM_t; + +typedef struct NR3D_EX_MANUAL_ATTR_s +{ + NR3D_EX_PARAM_t stParaAPI; +} NR3D_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + NR3D_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_EX_TYPE_t; + +typedef struct MI_ISP_IQ_NR3D_P1_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NR3D_P1_TYPE_t; + +typedef struct NRDESPIKE_PARAM_s +{ + MI_U8 u8BlendRatio; //0 ~ 15 + MI_U8 u8StrengthCenterNeighbor; //0 ~ 5 + MI_U8 u8StrengthMeanStd; //0 ~ 5 + MI_U8 u8StrengthCornerCross; //0 ~ 5 + MI_U8 u8DiffGainMeanStd; //0 ~ 31 + MI_U8 u8DiffGainCenterNeighbor; //0 ~ 255 + MI_U8 u8DiffThdCornerCross; //0 ~ 255 + MI_U16 u16BlendLut[5]; //0 ~ 2047 + MI_U8 u8StrengthByY[15]; //0 ~ 127 +} NRDESPIKE_PARAM_t; + +typedef struct NRDESPIKE_MANUAL_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI; +} NRDESPIKE_MANUAL_ATTR_t; + +typedef struct NRDESPIKE_AUTO_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRDESPIKE_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRDESPIKE_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRDESPIKE_AUTO_ATTR_t stAuto; + NRDESPIKE_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRDESPIKE_TYPE_t; + +typedef struct NRLUMA_PARAM_s +{ + MI_U8 u8Strength; + MI_U8 u8GMaskSel; + MI_U16 u16SpfBlendLut[2]; +} NRLUMA_PARAM_t; + +typedef struct NRLUMA_MANUAL_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI; +} NRLUMA_MANUAL_ATTR_t; + +typedef struct NRLUMA_AUTO_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLUMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_AUTO_ATTR_t stAuto; + NRLUMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLUMA_TYPE_t; + +typedef struct NRLUMA_Adv_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; + MI_U8 u8Strength; + MI_U8 u8StrengthByY[10]; + MI_U8 u8StrengthByMot[16]; + MI_U16 u16EdgeTh[8]; + MI_U32 u32EdgeGain[8]; + MI_U8 u8StrengthByType[2]; +} NRLUMA_Adv_PARAM_t; + +typedef struct NRLUMA_Adv_MANUAL_ATTR_s +{ + NRLUMA_Adv_PARAM_t stParaAPI; +} NRLUMA_Adv_MANUAL_ATTR_t; + +typedef struct NRLUMA_Adv_AUTO_ATTR_s +{ + NRLUMA_Adv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_Adv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLuma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_Adv_AUTO_ATTR_t stAuto; + NRLUMA_Adv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLuma_Adv_TYPE_t; + +typedef struct NRChroma_PARAM_s +{ + MI_U8 u8MatchRatio; //0 ~ 127 + MI_U16 u16UvTh; //0 ~ 1023 + MI_U16 u16StrengthByCEdge[6]; //0 ~ 1023 +} NRChroma_PARAM_t; + +typedef struct NRChroma_MANUAL_ATTR_s +{ + NRChroma_PARAM_t stParaAPI; +} NRChroma_MANUAL_ATTR_t; + +typedef struct NRChroma_AUTO_ATTR_s +{ + NRChroma_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_AUTO_ATTR_t stAuto; + NRChroma_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_TYPE_t; + +typedef struct NRChroma_Adv_PARAM_s +{ + MI_U8 u8StrengthByY[8]; //0 ~ 255 + MI_U8 u8StrengthByYEdge[8]; //0 ~ 63 + MI_U8 u8StrengthByCEdge[8]; //0 ~ 255 + MI_U8 u8MaxStrength; //0 ~ 255 + MI_U8 u8StaticLimitRatio; //0 ~ 63 + MI_U8 u8MotionClip; //0 ~ 255 + MI_U8 u8MotionColorReduce; //0 ~ 255 + MI_U8 u8MotionColorRecover; //0 ~ 255 + MI_U8 u8PreStrength; //0 ~ 128 +} NRChroma_Adv_PARAM_t; + +typedef struct NRChroma_Adv_MANUAL_ATTR_s +{ + NRChroma_Adv_PARAM_t stParaAPI; +} NRChroma_Adv_MANUAL_ATTR_t; + +typedef struct NRChroma_Adv_AUTO_ATTR_s +{ + NRChroma_Adv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_Adv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_Adv_AUTO_ATTR_t stAuto; + NRChroma_Adv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_Adv_TYPE_t; + +typedef struct MI_ISP_IQ_NRChroma_Pre_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NRChroma_Pre_TYPE_t; + +typedef struct SHARPNESS_PARAM_s +{ + MI_U8 u8OverShootGain; //0 ~ 255 + MI_U8 u8UnderShootGain; //0 ~ 255 + MI_U8 u8CorLUT[6]; //0 ~ 255 + MI_U8 u8SclLUT[6]; //0 ~ 255 + MI_U16 u16EdgeKillLUT[6]; //0 ~ 1023 + MI_U8 u8CornerReduce; //0 ~ 32 + MI_U8 u8DirTh; //0 ~ 255 + MI_U16 u16SharpnessUD[2]; //0 ~ 1023 + MI_U16 u16SharpnessD[2]; //0 ~ 1023 + MI_U8 u8PreCorUD[2]; //0 ~ 63 + MI_U8 u8PreCorD[2]; //0 ~ 63 + MI_U8 u8PreCorMotGain; //0 ~ 255 + MI_U8 u8LpfEdgeGainUD; //0 ~ 255 + MI_U8 u8LpfEdgeGainD; //0 ~ 255 + MI_U8 u8WeakDetailEnhance; //0 ~ 15 + MI_U16 u16DetailTh; //0 ~ 4095 + MI_U8 u8DetailMotOffset; //0 ~ 255 + MI_U8 u8DetailByY[6]; //0 ~ 255 + MI_U16 u16OverShootLimit; //0 ~ 1023 + MI_U16 u16UnderShootLimit; //0 ~ 1023 + MI_U8 u8MotGain[16]; //0 ~ 255 +} SHARPNESS_PARAM_t; + +typedef struct SHARPNESS_MANUAL_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI; +} SHARPNESS_MANUAL_ATTR_t; + +typedef struct SHARPNESS_AUTO_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SHARPNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SHARPNESS_AUTO_ATTR_t stAuto; + SHARPNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_TYPE_t; + +typedef struct SHARPNESS_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_U8 u8DirSel; //0 ~ 1 + MI_U8 u8DirOffA; //0 ~ 255 + MI_U8 u8MaxRatio; //0 ~ 255 + MI_U8 u8LpfY; //0 ~ 1 + MI_U8 u8SblLutY[6]; //0 ~ 255 + MI_U8 u8Sbl2LutY[6]; //0 ~ 255 + MI_U8 u8StrengthByHue[24]; //0 ~ 255 +} SHARPNESS_EX_PARAM_t; + +typedef struct SHARPNESS_EX_MANUAL_ATTR_s +{ + SHARPNESS_EX_PARAM_t stParaAPI; +} SHARPNESS_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + SHARPNESS_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_EX_TYPE_t; + +typedef struct CROSSTALK_PARAM_s +{ + MI_U8 u8Strength; //0 ~ 31 + MI_U8 u8StrengthByY[15]; //0 ~ 127 + MI_U8 u8Threshold; //0 ~ 255 + MI_U16 u16Offset; //0 ~ 4095 +} CROSSTALK_PARAM_t; + +typedef struct CROSSTALK_MANUAL_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI; +} CROSSTALK_MANUAL_ATTR_t; + +typedef struct CROSSTALK_AUTO_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CROSSTALK_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CROSSTALK_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + CROSSTALK_AUTO_ATTR_t stAuto; + CROSSTALK_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CROSSTALK_TYPE_t; + +typedef struct OBC_PARAM_s +{ + MI_U16 u16ValR; //0 ~ 255 + MI_U16 u16ValGr; //0 ~ 255 + MI_U16 u16ValGb; //0 ~ 255 + MI_U16 u16ValB; //0 ~ 255 +} OBC_PARAM_t; + +typedef struct OBC_MANUAL_ATTR_s +{ + OBC_PARAM_t stParaAPI; +} OBC_MANUAL_ATTR_t; + +typedef struct OBC_AUTO_ATTR_s +{ + OBC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} OBC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_OBC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + OBC_AUTO_ATTR_t stAuto; + OBC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_OBC_TYPE_t; + +typedef struct WDR_PARAM_s +{ + MI_U8 u8BoxNum; //1 ~ 4 + MI_U8 u8PreEnhance; //0 ~ 6 + MI_ISP_BOOL_e bAutoDetailEnhance; //0 ~ 1 + MI_U8 u8ManualDetailEnhance; //0~255; default:128 + MI_U8 u8GlobalDarkToneEnhance; //0 ~ 15 + MI_U8 u8WDRStrByY[33]; //0 ~ 255 + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8DarkLimit; //0 ~ 255 + MI_U8 u8BrightLimit; //0 ~ 255 + MI_ISP_BOOL_e bGammaSyncEn; //0 ~ 1 +} WDR_PARAM_t; + +typedef struct WDR_MANUAL_ATTR_s +{ + WDR_PARAM_t stParaAPI; +} WDR_MANUAL_ATTR_t; + +typedef struct WDR_AUTO_ATTR_s +{ + WDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDR_AUTO_ATTR_t stAuto; + WDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDR_TYPE_t; + +typedef struct WDRCurveFull_PARAM_s +{ + MI_U16 u16FCurve[256]; +} WDRCurveFull_PARAM_t; + +typedef struct WDRCurveFull_MANUAL_ATTR_s +{ + WDRCurveFull_PARAM_t stParaAPI; +} WDRCurveFull_MANUAL_ATTR_t; + +typedef struct WDRCurveFull_AUTO_ATTR_s +{ + WDRCurveFull_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveFull_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveFull_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveFull_AUTO_ATTR_t stAuto; + WDRCurveFull_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveFull_TYPE_t; + +typedef struct WDRCurveAdv_PARAM_s +{ + MI_U16 u16Slope; //1024~16384 + MI_U8 u8TransitionPoint0; //0~255 + MI_U8 u8TransitionPoint1; //0~255 + MI_U8 u8SaturatedPoint; //0~255 + MI_U8 u8CurveModeSel; //0~5 +} WDRCurveAdv_PARAM_t; + +typedef struct WDRCurveAdv_MANUAL_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI; +} WDRCurveAdv_MANUAL_ATTR_t; + +typedef struct WDRCurveAdv_AUTO_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveAdv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveAdv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveAdv_AUTO_ATTR_t stAuto; + WDRCurveAdv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveAdv_TYPE_t; + +typedef struct DYNAMIC_DP_PARAM_s +{ + MI_ISP_BOOL_e bHotPixEn; //0 ~ 1 + MI_U16 u16HotPixCompSlpoe; + MI_ISP_BOOL_e bDarkPixEn; //0 ~ 1 + MI_U16 u16DarkPixCompSlpoe; + MI_U16 u16DPCTH; + MI_ISP_BOOL_e bBlendEn; + MI_U16 u16DiffLut[6]; + MI_U16 u16YLut[6]; +} DYNAMIC_DP_PARAM_t; + +typedef struct DYNAMIC_DP_MANUAL_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI; +} DYNAMIC_DP_MANUAL_ATTR_t; + +typedef struct DYNAMIC_DP_AUTO_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_AUTO_ATTR_t stAuto; + DYNAMIC_DP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DYNAMIC_DP_TYPE_t; + +typedef struct DYNAMIC_DP_CLUSTER_ATTR_S +{ + MI_ISP_BOOL_e bEdgeMode; + MI_U16 u16NeiDeltaTh; + MI_U8 u8NeiSmooth; + MI_ISP_BOOL_e bSortEn; + MI_ISP_BOOL_e bSortRGGBEn[4]; + MI_ISP_BOOL_e bSort1x3ModeEn; + MI_U16 u16SortLumTblL[6]; + MI_U16 u16SortLumTblD[6]; + MI_U16 u16SortLumTblS[6]; +} DYNAMIC_DP_CLUSTER_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI; +} DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_CLUSTER_AUTO_ATTR_S; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_CLUSTER_AUTO_ATTR_S stAuto; + DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_t; + +typedef struct HSV_PARAM_s +{ + MI_S16 s16HueLut[24]; //-64 ~ 64 + MI_U16 u16SatLut[24]; // 0 ~ 255 (64->1X) + MI_S16 s16HueLut_ForUnitCCM[24]; //-64 ~ 64 + MI_U16 u16SatLut_ForUnitCCM[24]; // 0 ~ 255 (64->1X) + MI_U8 u8GlobalSat; // 0 ~ 255 (64->1x) +} HSV_PARAM_t; + +typedef struct HSV_MANUAL_ATTR_s +{ + HSV_PARAM_t stParaAPI; +} HSV_MANUAL_ATTR_t; + +typedef struct HSV_AUTO_ATTR_s +{ + HSV_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HSV_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HSV_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + HSV_AUTO_ATTR_t stAuto; + HSV_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HSV_TYPE_t; + +typedef struct RGBIR_PARAM_s +{ + MI_U8 u8IrPosType; //0 ~ 7, def : 0 + MI_ISP_BOOL_e bRemovelEn; //0 ~ 1, def : 1 + MI_U16 u16Ratio_R[6]; + MI_U16 u16Ratio_G[6]; + MI_U16 u16Ratio_B[6]; +} RGBIR_PARAM_t; + +typedef struct RGBIR_MANUAL_ATTR_s +{ + RGBIR_PARAM_t stParaAPI; +} RGBIR_MANUAL_ATTR_t; + +typedef struct RGBIR_AUTO_ATTR_s +{ + RGBIR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBIR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBIR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBIR_AUTO_ATTR_t stAuto; + RGBIR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBIR_TYPE_t; + +typedef struct MI_ISP_IQ_FPN_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_FPN_TYPE_t; + +typedef struct PFC_PARAM_s +{ + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8UStrength; //0 ~ 63 + MI_U8 u8VStrength; //0 ~ 63 + MI_U8 u8StrengthByY[8]; //0 ~ 255 + MI_U8 u8FlatProtect; //0 ~ 127 + MI_U8 u8SatByY[2]; //0 ~ 25 + MI_U8 u8SatSrcSel; //0 ~ 1 + MI_U8 u8StrengthByContrast[8]; //0 ~ 127 +} PFC_PARAM_t; + +typedef struct PFC_MANUAL_ATTR_s +{ + PFC_PARAM_t stParaAPI; +} PFC_MANUAL_ATTR_t; + +typedef struct PFC_AUTO_ATTR_s +{ + PFC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} PFC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_PFC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + PFC_AUTO_ATTR_t stAuto; + PFC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_PFC_TYPE_t; + +typedef struct PFC_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_ISP_BOOL_e bGSkipEn; //0 ~ 1 + MI_U8 u8SatMaskSel; //0 ~ 1 + MI_ISP_BOOL_e bSatAmpEn; //0 ~ 1 + MI_U8 u8StrengthByHue[12]; //0 ~ 255 +} PFC_EX_PARAM_t; + +typedef struct PFC_EX_MANUAL_ATTR_s +{ + PFC_EX_PARAM_t stParaAPI; +} PFC_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_PFC_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + PFC_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_PFC_EX_TYPE_t; + +typedef struct DEMOSAIC_PARAM_s +{ + MI_U8 u8DirThrd; //0~63 def:35 + MI_U8 u8EdgeSmoothThrdY; //0~255 def:230 + MI_U8 u8EdgeSmoothThrdC; //0~127 def:20 +} DEMOSAIC_PARAM_t; + +typedef struct DEMOSAIC_MANUAL_ATTR_s +{ + DEMOSAIC_PARAM_t stParaAPI; +} DEMOSAIC_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_DEMOSAIC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DEMOSAIC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEMOSAIC_TYPE_t; + +typedef struct COLORTRANS_PARAM_s +{ + MI_U16 u16Y_OFST; //0 ~ 2047 + MI_U16 u16U_OFST; //0 ~ 2047 + MI_U16 u16V_OFST; //0 ~ 2047 + MI_U16 u16Matrix[9]; //0 ~ 1023 +} COLORTRANS_PARAM_t; + +typedef struct COLORTRANS_MANUAL_ATTR_s +{ + COLORTRANS_PARAM_t stParaAPI; +} COLORTRANS_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_COLORTRANS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + COLORTRANS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_COLORTRANS_TYPE_t; + +typedef struct HDR_PARAM_s +{ + MI_ISP_BOOL_e bNrEn; + MI_U16 u16YwtTh1; + MI_U16 u16YwtTh2; + MI_U16 u16NoiseLevel[16]; + MI_U16 u16MotionTh; + MI_U16 u16MotionAdjLut[7]; +} HDR_PARAM_t; + +typedef struct HDR_MANUAL_ATTR_s +{ + HDR_PARAM_t stParaAPI; +} HDR_MANUAL_ATTR_t; + +typedef struct HDR_AUTO_ATTR_s +{ + HDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + HDR_AUTO_ATTR_t stAuto; + HDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_TYPE_t; + +typedef struct HDR_EX_PARAM_s +{ + MI_U16 u16SensorExpRatio; + MI_ISP_BOOL_e bDynRatioEn; + MI_U8 u8DynRatioSrcSel; + MI_U8 u8YSrcSel; + MI_U8 u8NoiseLevelSrcSel; + MI_U8 u8MotionMaxVal; + MI_U16 u16MotionLumaTh; + MI_U8 u8MotionAdjSft[6]; +} HDR_EX_PARAM_t; + +typedef struct HDR_EX_MANUAL_ATTR_s +{ + HDR_EX_PARAM_t stParaAPI; +} HDR_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + HDR_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_EX_TYPE_t; + +typedef struct MI_ISP_IQ_EFFECT_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_EFFECT_TYPE_t; + +typedef struct MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U16 u16CenterX; + MI_U16 u16CenterY; + MI_U8 u8Shift; + MI_U16 u16RGainTable[32*3]; + MI_U16 u16GGainTable[32*3]; + MI_U16 u16BGainTable[32*3]; +} MI_ISP_IQ_LSC_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_LSC_CTRL_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8GridX; + MI_U8 u8GridY; + MI_U16 u16CCTthr[3]; + MI_U8 u8DeltaMode; + MI_ISP_BOOL_e bDeltaModeAdvEn; + MI_U8 u8DeltaLutX[26]; + MI_U8 u8DeltaLutY[26]; + MI_U16 u16TableR[3][ALSC_TBL_MAX]; + MI_U16 u16TableG[3][ALSC_TBL_MAX]; + MI_U16 u16TableB[3][ALSC_TBL_MAX]; +} MI_ISP_IQ_ALSC_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_ALSC_CTRL_TYPE_t; + +typedef struct R2Y_PARAM_s +{ + MI_U16 u16Matrix[9]; + MI_U8 u8AddY16; +} R2Y_PARAM_t; + +typedef struct R2Y_MANUAL_ATTR_s +{ + R2Y_PARAM_t stParaAPI; +} R2Y_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_R2Y_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + R2Y_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_R2Y_TYPE_t; + +typedef struct DUMMY_ATTR_s +{ + MI_S16 s16Dummy0[256]; + MI_S16 s16Dummy1[256]; + MI_S16 s16Dummy2[256]; + MI_S16 s16Dummy3; + MI_S16 s16Dummy4; +} DUMMY_ATTR_t; + +typedef struct DUMMY_MANUAL_ATTR_s +{ + DUMMY_ATTR_t stParaAPI; +} DUMMY_MANUAL_ATTR_t; + +typedef struct DUMMY_AUTO_ATTR_s +{ + DUMMY_ATTR_t stParaAPI[MI_ISP_AUTO_NUM]; +} DUMMY_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DUMMY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + DUMMY_AUTO_ATTR_t stAuto; + DUMMY_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DUMMY_TYPE_t; + +typedef struct DUMMY_EX_ATTR_s +{ + MI_S16 s16DummyEx0[256]; + MI_S16 s16DummyEx1[256]; + MI_S16 s16DummyEx2[256]; + MI_S16 s16DummyEx3; + MI_S16 s16DummyEx4; +} DUMMY_EX_ATTR_t; + +typedef struct +{ + DUMMY_EX_ATTR_t stParaAPI; +} DUMMY_EX_MANUAL_ATTR_S; + +typedef struct MI_ISP_IQ_DUMMY_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DUMMY_EX_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DUMMY_EX_TYPE_t; + +#endif + +#if 1 // ISP IQ API +typedef struct IQ_VERSION_INFO_PARAM_s +{ + MI_U32 u32Vendor; + MI_U32 u32Major; + MI_U32 u32Minor; +} IQ_VERSION_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_VERSION_INFO_TYPE_s +{ + IQ_VERSION_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_VERSION_INFO_TYPE_t; + +typedef struct IQ_PARAM_INIT_INFO_PARAM_s +{ + MI_ISP_BOOL_e bFlag; +} IQ_PARAM_INIT_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_PARAM_INIT_INFO_TYPE_s +{ + IQ_PARAM_INIT_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_PARAM_INIT_INFO_TYPE_t; + +typedef struct FAST_MODE_PARAM_s +{ + MI_ISP_BOOL_e bFastMode; +} FAST_MODE_PARAM_t; + +typedef struct MI_ISP_IQ_FAST_MODE_TYPE_s +{ + FAST_MODE_PARAM_t stParaAPI; +} MI_ISP_IQ_FAST_MODE_TYPE_t; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_PARAM_MODE_NORMAL = 0, + SS_IQ_PARAM_MODE_NIGHT = 1, //Night Mode + SS_IQ_PARAM_MODE_MAX +} MI_ISP_IQ_PARAM_MODE_e; + +typedef struct MI_ISP_IQ_GAMMA_LUT_TYPE_s +{ + MI_U16 u16LutR[256]; + MI_U16 u16LutG[256]; + MI_U16 u16LutB[256]; +} MI_ISP_IQ_GAMMA_LUT_TYPE_t; + +typedef struct MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_U16 u16BTGamma[256]; + MI_U16 u16DTGamma[256]; +} MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_t; + +typedef struct MI_ISP_IQ_OBC4Ch_TYPE_s +{ + MI_U16 u16OBC4Ch[4]; +} MI_ISP_IQ_OBC4Ch_TYPE_t; +#endif + +typedef struct TEMP_PARAM_s +{ + MI_S16 s16ObcOffset; + MI_U8 u8DynamicDPRatio; + MI_U8 u8CrosstalkRatio; + MI_U8 u8NRDeSpikeRatio; + MI_U8 u8NR3DRatio[2]; + MI_U8 u8NRLumaRatio; + MI_U8 u8SharpnessRatio[2]; + MI_U8 u8SaturationRatio; + MI_U8 u8ColorToneRatio[3]; +} TEMP_PARAM_t; + +typedef struct TEMP_MANUAL_ATTR_s +{ + TEMP_PARAM_t stParaAPI; +} TEMP_MANUAL_ATTR_t; + +typedef struct TEMP_AUTO_ATTR_s +{ + TEMP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} TEMP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_TEMP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8TemperatureLut[16]; + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + TEMP_AUTO_ATTR_t stAuto; + TEMP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_TEMP_TYPE_t; + +typedef struct MI_ISP_IQ_TEMP_INFO_TYPE_s +{ + MI_U8 u8Temperature; +} MI_ISP_IQ_TEMP_INFO_TYPE_t; + +#if 1 // MAINTOOL API +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_INDEX_0 = 0, + SS_IQ_INDEX_1, + SS_IQ_INDEX_2, + SS_IQ_INDEX_3, + SS_IQ_INDEX_4, + SS_IQ_INDEX_5, + SS_IQ_INDEX_6, + SS_IQ_INDEX_7, + SS_IQ_INDEX_8, + SS_IQ_INDEX_9, + SS_IQ_INDEX_10, + SS_IQ_INDEX_11, + SS_IQ_INDEX_12, + SS_IQ_INDEX_13, + SS_IQ_INDEX_14, + SS_IQ_INDEX_15, + SS_IQ_INDEX_MAX +} MI_ISP_IQ_INDEX_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_BYPASS_OFF = 0, + SS_BYPASS_ON, + SS_BYPASS_MAX +} MI_ISP_BYPASS_MODE_e; + +typedef struct MI_ISP_API_BYPASS_TYPE_s +{ + MI_ISP_BYPASS_MODE_e bEnable; //0 ~ 1 + MI_ISP_API_ID_e eAPIIndex; +} MI_ISP_API_BYPASS_TYPE_t; +#endif + + +/************************************* IQ - Define the structure declaration - END *************************************/ + + +#endif /* _MI_ISP_IQ_DATATYPE_H_ */ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/tiramisu/mi_isp_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/tiramisu/mi_isp_datatype.h new file mode 100644 index 000000000..b058e1868 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/tiramisu/mi_isp_datatype.h @@ -0,0 +1,430 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_isp_datatype.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_ISP_DATATYPE_H_ +#define _MI_ISP_DATATYPE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mi_common.h" +#include "mi_sys_datatype.h" +#include "mi_isp_3a_datatype.h" +#include "mi_isp_iq_datatype.h" + +/************************************* AF - Define the structure declaration - START *************************************/ + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************** Cus3A ***********************/ + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; + MI_U8 uAvgY; +} MI_ISP_AE_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AE_AVGS nAvg[128*90]; +}MI_ISP_AE_HW_STATISTICS_t; + +typedef struct +{ + MI_U8 uAvgR; + MI_U8 uAvgG; + MI_U8 uAvgB; +} MI_ISP_AWB_AVGS; + +typedef struct +{ + MI_U32 nBlkX; + MI_U32 nBlkY; + MI_ISP_AWB_AVGS nAvg[128*90]; +} MI_ISP_AWB_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[128]; +} MI_ISP_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_U16 nHisto[256]; +} MI_ISP_RGBIR_HISTO_HW_STATISTICS_t; + +typedef struct +{ + MI_BOOL bAE; + MI_BOOL bAWB; + MI_BOOL bAF; +}Cus3AEnable_t; + +typedef struct +{ + MI_U32 Size; /**< struct size*/ + char sensor_id[32]; /**< sensor module id*/ + MI_U32 shutter; /**< shutter Shutter in ns*/ + MI_U32 shutter_step; /**< shutter Shutter step ns*/ + MI_U32 shutter_min; /**< shutter Shutter min us*/ + MI_U32 shutter_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gain; /**< sensor_gain Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gain_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + MI_U32 isp_gain; /**< isp_gain Isp digital gain , 1X = 1024 */ + MI_U32 isp_gain_max; /**< isp_gain Maximum Isp digital gain , 1X = 1024 */ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 fps; /**< initial frame per second*/ + MI_U32 shutterHDRShort_step; /**< shutter Shutter step ns*/ + MI_U32 shutterHDRShort_min; /**< shutter Shutter min us*/ + MI_U32 shutterHDRShort_max; /**< shutter Shutter max us*/ + MI_U32 sensor_gainHDRShort_min; /**< sensor_gain_min Minimum Sensor gain, 1X = 1024*/ + MI_U32 sensor_gainHDRShort_max; /**< sensor_gain_max Maximum Sensor gain, 1X = 1024*/ + /*CUS3A v1.1*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ +}CusAEInitParam_t,CusAeInitParam_t; + +/*! @brief ISP report to AE, hardware statistic */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + void *hist1; /**< HW statistic histogram 1*/ + void *hist2; /**< HW statistic histogram 2*/ + MI_U32 AvgBlkX; /**< HW statistics average block number*/ + MI_U32 AvgBlkY; /**< HW statistics average block number*/ + void * avgs; /**< HW statistics average block data*/ + MI_U32 Shutter; /**< Current shutter in ns*/ + MI_U32 SensorGain; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< Current ISP gain, 1X = 1024*/ + MI_U32 ShutterHDRShort; /**< Current shutter in ns*/ + MI_U32 SensorGainHDRShort; /**< Current Sensor gain, 1X = 1024 */ + MI_U32 IspGainHDRShort; /**< Current ISP gain, 1X = 1024*/ + /*CUS3A V1.1*/ + MI_U32 PreAvgY; /**< Previous frame brightness*/ + MI_U8 HDRCtlMode; /**< 0 = HDR off; */ + /**< 1 = Separate shutter & Separate sensor gain settings */ + /**< 2 = Separate shutter & Share sensor gain settings */ + /**< 3 = Share shutter & Separate sensor gain settings */ + MI_U32 FNx10; /**< Aperture in FNx10*/ + MI_U32 CurFPS; /**Current sensor FPS */ + MI_U32 PreWeightY; /**< Previous frame brightness with ROI weight*/ +} __attribute__((packed, aligned(1))) CusAEInfo_t, CusAeInput_t; + +/*! @brief ISP ae algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 Shutter; /**< Shutter in ns */ + MI_U32 SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGain; /**< ISP gain, 1X = 1024 */ + MI_U32 ShutterHdrShort; /**< Shutter in ns */ + MI_U32 SensorGainHdrShort; /**< Sensor gain, 1X = 1024 */ + MI_U32 IspGainHdrShort; /**< ISP gain, 1X = 1024 */ + MI_U32 u4BVx16384; /**< Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_U32 AvgY; /**< frame brightness */ + MI_U32 HdrRatio; /**< hdr ratio, 1X = 1024 */ + /*CUS3A V1.1*/ + MI_U32 FNx10; /**< F number * 10*/ + MI_U32 DebandFPS; /** Target fps when running auto debanding**/ + MI_U32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAEResult_t, CusAeOutput_t; + +/*! @brief AWB HW statistics data*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 AvgBlkX; + MI_U32 AvgBlkY; + MI_U32 CurRGain; + MI_U32 CurGGain; + MI_U32 CurBGain; + void *avgs; //ISP_AWB_SAMPLE + /*CUS3A V1.1*/ + MI_U8 HDRMode; /**< Noramal or HDR mode*/ + void* *pAwbStatisShort; /**< Short Shutter AWB statistic data */ + MI_U32 u4BVx16384; /**< From AE output, Bv * 16384 in APEX system, EV = Av + Tv = Sv + Bv */ + MI_S32 WeightY; /**< frame brightness with ROI weight*/ +}__attribute__((packed, aligned(1))) CusAWBInfo_t, CusAWBInput_t; + +/*! @brief AWB algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 R_gain; /**< AWB gain for R channel*/ + MI_U32 G_gain; /**< AWB gain for G channel*/ + MI_U32 B_gain; /**< AWB gain for B channel*/ + MI_U32 ColorTmp; /**< Return color temperature*/ +}CusAWBResult_t, CusAwbOutput_t;; + +typedef enum __attribute__ ((aligned (1))) +{ + SS_AE_16x24 = 0, + SS_AE_32x24, + SS_AE_64x48, + SS_AE_64x45, + SS_AE_128x80, + SS_AE_128x90, + SS_AE_32x32 +} MS_CUST_AE_WIN_BLOCK_NUM_TYPE_e; + +typedef struct { + MI_U16 u2Stawin_x_offset; + MI_U16 u2Stawin_x_size; + MI_U16 u2Stawin_y_offset; + MI_U16 u2Stawin_y_size; + MI_U16 u2WinIdx; +} CusAEHistWin_t; + +typedef struct +{ + MI_U32 SizeX; + MI_U32 SizeY; + MI_U32 IncRatio; +}CusAWBSample_t; + +typedef struct +{ + MI_U16 CropX; // 0~1023 + MI_U16 CropY; // 0~1023 + MI_U16 CropW; // 0~1023 + MI_U16 CropH; // 0~1023 +}CusAEAWBCropSize_t; + +typedef struct +{ + MI_U8 iir_1[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 iir_2[5*16]; //[5]: iir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 luma[4*16]; //[4]: luma 32bit, use 4*u8 datatype, [16]: 16wins + MI_U8 fir_v[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 fir_h[5*16]; //[5]: fir 35bit, use 5*u8 datatype, [16]: 16wins + MI_U8 ysat[3*16]; //[3]: ysat 22bit, use 3*u8 datatype, [16]: 16wins +} AF_STATS_PARAM_t; + +typedef struct +{ + AF_STATS_PARAM_t stParaAPI[16]; +} CusAFStats_t; + +typedef struct AF_WINDOW_PARAM_s +{ + MI_U32 u32StartX; /*range : 0~1023*/ + MI_U32 u32StartY; /*range : 0~1023*/ + MI_U32 u32EndX; /*range : 0~1023*/ + MI_U32 u32EndY; /*range : 0~1023*/ +} AF_WINDOW_PARAM_t; + +typedef struct +{ + MI_U8 u8WindowIndex; + AF_WINDOW_PARAM_t stParaAPI; +} CusAFWin_t; + +typedef struct +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; + + MI_U16 u16IIR1_e1_en; + MI_U16 u16IIR1_e1_a0; + MI_U16 u16IIR1_e1_a1; + MI_U16 u16IIR1_e1_a2; + MI_U16 u16IIR1_e1_b1; + MI_U16 u16IIR1_e1_b2; + MI_U16 u16IIR1_e2_en; + MI_U16 u16IIR1_e2_a0; + MI_U16 u16IIR1_e2_a1; + MI_U16 u16IIR1_e2_a2; + MI_U16 u16IIR1_e2_b1; + MI_U16 u16IIR1_e2_b2; + + MI_U16 u16IIR2_e1_en; + MI_U16 u16IIR2_e1_a0; + MI_U16 u16IIR2_e1_a1; + MI_U16 u16IIR2_e1_a2; + MI_U16 u16IIR2_e1_b1; + MI_U16 u16IIR2_e1_b2; + MI_U16 u16IIR2_e2_en; + MI_U16 u16IIR2_e2_a0; + MI_U16 u16IIR2_e2_a1; + MI_U16 u16IIR2_e2_a2; + MI_U16 u16IIR2_e2_b1; + MI_U16 u16IIR2_e2_b2; +} CusAFFilter_t; + +typedef struct +{ + MI_U16 u16Coeff[70]; +} CusAFFilter_Geo_t; + +typedef struct +{ + MI_BOOL bSobelYSatEn; + MI_U16 u16SobelYThd; + + MI_BOOL bIIRSquareAccEn; + MI_BOOL bSobelSquareAccEn; + + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} CusAFFilterSq_t; + + +typedef enum __attribute__ ((aligned (1))) +{ + AF_ROI_MODE_NORMAL, + AF_ROI_MODE_MATRIX +} ISP_AF_ROI_MODE_e; + +typedef struct +{ + ISP_AF_ROI_MODE_e mode; + MI_U32 u32_vertical_block_number; +} CusAFRoiMode_t; + +/* Raw store control */ +typedef enum +{ + eRawStoreNode_P0HEAD = 0, /* Control by VIF, Do not use */ + eRawStoreNode_P1HEAD = 1, /* Control by VIF, Do not use */ + eRawStoreNode_P0TAIL = 2, + eRawStoreNode_P1TAIL = 3, + eRawStoreNode_ISPOUT = 4, + eRawStoreNode_VDOS = 5, + eRawStoreNode_ISPOUT_BEFORE_YEE = 6, + eRawStoreNode_RGBIR_IR_ONLY = 7 +}CameraRawStoreNode_e; + +typedef struct +{ + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusImageResolution_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; +} CusISPOutImage_t; + +typedef struct +{ + MI_U32 u32enable; + MI_U32 u32image_width; + MI_U32 u32image_height; + MI_U32 u32physical_address; + MI_U32 u32Node; + MI_U32 u32PixelDepth; +} CusHdrRawImage_t; + +typedef struct +{ + MI_U64 u64Pts; /** frame PTS */ + MI_U32 u32Shutter; /**< Shutter in us */ + MI_U32 u32SensorGain; /**< Sensor gain, 1X = 1024 */ + MI_U32 u32ColorTmp; /**< Return color temperature*/ +} IspFrameMetaInfo_t; + +/*! @brief ISP report to AF, hardware status */ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 MinPos; /**< Maximum position of AF motor */ + MI_U32 MaxPos; /**< Minimum position of AF motor */ + MI_U32 CurPos; /**< Current position of AF motor */ +} __attribute__((packed, aligned(1))) CusAFInfo_t, CusAfInput_t; + +/*! @brief AF algorithm result*/ +typedef struct +{ + MI_U32 Size; /**< struct size*/ + MI_U32 Change; /**< if true, apply this result to hw register*/ + MI_U32 NextPos; /**< Next absolute position of AF motor */ +}__attribute__((packed, aligned(1))) CusAfResult_t, CusAfOutput_t; + +typedef struct +{ + MI_U32 u32SlaveAddr; //sensor slave address + MI_U32 u32RegLen; //sensor register length , 1 or 2 bytes + MI_U32 u32DataLen; //sensor register data length, 1 or 2 bytes + MI_U32 u32I2cSpeed; //i2c speed , 100/200/300/400 KHz + MI_U32 u32Reg; //sensor register address + MI_U32 u32Data; //sensor register data +}CusSensorI2cParam_t; + +/***************************** end of Cus3A ****************************/ + +// COMMON API +typedef struct MI_ISP_API_CHANNEL_ID_TYPE_s +{ + MI_U32 u32ChannelID; +} MI_ISP_API_CHANNEL_ID_TYPE_t; + +typedef struct MI_ISP_API_USERSPACE3A_ATTR_s +{ + MI_SYS_PixelFormat_e ePixelFmt; + MI_U32 eSensorBindId; +} MI_ISP_API_USERSPACE3A_ATTR_t; + +typedef struct +{ + MI_S8 strIspRoot[64]; +} MI_ISP_ROOT_PATH_T; + +#ifdef __cplusplus +} //end of extern C +#endif + +#endif //_MI_ISP_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/tiramisu/mi_isp_iq_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/tiramisu/mi_isp_iq_datatype.h new file mode 100644 index 000000000..c6cbc9f70 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp/tiramisu/mi_isp_iq_datatype.h @@ -0,0 +1,1399 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* + * iq_apiset.h + * + * Created on: 2016/8/16 + * Author: Elsa-cf.Lin + */ + +#ifndef _MI_ISP_IQ_DATATYPE_H_ +#define _MI_ISP_IQ_DATATYPE_H_ + +#include "mi_isp_3a_datatype.h" + +//put here temporarily, should add mi_isp_cali_datatype.h? + +typedef enum __attribute__ ((aligned (1))) +{ + SS_CALI_ITEM_AWB = 0, + SS_CALI_ITEM_OBC = 1, + SS_CALI_ITEM_SDC = 2, + SS_CALI_ITEM_ALSC = 3, + SS_CALI_ITEM_LSC = 4, + SS_CALI_ITEM_MAX, +} MI_ISP_CALI_ITEM_e; + +/************************************* AF - Define the structure declaration - START *************************************/ + +typedef struct MI_ISP_AF_HW_ROI_MODE_TYPE_s +{ + MI_U8 u8Mode; // 0: Normal, 1: Matrix + MI_U32 u32VerticalBlockNumber; +} MI_ISP_AF_HW_ROI_MODE_TYPE_t; + +typedef struct MI_ISP_AF_HW_WIN_TYPE_s +{ + MI_U16 u16Win[4*16]; +} MI_ISP_AF_HW_WIN_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTER_ATTR_TYPE_s +{ + MI_U16 u16IIR1_a0; + MI_U16 u16IIR1_a1; + MI_U16 u16IIR1_a2; + MI_U16 u16IIR1_b1; + MI_U16 u16IIR1_b2; + MI_U16 u16IIR1_1st_low_clip; + MI_U16 u16IIR1_1st_high_clip; + MI_U16 u16IIR1_2nd_low_clip; + MI_U16 u16IIR1_2nd_high_clip; + MI_U16 u16IIR2_a0; + MI_U16 u16IIR2_a1; + MI_U16 u16IIR2_a2; + MI_U16 u16IIR2_b1; + MI_U16 u16IIR2_b2; + MI_U16 u16IIR2_1st_low_clip; + MI_U16 u16IIR2_1st_high_clip; + MI_U16 u16IIR2_2nd_low_clip; + MI_U16 u16IIR2_2nd_high_clip; + + MI_U16 u16IIR1_e1_en; + MI_U16 u16IIR1_e1_a0; + MI_U16 u16IIR1_e1_a1; + MI_U16 u16IIR1_e1_a2; + MI_U16 u16IIR1_e1_b1; + MI_U16 u16IIR1_e1_b2; + MI_U16 u16IIR1_e2_en; + MI_U16 u16IIR1_e2_a0; + MI_U16 u16IIR1_e2_a1; + MI_U16 u16IIR1_e2_a2; + MI_U16 u16IIR1_e2_b1; + MI_U16 u16IIR1_e2_b2; + + MI_U16 u16IIR2_e1_en; + MI_U16 u16IIR2_e1_a0; + MI_U16 u16IIR2_e1_a1; + MI_U16 u16IIR2_e1_a2; + MI_U16 u16IIR2_e1_b1; + MI_U16 u16IIR2_e1_b2; + MI_U16 u16IIR2_e2_en; + MI_U16 u16IIR2_e2_a0; + MI_U16 u16IIR2_e2_a1; + MI_U16 u16IIR2_e2_a2; + MI_U16 u16IIR2_e2_b1; + MI_U16 u16IIR2_e2_b2; +} MI_ISP_AF_HW_FILTER_ATTR_TYPE_t; + +typedef struct MI_ISP_AF_HW_FILTERSQ_TYPE_s +{ + MI_U8 bSobelYSatEn; + MI_U16 u16SobelYThd; + MI_U8 bIIRSquareAccEn; + MI_U8 bSobelSquareAccEn; + MI_U16 u16IIR1Thd; + MI_U16 u16IIR2Thd; + MI_U16 u16SobelHThd; + MI_U16 u16SobelVThd; + MI_U8 u8AFTblX[12]; + MI_U16 u16AFTblY[13]; +} MI_ISP_AF_HW_FILTERSQ_TYPE_t; + +/************************************* AF - Define the structure declaration - END *************************************/ + +/************************************* IQ - Define the structure declaration - START *************************************/ + +typedef struct +{ + MI_U16 u16NumOfPoints; + MI_S32 s32Y[16]; + MI_S32 s32X[16]; +} MI_INTP_LUT_IQ; + +#if 1 //API20 struct + +#define MI_ISP_AUTO_NUM (16) +#define ALSC_TBL_MAX 459 +#define ENABLE_CCM_COEFF_SUM_INFO 1 + +typedef enum __attribute__ ((aligned (4))) +{ + API20_AUTO = 0, //[00] + //API2.0 + API20_FPN, //[01] + API20_CCM, //[02] + API20_SAT, //[03] + API20_OBC, //[04] + API20_OBC_P1, //[05] + API20_FCOLOR, //[06] + API20_CR, //[07] + API20_NR_DeSpike, //[08] + API20_SHP, //[09] + API20_NR_3D, //[10] + API20_BRI, //[11] + API20_LIG, //[12] + API20_CST, //[13] + API20_GMA, //[14] + API20_CTG, //[15] + API20_NR_NLM, //[16] + API20_DEFOG, //[17] + API20_DRC, //[18] + API20_DPC, //[19] + API20_HSV, //[20] + API20_WDR_LOC, //[21] + API20_RGBIR, //[22] + API20_YUVGMA, //[23] + API20_HDR16to12, //[24] + API20_COLORTRANS, //[25] + API20_HDR, //[26] + API20_EFFECT, //[27] + API20_PFC, //[28] + API20_SIIR, //[29] + API20_DM, //[30] + API20_NR_3D_P1, //[31] + API20_WDRCurveAdv, //[32] + API20_MXNR, //[33] + API20_R2Y, //[34] + API20_LSC, //[35] + API20_LSC_CTRL, //[36] + API20_ALSC, //[37] + API20_ALSC_CTRL, //[38] + API20_DPC_CLUSTER, //[39] + API20_PFC_EX, //[40] + API20_HDR_EX, //[41] + API20_SHP_EX, //[42] + API20_NR_3D_EX, //[43] + API20_GNR, //[44] + API20_DUMMY, //[45] + API20_DUMMY_EX, //[46] + API20_WDRCurveFull, //[47] + API20_ADAPTIVE_GMA, //[48] + API20_XNR, //[49] + API20_TEMP, //[50] + API20_TEMP_INFO, //[51] + API20_MAX, //for para reset +} MI_ISP_API_ID_e; + +typedef struct MI_ISP_IQ_COLORTOGRAY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 +} MI_ISP_IQ_COLORTOGRAY_TYPE_t; + +typedef struct LEVEL_BASE_PARAM_s +{ + MI_U32 u32Lev; //0 ~ 100 +} LEVEL_BASE_PARAM_t; + +typedef struct LIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} LIGHTNESS_MANUAL_ATTR_t; + +typedef struct LIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} LIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_LIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + LIGHTNESS_AUTO_ATTR_t stAuto; + LIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_LIGHTNESS_TYPE_t; + +typedef struct CONTRAST_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} CONTRAST_MANUAL_ATTR_t; + +typedef struct CONTRAST_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CONTRAST_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CONTRAST_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + CONTRAST_AUTO_ATTR_t stAuto; + CONTRAST_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CONTRAST_TYPE_t; + +typedef struct BRIGHTNESS_MANUAL_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI; +} BRIGHTNESS_MANUAL_ATTR_t; + +typedef struct BRIGHTNESS_AUTO_ATTR_s +{ + LEVEL_BASE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} BRIGHTNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_BRIGHTNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; // 0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; // M_AUTO ~ (M_MODMAX-1) + BRIGHTNESS_AUTO_ATTR_t stAuto; + BRIGHTNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_BRIGHTNESS_TYPE_t; + + +typedef struct RGBGAMMA_PARAM_s +{ + MI_U16 u16LutR[256]; //0 ~ 4095 + MI_U16 u16LutG[256]; //0 ~ 4095 + MI_U16 u16LutB[256]; //0 ~ 4095 +} RGBGAMMA_PARAM_t; + +typedef struct RGBGAMMA_MANUAL_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI; +} RGBGAMMA_MANUAL_ATTR_t; + +typedef struct RGBGAMMA_AUTO_ATTR_s +{ + RGBGAMMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBGAMMA_AUTO_ATTR_t stAuto; + RGBGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBGAMMA_TYPE_t; + +typedef struct YUVGAMMA_PAMAR_s +{ + MI_U16 u16LutY[256]; //0 ~ 1023 + MI_U16 u16LutU[128]; //0 ~ 511 + MI_U16 u16LutV[128]; //0 ~ 511 +} YUVGAMMA_PAMAR_t; + +typedef struct YUVGAMMA_MANUAL_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI; +} YUVGAMMA_MANUAL_ATTR_t; + +typedef struct YUVGAMMA_AUTO_ATTR_s +{ + YUVGAMMA_PAMAR_t stParaAPI[MI_ISP_AUTO_NUM]; +} YUVGAMMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_YUVGAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + YUVGAMMA_AUTO_ATTR_t stAuto; + YUVGAMMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_YUVGAMMA_TYPE_t; + +typedef struct SATURATION_PARAM_s +{ + MI_U8 u8SatAllStr; //0 ~ 127 (32 = 1X) + MI_U8 u8SatByYSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatByYLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatBySSFTAdv[5]; //0 ~ 8 + MI_U8 u8SatBySLUTAdv[6]; //0 ~ 128 + MI_U8 u8SatCoring; +} SATURATION_PARAM_t; + +typedef struct SATURATION_MANUAL_ATTR_s +{ + SATURATION_PARAM_t stParaAPI; +} SATURATION_MANUAL_ATTR_t; + +typedef struct SATURATION_AUTO_ATTR_s +{ + SATURATION_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SATURATION_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SATURATION_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SATURATION_AUTO_ATTR_t stAuto; + SATURATION_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SATURATION_TYPE_t; + +typedef struct DEFOG_PARAM_s +{ + MI_U8 u8Strength; +} DEFOG_PARAM_t; + +typedef struct DEFOG_MANUAL_ATTR_s +{ + DEFOG_PARAM_t stParaAPI; +} DEFOG_MANUAL_ATTR_t; + +typedef struct DEFOG_AUTO_ATTR_s +{ + DEFOG_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DEFOG_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DEFOG_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DEFOG_AUTO_ATTR_t stAuto; + DEFOG_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEFOG_TYPE_t; + +typedef struct RGBMATRIX_PARAM_s +{ + MI_U16 u16CCTthr; +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_PARAM_t; + +typedef struct RGBMATRIX_MANUAL_ATTR_s +{ +#if ENABLE_CCM_COEFF_SUM_INFO + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) +#else + MI_U16 u16CCM[9]; //0 ~ 8191(1024 = 1X) +#endif + MI_U8 u8CCMSat; //0 ~ 100 0:Unit matrix, 100:User matrix +} RGBMATRIX_MANUAL_ATTR_t; + +typedef struct RGBMATRIX_AUTO_ATTR_s +{ + MI_ISP_BOOL_e bISOActEn; //0 ~ 1 + RGBMATRIX_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBMATRIX_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBMATRIX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBMATRIX_AUTO_ATTR_t stAuto; + RGBMATRIX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBMATRIX_TYPE_t; + +typedef struct MI_ISP_IQ_CCM_INFO_TYPE_s +{ + MI_U16 u16CCM[12]; //0 ~ 8191(1024 = 1X) + MI_U16 u16CCT; +} MI_ISP_IQ_CCM_INFO_TYPE_t; + +typedef struct FALSECOLOR_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0~1 + MI_U8 u8ColorSpaceSel; //0~1 + MI_U8 u8Preserve; //0~7 + MI_U8 u8Strength; //0~31 +} FALSECOLOR_PARAM_t; + +typedef struct FALSECOLOR_MANUAL_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI; +} FALSECOLOR_MANUAL_ATTR_t; + +typedef struct FALSECOLOR_AUTO_ATTR_s +{ + FALSECOLOR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} FALSECOLOR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_FALSECOLOR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + FALSECOLOR_AUTO_ATTR_t stAuto; + FALSECOLOR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_FALSECOLOR_TYPE_t; + +typedef struct NR3D_PARAM_s +{ + MI_U8 u8MdThd; //0~255 + MI_U16 u16MdGain; //0~1023 + MI_U8 u8TfStr; //0~64 + MI_U8 u8TfStrEx; //0~64 + MI_U8 u8MdThdByY[16]; //0~255 + MI_U8 u8MdGainByY[16]; //0~255 + MI_U8 u8M2SLut[16]; //0~31 + MI_U16 u16TfLut[16]; //0~4095 + MI_U8 u8YSfBlendLut[16]; //0~16 + MI_U8 u8YSfBlendOffset; //0~16 + MI_U8 u8MotHistDelayByDiff[16]; //0~7 + MI_U16 u16DeDotDiffOffset; //0~4095 + MI_U8 u8DeDotDiffShift; //0~7 +} NR3D_PARAM_t; + +typedef struct NR3D_MANUAL_ATTR_s +{ + NR3D_PARAM_t stParaAPI; +} NR3D_MANUAL_ATTR_t; + +typedef struct NR3D_AUTO_ATTR_s +{ + NR3D_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NR3D_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NR3D_AUTO_ATTR_t stAuto; + NR3D_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_TYPE_t; + +typedef struct NR3D_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0~1 + MI_U8 u8WinSizeSel; //0~2 + MI_ISP_BOOL_e bAREn; //0~1 + MI_U8 u8ARLumaTh[2]; //0~255 + MI_U8 u8ARMotTh[2]; //0~255 + MI_ISP_BOOL_e bPREn; //0~1 + MI_U16 u16PRDiffTh; //0~4095 + MI_U8 u8PRRatioConf[4]; //0~16 + MI_U8 u8PRContrastTh[2]; //0~15 + MI_U8 u8PRMotTh[2]; //0~255 +} NR3D_EX_PARAM_t; + +typedef struct NR3D_EX_MANUAL_ATTR_s +{ + NR3D_EX_PARAM_t stParaAPI; +} NR3D_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_NR3D_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + NR3D_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NR3D_EX_TYPE_t; + +typedef struct MI_ISP_IQ_NR3D_P1_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_NR3D_P1_TYPE_t; + +typedef struct NRDESPIKE_PARAM_s +{ + MI_U8 u8BlendRatio; //0 ~ 15 + MI_U8 u8StrengthCenterNeighbor; //0 ~ 5 + MI_U8 u8StrengthMeanStd; //0 ~ 5 + MI_U8 u8StrengthCornerCross; //0 ~ 5 + MI_U8 u8DiffGainMeanStd; //0 ~ 31 + MI_U8 u8DiffGainCenterNeighbor; //0 ~ 255 + MI_U8 u8DiffThdCornerCross; //0 ~ 255 + MI_U16 u16BlendLut[5]; //0 ~ 2047 + MI_U8 u8StrengthByY[15]; //0 ~ 127 +} NRDESPIKE_PARAM_t; + +typedef struct NRDESPIKE_MANUAL_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI; +} NRDESPIKE_MANUAL_ATTR_t; + +typedef struct NRDESPIKE_AUTO_ATTR_s +{ + NRDESPIKE_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRDESPIKE_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRDESPIKE_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRDESPIKE_AUTO_ATTR_t stAuto; + NRDESPIKE_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRDESPIKE_TYPE_t; + +typedef struct NRLUMA_PARAM_s +{ + MI_U8 u8Strength; + MI_U8 u8GMaskSel; + MI_U16 u16SpfBlendLut[2]; +} NRLUMA_PARAM_t; + +typedef struct NRLUMA_MANUAL_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI; +} NRLUMA_MANUAL_ATTR_t; + +typedef struct NRLUMA_AUTO_ATTR_s +{ + NRLUMA_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLUMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_AUTO_ATTR_t stAuto; + NRLUMA_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLUMA_TYPE_t; + +typedef struct NRLUMA_Adv_PARAM_s +{ + MI_U8 u8DbgMode; //0~3 + MI_U16 u16EdgeTh[16]; //0~8191 + MI_U8 u8SmoDeltaSft; //0~9 + MI_U16 u16SmoDeltaTh[16]; //0~1023 + MI_U8 u8SmoDeltaLut[16]; //0~63 + MI_U8 u8SmoByMot[16]; //0~64 + MI_U16 u16Strength[2]; //0~256 + MI_U8 u8StrengthByHue[24]; //0~64 + MI_U8 u8StrengthBySat[2]; //0~127 + MI_U8 u8StrengthByMot[16]; //0~64 +} NRLUMA_Adv_PARAM_t; + +typedef struct NRLUMA_Adv_MANUAL_ATTR_s +{ + NRLUMA_Adv_PARAM_t stParaAPI; +} NRLUMA_Adv_MANUAL_ATTR_t; + +typedef struct NRLUMA_Adv_AUTO_ATTR_s +{ + NRLUMA_Adv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRLUMA_Adv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRLuma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRLUMA_Adv_AUTO_ATTR_t stAuto; + NRLUMA_Adv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRLuma_Adv_TYPE_t; + +typedef struct NRChroma_PARAM_s +{ + MI_U8 u8MatchRatio; //0 ~ 127 + MI_U16 u16UvTh; //0 ~ 1023 + MI_U16 u16StrengthByCEdge[6]; //0 ~ 1023 +} NRChroma_PARAM_t; + +typedef struct NRChroma_MANUAL_ATTR_s +{ + NRChroma_PARAM_t stParaAPI; +} NRChroma_MANUAL_ATTR_t; + +typedef struct NRChroma_AUTO_ATTR_s +{ + NRChroma_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_AUTO_ATTR_t stAuto; + NRChroma_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_TYPE_t; + +typedef struct NRChroma_Adv_PARAM_s +{ + MI_U8 u8StrengthByY[8]; //0 ~ 255 + MI_U8 u8StrengthByYEdge[8]; //0 ~ 63 + MI_U8 u8StrengthByCEdge[8]; //0 ~ 255 + MI_U8 u8MaxStrength; //0 ~ 255 + MI_U8 u8StrengthByMot[16]; //0 ~ 63 + MI_U8 u8MotionClip; //0 ~ 255 + MI_U8 u8MotionColorReduce; //0 ~ 255 + MI_U8 u8MotionColorRecover; //0 ~ 255 + MI_U8 u8PreStrength; //0 ~ 128 +} NRChroma_Adv_PARAM_t; + +typedef struct NRChroma_Adv_MANUAL_ATTR_s +{ + NRChroma_Adv_PARAM_t stParaAPI; +} NRChroma_Adv_MANUAL_ATTR_t; + +typedef struct NRChroma_Adv_AUTO_ATTR_s +{ + NRChroma_Adv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_Adv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_Adv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_Adv_AUTO_ATTR_t stAuto; + NRChroma_Adv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_Adv_TYPE_t; + +typedef struct NRChroma_Pre_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_U16 u16Strength; //0 ~ 256 + MI_U8 u8MotionEnhance[2]; //0 ~ 127 + MI_U16 u16MaskGenTh; //0 ~ 1023 + MI_U16 u16MeanFilterTh[2]; //0 ~ 1023 + MI_U16 u16MedianFilterTh[2]; //0 ~ 1023 + MI_U16 u16BlendTh; //0 ~ 1023 + MI_U8 u8BlendGap; //0 ~ 15 +} NRChroma_Pre_PARAM_t; + +typedef struct NRChroma_Pre_MANUAL_ATTR_s +{ + NRChroma_Pre_PARAM_t stParaAPI; +} NRChroma_Pre_MANUAL_ATTR_t; + +typedef struct NRChroma_Pre_AUTO_ATTR_s +{ + NRChroma_Pre_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} NRChroma_Pre_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_NRChroma_Pre_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + NRChroma_Pre_AUTO_ATTR_t stAuto; + NRChroma_Pre_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_NRChroma_Pre_TYPE_t; + +typedef struct SHARPNESS_PARAM_s +{ + MI_U8 u8SharpnessUD[3]; //0 ~ 127 + MI_U8 u8SharpnessD[3]; //0 ~ 127 + MI_U8 u8PreCorUD[3]; //0 ~ 63 + MI_U8 u8PreCorD[3]; //0 ~ 63 + MI_U16 u16MidRatioUDByMot[16]; //0 ~ 256 + MI_U16 u16HighRatioUDByMot[16]; //0 ~ 256 + MI_U16 u16MidRatioDByMot[16]; //0 ~ 256 + MI_U16 u16HighRatioDByMot[16]; //0 ~ 256 + MI_U16 u16HighRatioUDByState[3]; //0 ~ 256 + MI_U16 u16HighRatioDByState[3]; //0 ~ 256 + MI_U8 u8DetailGainUDByMot[16]; //0 ~ 255 + MI_U16 u16DirRatioByState[9]; //0 ~ 256 + MI_U8 u8StdAdjByMot[16]; //0 ~ 63 + MI_U8 u8StdAdjByY[9]; //0 ~ 255 + MI_U8 u8GainByStd[7]; //0 ~ 255 + MI_U8 u8CorByY[9]; //0 ~ 255 + MI_U8 u8CorByMot[16]; //0 ~ 255 + MI_U8 u8OverShootGain; //0 ~ 255 + MI_U8 u8UnderShootGain; //0 ~ 255 + MI_U8 u8SclByY[9]; //0 ~ 255 + MI_U16 u16EdgeKillLut[7]; //0 ~ 1023 + MI_U16 u16OverShootLimit; //0 ~ 1023 + MI_U16 u16UnderShootLimit; //0 ~ 1023 + MI_U8 u8GainByMot[16]; //0 ~ 255 +} SHARPNESS_PARAM_t; + +typedef struct SHARPNESS_MANUAL_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI; +} SHARPNESS_MANUAL_ATTR_t; + +typedef struct SHARPNESS_AUTO_ATTR_s +{ + SHARPNESS_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SHARPNESS_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SHARPNESS_AUTO_ATTR_t stAuto; + SHARPNESS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_TYPE_t; + +typedef struct SHARPNESS_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_U8 u8SmoNRFilterSel; //0 ~ 1 + MI_U16 u16SmoDiffThByY[8]; //0 ~ 1023 + MI_U8 u8SmoBlendByStd[7]; //0 ~ 16 + MI_U8 u8SmoBlendByMot[16]; //0 ~ 63 + MI_U8 u8SblLut[6]; //0 ~ 127 + MI_U8 u8EdgeLabelSel; //0 ~ 1 + MI_U8 u8GainByStdSft[6]; //0 ~ 15 + MI_U8 u8EdgeKillLutSft[6]; //0 ~ 15 + MI_U8 u8BoundaryThByY[9]; //0 ~ 255 + MI_U8 u8BoundaryGainByY[9]; //0 ~ 255 + MI_U8 u8BoundaryLut[7]; //0 ~ 255 + MI_U8 u8StrengthByHue[24]; //0 ~ 255 + MI_U8 u8StrengthBySat[2]; //0 ~ 127 +} SHARPNESS_EX_PARAM_t; + +typedef struct SHARPNESS_EX_MANUAL_ATTR_s +{ + SHARPNESS_EX_PARAM_t stParaAPI; +} SHARPNESS_EX_MANUAL_ATTR_t; + +typedef struct SHARPNESS_EX_AUTO_ATTR_s +{ + SHARPNESS_EX_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} SHARPNESS_EX_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_SHARPNESS_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + SHARPNESS_EX_AUTO_ATTR_t stAuto; + SHARPNESS_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_SHARPNESS_EX_TYPE_t; + +typedef struct CROSSTALK_PARAM_s +{ + MI_U8 u8Strength; //0 ~ 31 + MI_U8 u8StrengthByY[15]; //0 ~ 127 + MI_U8 u8Threshold; //0 ~ 255 + MI_U16 u16Offset; //0 ~ 4095 +} CROSSTALK_PARAM_t; + +typedef struct CROSSTALK_MANUAL_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI; +} CROSSTALK_MANUAL_ATTR_t; + +typedef struct CROSSTALK_AUTO_ATTR_s +{ + CROSSTALK_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} CROSSTALK_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_CROSSTALK_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + CROSSTALK_AUTO_ATTR_t stAuto; + CROSSTALK_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_CROSSTALK_TYPE_t; + +typedef struct OBC_PARAM_s +{ + MI_U16 u16ValR; //0 ~ 255 + MI_U16 u16ValGr; //0 ~ 255 + MI_U16 u16ValGb; //0 ~ 255 + MI_U16 u16ValB; //0 ~ 255 +} OBC_PARAM_t; + +typedef struct OBC_MANUAL_ATTR_s +{ + OBC_PARAM_t stParaAPI; +} OBC_MANUAL_ATTR_t; + +typedef struct OBC_AUTO_ATTR_s +{ + OBC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} OBC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_OBC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + OBC_AUTO_ATTR_t stAuto; + OBC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_OBC_TYPE_t; + +typedef struct WDR_PARAM_s +{ + MI_U8 u8BoxNum; //1 ~ 4 + MI_ISP_BOOL_e bAutoDetailEnhance; //0 ~ 1 + MI_U8 u8ManualDetailEnhance; //0~255; default:128 + MI_U8 u8GlobalDarkToneEnhance; //0 ~ 15 + MI_U8 u8WDRStrByY[33]; //0 ~ 255 + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8DarkLimit; //0 ~ 255 + MI_U8 u8BrightLimit; //0 ~ 255 +} WDR_PARAM_t; + +typedef struct WDR_MANUAL_ATTR_s +{ + WDR_PARAM_t stParaAPI; +} WDR_MANUAL_ATTR_t; + +typedef struct WDR_AUTO_ATTR_s +{ + WDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDR_AUTO_ATTR_t stAuto; + WDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDR_TYPE_t; + + +typedef struct MI_ISP_IQ_WDRCurveFull_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_WDRCurveFull_TYPE_t; + +typedef struct WDRCurveAdv_PARAM_s +{ + MI_U16 u16StrengthByOpsCnt[8]; //0~4095 + MI_S32 s32GlobalToneParam[8]; //-65536~65536 + MI_U8 u8GlobalToneSft[31]; //3~15 + MI_U16 u16GlobalToneLut[32]; //0~4095 + MI_U16 u16GammaParam[10]; //0~65535 + MI_U16 u16GammaLut[33]; //0~4095 + MI_U16 u16DeGammaParam[10]; //0~65535 + MI_U16 u16DeGammaLut[33]; //0~65535 + MI_U8 u8DeSatSrcSel; //0~2 + MI_U8 u8DeSatLut[33]; //0~255 +} WDRCurveAdv_PARAM_t; + +typedef struct WDRCurveAdv_MANUAL_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI; +} WDRCurveAdv_MANUAL_ATTR_t; + +typedef struct WDRCurveAdv_AUTO_ATTR_s +{ + WDRCurveAdv_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} WDRCurveAdv_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_WDRCurveAdv_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + WDRCurveAdv_AUTO_ATTR_t stAuto; + WDRCurveAdv_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_WDRCurveAdv_TYPE_t; + +typedef struct DYNAMIC_DP_PARAM_s +{ + MI_ISP_BOOL_e bHotPixEn; //0 ~ 1 + MI_U16 u16HotPixCompSlpoe; + MI_ISP_BOOL_e bDarkPixEn; //0 ~ 1 + MI_U16 u16DarkPixCompSlpoe; + MI_U16 u16DPCTH; + MI_ISP_BOOL_e bBlendEn; + MI_U16 u16DiffLut[6]; + MI_U16 u16YLut[6]; +} DYNAMIC_DP_PARAM_t; + +typedef struct DYNAMIC_DP_MANUAL_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI; +} DYNAMIC_DP_MANUAL_ATTR_t; + +typedef struct DYNAMIC_DP_AUTO_ATTR_s +{ + DYNAMIC_DP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_AUTO_ATTR_t stAuto; + DYNAMIC_DP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DYNAMIC_DP_TYPE_t; + +typedef struct DYNAMIC_DP_CLUSTER_ATTR_S +{ + MI_ISP_BOOL_e bEdgeMode; + MI_U16 u16NeiDeltaTh; + MI_U8 u8NeiSmooth; + MI_ISP_BOOL_e bSortEn; + MI_ISP_BOOL_e bSortRGGBEn[4]; + MI_ISP_BOOL_e bSort1x3ModeEn; + MI_U16 u16SortLumTblL[6]; + MI_U16 u16SortLumTblD[6]; + MI_U16 u16SortLumTblS[6]; +} DYNAMIC_DP_CLUSTER_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI; +} DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S; + +typedef struct +{ + DYNAMIC_DP_CLUSTER_ATTR_S stParaAPI[MI_ISP_AUTO_NUM]; +} DYNAMIC_DP_CLUSTER_AUTO_ATTR_S; + +typedef struct MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + DYNAMIC_DP_CLUSTER_AUTO_ATTR_S stAuto; + DYNAMIC_DP_CLUSTER_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DYNAMIC_DP_CLUSTER_TYPE_t; + +typedef struct HSV_PARAM_s +{ + MI_S16 s16HueLut[24]; //-64 ~ 64 + MI_U16 u16SatLut[24]; // 0 ~ 255 (64->1X) + MI_S16 s16HueLut_ByIso[24]; //-64 ~ 64 + MI_U16 u16SatLut_ByIso[24]; // 0 ~ 255 (64->1X) + MI_S16 s16HueLut_ForUnitCCM[24]; //-64 ~ 64 + MI_U16 u16SatLut_ForUnitCCM[24]; // 0 ~ 255 (64->1X) + MI_U8 u8GlobalSat; // 0 ~ 255 (64->1x) +} HSV_PARAM_t; + +typedef struct HSV_MANUAL_ATTR_s +{ + HSV_PARAM_t stParaAPI; +} HSV_MANUAL_ATTR_t; + +typedef struct HSV_AUTO_ATTR_s +{ + HSV_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HSV_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HSV_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + HSV_AUTO_ATTR_t stAuto; + HSV_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HSV_TYPE_t; + +typedef struct RGBIR_PARAM_s +{ + MI_U8 u8IrPosType; //0 ~ 7, def : 0 + MI_ISP_BOOL_e bRemovelEn; //0 ~ 1, def : 1 + MI_U16 u16Ratio_R[6]; + MI_U16 u16Ratio_G[6]; + MI_U16 u16Ratio_B[6]; +} RGBIR_PARAM_t; + +typedef struct RGBIR_MANUAL_ATTR_s +{ + RGBIR_PARAM_t stParaAPI; +} RGBIR_MANUAL_ATTR_t; + +typedef struct RGBIR_AUTO_ATTR_s +{ + RGBIR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} RGBIR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_RGBIR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + RGBIR_AUTO_ATTR_t stAuto; + RGBIR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_RGBIR_TYPE_t; + +typedef struct MI_ISP_IQ_FPN_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_FPN_TYPE_t; + +typedef struct PFC_PARAM_s +{ + MI_U8 u8Strength; //0 ~ 255 + MI_U8 u8UStrength; //0 ~ 63 + MI_U8 u8VStrength; //0 ~ 63 + MI_U8 u8StrengthByY[8]; //0 ~ 255 + MI_U8 u8FlatProtect; //0 ~ 127 + MI_U8 u8SatByY[2]; //0 ~ 25 + MI_U8 u8SatSrcSel; //0 ~ 1 + MI_U8 u8StrengthByContrast[8]; //0 ~ 127 +} PFC_PARAM_t; + +typedef struct PFC_MANUAL_ATTR_s +{ + PFC_PARAM_t stParaAPI; +} PFC_MANUAL_ATTR_t; + +typedef struct PFC_AUTO_ATTR_s +{ + PFC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} PFC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_PFC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + PFC_AUTO_ATTR_t stAuto; + PFC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_PFC_TYPE_t; + +typedef struct PFC_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; //0 ~ 1 + MI_ISP_BOOL_e bGSkipEn; //0 ~ 1 + MI_U8 u8SatMaskSel; //0 ~ 1 + MI_ISP_BOOL_e bSatAmpEn; //0 ~ 1 + MI_U8 u8StrengthByHue[12]; //0 ~ 255 +} PFC_EX_PARAM_t; + +typedef struct PFC_EX_MANUAL_ATTR_s +{ + PFC_EX_PARAM_t stParaAPI; +} PFC_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_PFC_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + PFC_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_PFC_EX_TYPE_t; + +typedef struct DEMOSAIC_PARAM_s +{ + MI_U8 u8DbgMode; //0~2 + MI_U8 u8IsoTh; //0~127 + MI_U8 u8GradientTh; //32~63 + MI_ISP_BOOL_e bSmoEn; //0~1 + MI_U8 u8SmoRange; //0~7 + MI_U8 u8SmoStrength; //0~255 + MI_ISP_BOOL_e bDtlBypassColorCheck; //0~1 + MI_U8 u8DtlColorRatio; //0~255 + MI_U8 u8DtlColorOft; //0~63 + MI_U8 u8DtlHScale; //0~15 + MI_U8 u8DtlMScale; //0~15 +} DEMOSAIC_PARAM_t; + +typedef struct DEMOSAIC_MANUAL_ATTR_s +{ + DEMOSAIC_PARAM_t stParaAPI; +} DEMOSAIC_MANUAL_ATTR_t; + +typedef struct DEMOSAIC_AUTO_ATTR_s +{ + DEMOSAIC_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} DEMOSAIC_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DEMOSAIC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + DEMOSAIC_AUTO_ATTR_t stAuto; + DEMOSAIC_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DEMOSAIC_TYPE_t; + +typedef struct COLORTRANS_PARAM_s +{ + MI_U16 u16Y_OFST; //0 ~ 2047 + MI_U16 u16U_OFST; //0 ~ 2047 + MI_U16 u16V_OFST; //0 ~ 2047 + MI_U16 u16Matrix[9]; //0 ~ 1023 +} COLORTRANS_PARAM_t; + +typedef struct COLORTRANS_MANUAL_ATTR_s +{ + COLORTRANS_PARAM_t stParaAPI; +} COLORTRANS_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_COLORTRANS_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + COLORTRANS_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_COLORTRANS_TYPE_t; + +typedef struct HDR_PARAM_s +{ + MI_ISP_BOOL_e bNrEn; + MI_U16 u16YwtTh1; + MI_U16 u16YwtTh2; + MI_U16 u16NoiseLevel[16]; + MI_U16 u16MotionTh; + MI_U16 u16MotionAdjLut[7]; +} HDR_PARAM_t; + +typedef struct HDR_MANUAL_ATTR_s +{ + HDR_PARAM_t stParaAPI; +} HDR_MANUAL_ATTR_t; + +typedef struct HDR_AUTO_ATTR_s +{ + HDR_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} HDR_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + HDR_AUTO_ATTR_t stAuto; + HDR_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_TYPE_t; + +typedef struct HDR_EX_PARAM_s +{ + MI_ISP_BOOL_e bDbgEn; + MI_U16 u16SensorExpRatio; + MI_ISP_BOOL_e bDynRatioEn; + MI_U8 u8DynRatioSrcSel; + MI_U8 u8YSrcSel; + MI_U8 u8NoiseLevelSrcSel; + MI_U8 u8MotionMaxVal; + MI_U16 u16MotionLumaTh; + MI_U8 u8MotionAdjSft[6]; +} HDR_EX_PARAM_t; + +typedef struct HDR_EX_MANUAL_ATTR_s +{ + HDR_EX_PARAM_t stParaAPI; +} HDR_EX_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_HDR_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + HDR_EX_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_HDR_EX_TYPE_t; + +typedef struct MI_ISP_IQ_EFFECT_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_EFFECT_TYPE_t; + +typedef struct MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 +} MI_ISP_IQ_SYS_MCNR_MEMORY_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U16 u16CenterX; + MI_U16 u16CenterY; + MI_U16 u16RateX; + MI_U16 u16RateY; + MI_U8 u8Shift; + MI_U16 u16RGainTable[32*3]; + MI_U16 u16GGainTable[32*3]; + MI_U16 u16BGainTable[32*3]; +} MI_ISP_IQ_LSC_TYPE_t; + +typedef struct MI_ISP_IQ_LSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_LSC_CTRL_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8GridX; + MI_U8 u8GridY; + MI_U16 u16CCTthr[3]; + MI_U8 u8DeltaMode; + MI_ISP_BOOL_e bDeltaModeAdvEn; + MI_U8 u8DeltaLutX[26]; + MI_U8 u8DeltaLutY[26]; + MI_U16 u16TableR[3][ALSC_TBL_MAX]; + MI_U16 u16TableG[3][ALSC_TBL_MAX]; + MI_U16 u16TableB[3][ALSC_TBL_MAX]; +} MI_ISP_IQ_ALSC_TYPE_t; + +typedef struct MI_ISP_IQ_ALSC_CTRL_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8RRatioByCct[3]; + MI_U8 u8GRatioByCct[3]; + MI_U8 u8BRatioByCct[3]; + MI_INTP_LUT_IQ RatioByBv; +} MI_ISP_IQ_ALSC_CTRL_TYPE_t; + +typedef struct R2Y_PARAM_s +{ + MI_U16 u16Matrix[9]; + MI_U8 u8AddY16; +} R2Y_PARAM_t; + +typedef struct R2Y_MANUAL_ATTR_s +{ + R2Y_PARAM_t stParaAPI; +} R2Y_MANUAL_ATTR_t; + +typedef struct MI_ISP_IQ_R2Y_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + R2Y_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_R2Y_TYPE_t; + +typedef struct DUMMY_ATTR_s +{ + MI_S16 s16Dummy0[256]; + MI_S16 s16Dummy1[256]; + MI_S16 s16Dummy2[256]; + MI_S16 s16Dummy3; + MI_S16 s16Dummy4; +} DUMMY_ATTR_t; + +typedef struct DUMMY_MANUAL_ATTR_s +{ + DUMMY_ATTR_t stParaAPI; +} DUMMY_MANUAL_ATTR_t; + +typedef struct DUMMY_AUTO_ATTR_s +{ + DUMMY_ATTR_t stParaAPI[MI_ISP_AUTO_NUM]; +} DUMMY_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_DUMMY_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_ISP_OP_TYPE_e enOpType; //OP_TYP_AUTO ~ (OP_TPY_MODMAX-1) + DUMMY_AUTO_ATTR_t stAuto; + DUMMY_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_DUMMY_TYPE_t; + +typedef struct DUMMY_EX_ATTR_s +{ + MI_S16 s16DummyEx0[256]; + MI_S16 s16DummyEx1[256]; + MI_S16 s16DummyEx2[256]; + MI_S16 s16DummyEx3; + MI_S16 s16DummyEx4; +} DUMMY_EX_ATTR_t; + +typedef struct +{ + DUMMY_EX_ATTR_t stParaAPI; +} DUMMY_EX_MANUAL_ATTR_S; + +typedef struct MI_ISP_IQ_DUMMY_EX_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + DUMMY_EX_MANUAL_ATTR_S stManual; +} MI_ISP_IQ_DUMMY_EX_TYPE_t; + +#endif + +#if 1 // ISP IQ API +typedef struct IQ_VERSION_INFO_PARAM_s +{ + MI_U32 u32Vendor; + MI_U32 u32Major; + MI_U32 u32Minor; +} IQ_VERSION_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_VERSION_INFO_TYPE_s +{ + IQ_VERSION_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_VERSION_INFO_TYPE_t; + +typedef struct IQ_PARAM_INIT_INFO_PARAM_s +{ + MI_ISP_BOOL_e bFlag; +} IQ_PARAM_INIT_INFO_PARAM_t; + +typedef struct MI_ISP_IQ_PARAM_INIT_INFO_TYPE_s +{ + IQ_PARAM_INIT_INFO_PARAM_t stParaAPI; +} MI_ISP_IQ_PARAM_INIT_INFO_TYPE_t; + +typedef struct FAST_MODE_PARAM_s +{ + MI_ISP_BOOL_e bFastMode; +} FAST_MODE_PARAM_t; + +typedef struct MI_ISP_IQ_FAST_MODE_TYPE_s +{ + FAST_MODE_PARAM_t stParaAPI; +} MI_ISP_IQ_FAST_MODE_TYPE_t; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_PARAM_MODE_NORMAL = 0, + SS_IQ_PARAM_MODE_NIGHT = 1, //Night Mode + SS_IQ_PARAM_MODE_MAX +} MI_ISP_IQ_PARAM_MODE_e; + +typedef struct MI_ISP_IQ_GAMMA_LUT_TYPE_s +{ + MI_U16 u16LutR[256]; + MI_U16 u16LutG[256]; + MI_U16 u16LutB[256]; +} MI_ISP_IQ_GAMMA_LUT_TYPE_t; + +typedef struct MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_s +{ + MI_ISP_BOOL_e bEnable; + MI_U16 u16BTGamma[256]; + MI_U16 u16DTGamma[256]; +} MI_ISP_IQ_ADAPTIVE_GAMMA_TYPE_t; + +typedef struct MI_ISP_IQ_OBC4Ch_TYPE_s +{ + MI_U16 u16OBC4Ch[4]; +} MI_ISP_IQ_OBC4Ch_TYPE_t; +#endif + +typedef struct TEMP_PARAM_s +{ + MI_S16 s16ObcOffset; + MI_U8 u8DynamicDPRatio; + MI_U8 u8CrosstalkRatio; + MI_U8 u8NRDeSpikeRatio; + MI_U8 u8NR3DRatio[2]; + MI_U8 u8NRLumaRatio; + MI_U8 u8SharpnessRatio[2]; + MI_U8 u8SaturationRatio; + MI_U8 u8ColorToneRatio[3]; +} TEMP_PARAM_t; + +typedef struct TEMP_MANUAL_ATTR_s +{ + TEMP_PARAM_t stParaAPI; +} TEMP_MANUAL_ATTR_t; + +typedef struct TEMP_AUTO_ATTR_s +{ + TEMP_PARAM_t stParaAPI[MI_ISP_AUTO_NUM]; +} TEMP_AUTO_ATTR_t; + +typedef struct MI_ISP_IQ_TEMP_TYPE_s +{ + MI_ISP_BOOL_e bEnable; //0 ~ 1 + MI_U8 u8TemperatureLut[16]; + MI_ISP_OP_TYPE_e enOpType; //M_AUTO ~ (M_MODMAX-1) + TEMP_AUTO_ATTR_t stAuto; + TEMP_MANUAL_ATTR_t stManual; +} MI_ISP_IQ_TEMP_TYPE_t; + +typedef struct MI_ISP_IQ_TEMP_INFO_TYPE_s +{ + MI_U8 u8Temperature; +} MI_ISP_IQ_TEMP_INFO_TYPE_t; + +#if 1 // MAINTOOL API +typedef enum __attribute__ ((aligned (4))) +{ + SS_IQ_INDEX_0 = 0, + SS_IQ_INDEX_1, + SS_IQ_INDEX_2, + SS_IQ_INDEX_3, + SS_IQ_INDEX_4, + SS_IQ_INDEX_5, + SS_IQ_INDEX_6, + SS_IQ_INDEX_7, + SS_IQ_INDEX_8, + SS_IQ_INDEX_9, + SS_IQ_INDEX_10, + SS_IQ_INDEX_11, + SS_IQ_INDEX_12, + SS_IQ_INDEX_13, + SS_IQ_INDEX_14, + SS_IQ_INDEX_15, + SS_IQ_INDEX_MAX +} MI_ISP_IQ_INDEX_e; + +typedef enum __attribute__ ((aligned (4))) +{ + SS_BYPASS_OFF = 0, + SS_BYPASS_ON, + SS_BYPASS_MAX +} MI_ISP_BYPASS_MODE_e; + +typedef struct MI_ISP_API_BYPASS_TYPE_s +{ + MI_ISP_BYPASS_MODE_e bEnable; //0 ~ 1 + MI_ISP_API_ID_e eAPIIndex; +} MI_ISP_API_BYPASS_TYPE_t; +#endif + + +/************************************* IQ - Define the structure declaration - END *************************************/ + + +#endif /* _MI_ISP_IQ_DATATYPE_H_ */ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/isp_cus3a_if.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp_cus3a_if.h new file mode 100644 index 000000000..3d64d5d76 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/isp_cus3a_if.h @@ -0,0 +1,460 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _ISP_CUS3A_IF_H_ +#define _ISP_CUS3A_IF_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define CUS3A_VER_STR "CUS3A_V1.1" +#define CUS3A_VER_MAJOR 1 +#define CUS3A_VER_MINOR 1 + +#include "cam_os_wrapper.h" +#include "mi_isp_datatype.h" + +#if 0 +typedef unsigned char u8; +//typedef signed char s8; +typedef unsigned short u16; +//typedef signed short s16; +typedef unsigned int u32; +//typedef signed int s32; +typedef unsigned long long u64; +//typedef signed long long s64; +#endif + +#define MV_WIN_NUM 25 +#define CAM20_AUTO_NUM 16 +#define CAM20_SDC_CTRL_ITEM_NUMBER 2 +#define AWB_LV_CT_TBL_NUM 18 +#define AWB_CT_TBL_NUM 10 + +#define MS_GAMMA_TBL 256 +#define MS_ALSC_TBL_W 61 +#define MS_ALSC_TBL_H 69 +#define MS_ALSC_TBL 4209 +#define MS_SDC_TBL 1024 +#define MS_FPN_TBL 4000 //infinity5 +#define MS_YUVGAMA_Y_TBL 256 +#define MS_YUVGAMA_VU_TBL 128 +#define MS_WDR_LOC_TBL 88 + +#define MS_CAM_AF_MAX_WIN_NUM 16 // +#define MAX_CUST_3A_CHINFO_NUM (16) + +/*------AE/AWB interface--------*/ +/*! @brief API error code*/ +typedef enum CUS_3A_ERR_CODE +{ + CUS_3A_SUCCESS = 0, /**< operation successful */ + CUS_3A_ERROR = -1, /**< unspecified failure */ +}CUS3A_ERR_CODE; + +#define _3A_ROW (128) /**< number of 3A statistic blocks in a row */ +#define _3A_COL (90) /**< number of 3A statistic blocks in a column */ +#define _3A_HIST_BIN0 (40) /**< histogram type0 resolution*/ +#define _3A_HIST_BINX (128) /**< histogram type1 resolution*/ +#define _3A_IR_HIST_BIN (256) /**< histogram type2 resolution*/ + +typedef enum +{ + E_ISP_CH_0 = 0, + E_ISP_CH_1, + E_ISP_CH_2, + E_ISP_CH_3, + E_ISP_CH_4, + E_ISP_CH_5, + E_ISP_CH_6, + E_ISP_CH_7, + E_ISP_CH_8, + E_ISP_CH_9, + E_ISP_CH_10, + E_ISP_CH_11, + E_ISP_CH_12, + E_ISP_CH_13, + E_ISP_CH_14, + E_ISP_CH_15, + E_ISP_CH_MAX +}CUS3A_ISP_CH_e; + +typedef enum +{ + E_ALGO_TYPE_AE = 0x0, + E_ALGO_TYPE_AWB, + E_ALGO_TYPE_AF, + E_ALGO_TYPE_MAX +}CUS3A_ALGO_TYPE_e; + +typedef enum +{ + E_ALGO_ADAPTOR_NATIVE = 0x0, + E_ALGO_ADAPTOR_1, + E_ALGO_ADAPTOR_MAX +}CUS3A_ALGO_ADAPTOR_e; + +// AWB statistic , one sample +typedef struct +{ + u8 r; + u8 g; + u8 b; +} __attribute__((packed, aligned(1))) ISP_AWB_SAMPLE; + +#if 0 +/*! @brief AWB HW statistics data*/ +typedef struct +{ + //ISP_AWB_SAMPLE data[_3A_ROW*_3A_COL]; + u32 AvgBlkX; + u32 AvgBlkY; + ISP_AWB_SAMPLE *avgs; +} __attribute__((packed, aligned(1))) ISP_AWB_INFO; +#else +/*! @brief AWB HW statistics data*/ +typedef struct +{ + u32 Size; /**< struct size*/ + u32 AvgBlkX; + u32 AvgBlkY; + u32 CurRGain; + u32 CurGGain; + u32 CurBGain; + ISP_AWB_SAMPLE *avgs; /*awb statis for linear frame or HDR long frame*/ + /*CUS3A V1.1*/ + u8 HDRMode; /**< Noramal or HDR mode*/ + ISP_AWB_SAMPLE* pAwbStatisShort; /**<--7bits----><----8bits---><--4bits---><------12bits------->| +******************************************************************************/ + +#define MI_DEF_ERR( module, level, errid) \ + ((MI_S32)( (MI_ERR_ID) | ((module) << 16 ) | ((level)<<12) | (errid) )) + + +#ifndef __KERNEL__ +/// data type null pointer +#ifdef NULL +#undef NULL +#endif +#define NULL 0 + + +#if !defined(__cplusplus) +#ifndef true +/// definition for true +#define true 1 +/// definition for false +#define false 0 +#endif +#endif + +#if !defined(TRUE) && !defined(FALSE) +/// definition for TRUE +#define TRUE 1 +/// definition for FALSE +#define FALSE 0 +#endif +#endif + +#define TO_STR_NATIVE(e) #e +#define TO_STR_PROXY(m, e) m(e) +#define MACRO_TO_STRING(e) TO_STR_PROXY(TO_STR_NATIVE, e) +#define COMPILE_DATE_TIME() __DATE__ __TIME__ + +///ASCII color code +#define ASCII_COLOR_RED "\033[1;31m" +#define ASCII_COLOR_WHITE "\033[1;37m" +#define ASCII_COLOR_YELLOW "\033[1;33m" +#define ASCII_COLOR_BLUE "\033[1;36m" +#define ASCII_COLOR_GREEN "\033[1;32m" +#define ASCII_COLOR_END "\033[0m" + +//------------------------------------------------------------------------------------------------- +// Structures +//------------------------------------------------------------------------------------------------- + + + +//------------------------------------------------------------------------------------------------- +// Enum +//------------------------------------------------------------------------------------------------- +typedef enum +{ + E_MI_MODULE_ID_IVE = 0, + E_MI_MODULE_ID_VDF = 1, + E_MI_MODULE_ID_VENC = 2, + E_MI_MODULE_ID_RGN = 3, + E_MI_MODULE_ID_AI = 4, + E_MI_MODULE_ID_AO = 5, + E_MI_MODULE_ID_VIF = 6, + E_MI_MODULE_ID_VPE = 7, + E_MI_MODULE_ID_VDEC = 8, + E_MI_MODULE_ID_SYS = 9, + E_MI_MODULE_ID_FB = 10, + E_MI_MODULE_ID_HDMI = 11, + E_MI_MODULE_ID_DIVP = 12, + E_MI_MODULE_ID_GFX = 13, + E_MI_MODULE_ID_VDISP = 14, + E_MI_MODULE_ID_DISP = 15, + E_MI_MODULE_ID_OS = 16, + E_MI_MODULE_ID_IAE = 17, + E_MI_MODULE_ID_MD = 18, + E_MI_MODULE_ID_OD = 19, + E_MI_MODULE_ID_SHADOW = 20, + E_MI_MODULE_ID_WARP = 21, + E_MI_MODULE_ID_UAC = 22, + E_MI_MODULE_ID_LDC = 23, + E_MI_MODULE_ID_SD = 24, + E_MI_MODULE_ID_PANEL = 25, + E_MI_MODULE_ID_CIPHER = 26, + E_MI_MODULE_ID_SNR = 27, + E_MI_MODULE_ID_WLAN =28, + E_MI_MODULE_ID_IPU = 29, + E_MI_MODULE_ID_MIPITX = 30, + E_MI_MODULE_ID_GYRO = 31, + E_MI_MODULE_ID_JPD = 32, + //E_MI_MODULE_ID_SED = 29, + E_MI_MODULE_ID_MAX, +} MI_ModuleId_e; + +typedef enum +{ + E_MI_ERR_LEVEL_INFO, /* informational */ + E_MI_ERR_LEVEL_WARNING, /* warning conditions */ + E_MI_ERR_LEVEL_ERROR, /* error conditions */ + E_MI_ERR_LEVEL_BUTT +} MI_ErrLevel_e; + +typedef enum +{ + E_MI_ERR_INVALID_DEVID = 1, /* invlalid device ID */ + E_MI_ERR_INVALID_CHNID = 2, /* invlalid channel ID */ + E_MI_ERR_ILLEGAL_PARAM = 3, /* at lease one parameter is illagal + ** eg, an illegal enumeration value */ + E_MI_ERR_EXIST = 4, /* resource exists */ + E_MI_ERR_UNEXIST = 5,/* resource unexists */ + E_MI_ERR_NULL_PTR = 6, /* using a NULL point */ + E_MI_ERR_NOT_CONFIG = 7, /* try to enable or initialize system, device + ** or channel, before configing attribute */ + E_MI_ERR_NOT_SUPPORT = 8, /* operation or type is not supported by NOW */ + E_MI_ERR_NOT_PERM = 9, /* operation is not permitted + ** eg, try to change static attribute */ + E_MI_ERR_NOMEM = 12,/* failure caused by malloc memory */ + E_MI_ERR_NOBUF = 13,/* failure caused by malloc buffer */ + E_MI_ERR_BUF_EMPTY = 14,/* no data in buffer */ + E_MI_ERR_BUF_FULL = 15,/* no buffer for new data */ + E_MI_ERR_SYS_NOTREADY = 16,/* System is not ready,maybe not initialed or + ** loaded. Returning the error code when opening + ** a device file failed. */ + E_MI_ERR_BADADDR = 17,/* bad address, + ** eg. used for copy_from_user & copy_to_user */ + E_MI_ERR_BUSY = 18,/* resource is busy, + ** eg. destroy a venc chn without unregister it */ + E_MI_ERR_CHN_NOT_STARTED = 19,/* channel not start*/ + E_MI_ERR_CHN_NOT_STOPED = 20,/* channel not stop*/ + E_MI_ERR_NOT_INIT = 21,/* module not init before use it*/ + E_MI_ERR_INITED = 22,/* module already init*/ + E_MI_ERR_NOT_ENABLE = 23,/* device channel or port not enable*/ + E_MI_ERR_NOT_DISABLE = 24,/* device channel or port not disable*/ + E_MI_ERR_SYS_TIMEOUT = 25,/* sys timeout*/ + E_MI_ERR_DEV_NOT_STARTED = 26,/* device not started*/ + E_MI_ERR_DEV_NOT_STOPED = 27,/* device not stoped*/ + E_MI_ERR_CHN_NO_CONTENT = 28,/* there is no content in the channel.*/ + E_MI_ERR_NOVASPACE = 29,/* failure caused by va mmap */ + E_MI_ERR_NOITEM = 30,/* no item record in ringpool */ + E_MI_ERR_FAILED ,/* unexpected error */ + + E_MI_ERR_MAX = 127,/* maxium code, private error code of all modules + ** must be greater than it */ +}MI_ErrCode_e; + +typedef enum +{ + MI_DBG_NONE = 0, + MI_DBG_ERR, + MI_DBG_WRN, + MI_DBG_API, + MI_DBG_KMSG, + MI_DBG_INFO, + MI_DBG_DEBUG, + MI_DBG_TRACE, + MI_DBG_ALL +}MI_DBG_LEVEL_e; + +#ifndef __KERNEL__ +__attribute__((weak)) char sstar_mi_so_version_string[] = MACRO_TO_STRING(SIGMASTAR_MODULE_VERSION); +#endif +#endif///_MI_COMMON_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_disp.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_disp.h new file mode 100644 index 000000000..7c8da1b24 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_disp.h @@ -0,0 +1,85 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_DISP_H_ +#define _MI_DISP_H_ + +#include "mi_disp_datatype.h" + +#define DISP_MAJOR_VERSION 2 +#define DISP_SUB_VERSION 7 +#define MACRO_TO_STR(macro) #macro +#define DISP_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_disp_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_disp_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_disp_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_DISP_API_VERSION DISP_VERSION_STR(DISP_MAJOR_VERSION,DISP_SUB_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + +MI_S32 MI_DISP_Enable(MI_DISP_DEV DispDev); +MI_S32 MI_DISP_Disable(MI_DISP_DEV DispDev); +MI_S32 MI_DISP_SetPubAttr(MI_DISP_DEV DispDev, const MI_DISP_PubAttr_t *pstPubAttr); +MI_S32 MI_DISP_GetPubAttr(MI_DISP_DEV DispDev, MI_DISP_PubAttr_t *pstPubAttr); +MI_S32 MI_DISP_DeviceAttach(MI_DISP_DEV DispSrcDev, MI_DISP_DEV DispDstDev); +MI_S32 MI_DISP_DeviceDetach(MI_DISP_DEV DispSrcDev, MI_DISP_DEV DispDstDev); +MI_S32 MI_DISP_EnableVideoLayer(MI_DISP_LAYER DispLayer); +MI_S32 MI_DISP_DisableVideoLayer(MI_DISP_LAYER DispLayer); +MI_S32 MI_DISP_SetVideoLayerAttr(MI_DISP_LAYER DispLayer, const MI_DISP_VideoLayerAttr_t *pstLayerAttr); +MI_S32 MI_DISP_GetVideoLayerAttr(MI_DISP_LAYER DispLayer, MI_DISP_VideoLayerAttr_t *pstLayerAttr); +MI_S32 MI_DISP_BindVideoLayer(MI_DISP_LAYER DispLayer, MI_DISP_DEV DispDev); +MI_S32 MI_DISP_UnBindVideoLayer(MI_DISP_LAYER DispLayer, MI_DISP_DEV DispDev); +MI_S32 MI_DISP_SetPlayToleration(MI_DISP_LAYER DispLayer, MI_U32 u32Toleration); +MI_S32 MI_DISP_GetPlayToleration(MI_DISP_LAYER DispLayer, MI_U32 *pu32Toleration); +MI_S32 MI_DISP_GetScreenFrame(MI_DISP_LAYER DispLayer, MI_DISP_VideoFrame_t *pstVFrame); +MI_S32 MI_DISP_ReleaseScreenFrame(MI_DISP_LAYER DispLayer, MI_DISP_VideoFrame_t *pstVFrame); +MI_S32 MI_DISP_SetVideoLayerAttrBegin(MI_DISP_LAYER DispLayer); +MI_S32 MI_DISP_SetVideoLayerAttrEnd(MI_DISP_LAYER DispLayer); +MI_S32 MI_DISP_SetInputPortAttr(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort, const MI_DISP_InputPortAttr_t *pstInputPortAttr); +MI_S32 MI_DISP_GetInputPortAttr(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort, MI_DISP_InputPortAttr_t *pstInputPortAttr); +MI_S32 MI_DISP_EnableInputPort (MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort); +MI_S32 MI_DISP_DisableInputPort(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort); +MI_S32 MI_DISP_SetInputPortDispPos(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort, const MI_DISP_Position_t *pstDispPos); +MI_S32 MI_DISP_GetInputPortDispPos(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort, MI_DISP_Position_t *pstDispPos); +MI_S32 MI_DISP_PauseInputPort (MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort); +MI_S32 MI_DISP_ResumeInputPort (MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort); +MI_S32 MI_DISP_StepInputPort(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort); +MI_S32 MI_DISP_ShowInputPort(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort); +MI_S32 MI_DISP_HideInputPort(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort); +MI_S32 MI_DISP_SetInputPortSyncMode (MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort, MI_DISP_SyncMode_e eMode); +MI_S32 MI_DISP_QueryInputPortStat(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort, MI_DISP_QueryChannelStatus_t *pstStatus); +MI_S32 MI_DISP_SetZoomInWindow(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort, MI_DISP_VidWinRect_t* pstZoomRect); +MI_S32 MI_DISP_GetVgaParam(MI_DISP_DEV DispDev, MI_DISP_VgaParam_t *pstVgaParam); +MI_S32 MI_DISP_SetVgaParam(MI_DISP_DEV DispDev, MI_DISP_VgaParam_t *pstVgaParam); +MI_S32 MI_DISP_GetHdmiParam(MI_DISP_DEV DispDev, MI_DISP_HdmiParam_t *pstHdmiParam); +MI_S32 MI_DISP_SetHdmiParam(MI_DISP_DEV DispDev, MI_DISP_HdmiParam_t *pstHdmiParam); +MI_S32 MI_DISP_GetLcdParam(MI_DISP_DEV DispDev, MI_DISP_LcdParam_t *pstLcdParam); +MI_S32 MI_DISP_SetLcdParam(MI_DISP_DEV DispDev, MI_DISP_LcdParam_t *pstLcdParam); +MI_S32 MI_DISP_GetCvbsParam(MI_DISP_DEV DispDev, MI_DISP_CvbsParam_t *pstCvbsParam); +MI_S32 MI_DISP_SetCvbsParam(MI_DISP_DEV DispDev, MI_DISP_CvbsParam_t *pstCvbsParam); +MI_S32 MI_DISP_DeviceSetColorTempeture(MI_DISP_DEV DispDev, MI_DISP_ColorTemperature_t *pstColorTempInfo); +MI_S32 MI_DISP_DeviceGetColorTempeture(MI_DISP_DEV DispDev, MI_DISP_ColorTemperature_t *pstColorTempInfo); +MI_S32 MI_DISP_DeviceSetGammaParam(MI_DISP_DEV DispDev, MI_DISP_GammaParam_t * pstGammaParam); +MI_S32 MI_DISP_ClearInputPortBuffer(MI_DISP_LAYER DispLayer, MI_DISP_INPUTPORT LayerInputPort, MI_BOOL bClrAll); +MI_S32 MI_DISP_SetVideoLayerRotateMode(MI_DISP_LAYER DispLayer, MI_DISP_RotateConfig_t *pstRotateConfig); +MI_S32 MI_DISP_InitDev(MI_DISP_InitParam_t *pstInitParam); +MI_S32 MI_DISP_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif///_MI_DISP_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_disp_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_disp_datatype.h new file mode 100644 index 000000000..24ab36b97 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_disp_datatype.h @@ -0,0 +1,335 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_DISP_DATATYPE_H_ +#define _MI_DISP_DATATYPE_H_ +#include "mi_sys_datatype.h" + +#define MI_DISP_SUCCESS (0) +#define MI_DISP_FAIL (1) +#define MI_ERR_DISP_INVALID_DEVID (0xA00F8001) //The device ID does not fall within the value range. +#define MI_ERR_DISP_INVALID_CHNID (0xA00F8002) //The channel ID does not fall within the value range. +#define MI_ERR_DISP_ILLEGAL_PARAM (0xA00F8003) //The parameter value does not fall within the value range. +#define MI_ERR_DISP_NULL_PTR (0xA00F8006) //The pointer is null. +#define MI_ERR_DISP_NOT_SUPPORT (0xA00F8008) //The operation is not supported. +#define MI_ERR_DISP_NOT_PERMIT (0xA00F8009) //The operation is forbidden. +#define MI_ERR_DISP_NO_MEM (0xA00F800C) //The memory is insufficient. +#define MI_ERR_DISP_SYS_NOTREADY (0xA00F8010) //The system is not initialized. +#define MI_ERR_DISP_BUSY (0xA00F8012) //The resources are unavailable. +#define MI_ERR_DISP_DEV_NOT_CONFIG (0xA00F8040) //The MI_DISP device is not configured. +#define MI_ERR_DISP_DEV_NOT_ENABLE (0xA00F8041) //The MI_DISP device is not enabled. +#define MI_ERR_DISP_DEV_HAS_ENABLED (0xA00F8042) //The MI_DISP device has been enabled. +#define MI_ERR_DISP_DEV_HAS_BINDED (0xA00F8043) //The device has been bound. +#define MI_ERR_DISP_DEV_NOT_BINDED (0xA00F8044) //The device is not bound. +#define MI_ERR_DISP_VIDEO_NOT_ENABLE (0xA00F8045) //The video layer is not enabled. +#define MI_ERR_DISP_VIDEO_NOT_DISABLE (0xA00F8046) //The video layer is not disabled. +#define MI_ERR_DISP_VIDEO_NOT_CONFIG (0xA00F8047) //The video layer is not configured. +#define MI_ERR_DISP_CHN_NOT_DISABLE (0xA00F8048) //The MI_DISP input port is not disabled. +#define MI_ERR_DISP_CHN_NOT_ENABLE (0xA00F8049) //No MI_DISP input port is enabled. +#define MI_ERR_DISP_CHN_NOT_CONFIG (0xA00F804A) //The MI_DISP input port is not configured. +#define MI_ERR_DISP_CHN_NOT_ALLOC (0xA00F804B) //No MI_DISP input port is allocated. +#define MI_ERR_DISP_INVALID_PATTERN (0xA00F804C) //The pattern is invalid. +#define MI_ERR_DISP_INVALID_POSITION (0xA00F804D) //The cascade position is invalid. +#define MI_ERR_DISP_WAIT_TIMEOUT (0xA00F804E) //Waiting times out. +#define MI_ERR_DISP_INVALID_VFRAME (0xA00F804F) //The video frame is invalid. +#define MI_ERR_DISP_INVALID_RECT_PARA (0xA00F8050) //The rectangle parameter is invalid. +#define MI_ERR_DISP_GFX_NOT_DISABLE (0xA00F8065) //The graphics layer is not disabled. +#define MI_ERR_DISP_GFX_NOT_BIND (0xA00F8066) //The graphics layer is not bound. +#define MI_ERR_DISP_GFX_NOT_UNBIND (0xA00F8067) //The graphics layer is not unbound. +#define MI_ERR_DISP_GFX_INVALID_ID (0xA00F8068) //The graphics layer ID does not fall within the value range. +#define MI_ERR_DISP_CHN_AREA_OVERLAP (0xA00F806b) //The MI_DISP input port areas overlap. +#define MI_ERR_DISP_INVALID_LAYERID (0xA00F806d) //The video layer ID does not fall within the value range. +#define MI_ERR_DISP_VIDEO_HAS_BINDED (0xA00F806e) //The video layer has been bound. +#define MI_ERR_DISP_VIDEO_NOT_BINDED (0xA00F806f) //The video layer is not bound + +#define MI_DISP_DEV_MAX 1 +#define MI_DISP_LAYER_MAX 2 +#define MI_DISP_INPUTPORT_MAX 16 + +//typedef MI_U32 MI_DISP_DEV; +//typedef MI_U32 MI_DISP_LAYER; +typedef MI_U32 MI_DISP_INPUTPORT; + +typedef enum +{ + E_MI_DISP_INTF_CVBS = 0, + E_MI_DISP_INTF_YPBPR, + E_MI_DISP_INTF_VGA, + E_MI_DISP_INTF_BT656, + E_MI_DISP_INTF_BT1120, + E_MI_DISP_INTF_HDMI, + E_MI_DISP_INTF_LCD, + E_MI_DISP_INTF_BT656_H, + E_MI_DISP_INTF_BT656_L, + E_MI_DISP_INTF_TTL, + E_MI_DISP_INTF_MIPIDSI, + E_MI_DISP_INTF_MAX, +}MI_DISP_Interface_e; + +typedef enum +{ + E_MI_DISP_OUTPUT_PAL = 0, + E_MI_DISP_OUTPUT_NTSC, + E_MI_DISP_OUTPUT_960H_PAL, /* ITU-R BT.1302 960 x 576 at 50 Hz (interlaced)*/ + E_MI_DISP_OUTPUT_960H_NTSC, /* ITU-R BT.1302 960 x 480 at 60 Hz (interlaced)*/ + + E_MI_DISP_OUTPUT_480i60, + E_MI_DISP_OUTPUT_576i50, + E_MI_DISP_OUTPUT_480P60, + E_MI_DISP_OUTPUT_576P50, + E_MI_DISP_OUTPUT_720P50, + E_MI_DISP_OUTPUT_720P60, + E_MI_DISP_OUTPUT_1080P24, + E_MI_DISP_OUTPUT_1080P25, + E_MI_DISP_OUTPUT_1080P30, + E_MI_DISP_OUTPUT_1080I50, + E_MI_DISP_OUTPUT_1080I60, + E_MI_DISP_OUTPUT_1080P50, + E_MI_DISP_OUTPUT_1080P60, + + E_MI_DISP_OUTPUT_640x480_60, /* VESA 640 x 480 at 60 Hz (non-interlaced) CVT */ + E_MI_DISP_OUTPUT_800x600_60, /* VESA 800 x 600 at 60 Hz (non-interlaced) */ + E_MI_DISP_OUTPUT_1024x768_60, /* VESA 1024 x 768 at 60 Hz (non-interlaced) */ + E_MI_DISP_OUTPUT_1280x1024_60, /* VESA 1280 x 1024 at 60 Hz (non-interlaced) */ + E_MI_DISP_OUTPUT_1366x768_60, /* VESA 1366 x 768 at 60 Hz (non-interlaced) */ + E_MI_DISP_OUTPUT_1440x900_60, /* VESA 1440 x 900 at 60 Hz (non-interlaced) CVT Compliant */ + E_MI_DISP_OUTPUT_1280x800_60, /* 1280*800@60Hz VGA@60Hz*/ + E_MI_DISP_OUTPUT_1680x1050_60, /* VESA 1680 x 1050 at 60 Hz (non-interlaced) */ + E_MI_DISP_OUTPUT_1920x2160_30, /* 1920x2160_30 */ + E_MI_DISP_OUTPUT_1600x1200_60, /* VESA 1600 x 1200 at 60 Hz (non-interlaced) */ + E_MI_DISP_OUTPUT_1920x1200_60, /* VESA 1920 x 1600 at 60 Hz (non-interlaced) CVT (Reduced Blanking)*/ + + E_MI_DISP_OUTPUT_2560x1440_30, /* 2560x1440_30 */ + E_MI_DISP_OUTPUT_2560x1600_60, /* 2560x1600_60 */ + E_MI_DISP_OUTPUT_3840x2160_30, /* 3840x2160_30 */ + E_MI_DISP_OUTPUT_3840x2160_60, /* 3840x2160_60 */ + E_MI_DISP_OUTPUT_USER, + E_MI_DISP_OUTPUT_MAX, +} MI_DISP_OutputTiming_e; + +typedef enum +{ + E_MI_DISP_ROTATE_NONE, + E_MI_DISP_ROTATE_90, + E_MI_DISP_ROTATE_180, + E_MI_DISP_ROTATE_270, + E_MI_DISP_ROTATE_NUM, +}MI_DISP_RotateMode_e; + +typedef enum +{ + E_MI_DISP_CSC_MATRIX_BYPASS = 0, /* do not change color space */ + + E_MI_DISP_CSC_MATRIX_BT601_TO_BT709, /* change color space from BT.601 to BT.709 */ + E_MI_DISP_CSC_MATRIX_BT709_TO_BT601, /* change color space from BT.709 to BT.601 */ + + E_MI_DISP_CSC_MATRIX_BT601_TO_RGB_PC, /* change color space from BT.601 to RGB */ + E_MI_DISP_CSC_MATRIX_BT709_TO_RGB_PC, /* change color space from BT.709 to RGB */ + + E_MI_DISP_CSC_MATRIX_RGB_TO_BT601_PC, /* change color space from RGB to BT.601 */ + E_MI_DISP_CSC_MATRIX_RGB_TO_BT709_PC, /* change color space from RGB to BT.709 */ + + E_MI_DISP_CSC_MATRIX_NUM +} MI_DISP_CscMattrix_e; + +typedef enum +{ + E_MI_DISP_SYNC_MODE_INVALID = 0, + E_MI_DISP_SYNC_MODE_CHECK_PTS, + E_MI_DISP_SYNC_MODE_FREE_RUN, + E_MI_DISP_SYNC_MODE_NUM, +} MI_DISP_SyncMode_e; + +typedef enum +{ + E_MI_LAYER_INPUTPORT_STATUS_INVALID = 0, + E_MI_LAYER_INPUTPORT_STATUS_PAUSE, + E_MI_LAYER_INPUTPORT_STATUS_RESUME, + E_MI_LAYER_INPUTPORT_STATUS_STEP, + E_MI_LAYER_INPUTPORT_STATUS_REFRESH, + E_MI_LAYER_INPUTPORT_STATUS_SHOW, + E_MI_LAYER_INPUTPORT_STATUS_HIDE, + E_MI_LAYER_INPUTPORT_STATUS_NUM, +} MI_DISP_InputPortStatus_e; + +typedef struct MI_DISP_SyncInfo_s +{ + MI_BOOL bSynm; /* sync mode(0:timing,as BT.656; 1:signal,as LCD) */ + MI_BOOL bIop; /* interlaced or progressive display(0:i; 1:p) */ + MI_U8 u8Intfb; /* interlace bit width while output */ + + MI_U16 u16Vact ; /* vertical active area */ + MI_U16 u16Vbb; /* vertical back blank porch */ + MI_U16 u16Vfb; /* vertical front blank porch */ + + MI_U16 u16Hact; /* herizontal active area */ + MI_U16 u16Hbb; /* herizontal back blank porch */ + MI_U16 u16Hfb; /* herizontal front blank porch */ + MI_U16 u16Hmid; /* bottom herizontal active area */ + + MI_U16 u16Bvact; /* bottom vertical active area */ + MI_U16 u16Bvbb; /* bottom vertical back blank porch */ + MI_U16 u16Bvfb; /* bottom vertical front blank porch */ + + MI_U16 u16Hpw; /* horizontal pulse width */ + MI_U16 u16Vpw; /* vertical pulse width */ + + MI_BOOL bIdv; /* inverse data valid of output */ + MI_BOOL bIhs; /* inverse horizontal synch signal */ + MI_BOOL bIvs; /* inverse vertical synch signal */ + MI_U32 u32FrameRate; +} MI_DISP_SyncInfo_t; + + +typedef struct MI_DISP_PubAttr_s +{ + MI_U32 u32BgColor; /* Background color of a device, in RGB format. */ + MI_DISP_Interface_e eIntfType; /* Type of a VO interface */ + MI_DISP_OutputTiming_e eIntfSync; /* Type of a VO interface timing */ + MI_DISP_SyncInfo_t stSyncInfo; /* Information about VO interface timings */ +} MI_DISP_PubAttr_t; + +typedef struct MI_DISP_CompressAttr_s +{ + MI_BOOL bSupportCompress; /* Whether to support compress */ +} MI_DISP_CompressAttr_t; + +typedef struct MI_DISP_VidWin_Rect_s +{ + MI_U16 u16X; + MI_U16 u16Y; + MI_U16 u16Width; + MI_U16 u16Height; +} MI_DISP_VidWinRect_t; + +typedef struct MI_DISP_VideoLayerSize_s +{ + MI_U32 u16Width; + MI_U32 u16Height; +} MI_DISP_VideoLayerSize_t; + +typedef struct MI_DISP_VideoLayerAttr_s +{ + MI_DISP_VidWinRect_t stVidLayerDispWin; /* Display resolution */ +// TODO: dev + MI_DISP_VideoLayerSize_t stVidLayerSize; /* Canvas size of the video layer */ + // TODO: Tommy delete pixel format & doc + MI_SYS_PixelFormat_e ePixFormat; /* Pixel format of the video layer */ +} MI_DISP_VideoLayerAttr_t; + +typedef struct MI_DISP_Csc_s +{ + MI_DISP_CscMattrix_e eCscMatrix; + MI_U32 u32Luma; /* luminance: 0 ~ 100 default: 50 */ + MI_U32 u32Contrast; /* contrast : 0 ~ 100 default: 50 */ + MI_U32 u32Hue; /* hue : 0 ~ 100 default: 50 */ + MI_U32 u32Saturation; /* saturation: 0 ~ 100 default: 40 */ +} MI_DISP_Csc_t; + +typedef struct MI_DISP_VideoFrame_s +{ + MI_U32 u32Width; + MI_U32 u32Height; + MI_SYS_PixelFormat_e ePixelFormat; + MI_PHY aphyAddr; + void * pavirAddr; + MI_U64 u64pts; + MI_U32 u32PrivateData; + MI_U32 u32Size; + MI_U32 u32Stride; +} MI_DISP_VideoFrame_t; +/* General Operation of InputPort */ +typedef struct MI_DISP_InputPortAttr_s +{ + MI_DISP_VidWinRect_t stDispWin; /* rect of video out chn */ + MI_U16 u16SrcWidth; + MI_U16 u16SrcHeight; +} MI_DISP_InputPortAttr_t; +typedef struct MI_DISP_Position_s +{ + MI_U16 u16X; + MI_U16 u16Y; +} MI_DISP_Position_t; + +typedef struct MI_DISP_QueryChannelStatus_s +{ + MI_BOOL bEnable; + MI_DISP_InputPortStatus_e eStatus; +} MI_DISP_QueryChannelStatus_t; + +typedef struct MI_DISP_VgaParam_s +{ + MI_DISP_Csc_t stCsc; /* color space */ + MI_U32 u32Gain; /* current gain of VGA signals. [0, 64). default:0x30 */ + MI_U32 u32Sharpness; +} MI_DISP_VgaParam_t; + +typedef struct MI_DISP_HdmiParam_s +{ + MI_DISP_Csc_t stCsc; /* color space */ + MI_U32 u32Gain; /* current gain of HDMI signals. [0, 64). default:0x30 */ + MI_U32 u32Sharpness; +} MI_DISP_HdmiParam_t; + +typedef struct MI_DISP_LcdParam_s +{ + MI_DISP_Csc_t stCsc; /* color space */ + MI_U32 u32Sharpness; +} MI_DISP_LcdParam_t; + +typedef struct MI_DISP_CvbsParam_s +{ + MI_BOOL bEnable; +} MI_DISP_CvbsParam_t; + + +typedef struct MI_DISP_RotateConfig_s +{ + MI_DISP_RotateMode_e eRotateMode; +}MI_DISP_RotateConfig_t; + +typedef struct +{ + MI_U16 u16RedOffset; + MI_U16 u16GreenOffset; + MI_U16 u16BlueOffset; + + MI_U16 u16RedColor; // 00~FF, 0x80 is no change + MI_U16 u16GreenColor;// 00~FF, 0x80 is no change + MI_U16 u16BlueColor; // 00~FF, 0x80 is no change +}MI_DISP_ColorTemperature_t; + +typedef struct +{ + MI_BOOL bEn; + MI_U16 u16EntryNum; + MI_U8 *pu8ColorR; + MI_U8 *pu8ColorG; + MI_U8 *pu8ColorB; +}MI_DISP_GammaParam_t; + +typedef struct MI_DISP_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_DISP_InitParam_t; + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif///_MI_DISP_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_divp.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_divp.h new file mode 100644 index 000000000..4873e4a89 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_divp.h @@ -0,0 +1,158 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_DIVP_H_ +#define _MI_DIVP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mi_divp_datatype.h" + +#define DIVP_MAJOR_VERSION 2 +#define DIVP_SUB_VERSION 4 +#define MACRO_TO_STR(macro) #macro +#define DIVP_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_divp_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_divp_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_divp_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_DIVP_API_VERSION DIVP_VERSION_STR(DIVP_MAJOR_VERSION,DIVP_SUB_VERSION) + +//------------------------------------------------------------------------------ +/// @brief create a DIVP channel. +/// @param[out] pDivpChn: DIVP channel ID. +/// @param[in] pstAttr: Attribute of DIVP channel. +/// @return MI_SUCCESS: succeed in creating a channel. +/// MI_DIVP_ERR_INVALID_PARAM: invalid input patamter. +/// MI_DIVP_ERR_NULL_PTR: NULL poiter error. +/// MI_DIVP_ERR_FAILED: Fail to create a channel. +/// MI_DIVP_ERR_NO_RESOUCE: there is no resource. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_CreateChn (MI_DIVP_CHN DivpChn, MI_DIVP_ChnAttr_t* pstAttr); + +//------------------------------------------------------------------------------ +/// @brief deatroy a DIVP channel. +/// @param[in] DivpChn: DIVP channel ID. +/// @return MI_SUCCESS: succeed in deatroying a DIVP channel. +/// MI_DIVP_ERR_INVALID_CHNID: Invalid channel ID. +/// MI_DIVP_ERR_FAILED: Fail to deatroy a DIVP channel. +/// MI_DIVP_ERR_CHN_BUSY:channel is busy. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_DestroyChn(MI_DIVP_CHN DivpChn); + +//------------------------------------------------------------------------------ +/// @brief set attribute of DIVP channel. +/// @param[in] DivpChn: DIVP channel ID. +/// @param[in] pstAttr: Attribute of DIVP channel. +/// @return MI_SUCCESS: succeed in setting attribute of DIVP channel. +/// MI_DIVP_ERR_INVALID_CHNID: Invalid channel ID. +/// MI_DIVP_ERR_INVALID_PARAM: Invalid input patamter. +/// MI_DIVP_ERR_NULL_PTR: NULL poiter error. +/// MI_DIVP_ERR_CHN_NOT_SUPPORT: not support. +/// MI_DIVP_ERR_FAILED: Fail to set attribute of DIVP channel. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_SetChnAttr(MI_DIVP_CHN DivpChn, MI_DIVP_ChnAttr_t* pstAttr); + +//------------------------------------------------------------------------------ +/// @brief get attribute of DIVP channel. +/// @param[in] DivpChn: DIVP channel ID. +/// @param[in] pstAttr: Attribute of DIVP channel. +/// @return MI_SUCCESS: succeed in getting attribute of DIVP channel. +/// MI_DIVP_ERR_INVALID_CHNID: Invalid channel ID. +/// MI_DIVP_ERR_NULL_PTR: NULL poiter error. +/// MI_DIVP_ERR_FAILED: Fail to get attribute of DIVP channel. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_GetChnAttr(MI_DIVP_CHN DivpChn, MI_DIVP_ChnAttr_t* pstAttr); + +//------------------------------------------------------------------------------ +/// @brief start a DIVP channel. +/// @param[in] DivpChn: DIVP channel ID. +/// @return MI_SUCCESS: succeed in starting a DIVP channel. +/// MI_DIVP_ERR_INVALID_CHNID: Invalid channel ID. +/// MI_DIVP_ERR_FAILED: Fail to start a DIVP channel. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_StartChn(MI_DIVP_CHN DivpChn); + +//------------------------------------------------------------------------------ +/// @brief stop a DIVP channel. +/// @param[in] DivpChn: DIVP channel ID. +/// @return MI_SUCCESS: succeed in stopping a DIVP channel. +/// MI_DIVP_ERR_INVALID_CHNID: Invalid channel ID. +/// MI_DIVP_ERR_FAILED: Fail to stop a DIVP channel. +/// MI_DIVP_ERR_CHN_BUSY:channel is busy. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_StopChn(MI_DIVP_CHN DivpChn); + +//------------------------------------------------------------------------------ +/// @brief set attribute of DIVP channel output port. +/// @param[in] DivpChn: DIVP channel ID. +/// @param[in] pstOutputPortAttr: DIVP channel output port attribute. +/// @return MI_SUCCESS: succeed in setting attribute of DIVP channel output port. +/// MI_DIVP_ERR_INVALID_CHNID: Invalid channel ID. +/// MI_DIVP_ERR_INVALID_PARAM: Invalid input patamter. +/// MI_DIVP_ERR_NULL_PTR: NULL poiter error. +/// MI_DIVP_ERR_FAILED: Fail to set attribute of DIVP channel output port. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_SetOutputPortAttr (MI_DIVP_CHN DivpChn, MI_DIVP_OutputPortAttr_t * pstOutputPortAttr); + +//------------------------------------------------------------------------------ +/// @brief get attribute of DIVP channel output port. +/// @param[in] DivpChn: DIVP channel ID. +/// @param[out] pstOutputPortAttr: DIVP channel output port attribute. +/// @return MI_SUCCESS: succeed in getting attribute of DIVP channel output port. +/// MI_DIVP_ERR_FAILED: Fail to get attribute of DIVP channel output port. +/// MI_DIVP_ERR_INVALID_CHNID: Invalid channel ID. +/// MI_DIVP_ERR_NULL_PTR: NULL poiter error. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_GetOutputPortAttr (MI_DIVP_CHN DivpChn, MI_DIVP_OutputPortAttr_t * pstOutputPortAttr); + +//------------------------------------------------------------------------------ +/// @brief refresh a DIVP channel. +/// @param[in] DivpChn: DIVP channel ID. +/// @return MI_SUCCESS: succeed in refreshing a DIVP channel. +/// MI_DIVP_ERR_INVALID_CHNID: Invalid channel ID. +/// MI_DIVP_ERR_FAILED: Fail to refresh a DIVP channel. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_RefreshChn(MI_DIVP_CHN DivpChn); + +//------------------------------------------------------------------------------ +/// @brief stretch or crop image in specified memory to target memory +/// @param[in] pstSrcBuf: source buff info pointer +/// @param[in] pstSrcCrop: crop info pointer +/// @param[in] pstDstBuf: dest buff info pointer +/// @return MI_SUCCESS: succeed in stretching image +/// MI_DIVP_ERR_FAILED: Fail to stretch image +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_StretchBuf(MI_DIVP_DirectBuf_t *pstSrcBuf, MI_SYS_WindowRect_t *pstSrcCrop, MI_DIVP_DirectBuf_t *pstDstBuf); + +//------------------------------------------------------------------------------ +/// @brief Init DIVP module. +/// @return MI_SUCCESS: succeed in Init DIVP module. +/// MI_DIVP_ERR_FAILED: Fail to Init DIVP module. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_InitDev(MI_DIVP_InitParam_t *pstInitParam); + +//------------------------------------------------------------------------------ +/// @brief DeInit DIVP module. +/// @return MI_SUCCESS: succeed in DeInit DIVP module. +/// MI_DIVP_ERR_FAILED: Fail to DeInit DIVP module. +//------------------------------------------------------------------------------ +MI_S32 MI_DIVP_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_divp_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_divp_datatype.h new file mode 100644 index 000000000..ff53d35e4 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_divp_datatype.h @@ -0,0 +1,86 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_DIVP_DATATYPE_H_ +#define _MI_DIVP_DATATYPE_H_ +#pragma pack(push) +#pragma pack(4) + +#define MI_DIVP_ERR_INVALID_DEVID (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_DEVID)) +#define MI_DIVP_ERR_INVALID_CHNID (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_CHNID)) +#define MI_DIVP_ERR_INVALID_PARAM (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_ILLEGAL_PARAM)) +#define MI_DIVP_ERR_NULL_PTR (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NULL_PTR)) +#define MI_DIVP_ERR_FAILED (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_FAILED)) +#define MI_DIVP_ERR_CHN_NOT_STARTED (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_CHN_NOT_STARTED)) +#define MI_DIVP_ERR_CHN_NOT_STOPED (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_CHN_NOT_STOPED)) +#define MI_DIVP_ERR_CHN_NOT_SUPPORT (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_SUPPORT)) +#define MI_DIVP_ERR_NO_RESOUCE (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_UNEXIST)) +#define MI_DIVP_ERR_CHN_BUSY (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUSY)) +#define MI_DIVP_ERR_HAS_CREATED (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_EXIST)) +#define MI_DIVP_ERR_NO_CONTENT (MI_DEF_ERR( E_MI_MODULE_ID_DIVP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_CHN_NO_CONTENT)) + +typedef enum +{ + E_MI_DIVP_DI_TYPE_OFF,//off + E_MI_DIVP_DI_TYPE_2D,///2.5D DI + E_MI_DIVP_DI_TYPE_3D,///3D DI + E_MI_DIVP_DI_TYPE_NUM, +} MI_DIVP_DiType_e; + +typedef enum +{ + E_MI_DIVP_TNR_LEVEL_OFF, + E_MI_DIVP_TNR_LEVEL_LOW, + E_MI_DIVP_TNR_LEVEL_MIDDLE, + E_MI_DIVP_TNR_LEVEL_HIGH, + E_MI_DIVP_TNR_LEVEL_NUM, +} MI_DIVP_TnrLevel_e; + +typedef struct MI_DIVP_OutputPortAttr_s +{ + MI_U32 u32Width;//output width + MI_U32 u32Height;//output height + MI_SYS_PixelFormat_e ePixelFormat;//output pixel format + MI_SYS_CompressMode_e eCompMode;//compress mode +}MI_DIVP_OutputPortAttr_t; + +typedef struct MI_DIVP_ChnAttr_s +{ + MI_U32 u32MaxWidth;//support max input width + MI_U32 u32MaxHeight;//support max input height + MI_DIVP_TnrLevel_e eTnrLevel;//TNR level + MI_DIVP_DiType_e eDiType;//DI type + MI_SYS_Rotate_e eRotateType;//rotate angle + MI_SYS_WindowRect_t stCropRect;//crop information + MI_BOOL bHorMirror;//horizontal mirror + MI_BOOL bVerMirror;//vertical mirror +}MI_DIVP_ChnAttr_t; + +typedef struct MI_DIVP_DirectBuf_s +{ + MI_SYS_PixelFormat_e ePixelFormat; //YUV420SP or ARGB888 only + MI_U32 u32Width; + MI_U32 u32Height; + MI_U32 u32Stride[3]; + MI_PHY phyAddr[3]; +}MI_DIVP_DirectBuf_t; + +typedef struct MI_DIVP_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_DIVP_InitParam_t; + +#pragma pack(pop) +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gfx.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gfx.h new file mode 100644 index 000000000..45c424541 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gfx.h @@ -0,0 +1,87 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_GFX_H_ +#define _MI_GFX_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "mi_common.h" +#include "mi_gfx_datatype.h" + +#define GFX_MAJOR_VERSION 2 +#define GFX_SUB_VERSION 7 +#define MACRO_TO_STR(macro) #macro +#define GFX_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_gfx_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_gfx_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_gfx_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_GFX_API_VERSION GFX_VERSION_STR(GFX_MAJOR_VERSION,GFX_SUB_VERSION) + +/*------------------------------------------------------------------------------------------- + * Global Functions +-------------------------------------------------------------------------------------------*/ + +MI_S32 MI_GFX_Open(void); +MI_S32 MI_GFX_Close(void); +MI_S32 MI_GFX_WaitAllDone(MI_BOOL bWaitAllDone, MI_U16 u16TargetFence); + +//------------------------------------------------------------------------------------------------- +/// Fill Rect +/// @param pstDst \b IN: Target Surface info +/// @param pstDstRect \b IN: Target Rect info +/// @param u32ColorVal \b IN: Color to fill +/// For all RGB color, the color set as the ARGB8888 format.\n +/// Each color component need to shift to high bit.\n +/// Use ARGB1555 as the example, the source color key as the following:\n +/// ARGB1555 --> ARRRRRGGGGGBBBBB (every character represents one bit)\n +/// For I8 format, the index set to b component\n +/// @param pu16Fence \b OUT: wait fence +/// @return MI_SUCCESS - Success +/// @return OTHER - Failure +//------------------------------------------------------------------------------------------------ +MI_S32 MI_GFX_QuickFill(MI_GFX_Surface_t *pstDst, MI_GFX_Rect_t *pstDstRect, + MI_U32 u32ColorVal, MI_U16 *pu16Fence); + +//------------------------------------------------------------------------------------------------- +/// Draw line +/// @param pstDst \b IN: Target Surface info +/// @param pstLine \b IN: Line pattern info +/// @param pu16Fence \b OUT: wait fence +/// @return MI_SUCCESS - Success +/// @return OTHER - Failure +//------------------------------------------------------------------------------------------------- +MI_S32 MI_GFX_DrawLine(MI_GFX_Surface_t *pstDst, MI_GFX_Line_t *pstLine, MI_U16 *pu16Fence); + +MI_S32 MI_GFX_GetAlphaThresholdValue(MI_U8 *pu8ThresholdValue); +MI_S32 MI_GFX_SetAlphaThresholdValue(MI_U8 u8ThresholdValue); +MI_S32 MI_GFX_BitBlit(MI_GFX_Surface_t *pstSrc, MI_GFX_Rect_t *pstSrcRect, + MI_GFX_Surface_t *pstDst, MI_GFX_Rect_t *pstDstRect, MI_GFX_Opt_t *pstOpt, MI_U16 *pu16Fence); +//------------------------------------------------------------------------------------------------- +/// Set Palette for Index Color format(I2/I4/I8) +/// @param eColorFmt \b IN: Index Color format(I2/I4/I8) +/// @param pstPalette \b IN: RGB color data array for corresponding Index Color +/// @return MI_SUCCESS - Success +/// @return OTHER - Failure,refer to error code +//------------------------------------------------------------------------------------------------ +MI_S32 MI_GFX_SetPalette(MI_GFX_ColorFmt_e eColorFmt, MI_GFX_Palette_t* pstPalette); + +MI_S32 MI_GFX_InitDev(MI_GFX_InitParam_t *pstInitParam); +MI_S32 MI_GFX_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif //_MI_GFX_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gfx_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gfx_datatype.h new file mode 100644 index 000000000..6c8ec16b6 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gfx_datatype.h @@ -0,0 +1,262 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_GFX_DATATYPE_H_ +#define _MI_GFX_DATATYPE_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include "mi_common.h" +#include "mi_gfx_datatype.h" + +typedef enum +{ + E_MI_GFX_FMT_I1 = 0, /* MS_ColorFormat */ + E_MI_GFX_FMT_I2, + E_MI_GFX_FMT_I4, + E_MI_GFX_FMT_I8, + E_MI_GFX_FMT_FABAFGBG2266, + E_MI_GFX_FMT_1ABFGBG12355, + E_MI_GFX_FMT_RGB565, + E_MI_GFX_FMT_ARGB1555, + E_MI_GFX_FMT_ARGB4444, + E_MI_GFX_FMT_ARGB1555_DST, + E_MI_GFX_FMT_YUV422, + E_MI_GFX_FMT_ARGB8888, + E_MI_GFX_FMT_RGBA5551, + E_MI_GFX_FMT_RGBA4444, + E_MI_GFX_FMT_ABGR8888, + E_MI_GFX_FMT_BGRA5551, + E_MI_GFX_FMT_ABGR1555, + E_MI_GFX_FMT_ABGR4444, + E_MI_GFX_FMT_BGRA4444, + E_MI_GFX_FMT_BGR565, + E_MI_GFX_FMT_RGBA8888, + E_MI_GFX_FMT_BGRA8888, + E_MI_GFX_FMT_MAX +} MI_GFX_ColorFmt_e; + +typedef enum +{ + E_MI_GFX_RGB_OP_EQUAL = 0, + E_MI_GFX_RGB_OP_NOT_EQUAL, + E_MI_GFX_ALPHA_OP_EQUAL, + E_MI_GFX_ALPHA_OP_NOT_EQUAL, + E_MI_GFX_ARGB_OP_EQUAL, + E_MI_GFX_ARGB_OP_NOT_EQUAL, + E_MI_GFX_CKEY_OP_MAX, +} MI_GFX_ColorKeyOp_e; + +typedef enum +{ + E_MI_GFX_DFB_BLD_ZERO = 0, + E_MI_GFX_DFB_BLD_ONE, + E_MI_GFX_DFB_BLD_SRCCOLOR, + E_MI_GFX_DFB_BLD_INVSRCCOLOR, + E_MI_GFX_DFB_BLD_SRCALPHA, + E_MI_GFX_DFB_BLD_INVSRCALPHA, + E_MI_GFX_DFB_BLD_DESTALPHA, + E_MI_GFX_DFB_BLD_INVDESTALPHA, + E_MI_GFX_DFB_BLD_DESTCOLOR, + E_MI_GFX_DFB_BLD_INVDESTCOLOR, + E_MI_GFX_DFB_BLD_SRCALPHASAT, + E_MI_GFX_DFB_BLD_MAX, +} MI_GFX_DfbBldOp_e; + +typedef enum +{ + E_MI_GFX_MIRROR_NONE = 0, + E_MI_GFX_MIRROR_HORIZONTAL, + E_MI_GFX_MIRROR_VERTICAL, + E_MI_GFX_MIRROR_BOTH, + E_MI_GFX_MIRROR_MAX +} MI_GFX_Mirror_e; + +typedef enum +{ + E_MI_GFX_ROTATE_0 = 0, + E_MI_GFX_ROTATE_90, + E_MI_GFX_ROTATE_180, + E_MI_GFX_ROTATE_270, + E_MI_GFX_ROTATE_MAX +} MI_GFX_Rotate_e; + +typedef enum +{ + E_MI_GFX_ERR_NOT_INIT = MI_GFX_INITIAL_ERROR_CODE, + E_MI_GFX_ERR_GFX_DRV_NOT_SUPPORT, + E_MI_GFX_ERR_GFX_DRV_FAIL_FORMAT, + E_MI_GFX_ERR_GFX_NON_ALIGN_ADDRESS, + E_MI_GFX_ERR_GFX_NON_ALIGN_PITCH, + E_MI_GFX_ERR_GFX_DRV_FAIL_OVERLAP, + E_MI_GFX_ERR_GFX_DRV_FAIL_STRETCH, + E_MI_GFX_ERR_GFX_DRV_FAIL_ITALIC, + E_MI_GFX_ERR_GFX_DRV_FAIL_LOCKED, + E_MI_GFX_ERR_GFX_DRV_FAIL_BLTADDR, + E_MI_GFX_ERR_MAX +} MI_GFX_ErrCode_e; + + +/* GFX Module ErrorCode */ +#define MI_ERR_GFX_INVALID_PARAM MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_ILLEGAL_PARAM) +#define MI_ERR_GFX_INVALID_DEVID MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_DEVID) +#define MI_ERR_GFX_DEV_BUSY MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUSY) + +#define MI_ERR_GFX_NOT_INIT MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_NOT_INIT) +#define MI_ERR_GFX_DRV_NOT_SUPPORT MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_DRV_NOT_SUPPORT) +#define MI_ERR_GFX_DRV_FAIL_FORMAT MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_DRV_FAIL_FORMAT) +#define MI_ERR_GFX_NON_ALIGN_ADDRESS MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_NON_ALIGN_ADDRESS) +#define MI_ERR_GFX_NON_ALIGN_PITCH MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_NON_ALIGN_PITCH) +#define MI_ERR_GFX_DRV_FAIL_OVERLAP MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_DRV_FAIL_OVERLAP) +#define MI_ERR_GFX_DRV_FAIL_STRETCH MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_DRV_FAIL_STRETCH) +#define MI_ERR_GFX_DRV_FAIL_ITALIC MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_DRV_FAIL_ITALIC) +#define MI_ERR_GFX_DRV_FAIL_LOCKED MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_DRV_FAIL_LOCKED) +#define MI_ERR_GFX_DRV_FAIL_BLTADDR MI_DEF_ERR(E_MI_MODULE_ID_GFX, E_MI_ERR_LEVEL_ERROR, E_MI_GFX_ERR_GFX_DRV_FAIL_BLTADDR) + +//============================================================================= +// GFX point +//============================================================================= +typedef struct MI_GFX_Point_s +{ + /// x coordinate + MI_S16 s16x; + /// y coordinate + MI_S16 s16y; +} MI_GFX_Point_t; + +typedef struct MI_GFX_Rect_s +{ + MI_S32 s32Xpos; + MI_S32 s32Ypos; + MI_U32 u32Width; + MI_U32 u32Height; +} MI_GFX_Rect_t; + +//============================================================================= +// GFX line pattern infomation struct +//============================================================================= +typedef struct MI_GFX_Line_s +{ + /// start point of line + MI_GFX_Point_t stPointFrom; + /// end point of line + MI_GFX_Point_t stPointTo; + /// line width in pixel + MI_U16 u16Width; + /// Constant color or Gradient color + MI_BOOL bColorGradient; + /// color range from start to end + MI_U32 u32ColorFrom; + /// + MI_U32 u32ColorTo; +} MI_GFX_Line_t; + + +//============================================================================= +// GFX palette information +//============================================================================= + +typedef union +{ + /// ARGB8888 byte order + struct + { + MI_U8 u8A; + MI_U8 u8R; + MI_U8 u8G; + MI_U8 u8B; + } RGB; + // u8Data[0] = u8A + // u8Data[1] = u8R + // u8Data[2] = u8G + // u8Data[3] = u8B + MI_U8 u8Data[4]; +} MI_GFX_PaletteEntry_t; + +typedef struct MI_GFX_Palette_s +{ + /// array subscripts are indentical to value of Index Color + MI_GFX_PaletteEntry_t aunPalette[256]; + /// Starting Index in palette to config + MI_U16 u16PalStart; + /// Ending Index in palette to config + MI_U16 u16PalEnd; +}MI_GFX_Palette_t; + + +typedef struct MI_GFX_ColorKey_s +{ + MI_U32 u32ColorStart; + MI_U32 u32ColorEnd; +} MI_GFX_ColorKeyValue_t; + + +typedef struct MI_GFX_ColorKeyInfo_s +{ + MI_BOOL bEnColorKey; + MI_GFX_ColorKeyOp_e eCKeyOp; + MI_GFX_ColorFmt_e eCKeyFmt; + MI_GFX_ColorKeyValue_t stCKeyVal; +} MI_GFX_ColorKeyInfo_t; + +typedef struct MI_GFX_Surface_s +{ + MI_PHY phyAddr; + MI_GFX_ColorFmt_e eColorFmt; + MI_U32 u32Width; + MI_U32 u32Height; + MI_U32 u32Stride; +} MI_GFX_Surface_t; + +typedef enum +{ + E_MI_GFX_DFB_BLEND_NOFX = 0x00000000, + E_MI_GFX_DFB_BLEND_COLORALPHA = 0x00000001, + E_MI_GFX_DFB_BLEND_ALPHACHANNEL = 0x00000002, + E_MI_GFX_DFB_BLEND_COLORIZE = 0x00000004, + E_MI_GFX_DFB_BLEND_SRC_PREMULTIPLY = 0x00000008, + E_MI_GFX_DFB_BLEND_SRC_PREMULTCOLOR = 0x00000010, + E_MI_GFX_DFB_BLEND_DST_PREMULTIPLY = 0x00000020, + E_MI_GFX_DFB_BLEND_XOR = 0x00000040, + E_MI_GFX_DFB_BLEND_DEMULTIPLY = 0x00000080, + E_MI_GFX_DFB_BLEND_SRC_COLORKEY = 0x00000100, + E_MI_GFX_DFB_BLEND_DST_COLORKEY = 0x00000200, + E_MI_GFX_DFB_BLEND_MAX = 0x3FF +} MI_Gfx_DfbBlendFlags_e; + +typedef struct MI_GFX_Opt_s +{ + MI_GFX_Rect_t stClipRect; + MI_GFX_ColorKeyInfo_t stSrcColorKeyInfo; + MI_GFX_ColorKeyInfo_t stDstColorKeyInfo; + MI_GFX_DfbBldOp_e eSrcDfbBldOp; + MI_GFX_DfbBldOp_e eDstDfbBldOp; + MI_GFX_Mirror_e eMirror; + MI_GFX_Rotate_e eRotate; + MI_Gfx_DfbBlendFlags_e eDFBBlendFlag; + MI_U32 u32GlobalSrcConstColor; + MI_U32 u32GlobalDstConstColor; +} MI_GFX_Opt_t; + +typedef struct MI_GFX_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_GFX_InitParam_t; + +#ifdef __cplusplus +} +#endif + +#endif///_MI_GFX_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gyro.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gyro.h new file mode 100644 index 000000000..31362d886 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gyro.h @@ -0,0 +1,51 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_GYRO_H_ +#define _MI_GYRO_H_ +#ifdef __cplusplus +extern "C" { +#endif + + +#include "mi_gyro_datatype.h" + +int GyroSensor_SetSampleRateDiv(MI_U8 u8DevId, MI_U8 u8Div); + +int GyroSensor_SetGyroRange(MI_U8 u8DevId, GyroSensorGyroRange_e eFullScaleRange); +int GyroSensor_GetGyroRange(MI_U8 u8DevId, GyroSensorGyroRange_e *peFullScaleRange); +int GyroSensor_GetGyroSensitivity(MI_U8 u8DevId, MI_U16 *pu16SensitivityDen, MI_U16 *pu16SensitivityMol); +//pu16SensitivityDen+pu16SensitivityMol/1000 +int GyroSensor_ReadGyro_XYZ(MI_U8 u8DevId, MI_S16 *ps16X, MI_S16 *ps16Y, MI_S16 *ps16Z); + +int GyroSensor_SetAccelRange(MI_U8 u8DevId, GyroSensorAccelRange_e eFullScaleRange); +int GyroSensor_GetAccelRange(MI_U8 u8DevId, GyroSensorAccelRange_e *peFullScaleRange); +int GyroSensor_GetAccelSensitivity(MI_U8 u8DevId, MI_U16 *pu16SensitivityDen, MI_U16 *pu16SensitivityMol); +//pu16SensitivityDen+pu16SensitivityMol/1000 +int GyroSensor_ReadAccel_XYZ(MI_U8 u8DevId, MI_S16 *ps16X, MI_S16 *ps16Y, MI_S16 *ps16Z); + +int GyroSensor_ReadTemp(MI_U8 u8DevId, MI_S16 *s16Temp); + +int GyroSensor_EnableDev(MI_U8 u8DevId, MI_BOOL bEnFifoMode, MI_U8 u8FifoModeType); +int GyroSensor_ReadFifoData(MI_U8 u8DevId, MI_U16 *pu16FifoCnt, MI_U8 *pu8Data); + +MI_S32 MI_Gyro_InitDev(MI_Gyro_InitParam_t *pstInitParam); +MI_S32 MI_Gyro_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gyro_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gyro_datatype.h new file mode 100644 index 000000000..842e04407 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_gyro_datatype.h @@ -0,0 +1,62 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_GYRO_DATATYPE_H_ +#define _MI_GYRO_DATATYPE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define FIFO_MAX_CNT (512) + +typedef enum +{ + E_GYROSENSOR_ALL_ACCEL_FIFO_EN = 0x08, + E_GYROSENSOR_ZG_FIFO_EN = 0x10, + E_GYROSENSOR_YG_FIFO_EN = 0x20, + E_GYROSENSOR_XG_FIFO_EN = 0x40, + E_GYROSENSOR_TEMP_FIFO_EN = 0x80, + E_GYROSENSOR_FIFO_MAX_EN = 0xFF, +}GyroSensorEnFifoMode_e; + +typedef enum +{ + E_GYROSENSOR_GYRO_RANGE_125 =0x00, + E_GYROSENSOR_GYRO_RANGE_250 =0x08, + E_GYROSENSOR_GYRO_RANGE_500 =0x10, + E_GYROSENSOR_GYRO_RANGE_MASK =0x18, +}GyroSensorGyroRange_e; + +typedef enum +{ + E_GYROSENSOR_ACCEL_RANGE_2G =0x00, + E_GYROSENSOR_ACCEL_RANGE_4G =0x08, + E_GYROSENSOR_ACCEL_RANGE_8G =0x10, + E_GYROSENSOR_ACCEL_RANGE_16G =0x18, +}GyroSensorAccelRange_e; + +typedef struct MI_Gyro_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_Gyro_InitParam_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_hdmi.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_hdmi.h new file mode 100644 index 000000000..e9b015b12 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_hdmi.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_HDMI_H_ +#define _MI_HDMI_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "mi_common.h" +#include "mi_hdmi_datatype.h" + +#define HDMI_MAJOR_VERSION 2 +#define HDMI_SUB_VERSION 3 +#define MACRO_TO_STR(macro) #macro +#define HDMI_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_hdmi_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_hdmi_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_hdmi_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_HDMI_API_VERSION HDMI_VERSION_STR(HDMI_MAJOR_VERSION,HDMI_SUB_VERSION) + +MI_S32 MI_HDMI_Init(MI_HDMI_InitParam_t *pstInitParam); +MI_S32 MI_HDMI_DeInit(void); +MI_S32 MI_HDMI_Open(MI_HDMI_DeviceId_e eHdmi); +MI_S32 MI_HDMI_Close(MI_HDMI_DeviceId_e eHdmi); +MI_S32 MI_HDMI_SetAttr(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_Attr_t *pstAttr); +MI_S32 MI_HDMI_GetAttr(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_Attr_t *pstAttr); +MI_S32 MI_HDMI_Start(MI_HDMI_DeviceId_e eHdmi); +MI_S32 MI_HDMI_Stop(MI_HDMI_DeviceId_e eHdmi); +MI_S32 MI_HDMI_GetSinkInfo(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_SinkInfo_t *pstSinkInfo); +MI_S32 MI_HDMI_SetAvMute(MI_HDMI_DeviceId_e eHdmi, MI_BOOL bAvMute); +MI_S32 MI_HDMI_ForceGetEdid(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_Edid_t *pstEdidData); +MI_S32 MI_HDMI_SetDeepColor(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_DeepColor_e eDeepColor); +MI_S32 MI_HDMI_GetDeepColor(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_DeepColor_e *peDeepColor); +MI_S32 MI_HDMI_SetInfoFrame(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_InfoFrame_t *pstInfoFrame); +MI_S32 MI_HDMI_GetInfoFrame(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_InfoFrameType_e eInfoFrameType, + MI_HDMI_InfoFrame_t *pstInfoFrame); +MI_S32 MI_HDMI_SetAnalogDrvCurrent(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_AnalogDrvCurrent_t *pstAnalogDrvCurrent); +MI_S32 MI_HDMI_InitDev(MI_HDMI_InitParam_t *pstInitParam); +MI_S32 MI_HDMI_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif ///_MI_HDMI_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_hdmi_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_hdmi_datatype.h new file mode 100644 index 000000000..51a2ad41a --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_hdmi_datatype.h @@ -0,0 +1,412 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_HDMI_DATATYPE_H_ +#define _MI_HDMI_DATATYPE_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "mi_common.h" + +/*------------------------------------------------------------------------------------------------- + * Enum + ------------------------------------------------------------------------------------------------*/ +typedef enum +{ + E_MI_HDMI_ID_0 = 0, + E_MI_HDMI_ID_MAX +} MI_HDMI_DeviceId_e; + +typedef enum +{ + E_MI_HDMI_EVENT_HOTPLUG = 0, + E_MI_HDMI_EVENT_NO_PLUG, + E_MI_HDMI_EVENT_MAX +} MI_HDMI_EventType_e; + +typedef enum +{ + E_MI_HDMI_TIMING_480_60I = 0, + E_MI_HDMI_TIMING_480_60P = 1, + E_MI_HDMI_TIMING_576_50I = 2, + E_MI_HDMI_TIMING_576_50P = 3, + E_MI_HDMI_TIMING_720_50P = 4, + E_MI_HDMI_TIMING_720_60P = 5, + E_MI_HDMI_TIMING_1080_50I = 6, + E_MI_HDMI_TIMING_1080_50P = 7, + E_MI_HDMI_TIMING_1080_60I = 8, + E_MI_HDMI_TIMING_1080_60P = 9, + E_MI_HDMI_TIMING_1080_30P = 10, + E_MI_HDMI_TIMING_1080_25P = 11, + E_MI_HDMI_TIMING_1080_24P = 12, + E_MI_HDMI_TIMING_4K2K_30P = 13, + E_MI_HDMI_TIMING_1440_50P = 14, + E_MI_HDMI_TIMING_1440_60P = 15, + E_MI_HDMI_TIMING_1440_24P = 16, + E_MI_HDMI_TIMING_1440_30P = 17, + E_MI_HDMI_TIMING_1470_50P = 18, + E_MI_HDMI_TIMING_1470_60P = 19, + E_MI_HDMI_TIMING_1470_24P = 20, + E_MI_HDMI_TIMING_1470_30P = 21, + E_MI_HDMI_TIMING_1920x2205_24P = 22, + E_MI_HDMI_TIMING_1920x2205_30P = 23, + E_MI_HDMI_TIMING_4K2K_25P = 24, + E_MI_HDMI_TIMING_4K1K_60P = 25, + E_MI_HDMI_TIMING_4K2K_60P = 26, + E_MI_HDMI_TIMING_4K2K_24P = 27, + E_MI_HDMI_TIMING_4K2K_50P = 28, + E_MI_HDMI_TIMING_2205_24P = 29, + E_MI_HDMI_TIMING_4K1K_120P = 30, + E_MI_HDMI_TIMING_4096x2160_24P = 31, + E_MI_HDMI_TIMING_4096x2160_25P = 32, + E_MI_HDMI_TIMING_4096x2160_30P = 33, + E_MI_HDMI_TIMING_4096x2160_50P = 34, + E_MI_HDMI_TIMING_4096x2160_60P = 35, + E_MI_HDMI_TIMING_1024x768_60P = 36, + E_MI_HDMI_TIMING_1280x1024_60P = 37, + E_MI_HDMI_TIMING_1440x900_60P = 38, + E_MI_HDMI_TIMING_1600x1200_60P = 39, + E_MI_HDMI_TIMING_1280x800_60P = 40, + E_MI_HDMI_TIMING_1366x768_60P = 41, + E_MI_HDMI_TIMING_1680x1050_60P = 42, + E_MI_HDMI_TIMING_MAX, +} MI_HDMI_TimingType_e; + +typedef enum +{ + E_MI_HDMI_COLOR_TYPE_RGB444 = 0, + E_MI_HDMI_COLOR_TYPE_YCBCR422, + E_MI_HDMI_COLOR_TYPE_YCBCR444, + E_MI_HDMI_COLOR_TYPE_YCBCR420, + E_MI_HDMI_COLOR_TYPE_MAX +} MI_HDMI_ColorType_e; + +typedef enum +{ + E_MI_HDMI_OUTPUT_MODE_HDMI = 0, + E_MI_HDMI_OUTPUT_MODE_HDMI_HDCP, + E_MI_HDMI_OUTPUT_MODE_DVI, + E_MI_HDMI_OUTPUT_MODE_DVI_HDCP, + E_MI_HDMI_OUTPUT_MODE_MAX, +} MI_HDMI_OutputMode_e; + +typedef enum +{ + E_MI_HDMI_DEEP_COLOR_24BIT = 0, + E_MI_HDMI_DEEP_COLOR_30BIT, + E_MI_HDMI_DEEP_COLOR_36BIT, + E_MI_HDMI_DEEP_COLOR_48BIT, + E_MI_HDMI_DEEP_COLOR_MAX, +} MI_HDMI_DeepColor_e; + +typedef enum +{ + E_MI_HDMI_AUDIO_SAMPLERATE_UNKNOWN = 0, + E_MI_HDMI_AUDIO_SAMPLERATE_32K = 1, + E_MI_HDMI_AUDIO_SAMPLERATE_44K = 2, + E_MI_HDMI_AUDIO_SAMPLERATE_48K = 3, + E_MI_HDMI_AUDIO_SAMPLERATE_88K = 4, + E_MI_HDMI_AUDIO_SAMPLERATE_96K = 5, + E_MI_HDMI_AUDIO_SAMPLERATE_176K = 6, + E_MI_HDMI_AUDIO_SAMPLERATE_192K = 7, + E_MI_HDMI_AUDIO_SAMPLERATE_MAX, +} MI_HDMI_SampleRate_e; + +typedef enum +{ + E_MI_HDMI_BIT_DEPTH_8 = 8, + E_MI_HDMI_BIT_DEPTH_16 = 16, + E_MI_HDMI_BIT_DEPTH_18 = 18, + E_MI_HDMI_BIT_DEPTH_20 = 20, + E_MI_HDMI_BIT_DEPTH_24 = 24, + E_MI_HDMI_BIT_DEPTH_32 = 32, + E_MI_HDMI_BIT_DEPTH_MAX +} MI_HDMI_BitDepth_e; + +typedef enum +{ + E_MI_HDMI_ACODE_PCM = 0, + E_MI_HDMI_ACODE_NON_PCM, + E_MI_HDMI_ACODE_MAX +} MI_HDMI_AudioCodeType_e; + +typedef enum +{ + E_MI_HDMI_INFOFRAME_TYPE_AVI = 0, + E_MI_HDMI_INFOFRAME_TYPE_SPD, + E_MI_HDMI_INFOFRAME_TYPE_AUDIO, + E_MI_HDMI_INFOFRAME_TYPE_MAX +} MI_HDMI_InfoFrameType_e; + +typedef enum +{ + E_MI_HDMI_VIDEO_AFD_SameAsPictureAR = 8, // 1000 + E_MI_HDMI_VIDEO_AFD_4_3_Center = 9, // 1001 + E_MI_HDMI_VIDEO_AFD_16_9_Center = 10, // 1010 + E_MI_HDMI_VIDEO_AFD_14_9_Center = 11, // 1011 + E_MI_HDMI_VIDEO_AFD_Others = 15, // 0000~ 0111, 1100 ~ 1111 +} MI_HDMI_VideoAfdRatio_e; + +typedef enum +{ + E_MI_HDMI_AUDIO_CODING_REFER_STREAM_HEAD = 0, + E_MI_HDMI_AUDIO_CODING_PCM, + E_MI_HDMI_AUDIO_CODING_AC3, + E_MI_HDMI_AUDIO_CODING_MPEG1, + E_MI_HDMI_AUDIO_CODING_MP3, + E_MI_HDMI_AUDIO_CODING_MPEG2, + E_MI_HDMI_AUDIO_CODING_AAC, + E_MI_HDMI_AUDIO_CODING_DTS, + E_MI_HDMI_AUDIO_CODING_DDPLUS, + E_MI_HDMI_AUDIO_CODING_MLP, + E_MI_HDMI_AUDIO_CODING_WMA, + E_MI_HDMI_AUDIO_CODING_MAX +} MI_HDMI_AudioCodingType_e; + +typedef enum +{ + E_MI_HDMI_SCAN_INFO_NO_DATA = 0, /**< No Scan information*/ + E_MI_HDMI_SCAN_INFO_OVERSCANNED, /**< Scan information, Overscanned (for television) */ + E_MI_HDMI_SCAN_INFO_UNDERSCANNED, /**< Scan information, Underscanned (for computer) */ + E_MI_HDMI_SCAN_INFO_FUTURE, + E_MI_HDMI_SCAN_INFO_MAX +} MI_HDMI_ScanInfo_e; + +typedef enum +{ + E_MI_HDMI_COLORIMETRY_NO_DATA = 0, + E_MI_HDMI_COLORIMETRY_SMPTE170M, + E_MI_HDMI_COLORIMETRY_ITUR709, + E_MI_HDMI_COLORIMETRY_EXTEND, + E_MI_HDMI_COLORIMETRY_MAX, +} MI_HDMI_Colorimetry_e; + +typedef enum +{ + E_MI_HDMI_EXT_COLORIMETRY_XVYCC601 = 0, + E_MI_HDMI_EXT_COLORIMETRY_XVYCC709, + E_MI_HDMI_EXT_COLORIMETRY_SYCC601, + E_MI_HDMI_EXT_COLORIMETRY_ADOBEYCC601, + E_MI_HDMI_EXT_COLORIMETRY_ADOBERGB, + E_MI_HDMI_EXT_COLORIMETRY_BT2020CYCC, //mapping to ext. colorimetry format BT2020Y'cC'bcC'rc + E_MI_HDMI_EXT_COLORIMETRY_BT2020YCC, //mapping to ext. colorimetry format BT2020 RGB or YCbCr + E_MI_HDMI_EXT_COLORIMETRY_BT2020RGB, //mapping to ext. colorimetry format BT2020 RGB or YCbCr + E_MI_HDMI_EXT_COLORIMETRY_MAX, +} MI_HDMI_ExtColorimetry_e; + +typedef enum +{ + E_MI_HDMI_ASPECT_RATIO_INVALID = 0, /**< unknown aspect ratio */ + E_MI_HDMI_ASPECT_RATIO_4TO3, /**< 4:3 */ + E_MI_HDMI_ASPECT_RATIO_16TO9, /**< 16:9 */ + E_MI_HDMI_ASPECT_RATIO_21TO9, /**< 21:9 */ + E_MI_HDMI_ASPECT_RATIO_MAX +} MI_HDMI_AspectRatio_e; + +typedef enum +{ + E_MI_HDMI_YCC_QUANTIZATION_LIMITED_RANGE = 0, /**< Limited quantization range of 220 levels when receiving a CE video format*/ + E_MI_HDMI_YCC_QUANTIZATION_FULL_RANGE, /**< Full quantization range of 256 levels when receiving an IT video format*/ + E_MI_HDMI_YCC_QUANTIZATION_MAX +} MI_HDMI_YccQuantRange_e; + +typedef enum +{ + E_MI_HDMI_ERR_UNSUPPORT_TIMING = MI_HDMI_INITIAL_ERROR_CODE, + E_MI_HDMI_ERR_UNSUPPORT_COLORTYPE, + E_MI_HDMI_ERR_UNSUPPORT_COLORDEPTH, + E_MI_HDMI_ERR_UNSUPPORT_OUTPUTMODE, + E_MI_HDMI_ERR_UNSUPPORT_ACODETYPE, + E_MI_HDMI_ERR_UNSUPPORT_AFREQ, + E_MI_HDMI_ERR_EDID_HEADER_ERR, + E_MI_HDMI_ERR_EDID_DATA_ERR, + E_MI_HDMI_ERR_EDID_PRASE_ERR, + E_MI_HDMI_ERR_MAX +} MI_HDMI_ErrCode_e; + +/*------------------------------------------------------------------------------------------------- + * Defines + ------------------------------------------------------------------------------------------------*/ +#define MI_HDMI_MAX_ACAP_CNT 8 +#define MI_HDMI_MAX_AUDIO_SAMPLE_RATE_CNT 10 + +/* HDMI Module ErrorCode */ +#define MI_ERR_HDMI_INVALID_PARAM MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_ILLEGAL_PARAM) +#define MI_ERR_HDMI_INVALID_DEVID MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_DEVID) +#define MI_ERR_HDMI_DRV_FAILED MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_FAILED) +#define MI_ERR_HDMI_NOT_INIT MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_INIT) +#define MI_ERR_HDMI_NOT_SUPPORT MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_SUPPORT) +#define MI_ERR_HDMI_UNSUPPORT_TIMING MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_HDMI_ERR_UNSUPPORT_TIMING) +#define MI_ERR_HDMI_UNSUPPORT_COLORTYPE MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_HDMI_ERR_UNSUPPORT_COLORTYPE) +#define MI_ERR_HDMI_UNSUPPORT_ACODETYPE MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_HDMI_ERR_UNSUPPORT_ACODETYPE) +#define MI_ERR_HDMI_UNSUPPORT_AFREQ MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_HDMI_ERR_UNSUPPORT_AFREQ) +#define MI_ERR_HDMI_EDID_HEADER_ERR MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_HDMI_ERR_EDID_HEADER_ERR) +#define MI_ERR_HDMI_EDID_DATA_ERR MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_HDMI_ERR_EDID_DATA_ERR) +#define MI_ERR_HDMI_EDID_PRASE_ERR MI_DEF_ERR(E_MI_MODULE_ID_HDMI, E_MI_ERR_LEVEL_ERROR, E_MI_HDMI_ERR_EDID_PRASE_ERR) + +/*------------------------------------------------------------------------------------------------- + * Callback + ------------------------------------------------------------------------------------------------*/ +typedef MI_S32 (* MI_HDMI_EventCallBack)(MI_HDMI_DeviceId_e eHdmi, MI_HDMI_EventType_e event, void *pEventParam, void *pUsrParam); + +/*------------------------------------------------------------------------------------------------- + * Structures + ------------------------------------------------------------------------------------------------*/ +typedef struct MI_HDMI_InitParam_s +{ + MI_HDMI_EventCallBack pfnHdmiEventCallback; + void *pCallBackArgs; +} MI_HDMI_InitParam_t; + +typedef struct MI_HDMI_VideoAttr_s +{ + MI_BOOL bEnableVideo; + MI_HDMI_TimingType_e eTimingType; + MI_HDMI_OutputMode_e eOutputMode; + MI_HDMI_ColorType_e eColorType; + MI_HDMI_DeepColor_e eDeepColorMode; +} MI_HDMI_VideoAttr_t; + +typedef struct MI_HDMI_AudioAttr_s +{ + MI_BOOL bEnableAudio; + MI_BOOL bIsMultiChannel;// 0->2channel 1->8channel + MI_HDMI_SampleRate_e eSampleRate; + MI_HDMI_BitDepth_e eBitDepth; + MI_HDMI_AudioCodeType_e eCodeType; +} MI_HDMI_AudioAttr_t; + +typedef struct MI_HDMI_EnInfoFrame_s +{ + MI_BOOL bEnableAviInfoFrame; + MI_BOOL bEnableAudInfoFrame; + MI_BOOL bEnableSpdInfoFrame; +} MI_HDMI_EnInfoFrame_t; + +typedef struct MI_HDMI_Attr_s +{ + MI_BOOL bConnect; + MI_HDMI_VideoAttr_t stVideoAttr; + MI_HDMI_AudioAttr_t stAudioAttr; + MI_HDMI_EnInfoFrame_t stEnInfoFrame; +} MI_HDMI_Attr_t; + +typedef struct MI_HDMI_Edid_s +{ + MI_BOOL bEdidValid; + MI_U32 u32Edidlength; + MI_U8 au8Edid[512]; /* EDID buffer */ +} MI_HDMI_Edid_t; + +typedef struct MI_HDMI_Sink_Info_s +{ + MI_BOOL bConnected; + MI_BOOL bSupportHdmi; + MI_HDMI_TimingType_e eNativeTimingType; + MI_BOOL abVideoFmtSupported[E_MI_HDMI_TIMING_MAX]; + MI_BOOL bSupportYCbCr444; + MI_BOOL bSupportYCbCr422; + MI_BOOL bSupportYCbCr; + MI_BOOL bSupportxvYcc601; + MI_BOOL bSupportxvYcc709; + MI_U8 u8MdBit; + MI_BOOL abAudioFmtSupported[MI_HDMI_MAX_ACAP_CNT]; + MI_U32 au32AudioSampleRateSupported[MI_HDMI_MAX_AUDIO_SAMPLE_RATE_CNT]; + MI_U32 u32MaxPcmChannels; + MI_U8 u8Speaker; + MI_U8 au8IdManufactureName[4]; + MI_U32 u32IdProductCode; + MI_U32 u32IdSerialNumber; + MI_U32 u32WeekOfManufacture; + MI_U32 u32YearOfManufacture; + MI_U8 u8Version; + MI_U8 u8Revision; + MI_U8 u8EdidExternBlockNum; + MI_U8 au8IeeRegId[3];//IEEE registeration identifier + MI_U8 u8PhyAddr_A; + MI_U8 u8PhyAddr_B; + MI_U8 u8PhyAddr_C; + MI_U8 u8PhyAddr_D; + MI_BOOL bSupportDviDual; + MI_BOOL bSupportDeepColorYcbcr444; + MI_BOOL bSupportDeepColor30Bit; + MI_BOOL bSupportDeepColor36Bit; + MI_BOOL bSupportDeepColor48Bit; + MI_BOOL bSupportAi; + MI_U32 u8MaxTmdsClock; + MI_BOOL bILatencyFieldsPresent; + MI_BOOL bLatencyFieldsPresent; + MI_BOOL bHdmiVideoPresent; + MI_U8 u8VideoLatency; + MI_U8 u8AudioLatency; + MI_U8 u8InterlacedVideoLatency; + MI_U8 u8InterlacedAudioLatency; +} MI_HDMI_SinkInfo_t; + +typedef struct MI_HDMIAviInforFrameVer_s +{ + MI_BOOL bEnableAfdOverWrite; + MI_U8 A0Value; + MI_HDMI_ColorType_e eColorType; + MI_HDMI_Colorimetry_e eColorimetry; + MI_HDMI_ExtColorimetry_e eExtColorimetry; + MI_HDMI_YccQuantRange_e eYccQuantRange; + MI_HDMI_TimingType_e eTimingType; //trans to MS_VIDEO_TIMING in impl + MI_HDMI_VideoAfdRatio_e eAfdRatio; + MI_HDMI_ScanInfo_e eScanInfo; + MI_HDMI_AspectRatio_e eAspectRatio; +} MI_HDMI_AviInfoFrameVer_t; + +typedef struct MI_HDMI_AudInfoFrameVer_s +{ + MI_U32 u32ChannelCount; //2 4 6 8 channels + MI_HDMI_AudioCodeType_e eAudioCodeType;//PCM NON-PCM + MI_HDMI_SampleRate_e eSampleRate; +} MI_HDMI_AudInfoFrameVer_t; + +typedef struct MI_HDMI_SpdInfoFrame_s +{ + MI_U8 au8VendorName[8]; + MI_U8 au8ProductDescription[16]; +} MI_HDMI_SpdInfoFrame_t; + +typedef union +{ + MI_HDMI_AviInfoFrameVer_t stAviInfoFrame; + MI_HDMI_AudInfoFrameVer_t stAudInfoFrame; + MI_HDMI_SpdInfoFrame_t stSpdInfoFrame; +} MI_HDMI_InfoFrameUnit_u; + +typedef struct MI_HDMI_InfoFrame_s +{ + MI_HDMI_InfoFrameType_e eInfoFrameType; /* InfoFrame type */ + MI_HDMI_InfoFrameUnit_u unInforUnit; /* InfoFrame date */ +} MI_HDMI_InfoFrame_t; + +typedef struct MI_HDMI_AnalogDrvCurrent_s +{ + MI_U8 u8DrvCurTap1Ch0; + MI_U8 u8DrvCurTap1Ch1; + MI_U8 u8DrvCurTap1Ch2; + MI_U8 u8DrvCurTap1Ch3; + MI_U8 u8DrvCurTap2Ch0; + MI_U8 u8DrvCurTap2Ch1; + MI_U8 u8DrvCurTap2Ch2; + MI_U8 u8DrvCurTap2Ch3; +} MI_HDMI_AnalogDrvCurrent_t; + +#ifdef __cplusplus +} +#endif +#endif //_MI_HDMI_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_iqserver.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_iqserver.h new file mode 100644 index 000000000..cf8d2b5c7 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_iqserver.h @@ -0,0 +1,62 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_iqserver.h +* +* Created on: July 10, 2018 +* Author: Shan Li +*/ + + +#ifndef _MI_IQSERVER_H +#define _MI_IQSERVER_H + +#define IRQSERVER_MAJOR_VERSION 2 +#define IRQSERVER_SUB_VERSION 3 +#define MACRO_TO_STR(macro) #macro +#define IRQSERVER_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_irqserver_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_irqserver_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_irqserver_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_IRQSERVER_API_VERSION IRQSERVER_VERSION_STR(IRQSERVER_MAJOR_VERSION,IRQSERVER_SUB_VERSION) + +#ifdef __cplusplus +extern "C" +{ +#endif +#include "mi_iqserver_datatype.h" + +/* +* Open IQServer +* Param: +* width: sensor width +* height: sensor height +*/ +MI_S32 MI_IQSERVER_Open(MI_U16 width, MI_U16 height, MI_S32 vpeChn); + +MI_S32 MI_IQSERVER_SetDataPath(char* path); + +MI_S32 MI_IQSERVER_SetCustFunc(MI_S32(* func)(MI_U16 data_type, MI_U32 length, MI_U8 * data)); + +/* +* Close IQServer +*/ +MI_S32 MI_IQSERVER_Close(); +#endif + +#ifdef __cplusplus +} //end of extern C +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_iqserver_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_iqserver_datatype.h new file mode 100644 index 000000000..8084d2ea8 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_iqserver_datatype.h @@ -0,0 +1,31 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* +* mi_iqserver_datatype.h +* +* Created on: June 27, 2018 +* Author: Jeffrey Chou +*/ + +#ifndef _MI_IQSERVER_DATATYPE_H_ +#define _MI_IQSERVER_DATATYPE_H_ + +#define MI_IQSERVER_OK 0 +#define MI_ERR_IQSERVER_FAIL 1 +#define MI_ERR_IQSERVER_NULL_PTR 2 +#define MI_ERR_IQSERVER_NO_BUFF 3 + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ive.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ive.h new file mode 100644 index 000000000..4faaa8814 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ive.h @@ -0,0 +1,771 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_IVE_H_ +#define _MI_IVE_H_ + +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif /* End of #ifdef __cplusplus */ + +#include "mi_ive_datatype.h" + +/***************************************************************************** +* Prototype : MI_IVE_Create +* Description : Create IVE handle +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Create(MI_IVE_HANDLE hHandle); + +/***************************************************************************** +* Prototype : MI_IVE_Destroy +* Description : Destroy IVE handle +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Destroy(MI_IVE_HANDLE hHandle); + +/***************************************************************************** +* Prototype : MI_IVE_Filter +* Description : 5x5 template filter. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data. +* The U8C1,SP420 and SP422 input formats are supported. +* MI_IVE_DstImage_t *pstDst Output result, of same type with the input. +* MI_IVE_FilterCtrl_t *pstFltCtrl Control parameters of filter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Filter(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_FilterCtrl_t *pstFltCtrl,MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Csc +* Description : YUV2RGB\YUV2HSV\YUV2LAB\RGB2YUV color space conversion are supported. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data: +* 1. SP420\SP422 type for YUV2RGB\YUV2HSV\YUV2LAB; +* 2. U8C3_PACKAGE\U8C3_PLANAR type for RGB2YUV; +* MI_IVE_DstImage_t *pstDst Output result: +* 1. U8C3_PACKAGE\U8C3_PLANAR typed for YUV2RGB\YUV2HSV\YUV2LAB; +* 2. SP420\SP422 type for RGB2YUV; +* MI_IVE_CscCtrl_t *pstCscCtrl Control parameters for CSC +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Csc(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_CscCtrl_t *pstCscCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_FilterAndCsc +* Description : Only support YUV2RGB color space conversion. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task. +* MI_IVE_SrcImage_t *pstSrc Input source data.Only SP420\SP422 type are supported. +* MI_IVE_DstImage_t *pstDst Output result.Only U8C3_PACKAGE\U8C3_PLANAR are supported. +* MI_IVE_FilterAndCscCtrl_t *pstFltCscCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_FilterAndCsc(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_FilterAndCscCtrl_t *pstFltCscCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Sobel +* Description : SOBEL is used to extract the gradient information. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data. Only the U8C1 input image is supported. +* MI_IVE_DstImage_t *pstDstH The (horizontal) result of input image filtered by the input mask; +* MI_IVE_DstImage_t *pstDstV The (vertical) result of input image filtered by the transposed mask; +* MI_IVE_SobelCtrl_t *pstSobelCtrl Control parameters +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Sobel(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDstH, MI_IVE_DstImage_t *pstDstV, + MI_IVE_SobelCtrl_t *pstSobelCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_MagAndAng +* Description : MagAndAng is used to extract the edge information. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SRC_INFO_S *pstSrc Input source data. Only the U8C1 input format is supported. +* MI_IVE_MemInfo_t *pstDstMag Output magnitude. +* MI_IVE_MemInfo_t *pstDstAng Output angle. +* If the output mode is set to magnitude only, +* this item can be set to null. +* MI_IVE_MagAndAngCtrl_t *pstMagAndAngCtrl Control parameters +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_MagAndAng(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDstMag, MI_IVE_DstImage_t *pstDstAng, + MI_IVE_MagAndAngCtrl_t *pstMagAndAngCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Dilate +* Description : 5x5 template dilate. Only the U8C1 binary image input is supported.Or else the result is not expected. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input binary image, which consists of 0 or 255; +* MI_IVE_DstImage_t *pstDst Output result. +* MI_IVE_DilateCtrl_t *pstDilateCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* The input value, output value, and mask value must be 0 or 255. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Dilate(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_DilateCtrl_t *pstDilateCtrl,MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Erode +* Parameters : 5x5 template erode. Only the U8C1 binary image input is supported.Or else the result is not correct. +* Input : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input binary image, which consists of 0 or 255; +* MI_IVE_DstImage_t *pstDst Output result. +* MI_IVE_ErodeCtrl_t *pstErodeCtrl Control parameters +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* The input value, output value, and mask value must be 0 or 255. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Erode(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_ErodeCtrl_t *pstErodeCtrl,MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Thresh +* Description : Thresh operation to the input image. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data. Only the U8C1 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result +* MI_IVE_ThreshCtrl_t *pstThrCtrl Control parameters +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Thresh(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_ThreshCtrl_t *pstThrCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_And +* Description : Binary images' And operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 The input source1. Only U8C1 input format is supported. +* MI_IVE_SrcImage_t *pstSrc2 The input source2.Only U8C1 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result of " src1 & src2 ". +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* The types, widths, heights of two input sources must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_And(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, + MI_IVE_SrcImage_t *pstSrc2, MI_IVE_DstImage_t *pstDst, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Sub +* Description : Two gray images' Sub operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 Minuend of the input source.Only the U8C1 input format is supported. +* MI_IVE_SrcImage_t *pstSrc2 Subtrahend of the input source.Only the U8C1 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result of src1 minus src2 +* MI_IVE_SubCtrl_t *pstSubCtrl Control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* The types, widths, heights of two input sources must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Sub(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, + MI_IVE_SrcImage_t *pstSrc2, MI_IVE_DstImage_t *pstDst, MI_IVE_SubCtrl_t *pstSubCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Or +* Description : Two binary images' Or operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 Input source1. Only the U8C1 input format is supported. +* MI_IVE_SrcImage_t *pstSrc2 Input source2. Only the U8C1 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result src1 or src2 +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* The types, widths, heights of two input sources must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Or(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, + MI_IVE_SrcImage_t *pstSrc2, MI_IVE_DstImage_t *pstDst, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_INTEG +* Description : Calculate the input gray image's integral image. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data.Only the U8C1 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result.Can be U32C1 or U64C1, relied on the control parameter. +* MI_IVE_IntegCtrl_t *pstIntegCtrl Integ Control +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* The pixel can be 32bit or 64 bit relied on the control parameter. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Integ(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_IntegCtrl_t *pstIntegCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Hist +* Description : Calculate the input gray image's histogram. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data. Only the U8C1 input format is supported. +* MI_IVE_DstMemInfo_t *pstDst Output result. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Hist(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstMemInfo_t *pstDst, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_ThreshS16 +* Description : S16 image's THRESH operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data.Only the S16 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result. +* MI_IVE_ThreshS16Ctrl_t *pstThrS16Ctrl Control parameters +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The physical addresses of the input data must be 2-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_ThreshS16(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_ThreshS16Ctrl_t *pstThrS16Ctrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_ThreshU16 +* Description : U16 image's THRESH operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data. Only the U16 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result +* MI_IVE_ThreshU16Ctrl_t *pstThrU16Ctrl Control parameters +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The physical addresses of the input data must be 2-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_ThreshU16(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_ThreshU16Ctrl_t *pstThrU16Ctrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_16BitTo8Bit +* Description : Scale the input 16bit data to the output 8bit data. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data.Only U16C1\S16C1 input is supported. +* MI_IVE_DstImage_t *pstDst Output result +* MI_IVE_16BITTO8BIT_CTRL_S *pst16BitTo8BitCtrl control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The physical addresses of the input data must be 2-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_16BitTo8Bit(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_16bitTo8BitCtrl_t *pst16BitTo8BitCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_OrdStatFilter +* Description : Order Statistic Filter. It can be used as median\max\min value filter. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data. Only U8C1 input is supported +* MI_IVE_DstImage_t *pstDst Output result +* MI_IVE_OrdStatFilter_t *pstOrdStatFltCtrl Control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_OrdStatFilter(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_OrdStatFilter_t *pstOrdStatFltCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Map +* Description : Map a image to another through a lookup table. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source. Only the U8C1 input format is supported. +* MI_IVE_SrcMemInfo_t *pstMap Input lookup table. Must be an U8 array of size 256. +* MI_IVE_DstImage_t *pstDst Output result. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Map(MI_IVE_HANDLE hHandle,MI_IVE_SrcImage_t *pstSrc, + MI_IVE_SrcMemInfo_t *pstMap, MI_IVE_DstImage_t *pstDst,MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_EqualizeHist +* Description : Enhance the input image's contrast through histogram equalization. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source.Only U8C1 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result. +* MI_IVE_EQUALIZEHIST_CTRL_S *pstEqualizeHistCtrl EqualizeHist control parameter. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The physical addresses of map data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_EqualizeHist(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MI_IVE_EqualizeHistCtrl_t *pstEqualizeHistCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Add +* Description : Two gray images' Add operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 Augend of the input source.Only the U8C1 input format is supported. +* MI_IVE_SrcImage_t *pstSrc2 Addend of the input source.Only the U8C1 input format is supported. +* MI_IVE_DstImage_t *pstDst Output result of src1 plus src2 +* MI_IVE_AddCtrl_t *pstAddCtrl Control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* The types, widths, heights of two input sources must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Add(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, + MI_IVE_SrcImage_t *pstSrc2, MI_IVE_DstImage_t *pstDst, MI_IVE_AddCtrl_t *pstAddCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Xor +* Description : Two binary images' Xor operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 The input source1.Only the U8C1 input format is supported. +* MI_IVE_SrcImage_t *pstSrc2 The input source2. +* MI_IVE_DstImage_t *pstDst Output result +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* The types, widths, heights of two input sources must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Xor(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, + MI_IVE_SrcImage_t *pstSrc2, MI_IVE_DstImage_t *pstDst, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Ncc +* Description : Calculate two gray images' NCC (Normalized Cross Correlation). +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 Input source1. Only the U8C1 input format is supported. +* MI_IVE_SrcImage_t *pstSrc2 Input source2. Must be of the same typesize of source1. +* MI_IVE_DstMemInfo_t *pstDst Output result +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Ncc(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, + MI_IVE_SrcImage_t *pstSrc2, MI_IVE_DstMemInfo_t *pstDst, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Ccl +* Description : Connected Component Labeling. Only 8-Connected method is supported. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrcDst Input source +* MI_IVE_MemInfo_t *pstBlob Output result of detected region; +* MI_IVE_CclCtrl_t *pstCclCtrl CCL control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 720x640 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Ccl(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrcDst, + MI_IVE_DstMemInfo_t *pstBlob, MI_IVE_CclCtrl_t *pstCclCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Gmm +* Description : Separate foreground and background using GMM(Gaussian Mixture Model) method; +* Gray or RGB GMM are supported. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source. Only support U8C1 or U8C3_PACKAGE input. +* MI_IVE_DstImage_t *pstFg Output foreground (Binary) image. +* MI_IVE_DstImage_t *pstBg Output background image. Of the sampe type of pstSrc. +* MI_IVE_MemInfo_t *pstModel Model data. +* MI_IVE_GmmCtrl_t *pstGmmCtrl Control parameter. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 720x576 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Gmm(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, MI_IVE_DstImage_t *pstFg, + MI_IVE_DstImage_t *pstBg, MI_IVE_MemInfo_t *pstModel, MI_IVE_GmmCtrl_t *pstGmmCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_CannyHysEdge +* Description : The first part of canny Edge detection. Including step: gradient calculation, +* magnitude and angle calculation, hysteresis threshold, NMS(Non-Maximum Suppression) +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source. Only the U8C1 input format is supported +* MI_IVE_DstImage_t *pstEdge Output result. +* MI_IVE_DstMemInfo_t *pstStack OutPut stack for CannyEdge +* MI_IVE_CannyHysEdgeCtrl_t *pstCannyHysEdgeCtrl Control parameter. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. . +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_CannyHysEdge(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, MI_IVE_DstImage_t *pstEdge, + MI_IVE_DstMemInfo_t *pstStack, MI_IVE_CannyHysEdgeCtrl_t *pstCannyHysEdgeCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_CannyEdge +* Description : The second part of canny Edge detection: trace strong edge by weak edge. +* Parameters : MI_IVE_SrcImage_t *pstEdge Input and Output source. Only the U8C1 format is supported +* MI_IVE_MemInfo_t *pstStack stack for CannyEdge +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_CannyEdge(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstEdge, MI_IVE_MemInfo_t *pstStack, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Lbp +* Description : LBP calculation using the original method and a extensional method. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source.Only the U8C1 inpu format is supported. +* MI_IVE_DstImage_t *pstDst Output result +* MI_IVE_LbpCtrrl_t *pstLbpCtrl Control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Lbp(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, MI_IVE_SrcImage_t *pstSrc2, + MI_IVE_DstImage_t *pstDst, MI_IVE_LbpCtrrl_t *pstLbpCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_NormGrad +* Description : Gradient calculation and the output is normalized to S8. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source data +* MI_IVE_DstImage_t *pstDstH The (horizontal) result of input image filtered by the input mask; +* MI_IVE_DstImage_t *pstDstV The (vertical) result of input image filtered by the transposed mask; +* MI_IVE_DstImage_t *pstDstHV Output the horizontal and vertical component in single image in package format. +* MI_IVE_NormGradCtrl_t *pstNormGradCtrl Control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1024 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_NormGrad(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDstH, MI_IVE_DstImage_t *pstDstV, MI_IVE_DstImage_t *pstDstHV, + MI_IVE_NormGradCtrl_t *pstNormGradCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_LkOpticalFlow +* Description : Calculate LK-Optical Flow in single-layer of the pyramid. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrcPre Pre-frame input source.Must be U8C1 image +* MI_IVE_SrcImage_t *pstSrcCur Cur-frame input source.Same sizetype with pstPreSrc. +* MI_IVE_SrcMemInfo_t *pstPoint Intresting points coordinates in the cur-layer +* for LKOpticalFlow tracking. +* MI_IVE_MemInfo_t *pstMv Accumlative movements of the interesting points in pre-layers +* or init 0s for the first-layer as input. init 0s . +* Movements of the interesting points being tracked in cur-layer +* as output. +* MI_IVE_LKOPTICALFLOW_CTRL_S *pstLkOptiFlowCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 720x576 pixels. +* The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* History: +****************************************************************************/ +MI_S32 MI_IVE_LkOpticalFlow(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrcPre, MI_IVE_SrcImage_t *pstSrcCur, + MI_IVE_SrcMemInfo_t *pstPoint, MI_IVE_MemInfo_t *pstMv, MI_IVE_LkOpticalFlowCtrl_t *pstLkOptiFlowCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Sad +* Description : Sum of absolute differences. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 The input source1.Only the U8C1 input format is supported. +* MI_IVE_SrcImage_t *pstSrc2 The input source2.Only the U8C1 input format is supported. +* MI_IVE_DstImage_t *pstSad Output result of sad value.Only the U8C1/U16C1 format is supported. +* MI_IVE_DstImage_t *pstThr Output result of thresh.Only the U8C1 format is supported. +* MI_IVE_SadCtrl_t *pstSadCtrl Control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* The types, widths, heights of two input sources must be the same. +* Not support in hi3516a +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Sad(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, + MI_IVE_SrcImage_t *pstSrc2, MI_IVE_DstImage_t *pstSad, MI_IVE_DstImage_t *pstThr, + MI_IVE_SadCtrl_t *pstSadCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Resize +* Description : Resize image +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source. +* MI_IVE_DstImage_t *pstDst Output result +* MVE_IVE_ResizeCtrl_t *pstResizeCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 32x12 pixels to 1920x1080 pixels. +* The input and output height must be 2-pixel-aligned with mode YUV420SP. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Resize(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst, MVE_IVE_ResizeCtrl_t *pstResizeCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Bernsen +* Description : +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source. +* MI_IVE_DstImage_t *pstDst Output result +* MVE_IVE_BernsenCtrl_t *pstBernsenCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* The type of source and destination must be U8C1. +* The input size and output size must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Bernsen(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstImage_t *pstDst,MVE_IVE_BernsenCtrl_t *pstBernsenCtrl,MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_AdpThresh +* Description : +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source. +* MI_IVE_SrcImage_t *pstInteg Input integral image of source. +* MI_IVE_DstImage_t *pstDst Output result +* MVE_IVE_AdpThreshCtrl_t *pstAdpThrCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The physical addresses of the input data and output data must be 16-byte-aligned. +* The type of source and destination must be U8C1. +* The stride must be 16-pixel-aligned. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_AdpThresh(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_SrcImage_t *pstInteg, MI_IVE_DstImage_t *pstDst, MVE_IVE_AdpThreshCtrl_t *pstAdpThrCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_LineFilterHor +* Description : +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrcDst Input and output source. +* MVE_IVE_LineFilterHorCtrl_t *pstLineFilterHorCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The type of input source must be U8C1. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_LineFilterHor(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrcDst, + MVE_IVE_LineFilterHorCtrl_t *pstLineFilterHorCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_LineFilterVer +* Description : +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrcDst Input and output source. +* MVE_IVE_LineFilterVerCtrl_t *pstLineFilterVerCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The type of input source must be U8C1. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_LineFilterVer(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrcDst, + MVE_IVE_LineFilterVerCtrl_t *pstLineFilterVerCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_NoiseRemoveHor +* Description : +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrcDst Input and output source. +* MVE_IVE_NoiseRemoveHorCtrl_t *pstNoiseRemoveHorCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The type of input source must be U8C1. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_NoiseRemoveHor(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrcDst, + MVE_IVE_NoiseRemoveHorCtrl_t *pstNoiseRemoveHorCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_NoiseRemoveVer +* Description : +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrcDst Input and output source. +* MVE_IVE_NoiseRemoveVerCtrl_t *pstNoiseRemoveVerCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The type of input source must be U8C1. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_NoiseRemoveVer(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrcDst, + MVE_IVE_NoiseRemoveVerCtrl_t *pstNoiseRemoveVerCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Acc +* Description : +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc0 First input source. +* MI_IVE_SrcImage_t *pstSrc1 Second input source. +* MVE_IVE_AccCtrl_t *pstAccCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* The size of two input source must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Acc(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc0, + MI_IVE_SrcImage_t *pstSrc1, MI_IVE_DstImage_t *pstDst, MVE_IVE_AccCtrl_t *pstAccCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_MVE_BAT +* Description : +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc Input source. +* MI_IVE_DstMemInfo_t *pstDstH First output. +* MI_IVE_DstMemInfo_t *pstDstV Second output. +* MVE_IVE_BatCtrl_t *pstCtrl Control parameters. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The physical addresses of the input data and output data must be 16-byte-aligned. +* The stride must be 16-pixel-aligned. +* The type of input source must be U8C1. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_BAT(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc, + MI_IVE_DstMemInfo_t *pstDstH, MI_IVE_DstMemInfo_t *pstDstV, MVE_IVE_BatCtrl_t *pstCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Matrix_Transform +* Description : Matrix transform operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 Input source 1. +* MI_IVE_SrcImage_t *pstSrc2 Input source 2. +* MI_IVE_SrcImage_t *pstSrc3 Input source 3. +* MI_IVE_DstImage_t *pstDst1 Output result 1 +* MI_IVE_DstImage_t *pstDst2 Output result 2 +* MI_IVE_DstImage_t *pstDst3 Output result 3 +* MI_IVE_MatrTranfCtrl_t *pstMatrTranfCtrl Control parameter +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* The types, widths, heights of input sources must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Matrix_Transform(MI_IVE_HANDLE hHandle, + MI_IVE_SrcImage_t *pstSrc1, MI_IVE_SrcImage_t *pstSrc2, MI_IVE_SrcImage_t *pstSrc3, + MI_IVE_DstImage_t *pstDst1, MI_IVE_DstImage_t *pstDst2, MI_IVE_DstImage_t *pstDst3, + MI_IVE_MatrTranfCtrl_t *pstMatrTranfCtrl, MI_BOOL bInstant); + +/***************************************************************************** +* Prototype : MI_IVE_Image_Dot +* Description : Matrix transform operation. +* Parameters : MI_IVE_HANDLE hHandle Handle ID of a task +* MI_IVE_SrcImage_t *pstSrc1 Input source 1. +* MI_IVE_SrcImage_t *pstSrc2 Input source 2. +* MI_IVE_DstImage_t *pstDst Output result. +* MI_BOOL bInstant Reserved +* Return Value : MI_SUCCESS: Success;Error codes: Failure. +* Spec : The size of the input data ranges from 64x64 pixels to 1920x1080 pixels. +* The stride must be 16-pixel-aligned. +* The types, widths, heights of input sources must be the same. +* History: +*****************************************************************************/ +MI_S32 MI_IVE_Image_Dot(MI_IVE_HANDLE hHandle, MI_IVE_SrcImage_t *pstSrc1, MI_IVE_SrcImage_t *pstSrc2, + MI_IVE_DstImage_t *pstDst, MI_BOOL bInstant); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif/*_MI_IVE_H_*/ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ive_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ive_datatype.h new file mode 100644 index 000000000..890e178d8 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ive_datatype.h @@ -0,0 +1,811 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_IVE_DATATYPE_H_ +#define _MI_IVE_DATATYPE_H_ + +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif + +#include "mi_common_datatype.h" + +#define MI_IVE_HANDLE_MAX (128) +#define MI_IVE_HIST_NUM (256) +#define MI_IVE_MAP_NUM (256) +#define MI_IVE_MAX_REGION_NUM (255) +#define MI_IVE_ST_MAX_CORNER_NUM (200) +#define MI_IVE_MASK_SIZE_5X5 (25) +#define MI_IVE_CANNY_STACK_RESERVED_SIZE (12) + +/************************************************IVE error code ***********************************/ +#define MI_IVE_ERR_INVALID_DEVID MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_DEVID) +#define MI_IVE_ERR_INVALID_CHNID MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_CHNID) +#define MI_IVE_ERR_ILLEGAL_PARAM MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_ILLEGAL_PARAM) +#define MI_IVE_ERR_EXIST MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_EXIST) +#define MI_IVE_ERR_UNEXIST MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_UNEXIST) +#define MI_IVE_ERR_NULL_PTR MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NULL_PTR) +#define MI_IVE_ERR_NOT_CONFIG MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_CONFIG) +#define MI_IVE_ERR_NOT_SUPPORT MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_SUPPORT) +#define MI_IVE_ERR_NOT_PERM MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_PERM) +#define MI_IVE_ERR_NOMEM MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOMEM) +#define MI_IVE_ERR_NOBUF MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOBUF) +#define MI_IVE_ERR_BUF_EMPTY MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUF_EMPTY) +#define MI_IVE_ERR_BUF_FULL MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUF_FULL) +#define MI_IVE_ERR_SYS_NOTREADY MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_SYS_NOTREADY) +#define MI_IVE_ERR_BADADDR MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BADADDR) +#define MI_IVE_ERR_BUSY MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUSY) +#define MI_IVE_ERR_CHN_NOT_STARTED MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_CHN_NOT_STARTED) +#define MI_IVE_ERR_CHN_NOT_STOPED MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_CHN_NOT_STOPED) +#define MI_IVE_ERR_NOT_INIT MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_INIT) +#define MI_IVE_ERR_SYS_TIMEOUT MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_SYS_TIMEOUT) +#define MI_IVE_ERR_FAILED MI_DEF_ERR(E_MI_MODULE_ID_IVE, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_FAILED) + +/*-----------------------------------------------* + * The fixed-point data type, will be used to * + * represent float data in hardware calculations.* + *-----------------------------------------------*/ + +/*--u8bit----------------------------------------*/ +typedef unsigned char MI_U0Q8; +typedef unsigned char MI_U1Q7; +typedef unsigned char MI_U5Q3; + +/*--u16bit---------------------------------------*/ +typedef unsigned short MI_U0Q16; +typedef unsigned short MI_U4Q12; +typedef unsigned short MI_U6Q10; +typedef unsigned short MI_U8Q8; +typedef unsigned short MI_U12Q4; +typedef unsigned short MI_U14Q2; + +/*--s16bit---------------------------------------*/ +typedef short MI_S9Q7; +typedef short MI_S14Q2; +typedef short MI_S1Q15; + +/*--u32bit---------------------------------------*/ +typedef unsigned int MI_U22Q10; +typedef unsigned int MI_U25Q7; + +/*--s32bit---------------------------------------*/ +typedef int MI_S25Q7; +typedef int MI_S16Q16; + +/* +* Type of the MI_IVE_Image_t data. +* Aded by tanbing 2013-7-22 +*/ +typedef enum +{ + E_MI_IVE_IMAGE_TYPE_U8C1 = 0x0, + E_MI_IVE_IMAGE_TYPE_S8C1 = 0x1, + E_MI_IVE_IMAGE_TYPE_YUV420SP = 0x2, /*YUV420 SemiPlanar*/ + E_MI_IVE_IMAGE_TYPE_YUV422SP = 0x3, /*YUV422 SemiPlanar*/ + E_MI_IVE_IMAGE_TYPE_YUV420P = 0x4, /*YUV420 Planar */ + E_MI_IVE_IMAGE_TYPE_YUV422P = 0x5, /*YUV422 planar */ + E_MI_IVE_IMAGE_TYPE_S8C2_PACKAGE = 0x6, + E_MI_IVE_IMAGE_TYPE_S8C2_PLANAR = 0x7, + E_MI_IVE_IMAGE_TYPE_S16C1 = 0x8, + E_MI_IVE_IMAGE_TYPE_U16C1 = 0x9, + E_MI_IVE_IMAGE_TYPE_U8C3_PACKAGE = 0xA, + E_MI_IVE_IMAGE_TYPE_U8C3_PLANAR = 0xB, + E_MI_IVE_IMAGE_TYPE_S32C1 = 0xC, + E_MI_IVE_IMAGE_TYPE_U32C1 = 0xD, + E_MI_IVE_IMAGE_TYPE_S64C1 = 0xE, + E_MI_IVE_IMAGE_TYPE_U64C1 = 0xF, + + E_MI_IVE_IMAGE_TYPE_MAX + +}MI_IVE_ImageType_e; + +/* +* Definition of the MI_IVE_Image_t. +* Added by Tan Bing, 2013-7-22. +*/ +typedef struct MI_IVE_Image_s +{ + MI_IVE_ImageType_e eType; + + MI_PHY aphyPhyAddr[3]; + MI_U8 *apu8VirAddr[3]; + + MI_U16 azu16Stride[3]; + MI_U16 u16Width; + MI_U16 u16Height; + + MI_U16 u16Reserved; /*Can be used such as elemSize*/ +}MI_IVE_Image_t; + +typedef MI_IVE_Image_t MI_IVE_SrcImage_t; +typedef MI_IVE_Image_t MI_IVE_DstImage_t; + +/* +* Definition of the MI_IVE_MemInfo_t.This struct special purpose for input or ouput, such as Hist, CCL, ShiTomasi. +* Added by Chen Quanfu, 2013-7-23. +*/ +typedef struct MI_IVE_MemInfo_s +{ + MI_PHY phyPhyAddr; + MI_U8 *pu8VirAddr; + MI_U32 u32Size; +}MI_IVE_MemInfo_t; +typedef MI_IVE_MemInfo_t MI_IVE_SrcMemInfo_t; +typedef MI_IVE_MemInfo_t MI_IVE_DstMemInfo_t; + +/* +*Data struct ,created by Chen Quanfu 2013-07-19 +*/ +typedef struct MI_IVE_Data_s +{ + MI_PHY phyPhyAddr; /*Physical address of the data*/ + MI_U8 *pu8VirAddr; + + MI_U16 u16Stride; /*2D data stride by byte*/ + MI_U16 u16Width; /*2D data width by byte*/ + MI_U16 u16Height; /*2D data height*/ + + MI_U16 u16Reserved; +}MI_IVE_Data_s; +typedef MI_IVE_Data_s MI_IVE_SrcData_t; +typedef MI_IVE_Data_s MI_IVE_DstData_t; + +/* +* Definition of the union of MI_IVE_Length8bit_u. +* Added by Tan Bing, 2013-7-22. +*/ +typedef union +{ + MI_S8 s8Val; + MI_U8 u8Val; +}MI_IVE_Length8bit_u; + +/* +* Definition of u16 point +*/ +typedef struct MI_IVE_PointU16_s +{ + MI_U16 u16X; + MI_U16 u16Y; +}MI_IVE_PointU16_t; + +/* +*Float point represented by Fixed-point SQ25.7 +*/ +typedef struct MI_IVE_PointS25Q7_s +{ + MI_S25Q7 s25q7X; /*X coordinate*/ + MI_S25Q7 s25q7Y; /*Y coordinate*/ +}MI_IVE_PointS25Q7_t; + +/* +* Definition of rect +*/ +typedef struct MI_IVE_Rect_s +{ + MI_U16 u16X; + MI_U16 u16Y; + MI_U16 u16Width; + MI_U16 u16Height; +}MI_IVE_Rect_t; + + +/* +*Filter control parameters +*/ +typedef struct MI_IVE_FilterCtrl_s +{ + MI_S8 as8Mask[MI_IVE_MASK_SIZE_5X5]; /*Template parameter filter coefficient*/ + MI_U8 u8Norm; /*Normalization parameter, by right shift*/ +}MI_IVE_FilterCtrl_t; + +/* +* CSC working mode. +*/ +typedef enum +{ + E_MI_IVE_CSC_MODE_PIC_BT601_YUV2RGB = 0x0, /*CSC: YUV2RGB, picture transfer mode, RGB value range [0, 255]*/ + E_MI_IVE_CSC_MODE_PIC_BT601_RGB2YUV = 0x1, /*CSC: RGB2YUV, picture transfer mode, Y:[16, 235],U\V:[16, 240]*/ + E_MI_IVE_CSC_MODE_MAX +}MI_IVE_CscMode_e; + +/* +*CSC control parameters +*/ +typedef struct MI_IVE_CscCtrl_s +{ + MI_IVE_CscMode_e eMode; /*Working mode*/ +}MI_IVE_CscCtrl_t; + +/* +*Filter+CSC control parameters +*/ +typedef struct MI_IVE_FilterAndCscCtrl_s +{ + MI_IVE_CscMode_e eMode; /*CSC working mode*/ + MI_S8 as8Mask[MI_IVE_MASK_SIZE_5X5]; /*Template parameter filter coefficient*/ + MI_U8 u8Norm; /*Normalization parameter, by right shift*/ +}MI_IVE_FilterAndCscCtrl_t; + +/* +*SOBEL output ctrl +*/ +typedef enum +{ + E_MI_IVE_SOBEL_OUT_CTRL_BOTH = 0x0, /*Output horizontal and vertical*/ + E_MI_IVE_SOBEL_OUT_CTRL_HOR = 0x1, /*Output horizontal*/ + E_MI_IVE_SOBEL_OUT_CTRL_VER = 0x2, /*Output vertical*/ + E_MI_IVE_SOBEL_OUT_CTRL_MAX +}MI_IVE_SobelOutCtrl_e; + +/* +*SOBEL control parameter +*/ +typedef struct MI_IVE_SobelCtrl_s +{ + MI_IVE_SobelOutCtrl_e eOutCtrl; /*Output format*/ + MI_S8 as8Mask[MI_IVE_MASK_SIZE_5X5]; /*Template parameter*/ +}MI_IVE_SobelCtrl_t; + +/* +*Type of the magnitude and angle output results +*/ +typedef enum +{ + E_MI_IVE_MAG_AND_ANG_OUT_CTRL_MAG = 0x0, /*Only the magnitude is output.*/ + E_MI_IVE_MAG_AND_ANG_OUT_CTRL_MAG_AND_ANG = 0x1, /*The magnitude and angle are output.*/ + E_MI_IVE_MAG_AND_ANG_OUT_CTRL_MAX +}MI_IVE_MagAndAngOutCtrl_e; + +/* +*Magnitude and angle control parameter +*/ +typedef struct MI_IVE_MagAndAngCtrl_s +{ + MI_IVE_MagAndAngOutCtrl_e eOutCtrl; + MI_U16 u16Thr; + MI_S8 as8Mask[MI_IVE_MASK_SIZE_5X5]; /*Template parameter.*/ +}MI_IVE_MagAndAngCtrl_t; + +/* +*Dilate control parameters +*/ +typedef struct MI_IVE_DilateCtrl_s +{ + MI_U8 au8Mask[MI_IVE_MASK_SIZE_5X5]; /*The template parameter value must be 0 or 255.*/ +}MI_IVE_DilateCtrl_t; + +/* +*Erode control parameter +*/ +typedef struct MI_IVE_ErodeCtrl_s +{ + MI_U8 au8Mask[MI_IVE_MASK_SIZE_5X5]; /*The template parameter value must be 0 or 255.*/ +}MI_IVE_ErodeCtrl_t; + +/* +* Type of the Thresh mode. +*/ +typedef enum +{ + E_MI_IVE_THRESH_MODE_BINARY = 0x0, /*srcVal <= lowThr, dstVal = minVal; srcVal > lowThr, dstVal = maxVal.*/ + E_MI_IVE_THRESH_MODE_TRUNC = 0x1, /*srcVal <= lowThr, dstVal = srcVal; srcVal > lowThr, dstVal = maxVal.*/ + E_MI_IVE_THRESH_MODE_TO_MINVAL = 0x2, /*srcVal <= lowThr, dstVal = minVal; srcVal > lowThr, dstVal = srcVal.*/ + + E_MI_IVE_THRESH_MODE_MIN_MID_MAX = 0x3, /*srcVal <= lowThr, dstVal = minVal; lowThr < srcVal <= highThr, dstVal = midVal; srcVal > highThr, dstVal = maxVal.*/ + E_MI_IVE_THRESH_MODE_ORI_MID_MAX = 0x4, /*srcVal <= lowThr, dstVal = srcVal; lowThr < srcVal <= highThr, dstVal = midVal; srcVal > highThr, dstVal = maxVal.*/ + E_MI_IVE_THRESH_MODE_MIN_MID_ORI = 0x5, /*srcVal <= lowThr, dstVal = minVal; lowThr < srcVal <= highThr, dstVal = midVal; srcVal > highThr, dstVal = srcVal.*/ + E_MI_IVE_THRESH_MODE_MIN_ORI_MAX = 0x6, /*srcVal <= lowThr, dstVal = minVal; lowThr < srcVal <= highThr, dstVal = srcVal; srcVal > highThr, dstVal = maxVal.*/ + E_MI_IVE_THRESH_MODE_ORI_MID_ORI = 0x7, /*srcVal <= lowThr, dstVal = srcVal; lowThr < srcVal <= highThr, dstVal = midVal; srcVal > highThr, dstVal = srcVal.*/ + + E_MI_IVE_THRESH_MODE_MAX +}MI_IVE_ThreshMode_e; + +/* +* Thresh control parameters. +*/ +typedef struct MI_IVE_ThreshCtrl_s +{ + MI_IVE_ThreshMode_e eMode; + MI_U8 u8LowThr; /*user-defined threshold, 0<=u8LowThr<=255 */ + MI_U8 u8HighThr; /*user-defined threshold, if eMode0' and 'label = ArrayIndex+1'*/ +}MI_IVE_CcBlob_t; + +/* +*CCL control struct +*/ +typedef struct MI_IVE_Ccl_CTRL_S +{ + MI_U16 u16InitAreaThr; /*Init threshold of region area*/ + MI_U16 u16Step; /*Increase area step for once*/ +}MI_IVE_CclCtrl_t; + +/* +*GMM control struct +*/ +typedef struct MI_IVE_GmmCtrl_s +{ + MI_U22Q10 u22q10NoiseVar; /*Initial noise Variance*/ + MI_U22Q10 u22q10MaxVar; /*Max Variance*/ + MI_U22Q10 u22q10MinVar; /*Min Variance*/ + MI_U0Q16 u0q16LearnRate; /*Learning rate*/ + MI_U0Q16 u0q16BgRatio; /*Background ratio*/ + MI_U8Q8 u8q8VarThr; /*Variance Threshold*/ + MI_U0Q16 u0q16InitWeight; /*Initial Weight*/ + MI_U8 u8ModelNum; /*Model number: 3 or 5*/ +}MI_IVE_GmmCtrl_t; + +/* +*CannyHysEdge control struct +*/ +typedef struct MI_IVE_CannyHysEdgeCtrl_s +{ + MI_IVE_MemInfo_t stMem; + MI_U16 u16LowThr; + MI_U16 u16HighThr; + MI_S8 as8Mask[MI_IVE_MASK_SIZE_5X5]; +} MI_IVE_CannyHysEdgeCtrl_t; + +/* +*Canny stack size struct +*/ +typedef struct MI_IVE_CannyStackSize_s +{ + MI_U32 u32StackSize; /*Stack size for output*/ + MI_U8 u8Reserved[MI_IVE_CANNY_STACK_RESERVED_SIZE]; /*For 16 byte align*/ +}MI_IVE_CannyStackSize_t; + +/* +*LBP compare mode +*/ +typedef enum +{ + E_MI_IVE_LBP_CMP_MODE_NORMAL = 0x0, /* P(x)-P(center)>= un8BitThr.s8Val, s(x)=1; else s(x)=0; */ + E_MI_IVE_LBP_CMP_MODE_ABS = 0x1, /* Abs(P(x)-P(center))>=un8BitThr.u8Val, s(x)=1; else s(x)=0; */ + E_MI_IVE_LBP_CMP_MODE_ABS_MUL = 0x2, + + E_MI_IVE_LBP_CMP_MODE_MAX +}MI_IVE_LbpCmpMode_e; + +/* +*LBP channel mode +*/ +typedef enum +{ + E_MI_IVE_LBP_CHAL_MODE_U8C1 = 0x0, + E_MI_IVE_LBP_CHAL_MODE_U8C2 = 0x1, + + E_MI_IVE_LBP_CHAL_MODE_MAX +}MI_IVE_LbpChalMode_e; + +/* +*LBP control struct +*/ +typedef struct MI_IVE_LbpCtrrl_s +{ + MI_IVE_LbpCmpMode_e eMode; + MI_IVE_LbpChalMode_e chMode; + MI_IVE_Length8bit_u un8BitThr; +}MI_IVE_LbpCtrrl_t; + +/* +*Type of the GradientFilter output format +*/ +typedef enum +{ + E_MI_IVE_NORM_GRAD_OUT_CTRL_HOR_AND_VER = 0x0, + E_MI_IVE_NORM_GRAD_OUT_CTRL_HOR = 0x1, + E_MI_IVE_NORM_GRAD_OUT_CTRL_VER = 0x2, + E_MI_IVE_NORM_GRAD_OUT_CTRL_COMBINE = 0x3, + + E_MI_IVE_NORM_GRAD_OUT_CTRL_MAX +}MI_IVE_NormGradOutCtrl_e; + +/* +*GradientFilter control parameters +*/ +typedef struct MI_IVE_NormGradCtrl_s +{ + MI_IVE_NormGradOutCtrl_e eOutCtrl; + MI_S8 as8Mask[MI_IVE_MASK_SIZE_5X5]; + MI_U8 u8Norm; +}MI_IVE_NormGradCtrl_t; + +/* +* LKOpticalFlow movement +*/ +typedef struct MI_IVE_MvS9Q7_s +{ + MI_S32 s32Status; /*Result of tracking: 0-success; -1-failure*/ + MI_S9Q7 s9q7Dx; /*X-direction component of the movement*/ + MI_S9Q7 s9q7Dy; /*Y-direction component of the movement*/ +}MI_IVE_MvS9Q7_t; + +typedef struct MI_IVE_LkOpticalFlowCtrl_s +{ + MI_U16 u16CornerNum; /*Number of the feature points,<200*/ + MI_U0Q8 u0q8MinEigThr; /*Minimum eigenvalue threshold*/ + MI_U8 u8IterCount; /*Maximum iteration times*/ + MI_U0Q8 u0q8Epsilon; /*Threshold of iteration for dx^2 + dy^2 < u0q8Epsilon */ +}MI_IVE_LkOpticalFlowCtrl_t; + +/* +* Sad mode +*/ +typedef enum +{ + E_MI_IVE_SAD_MODE_MB_4X4 = 0x0, /*4x4*/ + E_MI_IVE_SAD_MODE_MB_8X8 = 0x1, /*8x8*/ + E_MI_IVE_SAD_MODE_MB_16X16 = 0x2, /*16x16*/ + + E_MI_IVE_SAD_MODE_MAX +}MI_IVE_SadMode_e; +/* +*Sad output ctrl +*/ +typedef enum +{ + E_MI_IVE_SAD_OUT_CTRL_16BIT_BOTH = 0x0, /*Output 16 bit sad and thresh*/ + E_MI_IVE_SAD_OUT_CTRL_8BIT_BOTH = 0x1, /*Output 8 bit sad and thresh*/ + E_MI_IVE_SAD_OUT_CTRL_16BIT_SAD = 0x2, /*Output 16 bit sad*/ + E_MI_IVE_SAD_OUT_CTRL_8BIT_SAD = 0x3, /*Output 8 bit sad*/ + E_MI_IVE_SAD_OUT_CTRL_THRESH = 0x4, /*Output thresh,16 bits sad */ + + E_MI_IVE_SAD_OUT_CTRL_MAX +}MI_IVE_SadOutCtrl_e; +/* +* Sad ctrl param +*/ +typedef struct MI_IVE_SadCtrl_s +{ + MI_IVE_SadMode_e eMode; + MI_IVE_SadOutCtrl_e eOutCtrl; + MI_U16 u16Thr; /*srcVal <= u16Thr, dstVal = minVal; srcVal > u16Thr, dstVal = maxVal.*/ + MI_U8 u8MinVal; /*Min value*/ + MI_U8 u8MaxVal; /*Max value*/ +}MI_IVE_SadCtrl_t; + +typedef enum +{ + E_MI_IVE_RESIZE_TYPE_U8C1 = 0x0, + E_MI_IVE_RESIZE_TYPE_U8C3_PLANAR = 0x1, + E_MI_IVE_RESIZE_TYPE_U8C3_PACKAGE = 0x2, + E_MI_IVE_RESIZE_TYPE_YUV420SP = 0x3, + + E_MI_IVE_RESIZE_TYPE_MAX +}MVE_IVE_ResizeMode_e; + +typedef struct _MVE_IVE_ResizeCtrl_s +{ + MVE_IVE_ResizeMode_e eMode; /*Input and output mode*/ +} MVE_IVE_ResizeCtrl_t; + +typedef enum +{ + E_MI_IVE_BERNSEN_MODE_NORMAL = 0x00, + E_MI_IVE_BERNSEN_MODE_THRESH = 0x01, + + E_MI_IVE_BERNSEN_MODE_MAX +} MVE_IVE_BernsenMode_e; + +typedef struct MVE_IVE_BernsenCtrl_s +{ + MVE_IVE_BernsenMode_e enMode; + MI_U8 u8WinSize; /*3 or 5*/ + MI_U8 u8Thr; +} MVE_IVE_BernsenCtrl_t; + +typedef struct MVE_IVE_AdpThreshCtrl_s +{ + MI_U8 u8RateThr; + MI_U8 u8HalfMaskx; + MI_U8 u8HalfMasky; + MI_S8 s8Offset; + MI_U8 u8ValueThr; +} MVE_IVE_AdpThreshCtrl_t; + +typedef struct MVE_IVE_LineFilterHorCtrl_s +{ + MI_U8 u8GapMinLen; + MI_U8 u8DensityThr; + MI_U8 u8HorThr; +} MVE_IVE_LineFilterHorCtrl_t; + +typedef struct MVE_IVE_LineFilterVerCtrl_s +{ + MI_U8 u8VerThr; +} MVE_IVE_LineFilterVerCtrl_t; + +typedef struct MVE_IVE_NoiseRemoveHorCtrl_s +{ + MI_U8 u8HorThr; + MI_U8 u8HorThrMax; +} MVE_IVE_NoiseRemoveHorCtrl_t; + +typedef struct MVE_IVE_NoiseRemoveVerCtrl_s +{ + MI_U8 u8VerThr; + MI_U8 u8VerThrMax; +} MVE_IVE_NoiseRemoveVerCtrl_t; + +typedef enum +{ + E_MI_IVE_ACC_MODE_INCREASE = 0x0, + E_MI_IVE_ACC_MODE_DECREASE = 0x1, + E_MI_IVE_ACC_MODE_INCREASE_MAP_255TO1 = 0x2, + + E_MI_IVE_ACC_MODE_MAX +} MVE_IVE_AccMode_e; + +typedef struct MVE_IVE_AccCtrl_s +{ + MVE_IVE_AccMode_e enMode; +} MVE_IVE_AccCtrl_t; + +typedef enum +{ + E_MI_IVE_BAT_OUT_CTRL_BOTH = 0x0, /*Output horizontal and vertical*/ + E_MI_IVE_BAT_OUT_CTRL_HOR = 0x1, /*Output horizontal*/ + E_MI_IVE_BAT_OUT_CTRL_VER = 0x2, /*Output vertical*/ + + E_MI_IVE_BAT_OUT_CTRL_MAX +} MVE_IVE_BatMode_e; + +typedef struct MVE_IVE_BatCtrl_s +{ + MVE_IVE_BatMode_e enMode; + MI_U16 u16HorTimes; + MI_U16 u16VerTimes; +} MVE_IVE_BatCtrl_t; + +typedef enum +{ + E_MI_IVE_MATRIX_TRANSFORM_TYPE_C1 = 0x0, + E_MI_IVE_MATRIX_TRANSFORM_TYPE_C2 = 0x1, + E_MI_IVE_MATRIX_TRANSFORM_TYPE_C3 = 0x2, + + E_MI_IVE_MATRIX_TRANSFORM_TYPE_MAX +}MVE_IVE_MatrTranfMode_e; + +typedef struct MI_IVE_MatrTranfCtrl_S +{ + MVE_IVE_MatrTranfMode_e enMode; /*Input channel mode*/ + MI_S16 s16MatrixArray[9]; //Official +} MI_IVE_MatrTranfCtrl_t; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif/*_MI_IVE_DATATYPE_H_*/ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_jpd.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_jpd.h new file mode 100644 index 000000000..ea80ab06e --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_jpd.h @@ -0,0 +1,61 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + + +#ifndef _MI_JPD_H_ +#define _MI_JPD_H_ + + +#include "mi_jpd_datatype.h" + + +#define JPD_MAJOR_VERSION 1 +#define JPD_SUB_VERSION 0 +#define MACRO_TO_STR(macro) #macro +#define JPD_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_jpd_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_jpd_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_jpd_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_JPD_API_VERSION JPD_VERSION_STR(JPD_MAJOR_VERSION,JPD_SUB_VERSION) + + +#ifdef __cplusplus +extern "C" { +#endif + + +MI_S32 MI_JPD_InitDev(MI_JPD_InitParam_t *pstInitParam);//for str support +MI_S32 MI_JPD_DeinitDev(void);//for str support + +MI_S32 MI_JPD_CreateChn(MI_JPD_CHN JpdChn, MI_JPD_ChnCreatConf_t *pstChnCreatConf); +MI_S32 MI_JPD_DestroyChn(MI_JPD_CHN JpdChn); +MI_S32 MI_JPD_GetChnAttr(MI_JPD_CHN JpdChn, MI_JPD_ChnAttr_t *pstChnAttr); +MI_S32 MI_JPD_StartChn(MI_JPD_CHN JpdChn); +MI_S32 MI_JPD_StopChn(MI_JPD_CHN JpdChn); +MI_S32 MI_JPD_GetChnStatus(MI_JPD_CHN JpdChn, MI_JPD_ChnStatus_t *pstChnStatus); +MI_S32 MI_JPD_ResetChn(MI_JPD_CHN JpdChn); +MI_S32 MI_JPD_GetStreamBuf(MI_JPD_CHN JpdChn, MI_U32 u32RequiredLength, MI_JPD_StreamBuf_t *pstRetStreamBuf, MI_S32 s32MilliSecToWait); +MI_S32 MI_JPD_PutStreamBuf(MI_JPD_CHN JpdChn, MI_JPD_StreamBuf_t *pstRetStreamBuf); +MI_S32 MI_JPD_DropStreamBuf(MI_JPD_CHN JpdChn, MI_JPD_StreamBuf_t *pstRetStreamBuf); +MI_S32 MI_JPD_QueryStreamInfo(MI_JPD_CHN JpdChn, MI_JPD_DirectInputBuf_t *pstInputBuf, MI_JPD_StreamInfo_t *pstStreamInfo); +MI_S32 MI_JPD_DirectBufDecode(MI_JPD_CHN JpdChn, MI_JPD_DirectInputBuf_t *pstInputBuf, MI_JPD_DirectOutputBuf_t *pstOutputBuf); + + +#ifdef __cplusplus +} +#endif + + +#endif///_MI_JPD_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_jpd_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_jpd_datatype.h new file mode 100644 index 000000000..81dc74c10 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_jpd_datatype.h @@ -0,0 +1,125 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + + +#ifndef _MI_JPD_DATATYPE_H_ +#define _MI_JPD_DATATYPE_H_ + + +#include "mi_common.h" +#include "mi_sys.h" + +#define MI_JPD_CHN MI_U32 +#define MI_JPD_MAX_CHN_NUM (16) + +#define MI_DEF_JPD_ERR(err) MI_DEF_ERR(E_MI_MODULE_ID_JPD, E_MI_ERR_LEVEL_ERROR, err) + +#define MI_ERR_JPD_INVALID_DEVID MI_DEF_JPD_ERR(E_MI_ERR_INVALID_DEVID) +#define MI_ERR_JPD_INVALID_CHNID MI_DEF_JPD_ERR(E_MI_ERR_INVALID_CHNID) +#define MI_ERR_JPD_ILLEGAL_PARAM MI_DEF_JPD_ERR(E_MI_ERR_ILLEGAL_PARAM) +#define MI_ERR_JPD_CHN_EXIST MI_DEF_JPD_ERR(E_MI_ERR_EXIST) +#define MI_ERR_JPD_CHN_UNEXIST MI_DEF_JPD_ERR(E_MI_ERR_UNEXIST) +#define MI_ERR_JPD_NULL_PTR MI_DEF_JPD_ERR(E_MI_ERR_NULL_PTR) +#define MI_ERR_JPD_NOT_CONFIG MI_DEF_JPD_ERR(E_MI_ERR_NOT_CONFIG) +#define MI_ERR_JPD_NOT_SUPPORT MI_DEF_JPD_ERR(E_MI_ERR_NOT_SUPPORT) +#define MI_ERR_JPD_NOT_PERM MI_DEF_JPD_ERR(E_MI_ERR_NOT_PERM) +#define MI_ERR_JPD_NOMEM MI_DEF_JPD_ERR(E_MI_ERR_NOMEM) +#define MI_ERR_JPD_NOBUF MI_DEF_JPD_ERR(E_MI_ERR_NOBUF) +#define MI_ERR_JPD_BUF_EMPTY MI_DEF_JPD_ERR(E_MI_ERR_BUF_EMPTY) +#define MI_ERR_JPD_BUF_FULL MI_DEF_JPD_ERR(E_MI_ERR_BUF_FULL) +#define MI_ERR_JPD_SYS_NOTREADY MI_DEF_JPD_ERR(E_MI_ERR_SYS_NOTREADY) +#define MI_ERR_JPD_BADADDR MI_DEF_JPD_ERR(E_MI_ERR_BADADDR) +#define MI_ERR_JPD_BUSY MI_DEF_JPD_ERR(E_MI_ERR_BUSY) +#define MI_ERR_JPD_CHN_NOT_START MI_DEF_JPD_ERR(E_MI_ERR_CHN_NOT_STARTED) +#define MI_ERR_JPD_CHN_NOT_STOP MI_DEF_JPD_ERR(E_MI_ERR_CHN_NOT_STOPED) +#define MI_ERR_JPD_NOT_INIT MI_DEF_JPD_ERR(E_MI_ERR_NOT_INIT) +#define MI_ERR_JPD_INITED MI_DEF_JPD_ERR(E_MI_ERR_INITED) +#define MI_ERR_JPD_CHN_NO_CONTENT MI_DEF_JPD_ERR(E_MI_ERR_CHN_NO_CONTENT) +#define MI_ERR_JPD_FAILED MI_DEF_JPD_ERR(E_MI_ERR_FAILED) + +typedef enum +{ + E_MI_JPD_ERR_CODE_UNKNOW = 0x0, + E_MI_JPD_ERR_CODE_ILLEGAL_ACCESS, + E_MI_JPD_ERR_CODE_DEC_TIMEOUT, + E_MI_JPD_ERR_CODE_OUT_OF_MEMORY, + E_MI_JPD_ERR_CODE_MAX +} MI_JPD_ErrCode_e; + +typedef struct MI_JPD_InitParam_s +{ + MI_U32 u32Reserved; +} MI_JPD_InitParam_t; + +typedef struct MI_JPD_ChnCreatConf_s +{ + MI_U32 u32StreamBufSize; + MI_SYS_PixelFormat_e ePixelFormat; + MI_U32 u32MaxPicWidth; + MI_U32 u32MaxPicHeight; +} MI_JPD_ChnCreatConf_t; + +typedef struct MI_JPD_StreamInfo_s +{ + MI_U32 u32CurPicWidth; + MI_U32 u32CurPicHeight; + MI_SYS_PixelFormat_e ePixelFormat; +} MI_JPD_StreamInfo_t; + +typedef struct MI_JPD_ChnAttr_s +{ + MI_U32 u32StreamBufSize; + MI_JPD_StreamInfo_t stStreamInfo; +} MI_JPD_ChnAttr_t; + +typedef struct MI_JPD_ChnStatus_s +{ + MI_U32 u32LeftStreamBytes; + MI_U32 u32LeftStreamFrames; + MI_U32 u32LeftPics; + MI_U32 u32RecvStreamFrames; + MI_U32 u32DecodeStreamFrames; + MI_BOOL bChnStart; + MI_JPD_ErrCode_e eErrCode; +} MI_JPD_ChnStatus_t; + +typedef struct MI_JPD_StreamBuf_s +{ + MI_U8 *pu8HeadVirtAddr;//ring buffer first part user mode VA + MI_PHY u64HeadPhyAddr;//ring buffer first part PA + MI_U32 u32HeadLength;//ring buffer first part Length + MI_U8 *pu8TailVirtAddr;//ring buffer 2nd part user mode VA + MI_PHY u64TailPhyAddr;//ring buffer 2nd part PA + MI_U32 u32TailLength;//ring buffer 2nd part length + MI_U32 u32ContentLength;//current used content length +} MI_JPD_StreamBuf_t; + +typedef struct MI_JPD_DirectInputBuf_s +{ + MI_U8 *pu8InputJPGRawFrameDataVirtAddr; + MI_PHY phyAddr; + MI_U32 u32Length; +} MI_JPD_DirectInputBuf_t; + +typedef struct MI_JPD_DirectOutputBuf_s +{ + MI_SYS_PixelFormat_e ePixelFormat; + MI_U32 u32Width; + MI_U32 u32Height; + MI_U32 u32Stride[2]; + MI_PHY phyAddr[2]; +} MI_JPD_DirectOutputBuf_t; + +#endif///_MI_JPD_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ldc.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ldc.h new file mode 100644 index 000000000..3519111a8 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ldc.h @@ -0,0 +1,56 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef __MI_LDC_H__ +#define __MI_LDC_H__ + +#include "mi_ldc_datatype.h" + +#define LDC_MAJOR_VERSION 2 +#define LDC_SUB_VERSION 4 +#define MACRO_TO_STR(macro) #macro +#define LDC_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_ldc_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_ldc_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_ldc_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_LDC_API_VERSION LDC_VERSION_STR(LDC_MAJOR_VERSION,LDC_SUB_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + + +MI_S32 MI_LDC_CreateDevice(MI_LDC_DEV devId); +MI_S32 MI_LDC_DestroyDevice(MI_LDC_DEV devId); + +MI_S32 MI_LDC_CreateChannel(MI_LDC_DEV devId, MI_LDC_CHN chnId); +MI_S32 MI_LDC_DestroyChannel(MI_LDC_DEV devId, MI_LDC_CHN chnId); + +MI_S32 MI_LDC_StartChannel(MI_LDC_DEV devId, MI_LDC_CHN chnId); +MI_S32 MI_LDC_StopChannel(MI_LDC_DEV devId, MI_LDC_CHN chnId); + +MI_S32 MI_LDC_GetOutputPortAttr(MI_LDC_DEV devId, MI_LDC_CHN chnId, MI_LDC_OutputPortAttr_t *pstOutputAttr); + +MI_S32 MI_LDC_SetConfig(MI_LDC_DEV devId, MI_LDC_CHN chnId, void *pConfigAddr, MI_U32 u32ConfigSize); +MI_S32 MI_LDC_SetBatchViewConfig(MI_LDC_DEV devId, MI_LDC_CHN chnId, MI_LDC_Config_t *pstCfg, MI_U32 u32CfgNum); + +MI_S32 MI_LDC_InitDev(MI_LDC_InitParam_t *pstInitParam); +MI_S32 MI_LDC_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif///_MI_VPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ldc_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ldc_datatype.h new file mode 100644 index 000000000..0ebeec588 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_ldc_datatype.h @@ -0,0 +1,82 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_LDC_DATATYPE_H_ +#define _MI_LDC_DATATYPE_H_ +#include "mi_sys_datatype.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + E_MI_LDC_ERR_DEV_CREATED = MI_LDC_INITIAL_ERROR_CODE, // dev has been created + E_MI_LDC_ERR_DEV_NOT_CREATE, // dev not be created + E_MI_LDC_ERR_DEV_NOT_DESTROY, // dev not be destroyed + E_MI_LDC_ERR_CHN_CREATED, // chn has been created + E_MI_LDC_ERR_CHN_NOT_CREATE, // chn not be created + E_MI_LDC_ERR_CHN_NOT_STOP, // chn is still working + E_MI_LDC_ERR_CHN_NOT_DESTROY, // chn not be destroyed + E_MI_LDC_ERR_PORT_NOT_UNBIND, // port not unbind +} MI_LDC_ErrCode_e; + +typedef MI_U32 MI_LDC_DEV; +typedef MI_U32 MI_LDC_CHN; + +typedef struct MI_LDC_OutputPortAttr_s +{ + MI_U16 u16Width; + MI_U16 u16Height; + MI_SYS_PixelFormat_e ePixelFmt; +} MI_LDC_OutputPortAttr_t; + +typedef struct MI_LDC_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_LDC_InitParam_t; + +typedef struct MI_LDC_Config_s +{ + void *pCfgAddr; + MI_U32 u32CfgSize; +} MI_LDC_Config_t; + +#define MI_LDC_OK MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_INFO, MI_SUCCESS) +#define MI_ERR_LDC_ILLEGAL_PARAM MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_ILLEGAL_PARAM) +#define MI_ERR_LDC_NULL_PTR MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NULL_PTR) +#define MI_ERR_LDC_BUSY MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUSY) +#define MI_ERR_LDC_FAIL MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_FAILED) +#define MI_ERR_LDC_INVALID_DEVID MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_DEVID) +#define MI_ERR_LDC_NOT_SUPPORT MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_SUPPORT) +#define MI_ERR_LDC_MOD_INITED MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INITED) +#define MI_ERR_LDC_MOD_NOT_INIT MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_INIT) +#define MI_ERR_LDC_DEV_CREATED MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_LDC_ERR_DEV_CREATED) +#define MI_ERR_LDC_DEV_NOT_CREATE MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_LDC_ERR_DEV_NOT_CREATE) +#define MI_ERR_LDC_DEV_NOT_DESTROY MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_LDC_ERR_DEV_NOT_DESTROY) +#define MI_ERR_LDC_CHN_CREATED MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_LDC_ERR_CHN_CREATED) +#define MI_ERR_LDC_CHN_NOT_CREATE MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_LDC_ERR_CHN_NOT_CREATE) +#define MI_ERR_LDC_CHN_NOT_STOP MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_LDC_ERR_CHN_NOT_STOP) +#define MI_ERR_LDC_CHN_NOT_DESTROY MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_LDC_ERR_CHN_NOT_DESTROY) +#define MI_ERR_LDC_PORT_NOT_DISABLE MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_DISABLE) +#define MI_ERR_LDC_PORT_NOT_UNBIND MI_DEF_ERR(E_MI_MODULE_ID_LDC, E_MI_ERR_LEVEL_ERROR, E_MI_LDC_ERR_PORT_NOT_UNBIND) + + +#ifdef __cplusplus +} +#endif + +#endif///_MI_VPE_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_md.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_md.h new file mode 100644 index 000000000..2aafdd8b4 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_md.h @@ -0,0 +1,167 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef __MI_MD_H__ +#define __MI_MD_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum _MI_MD_RET_E +{ + MI_MD_RET_SUCCESS = 0x00000000, /*MD API execution success*/ + MI_MD_RET_INIT_ERROR = 0x10000401, /*MD init error*/ + MI_MD_RET_IC_CHECK_ERROR = 0x10000402, /*Incorrect platform check for MD*/ + MI_MD_RET_INVALID_HANDLE = 0x10000403, /*Invalid MD handle*/ + MI_MD_RET_INVALID_PARAMETER = 0x10000404, /*Invalid MD parameter*/ + MI_MD_RET_MALLOC_ERROR = 0x10000405, /*Allocate MD workiung buffer error*/ + +} MI_MD_RET; + +typedef void* MD_HANDLE; + +typedef enum MDMB_MODE_E +{ + MDMB_MODE_MB_4x4 = 0x0, + MDMB_MODE_MB_8x8 = 0x1, + MDMB_MODE_MB_16x16 = 0x2, + MDMB_MODE_BUTT +} MDMB_MODE_e; + +typedef enum MDSAD_OUT_CTRL_E +{ + MDSAD_OUT_CTRL_16BIT_SAD = 0x0, + MDSAD_OUT_CTRL_8BIT_SAD = 0x1, + MDSAD_OUT_CTRL_BUTT +} MDSAD_OUT_CTRL_e; + +typedef enum MDALG_MODE_E +{ + MDALG_MODE_FG = 0x0, + MDALG_MODE_SAD = 0x1, + MDALG_MODE_FRAMEDIFF = 0x2, + MDALG_MODE_BUTT +} MDALG_MODE_e; + +typedef struct MDCCL_ctrl_s +{ + uint16_t u16InitAreaThr; + uint16_t u16Step; +} MDCCL_ctrl_t; + +typedef struct MDPreproc_ctrl_s +{ + uint16_t u16Md_rgn_size; + uint16_t u16Align; +} MDPreproc_ctrl_t; + +typedef struct MDblock_info_s +{ + uint16_t st_x; + uint16_t st_y; + uint16_t end_x; + uint16_t end_y; +} MDblock_info_t; + +typedef struct MDPoint_s +{ + uint16_t x; + uint16_t y; +} MDPoint_t; + +typedef struct MDROI_s +{ + uint8_t num; + MDPoint_t pnt[8]; +} MDROI_t; + +typedef struct MDSAD_DATA_s +{ + void *paddr; + uint32_t stride; + MDSAD_OUT_CTRL_e enOutCtrl; + +} MDSAD_DATA_t; + +typedef struct MDOBJ_s +{ + uint32_t u32Area; + uint16_t u16Left; + uint16_t u16Right; + uint16_t u16Top; + uint16_t u16Bottom; +} MDOBJ_t; + +typedef struct MDOBJ_DATA_s +{ + uint8_t u8RegionNum; + MDOBJ_t *astRegion; + uint8_t indexofmaxobj; + uint32_t areaofmaxobj; + uint32_t areaoftotalobj; + +} MDOBJ_DATA_t; + +typedef struct MI_MD_IMG_s +{ + void *pu32PhyAddr; + uint8_t *pu8VirAddr; +} MI_MD_IMG_t; + +typedef struct MI_MD_static_param_s +{ + uint16_t width; + uint16_t height; + uint8_t color; + uint32_t stride; + MDMB_MODE_e mb_size; + MDSAD_OUT_CTRL_e sad_out_ctrl; + MDROI_t roi_md; + MDALG_MODE_e md_alg_mode; +} MI_MD_static_param_t; + +typedef struct MI_MD_param_s +{ + uint8_t sensitivity; + uint16_t learn_rate; + uint32_t md_thr; + uint32_t obj_num_max; + uint8_t LSD_open; +} MI_MD_param_t; + +uint32_t MI_MD_GetLibVersion(); +MD_HANDLE MI_MD_Init(MI_MD_static_param_t *static_param, MI_MD_param_t *param); +void MI_MD_Uninit(MD_HANDLE handle); +int32_t MI_MD_Run(MD_HANDLE handle, const MI_MD_IMG_t* pImage); +MI_MD_RET MI_MD_Preproc(MD_HANDLE handle, const MI_MD_IMG_t* pImage0, const MI_MD_IMG_t* pImage1, MDPreproc_ctrl_t* PpCtrl, MDSAD_DATA_t *sad_data, MDblock_info_t *md_region); + +MI_MD_RET MI_MD_SetParam(MD_HANDLE handle, MI_MD_param_t *param); +MI_MD_RET MI_MD_GetParam(MD_HANDLE handle, MI_MD_param_t *param); +MI_MD_RET MI_MD_GetMBResult(MD_HANDLE handle, uint8_t *result_img, uint32_t *result_len); + +MI_MD_RET MI_MD_ComputeImageSAD(MD_HANDLE handle, const MI_MD_IMG_t* pImage, MDSAD_DATA_t *sad_data); +MI_MD_RET MI_MD_CCL(MD_HANDLE handle, MDCCL_ctrl_t* pCclCtrl, MDOBJ_DATA_t *ccobj); +MI_MD_RET MI_MD_GetMotionCnt(MD_HANDLE handle, uint32_t *obj_cnt); +MI_MD_RET MI_MD_LightSwitchDetect(MD_HANDLE handle, const MI_MD_IMG_t* pImage, MDOBJ_DATA_t *ccobj); + +void MI_MD_SetTime(MD_HANDLE handle, uint32_t time_diff); + +#ifdef __cplusplus +} +#endif + +#endif /* __MI_MD_H__ */ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_mipitx.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_mipitx.h new file mode 100644 index 000000000..d0b5f7f82 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_mipitx.h @@ -0,0 +1,53 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_MIPITX_H_ +#define _MI_MIPITX_H_ + +#include "mi_mipitx_datatype.h" + + +#define MIPITX_MAJOR_VERSION 2 +#define MIPITX_SUB_VERSION 0 +#define MACRO_TO_STR(macro) #macro +#define MIPITX_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_mipitx_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_mipitx_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_mipitx_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_MIPITX_API_VERSION MIPITX_VERSION_STR(MIPITX_MAJOR_VERSION,MIPITX_SUB_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + +MI_S32 MI_MipiTx_CreateChannel(MI_U32 u32ChannelId, MI_MipiTx_ChannelAttr_t *pstMipiTxChAttr); +MI_S32 MI_MipiTx_DestroyChannel(MI_U32 u32ChannelId); + +MI_S32 MI_MipiTx_GetChannelAttr(MI_U32 u32ChannelId, MI_MipiTx_ChannelAttr_t *pstMipiTxChAttr); + +MI_S32 MI_MipiTx_StartChannel(MI_U32 u32ChannelId); +MI_S32 MI_MipiTx_StopChannel(MI_U32 u32ChannelId); + +MI_S32 MI_MipiTx_SetTimingConfig(MI_U32 u32ChannelId, MI_MipiTx_TimingConfig_t *pstMipiTimingCfg); +MI_S32 MI_MipiTx_GetTimingConfig(MI_U32 u32ChannelId, MI_MipiTx_TimingConfig_t *pstMipiTimingCfg); +MI_S32 MI_MipiTx_InitDev(MI_MipiTx_InitParam_t *pstInitParam); +MI_S32 MI_MipiTx_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_mipitx_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_mipitx_datatype.h new file mode 100644 index 000000000..292af6c47 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_mipitx_datatype.h @@ -0,0 +1,88 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_MIPITX_DATATYPE_H_ +#define _MI_MIPITX_DATATYPE_H_ + +#include "mi_sys_datatype.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MI_ERR_MIPITX_CHN_HAVECREATE MI_DEF_ERR(E_MI_MODULE_ID_MIPITX, E_MI_ERR_LEVEL_WARNING, E_MI_ERR_INITED) +#define MI_ERR_MIPITX_CHNID_INVALID MI_DEF_ERR(E_MI_MODULE_ID_MIPITX, E_MI_ERR_LEVEL_WARNING, E_MI_ERR_INVALID_CHNID) +#define MI_ERR_MIPITX_CHN_NOTSTOP MI_DEF_ERR(E_MI_MODULE_ID_MIPITX, E_MI_ERR_LEVEL_WARNING, E_MI_ERR_CHN_NOT_STOPED) +#define MI_ERR_MIPITX_ILLEGAL_PARAM MI_DEF_ERR(E_MI_MODULE_ID_MIPITX, E_MI_ERR_LEVEL_WARNING, E_MI_ERR_ILLEGAL_PARAM) + + +#define MI_ERR_MIPITX_RUNFAIL MI_DEF_ERR(E_MI_MODULE_ID_MIPITX, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_EXIST) +#define MI_ERR_MIPITX_NULL_PTR MI_DEF_ERR(E_MI_MODULE_ID_MIPITX, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NULL_PTR) + +typedef struct MI_MipiTx_TimingConfig_s +{ + MI_U8 u8Lpx; + MI_U8 u8ClkHsPrpr; + MI_U8 u8ClkZero; + MI_U8 u8ClkHsPre; + MI_U8 u8ClkHsPost; + MI_U8 u8ClkTrail; + MI_U8 u8HsPrpr; + MI_U8 u8HsZero; + MI_U8 u8HsTrail; +} MI_MipiTx_TimingConfig_t; + +typedef enum +{ + E_MI_MIPITX_LANE_NUM_NONE = 0, + E_MI_MIPITX_LANE_NUM_1 = 1, + E_MI_MIPITX_LANE_NUM_2 = 2, + E_MI_MIPITX_LANE_NUM_3 = 3, + E_MI_MIPITX_LANE_NUM_4 = 4, +} MI_MipiTx_LaneNum_e; + +typedef enum +{ + E_MI_MIPITX_CH_SWAP_0, + E_MI_MIPITX_CH_SWAP_1, + E_MI_MIPITX_CH_SWAP_2, + E_MI_MIPITX_CH_SWAP_3, + E_MI_MIPITX_CH_SWAP_4, +} MI_MipiTx_ChannelSwapType_e; + +typedef struct +{ + MI_U32 u32Width; + MI_U32 u32Height; + MI_SYS_PixelFormat_e ePixFormat; // YUV422 YVYU, RAW8 + MI_MipiTx_LaneNum_e eLaneNum; + + MI_U8 u8DCLKDelay; ///< DCLK Delay + MI_U32 u32Dclk; ///< DCLK ( Htt * Vtt * Fps) + + MI_MipiTx_ChannelSwapType_e *peChSwapType; ///< all lane order swap +}MI_MipiTx_ChannelAttr_t; + +typedef struct MI_MipiTx_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_MipiTx_InitParam_t; + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_od.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_od.h new file mode 100644 index 000000000..921dfda82 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_od.h @@ -0,0 +1,108 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef __MI_OD_H__ +#define __MI_OD_H__ + +#include +#ifdef __cplusplus +extern "C" +{ +#endif +typedef enum _MI_OD_RET_E +{ + MI_OD_RET_SUCCESS = 0x00000000, /*OD API execution success*/ + + MI_OD_RET_INIT_ERROR = 0x10000501, /*OD init error*/ + MI_OD_RET_IC_CHECK_ERROR = 0x10000502, /*Incorrect platform check for OD*/ + MI_OD_RET_INVALID_HANDLE = 0x10000503, /*Invalid OD handle*/ + MI_OD_RET_INVALID_PARAMETER = 0x10000504, /*Invalid OD parameter*/ + MI_OD_RET_INVALID_WINDOW = 0x10000505, /*Invalid window*/ + MI_OD_RET_INVALID_COLOR_TYPE = 0x10000506, /*Invalid color tpye*/ +} MI_OD_RET; +typedef enum _MI_OD_WIN_STATE +{ + MI_OD_WIN_STATE_NON_TAMPER = 0, + MI_OD_WIN_STATE_TAMPER = 1, + MI_OD_WIN_STATE_NO_FEATURE = 2, + MI_OD_WIN_STATE_FAIL = -1, +} MI_OD_WIN_STATE; + +typedef enum +{ + OD_Y = 1, + OD_COLOR_MAX +} ODColor_e; + +typedef enum +{ + OD_WINDOW_1X1 = 0, + OD_WINDOW_2X2, + OD_WINDOW_3X3, + OD_WINDOW_MAX +} ODWindow_e; + +typedef struct ODPoint_s +{ + uint16_t x; + uint16_t y; +} ODPoint_t; + +typedef struct ODROI_s +{ + uint8_t num; + ODPoint_t pnt[8]; +} ODROI_t; + +typedef struct MI_OD_IMG_s +{ + void *pu32PhyAddr; + uint8_t *pu8VirAddr; +} MI_OD_IMG_t; + +typedef struct MI_OD_static_param_s +{ + uint16_t inImgW; + uint16_t inImgH; + uint32_t inImgStride; + ODColor_e nClrType; + ODWindow_e div; + ODROI_t roi_od; + int32_t alpha; + int32_t M; + int32_t MotionSensitivity; + +} MI_OD_static_param_t; + +typedef struct MI_OD_param_s +{ + int32_t thd_tamper; + int32_t tamper_blk_thd; + int32_t min_duration; +} MI_OD_param_t; + +typedef void* OD_HANDLE; + +uint32_t MI_OD_GetLibVersion(); +OD_HANDLE MI_OD_Init(MI_OD_static_param_t *static_param, MI_OD_param_t *param); +int32_t MI_OD_Run(OD_HANDLE odHandle, const MI_OD_IMG_t* yImage); +MI_OD_RET MI_OD_GetDetectWindowSize(OD_HANDLE odHandle, uint16_t* st_x, uint16_t* st_y, uint16_t* div_w, uint16_t* div_h); +MI_OD_WIN_STATE MI_OD_GetWindowResult(OD_HANDLE odHandle, uint8_t col, uint8_t row); +MI_OD_RET MI_OD_SetAttr(OD_HANDLE odHandle, MI_OD_param_t *param); +MI_OD_RET MI_OD_GetAttr(OD_HANDLE odHandle, MI_OD_param_t *param); +void MI_OD_Uninit(OD_HANDLE odHandle); +#ifdef __cplusplus +} +#endif + +#endif //__MI_OD_H__ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_panel.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_panel.h new file mode 100644 index 000000000..8842173ea --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_panel.h @@ -0,0 +1,56 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_PANEL_H_ +#define _MI_PANEL_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "mi_common.h" +#include "mi_panel_datatype.h" + +#define PANEL_MAJOR_VERSION 2 +#define PANEL_SUB_VERSION 11 +#define MACRO_TO_STR(macro) #macro +#define PANEL_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_panel_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_panel_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_panel_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_PANEL_API_VERSION PANEL_VERSION_STR(PANEL_MAJOR_VERSION,PANEL_SUB_VERSION) + +MI_S32 MI_PANEL_Init(MI_PANEL_IntfType_e eIntfType); +MI_S32 MI_PANEL_DeInit(void); +MI_S32 MI_PANEL_GetTotalNum(MI_U32 *pu32TotalNum); +MI_S32 MI_PANEL_SetPowerOn(MI_PANEL_IntfType_e eIntfType, MI_PANEL_PowerConfig_t *pstPowerCfg); +MI_S32 MI_PANEL_GetPowerOn(MI_PANEL_IntfType_e eIntfType, MI_PANEL_PowerConfig_t *pstPowerCfg); +MI_S32 MI_PANEL_SetBackLight(MI_PANEL_IntfType_e eIntfType, MI_PANEL_BackLightConfig_t *pstBackLightCfg); +MI_S32 MI_PANEL_GetBackLight(MI_PANEL_IntfType_e eIntfType, MI_PANEL_BackLightConfig_t *pstBackLightCfg); +MI_S32 MI_PANEL_SetBackLightLevel(MI_PANEL_IntfType_e eIntfType, MI_PANEL_BackLightConfig_t *pstBackLightCfg); +MI_S32 MI_PANEL_GetBackLightLevel(MI_PANEL_IntfType_e eIntfType, MI_PANEL_BackLightConfig_t *pstBackLightCfg); +MI_S32 MI_PANEL_SetSscConfig(MI_PANEL_IntfType_e eIntfType, MI_PANEL_SscConfig_t *pstSscCfg); +MI_S32 MI_PANEL_SetMipiDsiConfig(MI_PANEL_IntfType_e eIntfType, MI_PANEL_MipiDsiConfig_t *pstMipiDsiCfg); +MI_S32 MI_PANEL_SetTimingConfig(MI_PANEL_IntfType_e eIntfType, MI_PANEL_TimingConfig_t *pstTimingCfg); +MI_S32 MI_PANEL_SetDrvCurrentConfig(MI_PANEL_IntfType_e eIntfType, MI_PANEL_DrvCurrentConfig_t *pstDrvCurrentCfg); +MI_S32 MI_PANEL_SetOutputPattern(MI_PANEL_IntfType_e eIntfType, MI_PANEL_TestPatternConfig_t * pstTestPatternCfg); +MI_S32 MI_PANEL_SetPanelParam(MI_PANEL_IntfType_e eIntfType, MI_PANEL_ParamConfig_t *pstParamCfg); +MI_S32 MI_PANEL_GetPanelParam(MI_PANEL_IntfType_e eIntfType, MI_PANEL_ParamConfig_t *pstParamCfg); +MI_S32 MI_PANEL_InitDev(MI_PANEL_InitParam_t *pstInitParam); +MI_S32 MI_PANEL_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif ///_MI_PANEL_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_panel_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_panel_datatype.h new file mode 100644 index 000000000..090ee8234 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_panel_datatype.h @@ -0,0 +1,341 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_PANEL_DATATYPE_H_ +#define _MI_PANEL_DATATYPE_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "mi_common.h" + + +/*------------------------------------------------------------------------------------------------- + * Enum + ------------------------------------------------------------------------------------------------*/ + +typedef enum +{ + E_MI_PNL_MIPI_DSI_LANE_NONE = 0, + E_MI_PNL_MIPI_DSI_LANE_1 = 1, + E_MI_PNL_MIPI_DSI_LANE_2 = 2, + E_MI_PNL_MIPI_DSI_LANE_3 = 3, + E_MI_PNL_MIPI_DSI_LANE_4 = 4, +}MI_PANEL_MipiDsiLaneMode_e; + +typedef enum +{ + E_MI_PNL_MIPI_DSI_RGB565 = 0, + E_MI_PNL_MIPI_DSI_RGB666 = 1, + E_MI_PNL_MIPI_DSI_LOOSELY_RGB666 = 2, + E_MI_PNL_MIPI_DSI_RGB888 = 3, +}MI_PANEL_MipiDsiFormat_e; + +typedef enum +{ + E_MI_PNL_MIPI_DSI_CMD_MODE = 0, + E_MI_PNL_MIPI_DSI_SYNC_PULSE = 1, + E_MI_PNL_MIPI_DSI_SYNC_EVENT = 2, + E_MI_PNL_MIPI_DSI_BURST_MODE = 3, +}MI_PANEL_MipiDsiCtrlMode_e; + +typedef enum +{ + E_MI_PNL_INTF_TTL, ///< TTL type + E_MI_PNL_INTF_LVDS, ///< LVDS type + E_MI_PNL_INTF_RSDS, ///< RSDS type + E_MI_PNL_INTF_MINILVDS, ///< TCON + E_MI_PNL_INTF_ANALOG_MINILVDS, ///< Analog TCON + E_MI_PNL_INTF_DIGITAL_MINILVDS, ///< Digital TCON + E_MI_PNL_INTF_MFC, ///< Ursa (TTL output to Ursa) + E_MI_PNL_INTF_DAC_I, ///< DAC output + E_MI_PNL_INTF_DAC_P, ///< DAC output + E_MI_PNL_INTF_PDPLVDS, ///< For PDP(Vsync use Manually MODE) + E_MI_PNL_INTF_EXT, ///< EXT LPLL TYPE + E_MI_PNL_INTF_MIPI_DSI, ///< Mipi DSI + E_MI_PNL_INTF_BT656, +}MI_PANEL_IntfType_e; + +typedef enum +{ + E_MI_PNL_ASPECT_RATIO_4_3 = 0, ///< set aspect ratio to 4 : 3 + E_MI_PNL_ASPECT_RATIO_WIDE, ///< set aspect ratio to 16 : 9 + E_MI_PNL_ASPECT_RATIO_OTHER, ///< resvered for other aspect ratio other than 4:3/ 16:9 +}MI_PANEL_AspectRatio_e; + +typedef enum +{ + E_MI_PNL_TI_10BIT_MODE = 0, + E_MI_PNL_TI_8BIT_MODE = 2, + E_MI_PNL_TI_6BIT_MODE = 3, +}MI_PANEL_TiBitMode_e; + +typedef enum +{ + E_MI_PNL_OUTPUT_10BIT_MODE = 0, //default is 10bit, becasue 8bit panel can use 10bit config and 8bit config. + E_MI_PNL_OUTPUT_6BIT_MODE = 1, //but 10bit panel(like PDP panel) can only use 10bit config. + E_MI_PNL_OUTPUT_8BIT_MODE = 2, //and some PDA panel is 6bit. + E_MI_PNL_OUTPUT_565BIT_MODE = 3, +}MI_PANEL_OutputFormatBitMode_e; + +typedef enum +{ + E_MI_PNL_CHG_DCLK = 0, ///MI_VDF_MD_RESULT_S +// |——Vi-Chn0 ->MD_RESULT_HANDLE_LIST +// | |——Handle1 -->MD_RESULT_S +// | | |——sub-window-0 +// | | |——sub-window-1 +// | | |——... +// | | |__sub-window-255 +// | | +// | |——Handle2 +// | | |——sub-window-0 +// | | |——sub-window-1 +// | | |——... +// | | |__sub-window-255 +// | | +// | |——Handle... +// | +// |——Vi-Chn1 +// | |——Handle1 -->MD_RESULT_S +// | | |——sub-window-0 +// | | |——sub-window-1 +// | | |——... +// | | |__sub-window-255 +// | | +// | |——Handle2 +// | | |——sub-window-0 +// | | |——sub-window-1 +// | | |——... +// | | |__sub-window-255 +// | | +// | |——Handle... +// | +// |——Vi-Chnx +// | + +//——OD -->MI_VDF_OD_RESULT_S +// |——Vi-Chn0 +// | |——Handle1 -->OD_RESULT_S +// | | |——sub-window-0 +// | | |——sub-window-1 +// | | |——... +// | | |__sub-window-8 +// | | +// | |——Handle2 +// | | |——sub-window-0 +// | | |——sub-window-1 +// | | |——... +// | | |__sub-window-8 +// | | +// | |——Handle... +// | +// |——Vi-Chn1 +// | |——Handle1 -->OD_RESULT_S +// | | |——sub-window-0 +// | | |——sub-window-1 +// | | |——... +// | | |__sub-window-8 +// | | +// | |——Handle2 +// | | |——sub-window-0 +// | | |——sub-window-1 +// | | |——... +// | | |__sub-window-8 +// | | +// | |——Handle... +// | +// |——Vi-Chnx +// | + +typedef struct MDRST_STATUS_s +{ + MI_U8 *paddr; // 0-区块未检测运动,255-区块检测到运动 +} MDRST_STATUS_t; + +typedef struct MI_MD_Result_s +{ + MI_U64 u64Pts; //The PTS of Image + MI_U8 u8Enable; //=1表明该结果值有效 + MI_MD_ResultSize_t stSubResultSize; + MDRST_STATUS_t* pstMdResultStatus; //The MD result of Status + MDSAD_DATA_t* pstMdResultSad; //The MD result of SAD + MDOBJ_DATA_t* pstMdResultObj; //The MD result of Obj +} MI_MD_Result_t; + +typedef struct MI_OD_Result_s +{ + MI_U8 u8Enable; + MI_U8 u8WideDiv; //The number of divisions of window in horizontal direction + MI_U8 u8HightDiv; //The number of divisions of window in vertical direction + MI_U8 u8DataLen; //OD detect result readable size + MI_U64 u64Pts; //The PTS of Image + MI_S8 u8RgnAlarm[3][3]; //The OD result of the sub-window + MI_S32 od_status; //od_status=0 -> No OD detected, od_status>0 OD detected +} MI_OD_Result_t; + +typedef MI_VgResult_t MI_VG_Result_t; + +typedef struct MI_VDF_Result_s +{ + MI_VDF_WorkMode_e enWorkMode; + VDF_RESULT_HANDLE handle; + union + { + MI_MD_Result_t stMdResult; + MI_OD_Result_t stOdResult; + MI_VG_Result_t stVgResult; + }; +} MI_VDF_Result_t; + +typedef struct MI_VDF_ChnStat_s +{ + MI_BOOL bStart; + MI_U8 u32LeftPic; + MI_U8 u32LeftRst; +} MI_VDF_ChnStat_t; + +typedef struct MI_VDF_DebugInfo_s +{ + MI_VDF_WorkMode_e enWorkMode; + union + { + MI_VgDebug_t stVgDebugInfo; + }; +} MI_VDF_DebugInfo_t; + +#endif///_MI_VDF_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vdisp.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vdisp.h new file mode 100644 index 000000000..ffa356de1 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vdisp.h @@ -0,0 +1,67 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_VDISP_H_ +#define _MI_VDISP_H_ +#include "mi_vdisp_datatype.h" + +#define VDISP_MAJOR_VERSION 2 +#define VDISP_SUB_VERSION 5 +#define MACRO_TO_STR(macro) #macro +#define VDISP_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_vdisp_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_vdisp_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_vdisp_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_VDISP_API_VERSION VDISP_VERSION_STR(VDISP_MAJOR_VERSION,VDISP_SUB_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + +MI_S32 MI_VDISP_Init(void); +MI_S32 MI_VDISP_Exit(void); + +MI_S32 MI_VDISP_OpenDevice(MI_VDISP_DEV DevId); +MI_S32 MI_VDISP_CloseDevice(MI_VDISP_DEV DevId); + +MI_S32 MI_VDISP_SetOutputPortAttr(MI_VDISP_DEV DevId, + MI_VDISP_PORT PortId, + MI_VDISP_OutputPortAttr_t *pstOutputPortAttr); +MI_S32 MI_VDISP_GetOutputPortAttr(MI_VDISP_DEV DevId, + MI_VDISP_PORT PortId, + MI_VDISP_OutputPortAttr_t *pstOutputPortAttr); + +MI_S32 MI_VDISP_SetInputChannelAttr(MI_VDISP_DEV DevId, + MI_VDISP_CHN ChnId, + MI_VDISP_InputChnAttr_t *pstInputChnAttr); +MI_S32 MI_VDISP_GetInputChannelAttr(MI_VDISP_DEV DevId, + MI_VDISP_CHN ChnId, + MI_VDISP_InputChnAttr_t *pstInputChnAttr); + +MI_S32 MI_VDISP_EnableInputChannel(MI_VDISP_DEV DevId, + MI_VDISP_CHN ChnId); +MI_S32 MI_VDISP_DisableInputChannel(MI_VDISP_DEV DevId, + MI_VDISP_CHN ChnId); + +MI_S32 MI_VDISP_StartDev(MI_VDISP_DEV DevId); +MI_S32 MI_VDISP_StopDev(MI_VDISP_DEV DevId); + +MI_S32 MI_VDISP_InitDev(MI_VDISP_InitParam_t *pstInitParam); +MI_S32 MI_VDISP_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif///_MI_VDISP_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vdisp_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vdisp_datatype.h new file mode 100644 index 000000000..9df47f148 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vdisp_datatype.h @@ -0,0 +1,84 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_VDISP_DATATYPE_H_ +#define _MI_VDISP_DATATYPE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define VDISP_MAX_DEVICE_NUM 4 +#define VDISP_MAX_CHN_NUM_PER_DEV 16 +#define VDISP_MAX_INPUTPORT_NUM 1 +#define VDISP_MAX_OVERLAYINPUTCHN_NUM 4 +#define VDISP_OVERLAYINPUTCHNID VDISP_MAX_CHN_NUM_PER_DEV +#define VDISP_MAX_OUTPUTPORT_NUM 1 + +typedef MI_S32 MI_VDISP_DEV; +typedef MI_S32 MI_VDISP_PORT; +typedef MI_S32 MI_VDISP_CHN; + +typedef struct MI_VDISP_OutputPortAttr_s +{ + MI_U32 u32BgColor; /* Background color of a output port, in YUV format. [23:16]:v, [15:8]:y, [7:0]:u*/ + MI_SYS_PixelFormat_e ePixelFormat; /* pixel format of a output port */ + MI_U64 u64pts; /* current PTS */ + MI_U32 u32FrmRate; /* the frame rate of output port */ + MI_U32 u32Width; /* the frame width of a output port */ + MI_U32 u32Height; /* the frame height of a output port */ +} MI_VDISP_OutputPortAttr_t; + +typedef struct MI_VDISP_InputPortAttr_s +{ + MI_U32 u32OutX; /* the output frame X position of this input port */ + MI_U32 u32OutY; /* the output frame Y position of this input port */ + MI_U32 u32OutWidth; /* the output frame width of this input port */ + MI_U32 u32OutHeight; /* the output frame height of this input port */ + MI_S32 s32IsFreeRun; /* is this port free run */ +} MI_VDISP_InputChnAttr_t; + +typedef enum +{ + E_MI_VDISP_ERR_DEV_OPENED=MI_VDISP_INITIAL_ERROR_CODE, + E_MI_VDISP_ERR_DEV_NOT_OPEN, + E_MI_VDISP_ERR_DEV_NOT_CLOSE, + E_MI_VDISP_ERR_PORT_NOT_UNBIND, +}MI_VDISP_ErrCode_e; + +typedef struct MI_VDISP_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_VDISP_InitParam_t; + +#define MI_VDISP_ERR_FAIL (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_FAILED)) +#define MI_VDISP_ERR_INVALID_DEVID (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_DEVID)) +#define MI_VDISP_ERR_ILLEGAL_PARAM (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_ILLEGAL_PARAM)) +#define MI_VDISP_ERR_NOT_SUPPORT (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_SUPPORT)) +#define MI_VDISP_ERR_MOD_INITED (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INITED)) +#define MI_VDISP_ERR_MOD_NOT_INIT (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_INIT)) +#define MI_VDISP_ERR_DEV_OPENED (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_VDISP_ERR_DEV_OPENED)) +#define MI_VDISP_ERR_DEV_NOT_OPEN (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_VDISP_ERR_DEV_NOT_OPEN)) +#define MI_VDISP_ERR_DEV_NOT_STOP (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_DEV_NOT_STOPED)) +#define MI_VDISP_ERR_DEV_NOT_CLOSE (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_VDISP_ERR_DEV_NOT_CLOSE)) +#define MI_VDISP_ERR_NOT_CONFIG (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_CONFIG)) +#define MI_VDISP_ERR_PORT_NOT_DISABLE (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_DISABLE)) +#define MI_VDISP_ERR_PORT_NOT_UNBIND (MI_DEF_ERR( E_MI_MODULE_ID_VDISP, E_MI_ERR_LEVEL_ERROR, E_MI_VDISP_ERR_PORT_NOT_UNBIND)) + +#ifdef __cplusplus +} +#endif + +#endif///_MI_VDISP_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_venc.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_venc.h new file mode 100644 index 000000000..8bf74cf45 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_venc.h @@ -0,0 +1,117 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_VENC_H_ +#define _MI_VENC_H_ + +#include "mi_venc_datatype.h" + +#define VENC_MAJOR_VERSION 2 +#define VENC_SUB_VERSION 16 +#define MACRO_TO_STR(macro) #macro +#define VENC_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_venc_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_venc_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_venc_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_VENC_API_VERSION VENC_VERSION_STR(VENC_MAJOR_VERSION,VENC_SUB_VERSION) + +#ifdef __cplusplus +extern "C" +{ +#endif + +MI_S32 MI_VENC_GetChnDevid(MI_VENC_CHN VeChn, MI_U32 *pu32Devid); +MI_S32 MI_VENC_SetModParam(MI_VENC_ModParam_t *pstModParam); +MI_S32 MI_VENC_GetModParam(MI_VENC_ModParam_t *pstModParam); +MI_S32 MI_VENC_CreateChn(MI_VENC_CHN VeChn, MI_VENC_ChnAttr_t *pstAttr); +MI_S32 MI_VENC_DestroyChn(MI_VENC_CHN VeChn); +MI_S32 MI_VENC_ResetChn(MI_VENC_CHN VeChn); +MI_S32 MI_VENC_StartRecvPic(MI_VENC_CHN VeChn); +MI_S32 MI_VENC_StartRecvPicEx(MI_VENC_CHN VeChn, MI_VENC_RecvPicParam_t *pstRecvParam); +MI_S32 MI_VENC_StopRecvPic(MI_VENC_CHN VeChn); +MI_S32 MI_VENC_Query(MI_VENC_CHN VeChn, MI_VENC_ChnStat_t *pstStat); +MI_S32 MI_VENC_SetChnAttr(MI_VENC_CHN VeChn, MI_VENC_ChnAttr_t *pstAttr); +MI_S32 MI_VENC_GetChnAttr(MI_VENC_CHN VeChn, MI_VENC_ChnAttr_t *pstAttr); +MI_S32 MI_VENC_GetStream(MI_VENC_CHN VeChn, MI_VENC_Stream_t *pstStream, MI_S32 s32MilliSec); +MI_S32 MI_VENC_ReleaseStream(MI_VENC_CHN VeChn, MI_VENC_Stream_t *pstStream); +MI_S32 MI_VENC_InsertUserData(MI_VENC_CHN VeChn, MI_U8 *pu8Data, MI_U32 u32Len); +MI_S32 MI_VENC_SetMaxStreamCnt(MI_VENC_CHN VeChn, MI_U32 u32MaxStrmCnt); +MI_S32 MI_VENC_GetMaxStreamCnt(MI_VENC_CHN VeChn, MI_U32 *pu32MaxStrmCnt); +MI_S32 MI_VENC_RequestIdr(MI_VENC_CHN VeChn, MI_BOOL bInstant); +MI_S32 MI_VENC_EnableIdr(MI_VENC_CHN VeChn, MI_BOOL bEnableIdr); +MI_S32 MI_VENC_SetH264IdrPicId(MI_VENC_CHN VeChn, MI_VENC_H264IdrPicIdCfg_t *pstH264eIdrPicIdCfg); +MI_S32 MI_VENC_GetH264IdrPicId(MI_VENC_CHN VeChn, MI_VENC_H264IdrPicIdCfg_t *pstH264eIdrPicIdCfg); +MI_S32 MI_VENC_GetFd(MI_VENC_CHN VeChn); +MI_S32 MI_VENC_CloseFd(MI_VENC_CHN VeChn); +MI_S32 MI_VENC_SetRoiCfg(MI_VENC_CHN VeChn, MI_VENC_RoiCfg_t *pstVencRoiCfg); +MI_S32 MI_VENC_GetRoiCfg(MI_VENC_CHN VeChn, MI_U32 u32Index, MI_VENC_RoiCfg_t *pstVencRoiCfg); +MI_S32 MI_VENC_SetRoiBgFrameRate(MI_VENC_CHN VeChn, MI_VENC_RoiBgFrameRate_t *pstRoiBgFrmRate); +MI_S32 MI_VENC_GetRoiBgFrameRate(MI_VENC_CHN VeChn, MI_VENC_RoiBgFrameRate_t *pstRoiBgFrmRate); +MI_S32 MI_VENC_SetH264SliceSplit(MI_VENC_CHN VeChn, MI_VENC_ParamH264SliceSplit_t *pstSliceSplit); +MI_S32 MI_VENC_GetH264SliceSplit(MI_VENC_CHN VeChn, MI_VENC_ParamH264SliceSplit_t *pstSliceSplit); +MI_S32 MI_VENC_SetH264InterPred(MI_VENC_CHN VeChn, MI_VENC_ParamH264InterPred_t *pstH264InterPred); +MI_S32 MI_VENC_GetH264InterPred(MI_VENC_CHN VeChn, MI_VENC_ParamH264InterPred_t *pstH264InterPred); +MI_S32 MI_VENC_SetH264IntraPred(MI_VENC_CHN VeChn, MI_VENC_ParamH264IntraPred_t *pstH264IntraPred); +MI_S32 MI_VENC_GetH264IntraPred(MI_VENC_CHN VeChn, MI_VENC_ParamH264IntraPred_t *pstH264IntraPred); +MI_S32 MI_VENC_SetH264Trans(MI_VENC_CHN VeChn, MI_VENC_ParamH264Trans_t *pstH264Trans); +MI_S32 MI_VENC_GetH264Trans(MI_VENC_CHN VeChn, MI_VENC_ParamH264Trans_t *pstH264Trans); +MI_S32 MI_VENC_SetH264Entropy(MI_VENC_CHN VeChn, MI_VENC_ParamH264Entropy_t *pstH264EntropyEnc); +MI_S32 MI_VENC_GetH264Entropy(MI_VENC_CHN VeChn, MI_VENC_ParamH264Entropy_t *pstH264EntropyEnc); +MI_S32 MI_VENC_SetH264Dblk(MI_VENC_CHN VeChn, MI_VENC_ParamH264Dblk_t *pstH264Dblk); +MI_S32 MI_VENC_GetH264Dblk(MI_VENC_CHN VeChn, MI_VENC_ParamH264Dblk_t *pstH264Dblk); +MI_S32 MI_VENC_SetH264Vui(MI_VENC_CHN VeChn, MI_VENC_ParamH264Vui_t*pstH264Vui); +MI_S32 MI_VENC_GetH264Vui(MI_VENC_CHN VeChn, MI_VENC_ParamH264Vui_t *pstH264Vui); +MI_S32 MI_VENC_SetH265SliceSplit(MI_VENC_CHN VeChn, MI_VENC_ParamH265SliceSplit_t *pstSliceSplit); +MI_S32 MI_VENC_GetH265SliceSplit(MI_VENC_CHN VeChn, MI_VENC_ParamH265SliceSplit_t *pstSliceSplit); +MI_S32 MI_VENC_SetH265InterPred(MI_VENC_CHN VeChn, MI_VENC_ParamH265InterPred_t *pstH265InterPred); +MI_S32 MI_VENC_GetH265InterPred(MI_VENC_CHN VeChn, MI_VENC_ParamH265InterPred_t *pstH265InterPred); +MI_S32 MI_VENC_SetH265IntraPred(MI_VENC_CHN VeChn, MI_VENC_ParamH265IntraPred_t *pstH265IntraPred); +MI_S32 MI_VENC_GetH265IntraPred(MI_VENC_CHN VeChn, MI_VENC_ParamH265IntraPred_t *pstH265IntraPred); +MI_S32 MI_VENC_SetH265Trans(MI_VENC_CHN VeChn, MI_VENC_ParamH265Trans_t *pstH265Trans); +MI_S32 MI_VENC_GetH265Trans(MI_VENC_CHN VeChn, MI_VENC_ParamH265Trans_t *pstH265Trans); +MI_S32 MI_VENC_SetH265Dblk(MI_VENC_CHN VeChn, MI_VENC_ParamH265Dblk_t *pstH265Dblk); +MI_S32 MI_VENC_GetH265Dblk(MI_VENC_CHN VeChn, MI_VENC_ParamH265Dblk_t *pstH265Dblk); +MI_S32 MI_VENC_SetH265Vui(MI_VENC_CHN VeChn, MI_VENC_ParamH265Vui_t*pstH265Vui); +MI_S32 MI_VENC_GetH265Vui(MI_VENC_CHN VeChn, MI_VENC_ParamH265Vui_t *pstH265Vui); +MI_S32 MI_VENC_SetJpegParam(MI_VENC_CHN VeChn, MI_VENC_ParamJpeg_t *pstJpegParam); +MI_S32 MI_VENC_GetJpegParam(MI_VENC_CHN VeChn, MI_VENC_ParamJpeg_t *pstJpegParam); +MI_S32 MI_VENC_SetRcParam(MI_VENC_CHN VeChn, MI_VENC_RcParam_t *pstRcParam); +MI_S32 MI_VENC_GetRcParam(MI_VENC_CHN VeChn, MI_VENC_RcParam_t *pstRcParam); +MI_S32 MI_VENC_SetRefParam(MI_VENC_CHN VeChn, MI_VENC_ParamRef_t *pstRefParam); +MI_S32 MI_VENC_GetRefParam(MI_VENC_CHN VeChn, MI_VENC_ParamRef_t *pstRefParam); +MI_S32 MI_VENC_SetCrop(MI_VENC_CHN VeChn, MI_VENC_CropCfg_t *pstCropCfg); +MI_S32 MI_VENC_GetCrop(MI_VENC_CHN VeChn, MI_VENC_CropCfg_t *pstCropCfg); +MI_S32 MI_VENC_SetFrameLostStrategy(MI_VENC_CHN VeChn, MI_VENC_ParamFrameLost_t *pstFrmLostParam); +MI_S32 MI_VENC_GetFrameLostStrategy(MI_VENC_CHN VeChn, MI_VENC_ParamFrameLost_t *pstFrmLostParam); +MI_S32 MI_VENC_SetSuperFrameCfg(MI_VENC_CHN VeChn, MI_VENC_SuperFrameCfg_t *pstSuperFrmParam); +MI_S32 MI_VENC_GetSuperFrameCfg(MI_VENC_CHN VeChn, MI_VENC_SuperFrameCfg_t *pstSuperFrmParam); +MI_S32 MI_VENC_SetRcPriority(MI_VENC_CHN VeChn, MI_VENC_RcPriority_e *peRcPriority); +MI_S32 MI_VENC_GetRcPriority(MI_VENC_CHN VeChn, MI_VENC_RcPriority_e *peRcPriority); +MI_S32 MI_VENC_DupChn(MI_VENC_CHN VeChn); +MI_S32 MI_VENC_SetInputSourceConfig(MI_VENC_CHN VeChn, MI_VENC_InputSourceConfig_t *pstInputSourceConfig); +MI_S32 MI_VENC_AllocCustomMap (MI_VENC_CHN VeChn, MI_PHY *pPhyAddr, void **ppCpuAddr); +MI_S32 MI_VENC_ApplyCustomMap (MI_VENC_CHN VeChn, MI_PHY PhyAddr); +MI_S32 MI_VENC_GetLastHistoStaticInfo (MI_VENC_CHN VeChn, MI_VENC_FrameHistoStaticInfo_t** ppFrmHistoStaticInfo); +MI_S32 MI_VENC_ReleaseHistoStaticInfo(MI_VENC_CHN VeChn); +MI_S32 MI_VENC_SetAdvCustRcAttr(MI_VENC_CHN VeChn, MI_VENC_AdvCustRcAttr_t *pstAdvCustRcAttr); +MI_S32 MI_VENC_SetSmartDetInfo(MI_VENC_CHN VeChn, MI_VENC_SmartDetInfo_t *pstSmartDetInfo); +MI_S32 MI_VENC_SetIntraRefresh(MI_VENC_CHN VeChn, MI_VENC_IntraRefresh_t *pstIntraRefresh); +MI_S32 MI_VENC_GetIntraRefresh(MI_VENC_CHN VeChn, MI_VENC_IntraRefresh_t *pstIntraRefresh); +MI_S32 MI_VENC_InitDev(MI_VENC_InitParam_t *pstInitParam); +MI_S32 MI_VENC_DeInitDev(void); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_venc_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_venc_datatype.h new file mode 100644 index 000000000..8cf9006dd --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_venc_datatype.h @@ -0,0 +1,945 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef __MI_VENC_DATATYPE_ +#define __MI_VENC_DATATYPE_ + +#include "mi_common_datatype.h" +#include "mi_sys_datatype.h" + +#define MI_VENC_MAX_CHN_NUM_PER_MODULE (9) +#define MI_VENC_MAX_CHN_NUM_PER_DC (3) +#define VENC_CUST_MAP_NUM (2) +#define VENC_MAX_SAD_RANGE_NUM (16) + +//max supported channel number. But the number would be limited by each module. +#define VENC_MAX_CHN_NUM (16) //from SPEC + + +#define MI_DEF_VENC_ERR(err) MI_DEF_ERR(E_MI_MODULE_ID_VENC, E_MI_ERR_LEVEL_ERROR, err) + +#define MI_VENC_OK MI_DEF_VENC_ERR(MI_SUCCESS) + +/* invalid handle */ +//#define MI_ERR_VENC_INVALID_HANDLE MI_DEF_VENC_ERR(E_MI_ERR_INVALID_DEVID) + +/* invalid device ID */ +#define MI_ERR_VENC_INVALID_DEVID MI_DEF_VENC_ERR(E_MI_ERR_INVALID_DEVID) +/* invalid channel ID */ +#define MI_ERR_VENC_INVALID_CHNID MI_DEF_VENC_ERR(E_MI_ERR_INVALID_CHNID) +/* at lease one parameter is illegal, e.g, an illegal enumeration value */ +#define MI_ERR_VENC_ILLEGAL_PARAM MI_DEF_VENC_ERR(E_MI_ERR_ILLEGAL_PARAM) +/* channel exists */ +#define MI_ERR_VENC_EXIST MI_DEF_VENC_ERR(E_MI_ERR_EXIST) +/*UN exist*/ +#define MI_ERR_VENC_UNEXIST MI_DEF_VENC_ERR(E_MI_ERR_UNEXIST) +/* using a NULL point */ +#define MI_ERR_VENC_NULL_PTR MI_DEF_VENC_ERR(E_MI_ERR_NULL_PTR) +/* try to enable or initialize system,device or channel, before configuring attribute */ +#define MI_ERR_VENC_NOT_CONFIG MI_DEF_VENC_ERR(E_MI_ERR_NOT_CONFIG) +/* operation is not supported by NOW */ +#define MI_ERR_VENC_NOT_SUPPORT MI_DEF_VENC_ERR(E_MI_ERR_NOT_SUPPORT) +/* operation is not permitted, e.g, try to change static attribute */ +#define MI_ERR_VENC_NOT_PERM MI_DEF_VENC_ERR(E_MI_ERR_NOT_PERM) +/* failure caused by malloc memory */ +#define MI_ERR_VENC_NOMEM MI_DEF_VENC_ERR(E_MI_ERR_NOMEM) +/* failure caused by malloc buffer */ +#define MI_ERR_VENC_NOBUF MI_DEF_VENC_ERR(E_MI_ERR_NOBUF) +/* no data in buffer */ +#define MI_ERR_VENC_BUF_EMPTY MI_DEF_VENC_ERR(E_MI_ERR_BUF_EMPTY) +/* no buffer for new data */ +#define MI_ERR_VENC_BUF_FULL MI_DEF_VENC_ERR(E_MI_ERR_BUF_FULL) +/* System is not ready,maybe not initialed or loaded. + * Returning the error code when opening a device file failed. + */ +#define MI_ERR_VENC_NOTREADY MI_DEF_VENC_ERR(E_MI_ERR_SYS_NOTREADY) + +/* bad address, e.g. used for copy_from_user & copy_to_user */ +#define MI_ERR_VENC_BADADDR MI_DEF_VENC_ERR(E_MI_ERR_BADADDR) +/* resource is busy, e.g. destroy a VENC channel without unregistering it */ +#define MI_ERR_VENC_BUSY MI_DEF_VENC_ERR(E_MI_ERR_BUSY) + +/* channel not start*/ +#define MI_ERR_VENC_CHN_NOT_STARTED MI_DEF_VENC_ERR(E_MI_ERR_CHN_NOT_STARTED) +/* channel not stop*/ +#define MI_ERR_VENC_CHN_NOT_STOPPED MI_DEF_VENC_ERR(E_MI_ERR_CHN_NOT_STOPED) + +#define MI_ERR_VENC_PRIVATE_START MI_DEF_VENC_ERR(MI_VENC_INITIAL_ERROR_CODE) +/* to be removed later */ +#define MI_ERR_VENC_UNDEFINED MI_DEF_VENC_ERR(E_MI_ERR_FAILED) + +/* No error but return it's VENC no error.*/ +//#define MI_ERR_VENC_NONE MI_DEF_VENC_ERR(0) + +/* ======================================================= + * Missing definitions + * =======================================================*/ +#define RC_TEXTURE_THR_SIZE 1 // Fixme + +/* ======================================================= + * Missing Types + * =======================================================*/ +//FIXME add dummy fields at least +/* +#define MI_VENC_ParamModH264e_t MI_VENC_ParamModH265e_t +#define MI_VENC_ParamModVenc_t MI_VENC_ParamModH265e_t +*/ + +/* ======================================================= + * Data Types + * =======================================================*/ + +//==== Enumerates ==== +typedef enum +{ + E_MI_VENC_MODTYPE_VENC = 1, //!< E_MI_VENC_MODTYPE_VENC + E_MI_VENC_MODTYPE_H264E, //!< E_MI_VENC_MODTYPE_H264E + E_MI_VENC_MODTYPE_H265E, //!< E_MI_VENC_MODTYPE_H265E + E_MI_VENC_MODTYPE_JPEGE, //!< E_MI_VENC_MODTYPE_JPEGE + E_MI_VENC_MODTYPE_MAX //!< E_MI_VENC_MODTYPE_MAX +} MI_VENC_ModType_e; + +typedef enum +{ + E_MI_VENC_BASE_IDR = 0, + E_MI_VENC_BASE_P_REFTOIDR, + E_MI_VENC_BASE_P_REFBYBASE, + E_MI_VENC_BASE_P_REFBYENHANCE, + E_MI_VENC_ENHANCE_P_REFBYENHANCE, + E_MI_VENC_ENHANCE_P_NOTFORREF, + E_MI_VENC_REF_TYPE_MAX +} MI_VENC_H264eRefType_e; +typedef MI_VENC_H264eRefType_e MI_VENC_H265eRefType_e; + +typedef enum +{ + E_MI_VENC_H264E_NALU_PSLICE = 1, + E_MI_VENC_H264E_NALU_ISLICE = 5, + E_MI_VENC_H264E_NALU_SEI = 6, + E_MI_VENC_H264E_NALU_SPS = 7, + E_MI_VENC_H264E_NALU_PPS = 8, + E_MI_VENC_H264E_NALU_IPSLICE = 9, + E_MI_VENC_H264E_NALU_PREFIX = 14, + E_MI_VENC_H264E_NALU_MAX +} MI_VENC_H264eNaluType_e; + +typedef enum +{ + E_MI_VENC_H264E_REFSLICE_FOR_1X = 1, + E_MI_VENC_H264E_REFSLICE_FOR_2X = 2, + E_MI_VENC_H264E_REFSLICE_FOR_4X, + E_MI_VENC_H264E_REFSLICE_FOR_MAX = 5 +} MI_VENC_H264eRefSliceType_e; + +typedef enum +{ + E_MI_VENC_JPEGE_PACK_ECS = 5, + E_MI_VENC_JPEGE_PACK_APP = 6, + E_MI_VENC_JPEGE_PACK_VDO = 7, + E_MI_VENC_JPEGE_PACK_PIC = 8, + E_MI_VENC_JPEGE_PACK_MAX +} MI_VENC_JpegePackType_e; + +typedef enum +{ + E_MI_VENC_H265E_NALU_PSLICE = 1, + E_MI_VENC_H265E_NALU_ISLICE = 19, + E_MI_VENC_H265E_NALU_VPS = 32, + E_MI_VENC_H265E_NALU_SPS = 33, + E_MI_VENC_H265E_NALU_PPS = 34, + E_MI_VENC_H265E_NALU_SEI = 39, + E_MI_VENC_H265E_NALU_MAX +} MI_VENC_H265eNaulType_e; + +typedef enum +{ + E_MI_VENC_RC_MODE_H264CBR = 1, + E_MI_VENC_RC_MODE_H264VBR, + E_MI_VENC_RC_MODE_H264ABR, + E_MI_VENC_RC_MODE_H264FIXQP, + E_MI_VENC_RC_MODE_H264AVBR, + E_MI_VENC_RC_MODE_MJPEGCBR, + E_MI_VENC_RC_MODE_MJPEGFIXQP, + E_MI_VENC_RC_MODE_H265CBR, + E_MI_VENC_RC_MODE_H265VBR, + E_MI_VENC_RC_MODE_H265FIXQP, + E_MI_VENC_RC_MODE_H265AVBR, + E_MI_VENC_RC_MODE_MAX, +} MI_VENC_RcMode_e; + +typedef enum +{ + E_MI_VENC_SUPERFRM_NONE, + E_MI_VENC_SUPERFRM_DISCARD, + E_MI_VENC_SUPERFRM_REENCODE, + E_MI_VENC_SUPERFRM_MAX +} MI_VENC_SuperFrmMode_e; + +typedef enum +{ + E_MI_VENC_H264E_IDR_PIC_ID_MODE_USR, +} MI_VENC_H264eIdrPicIdMode_e; + +typedef enum +{ + E_MI_VENC_FRMLOST_NORMAL, + E_MI_VENC_FRMLOST_PSKIP, + E_MI_VENC_FRMLOST_MAX, +} MI_VENC_FrameLostMode_e; + +typedef enum +{ + E_MI_VENC_RC_PRIORITY_BITRATE_FIRST = 1, + E_MI_VENC_RC_PRIORITY_FRAMEBITS_FIRST, + E_MI_VENC_RC_PRIORITY_MAX, +} MI_VENC_RcPriority_e; + +typedef enum +{ + E_MI_VENC_INPUT_MODE_NORMAL_FRMBASE = 0, /*Handshake with input by about 3 buffers in frame mode*/ + E_MI_VENC_INPUT_MODE_RING_ONE_FRM, /*Handshake with input by one buffer in ring mode*/ + E_MI_VENC_INPUT_MODE_RING_HALF_FRM, /*Handshake with input by half buffer in ring mode*/ + E_MI_VENC_INPUT_MODE_MAX +} MI_VENC_InputSrcBufferMode_e; + +typedef enum +{ + E_MI_VENC_MD_DET=1, + E_MI_VENC_ROI_DET, + E_MI_VENC_SMART_DET_MAX, +} MI_VENC_SmartDetType_e; + +//==== Structures ==== + +typedef struct MI_VENC_Rect_s +{ + MI_U32 u32Left; + MI_U32 u32Top; + MI_U32 u32Width; + MI_U32 u32Height; +} MI_VENC_Rect_t; + +typedef union MI_VENC_DataType_s +{ + MI_VENC_H264eNaluType_e eH264EType; + MI_VENC_JpegePackType_e eJPEGEType; + MI_VENC_H265eNaulType_e eH265EType; +} MI_VENC_DataType_t; + +typedef struct MI_VENC_PackInfo_s +{ + MI_VENC_DataType_t stPackType; + MI_U32 u32PackOffset; + MI_U32 u32PackLength; + MI_U32 u32SliceId; +} MI_VENC_PackInfo_t; + +typedef struct MI_VENC_Pack_s +{ + MI_PHY phyAddr; + MI_U8 *pu8Addr; + MI_U32 u32Len; + MI_U64 u64PTS; + MI_BOOL bFrameEnd; + MI_VENC_DataType_t stDataType; + MI_U32 u32Offset; + MI_U32 u32DataNum; + MI_VENC_PackInfo_t asackInfo[8]; +} MI_VENC_Pack_t; + +typedef struct MI_VENC_StreamInfoH264_s +{ + MI_U32 u32PicBytesNum; + MI_U32 u32PSkipMbNum; + MI_U32 u32IpcmMbNum; + MI_U32 u32Inter16x8MbNum; + MI_U32 u32Inter16x16MbNum; + MI_U32 u32Inter8x16MbNum; + MI_U32 u32Inter8x8MbNum; + MI_U32 u32Intra16MbNum; + MI_U32 u32Intra8MbNum; + MI_U32 u32Intra4MbNum; + MI_VENC_H264eRefSliceType_e eRefSliceType; + MI_VENC_H264eRefType_e eRefType; + MI_U32 u32UpdateAttrCnt; + MI_U32 u32StartQp; +} MI_VENC_StreamInfoH264_t; + +typedef struct MI_VENC_StreamInfoJpeg_s +{ + MI_U32 u32PicBytesNum; + MI_U32 u32UpdateAttrCnt; + MI_U32 u32Qfactor; +} MI_VENC_StreamInfoJpeg_t; + +typedef struct MI_VENC_StreamInfoH265_s +{ + MI_U32 u32PicBytesNum; + MI_U32 u32Inter64x64CuNum; + MI_U32 u32Inter32x32CuNum; + MI_U32 u32Inter16x16CuNum; + MI_U32 u32Inter8x8CuNum; + MI_U32 u32Intra32x32CuNum; + MI_U32 u32Intra16x16CuNum; + MI_U32 u32Intra8x8CuNum; + MI_U32 u32Intra4x4CuNum; + MI_VENC_H265eRefType_e eRefType; + MI_U32 u32UpdateAttrCnt; + MI_U32 u32StartQp; +} MI_VENC_StreamInfoH265_t; + +typedef struct MI_VENC_Stream_s +{ + MI_VENC_Pack_t *pstPack; + MI_U32 u32PackCount; + MI_U32 u32Seq; + MI_SYS_BUF_HANDLE hMiSys; + union + { + MI_VENC_StreamInfoH264_t stH264Info; + MI_VENC_StreamInfoJpeg_t stJpegInfo; + MI_VENC_StreamInfoH265_t stH265Info; + }; +} MI_VENC_Stream_t; + +typedef struct MI_VENC_StreamBufInfo_s +{ + MI_PHY phyAddr; + void *pUserAddr; + MI_U32 u32BufSize; +} MI_VENC_StreamBufInfo_t; + +typedef struct MI_VENC_AttrH264_s +{ + MI_U32 u32MaxPicWidth; + MI_U32 u32MaxPicHeight; + MI_U32 u32BufSize; + MI_U32 u32Profile; + MI_BOOL bByFrame; + MI_U32 u32PicWidth; + MI_U32 u32PicHeight; + MI_U32 u32BFrameNum; + MI_U32 u32RefNum; +} MI_VENC_AttrH264_t; + +/* +typedef struct MI_VENC_AttrMjpeg_s +{ + MI_U32 u32MaxPicWidth; + MI_U32 u32MaxPicHeight; + MI_U32 u32BufSize; + MI_BOOL bByFrame; + MI_U32 u32PicWidth; + MI_U32 u32PicHeight; +} MI_VENC_AttrMjpeg_t; +*/ + +typedef struct MI_VENC_AttrJpeg_s +{ + MI_U32 u32MaxPicWidth; + MI_U32 u32MaxPicHeight; + MI_U32 u32BufSize; + MI_BOOL bByFrame; + MI_U32 u32PicWidth; + MI_U32 u32PicHeight; + MI_BOOL bSupportDCF; + MI_U32 u32RestartMakerPerRowCnt; +} MI_VENC_AttrJpeg_t; + +typedef struct MI_VENC_AttrH265_s +{ + MI_U32 u32MaxPicWidth; + MI_U32 u32MaxPicHeight; + MI_U32 u32BufSize; + MI_U32 u32Profile; + MI_BOOL bByFrame; + MI_U32 u32PicWidth; + MI_U32 u32PicHeight; + MI_U32 u32BFrameNum; + MI_U32 u32RefNum; +} MI_VENC_AttrH265_t; + +typedef struct MI_VENC_Attr_s +{ + MI_VENC_ModType_e eType; + union + { + MI_VENC_AttrH264_t stAttrH264e; + //MI_VENC_AttrMjpeg_t stAttrMjpeg; + MI_VENC_AttrJpeg_t stAttrJpeg; + MI_VENC_AttrH265_t stAttrH265e; + }; +} MI_VENC_Attr_t; + +typedef struct MI_VENC_ChnStat_s +{ + MI_U32 u32LeftPics; + MI_U32 u32LeftStreamBytes; + MI_U32 u32LeftStreamFrames; + MI_U32 u32LeftStreamMillisec; + MI_U32 u32CurPacks; + MI_U32 u32LeftRecvPics; + MI_U32 u32LeftEncPics; + MI_U32 u32FrmRateNum; + MI_U32 u32FrmRateDen; + MI_U32 u32BitRate; +} MI_VENC_ChnStat_t; + +typedef struct MI_VENC_ParamH264SliceSplit_s +{ + MI_BOOL bSplitEnable; + MI_U32 u32SliceRowCount; +} MI_VENC_ParamH264SliceSplit_t; + +typedef struct MI_VENC_ParamH264InterPred_s +{ + /* search window */ + MI_U32 u32HWSize; + MI_U32 u32VWSize; + MI_BOOL bInter16x16PredEn; + MI_BOOL bInter16x8PredEn; + MI_BOOL bInter8x16PredEn; + MI_BOOL bInter8x8PredEn; + MI_BOOL bInter8x4PredEn; + MI_BOOL bInter4x8PredEn; + MI_BOOL bInter4x4PredEn; + MI_BOOL bExtedgeEn; +} MI_VENC_ParamH264InterPred_t; + +typedef struct MI_VENC_ParamH264IntraPred_s +{ + MI_BOOL bIntra16x16PredEn; + MI_BOOL bIntraNxNPredEn; + MI_BOOL bConstrainedIntraPredFlag; //special naming for CODEC ISO SPEC. + MI_BOOL bIpcmEn; + MI_U32 u32Intra16x16Penalty; + MI_U32 u32Intra4x4Penalty; + MI_BOOL bIntraPlanarPenalty; +} MI_VENC_ParamH264IntraPred_t; + +typedef struct MI_VENC_ParamH264Trans_s +{ + MI_U32 u32IntraTransMode; + MI_U32 u32InterTransMode; + MI_S32 s32ChromaQpIndexOffset; +} MI_VENC_ParamH264Trans_t; + +typedef struct MI_VENC_ParamH264Entropy_s +{ + MI_U32 u32EntropyEncModeI; + MI_U32 u32EntropyEncModeP; +} MI_VENC_ParamH264Entropy_t; + +typedef struct MI_VENC_ParamH265InterPred_s +{ + /* search window */ + MI_U32 u32HWSize; + MI_U32 u32VWSize; + MI_BOOL bInter16x16PredEn; + MI_BOOL bInter16x8PredEn; + MI_BOOL bInter8x16PredEn; + MI_BOOL bInter8x8PredEn; + MI_BOOL bInter8x4PredEn; + MI_BOOL bInter4x8PredEn; + MI_BOOL bInter4x4PredEn; + MI_U32 u32Inter32x32Penalty; + MI_U32 u32Inter16x16Penalty; + MI_U32 u32Inter8x8Penalty; + MI_BOOL bExtedgeEn; +} MI_VENC_ParamH265InterPred_t; + +typedef struct MI_VENC_ParamH265IntraPred_s +{ + MI_BOOL bIntra32x32PredEn; + MI_BOOL bIntra16x16PredEn; + MI_BOOL bIntra8x8PredEn; + MI_BOOL bConstrainedIntraPredFlag; + MI_U32 u32Intra32x32Penalty; + MI_U32 u32Intra16x16Penalty; + MI_U32 u32Intra8x8Penalty; +} MI_VENC_ParamH265IntraPred_t; + +typedef struct MI_VENC_ParamH265Trans_s +{ + MI_U32 u32IntraTransMode; + MI_U32 u32InterTransMode; + MI_S32 s32ChromaQpIndexOffset; +} MI_VENC_ParamH265Trans_t; + +typedef struct MI_VENC_ParamH264Dblk_s +{ + MI_U32 disable_deblocking_filter_idc; //special naming for CODEC ISO SPEC. + MI_S32 slice_alpha_c0_offset_div2; //special naming for CODEC ISO SPEC. + MI_S32 slice_beta_offset_div2; //special naming for CODEC ISO SPEC. +} MI_VENC_ParamH264Dblk_t; + +typedef struct MI_VENC_ParamH264VuiAspectRatio_s +{ + MI_U8 u8AspectRatioInfoPresentFlag; + MI_U8 u8AspectRatioIdc; + MI_U8 u8OverscanInfoPresentFlag; + MI_U8 u8OverscanAppropriateFlag; + MI_U16 u16SarWidth; + MI_U16 u16SarHeight; +} MI_VENC_ParamH264VuiAspectRatio_t; + +typedef struct MI_VENC_ParamH264VuiTimeInfo_s +{ + MI_U8 u8TimingInfoPresentFlag; + MI_U8 u8FixedFrameRateFlag; + MI_U32 u32NumUnitsInTick; + MI_U32 u32TimeScale; +} MI_VENC_ParamH264VuiTimeInfo_t; + +typedef struct MI_VENC_ParamH264VuiVideoSignal_s +{ + MI_U8 u8VideoSignalTypePresentFlag; + MI_U8 u8VideoFormat; + MI_U8 u8VideoFullRangeFlag; + MI_U8 u8ColourDescriptionPresentFlag; + MI_U8 u8ColourPrimaries; + MI_U8 u8TransferCharacteristics; + MI_U8 u8MatrixCoefficients; +} MI_VENC_ParamH264VuiVideoSignal_t; + +typedef struct MI_VENC_ParamH264Vui_s +{ + MI_VENC_ParamH264VuiAspectRatio_t stVuiAspectRatio; + MI_VENC_ParamH264VuiTimeInfo_t stVuiTimeInfo; + MI_VENC_ParamH264VuiVideoSignal_t stVuiVideoSignal; +} MI_VENC_ParamH264Vui_t; + +typedef struct MI_VENC_ParamH265VuiAspectRatio_s +{ + MI_U8 u8AspectRatioInfoPresentFlag; + MI_U8 u8AspectRatioIdc; + MI_U8 u8OverscanInfoPresentFlag; + MI_U8 u8OverscanAppropriateFlag; + MI_U16 u16SarWidth; + MI_U16 u16SarHeight; +} MI_VENC_ParamH265VuiAspectRatio_t; + +typedef struct MI_VENC_ParamH265VuiTimeInfo_s +{ + MI_U8 u8TimingInfoPresentFlag; + //MI_U8 u8FixedFrameRateFlag; + MI_U32 u32NumUnitsInTick; + MI_U32 u32TimeScale; +} MI_VENC_ParamH265VuiTimeInfo_t; + +typedef struct MI_VENC_ParamH265VuiVideoSignal_s +{ + MI_U8 u8VideoSignalTypePresentFlag; + MI_U8 u8VideoFormat; + MI_U8 u8VideoFullRangeFlag; + MI_U8 u8ColourDescriptionPresentFlag; + MI_U8 u8ColourPrimaries; + MI_U8 u8TransferCharacteristics; + MI_U8 u8MatrixCoefficients; +} MI_VENC_ParamH265VuiVideoSignal_t; + +typedef struct MI_VENC_ParamH265Vui_s +{ + MI_VENC_ParamH265VuiAspectRatio_t stVuiAspectRatio; + MI_VENC_ParamH265VuiTimeInfo_t stVuiTimeInfo; + MI_VENC_ParamH265VuiVideoSignal_t stVuiVideoSignal; +} MI_VENC_ParamH265Vui_t; + +typedef struct MI_VENC_ParamH265SliceSplit_s +{ + MI_BOOL bSplitEnable; + MI_U32 u32SliceRowCount; +} MI_VENC_ParamH265SliceSplit_t; + +typedef struct MI_VENC_ParamH265Dblk_s +{ + MI_U32 disable_deblocking_filter_idc; //special naming for CODEC ISO SPEC. + MI_S32 slice_tc_offset_div2; //special naming for CODEC ISO SPEC. + MI_S32 slice_beta_offset_div2; //special naming for CODEC ISO SPEC. +} MI_VENC_ParamH265Dblk_t; + +typedef struct MI_VENC_ParamJpeg_s +{ + MI_U32 u32Qfactor; + MI_U8 au8YQt[64]; + MI_U8 au8CbCrQt[64]; + MI_U32 u32McuPerEcs; +} MI_VENC_ParamJpeg_t; + +typedef struct MI_VENC_ParamMjpeg_s +{ + MI_U8 au8YQt[64]; + MI_U32 u32McuPerEcs; +} MI_VENC_ParamMjpeg_t; + +typedef struct MI_VENC_RoiCfg_s +{ + MI_U32 u32Index; + MI_BOOL bEnable; + MI_BOOL bAbsQp; + MI_S32 s32Qp; + MI_VENC_Rect_t stRect; +} MI_VENC_RoiCfg_t; + +typedef struct MI_VENC_RoiBgFrameRate_s +{ + MI_S32 s32SrcFrmRate; + MI_S32 s32DstFrmRate; +} MI_VENC_RoiBgFrameRate_t; + +typedef struct MI_VENC_ParamRef_s +{ + MI_U32 u32Base; + MI_U32 u32Enhance; + MI_BOOL bEnablePred; +} MI_VENC_ParamRef_t; + +typedef struct MI_VENC_AttrH264Cbr_s +{ + MI_U32 u32Gop; + MI_U32 u32StatTime; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32BitRate; + MI_U32 u32FluctuateLevel; +} MI_VENC_AttrH264Cbr_t; + +typedef struct MI_VENC_AttrH264Vbr_s +{ + MI_U32 u32Gop; + MI_U32 u32StatTime; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32MaxBitRate; + MI_U32 u32MaxQp; + MI_U32 u32MinQp; +} MI_VENC_AttrH264Vbr_t; + +typedef struct MI_VENC_AttrH264FixQp_s +{ + MI_U32 u32Gop; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32IQp; + MI_U32 u32PQp; +} MI_VENC_AttrH264FixQp_t; + +typedef struct MI_VENC_AttrH264Abr_s +{ + MI_U32 u32Gop; /*the interval of ISLICE. */ + MI_U32 u32StatTime; /* the rate statistic time, the unit is seconds(s) */ + MI_U32 u32SrcFrmRateNum;/* the input frame rate of the venc */ + MI_U32 u32SrcFrmRateDen; + MI_U32 u32AvgBitRate; /* average bitrate */ + MI_U32 u32MaxBitRate; /* the max bitrate */ +} MI_VENC_AttrH264Abr_t; + +typedef struct MI_VENC_AttrH264Avbr_s +{ + MI_U32 u32Gop; + MI_U32 u32StatTime; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32MaxBitRate; + MI_U32 u32MaxQp; + MI_U32 u32MinQp; +} MI_VENC_AttrH264Avbr_t; + +typedef struct MI_VENC_AttrMjpegCbr_s +{ + MI_U32 u32BitRate; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; +} MI_VENC_AttrMjpegCbr_t; + +typedef struct MI_VENC_AttrMjpegFixQp_s +{ + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32Qfactor; +} MI_VENC_AttrMjpegFixQp_t; + +typedef struct MI_VENC_AttrH265Cbr_s +{ + MI_U32 u32Gop; + MI_U32 u32StatTime; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32BitRate; + MI_U32 u32FluctuateLevel; +} MI_VENC_AttrH265Cbr_t; + +typedef struct MI_VENC_AttrH265Vbr_s +{ + MI_U32 u32Gop; + MI_U32 u32StatTime; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32MaxBitRate; + MI_U32 u32MaxQp; + MI_U32 u32MinQp; +} MI_VENC_AttrH265Vbr_t; + +typedef struct MI_VENC_AttrH265FixQp_s +{ + MI_U32 u32Gop; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32IQp; + MI_U32 u32PQp; +} MI_VENC_AttrH265FixQp_t; + +typedef struct MI_VENC_AttrH265Avbr_s +{ + MI_U32 u32Gop; + MI_U32 u32StatTime; + MI_U32 u32SrcFrmRateNum; + MI_U32 u32SrcFrmRateDen; + MI_U32 u32MaxBitRate; + MI_U32 u32MaxQp; + MI_U32 u32MinQp; +} MI_VENC_AttrH265Avbr_t; + +typedef struct MI_VENC_RcAttr_s +{ + MI_VENC_RcMode_e eRcMode; + union + { + MI_VENC_AttrH264Cbr_t stAttrH264Cbr; + MI_VENC_AttrH264Vbr_t stAttrH264Vbr; + MI_VENC_AttrH264FixQp_t stAttrH264FixQp; + MI_VENC_AttrH264Abr_t stAttrH264Abr; + MI_VENC_AttrH264Avbr_t stAttrH264Avbr; + MI_VENC_AttrMjpegCbr_t stAttrMjpegCbr; + MI_VENC_AttrMjpegFixQp_t stAttrMjpegFixQp; + MI_VENC_AttrH265Cbr_t stAttrH265Cbr; + MI_VENC_AttrH265Vbr_t stAttrH265Vbr; + MI_VENC_AttrH265FixQp_t stAttrH265FixQp; + MI_VENC_AttrH265Avbr_t stAttrH265Avbr; + }; + void* pRcAttr; +} MI_VENC_RcAttr_t; + +typedef struct MI_VENC_ChnAttr_s +{ + MI_VENC_Attr_t stVeAttr; + MI_VENC_RcAttr_t stRcAttr; +} MI_VENC_ChnAttr_t; + +typedef struct MI_VENC_ParamH264Vbr_s +{ + MI_S32 s32IPQPDelta; + MI_S32 s32ChangePos; + MI_U32 u32MaxIQp; + MI_U32 u32MinIQp; + MI_U32 u32MaxIPProp; +} MI_VENC_ParamH264Vbr_t; + +typedef struct MI_VENC_ParamH264Cbr_s +{ + MI_U32 u32MaxQp; + MI_U32 u32MinQp; + MI_S32 s32IPQPDelta; + MI_U32 u32MaxIQp; + MI_U32 u32MinIQp; + MI_U32 u32MaxIPProp; +} MI_VENC_ParamH264Cbr_t; + +typedef struct MI_VENC_ParamH264Avbr_s +{ + MI_S32 s32IPQPDelta; + MI_S32 s32ChangePos; + MI_U32 u32MinIQp; + MI_U32 u32MaxIPProp; + MI_U32 u32MaxIQp; + MI_U32 u32MaxISize; + MI_U32 u32MaxPSize; + MI_U32 u32MinStillPercent; + MI_U32 u32MaxStillQp; + MI_U32 u32MotionSensitivity; +} MI_VENC_ParamH264Avbr_t; + +typedef struct MI_VENC_ParamMjpegCbr_s +{ + MI_U32 u32MaxQfactor; + MI_U32 u32MinQfactor; +} MI_VENC_ParamMjpegCbr_t; + +typedef struct MI_VENC_ParamH265Vbr_s +{ + MI_S32 s32IPQPDelta; + MI_S32 s32ChangePos; + MI_U32 u32MaxIQp; + MI_U32 u32MinIQp; + MI_U32 u32MaxIPProp; +} MI_VENC_ParamH265Vbr_t; + +typedef struct MI_VENC_ParamH265Cbr_s +{ + MI_U32 u32MaxQp; + MI_U32 u32MinQp; + MI_S32 s32IPQPDelta; + MI_U32 u32MaxIQp; + MI_U32 u32MinIQp; + MI_U32 u32MaxIPProp; +} MI_VENC_ParamH265Cbr_t; + +typedef struct MI_VENC_ParamH265Avbr_s +{ + MI_S32 s32IPQPDelta; + MI_S32 s32ChangePos; + MI_U32 u32MinIQp; + MI_U32 u32MaxIPProp; + MI_U32 u32MaxIQp; + MI_U32 u32MaxISize; + MI_U32 u32MaxPSize; + MI_U32 u32MinStillPercent; + MI_U32 u32MaxStillQp; + MI_U32 u32MotionSensitivity; +} MI_VENC_ParamH265Avbr_t; + +typedef struct MI_VENC_RcParam_s +{ + MI_U32 au32ThrdI[RC_TEXTURE_THR_SIZE]; + MI_U32 au32ThrdP[RC_TEXTURE_THR_SIZE]; + MI_U32 u32RowQpDelta; + union + { + MI_VENC_ParamH264Cbr_t stParamH264Cbr; + MI_VENC_ParamH264Vbr_t stParamH264VBR; + MI_VENC_ParamH264Avbr_t stParamH264Avbr; + MI_VENC_ParamMjpegCbr_t stParamMjpegCbr; + MI_VENC_ParamH265Cbr_t stParamH265Cbr; + MI_VENC_ParamH265Vbr_t stParamH265Vbr; + MI_VENC_ParamH265Avbr_t stParamH265Avbr; + }; + void* pRcParam; +} MI_VENC_RcParam_t; + +typedef struct MI_VENC_CropCfg_s +{ + MI_BOOL bEnable; /* Crop region enable */ + MI_VENC_Rect_t stRect; /* Crop region, note: s32X must be multi of 16 */ +} MI_VENC_CropCfg_t; + +typedef struct MI_VENC_RecvPicParam_s +{ + MI_S32 s32RecvPicNum; +} MI_VENC_RecvPicParam_t; + +typedef struct MI_VENC_H264IdrPicIdCfg_s +{ + MI_VENC_H264eIdrPicIdMode_e eH264eIdrPicIdMode; + MI_U32 u32H264eIdrPicId; +} MI_VENC_H264IdrPicIdCfg_t; + +typedef struct MI_VENC_ParamFrameLost_s +{ + MI_BOOL bFrmLostOpen; + MI_U32 u32FrmLostBpsThr; + MI_VENC_FrameLostMode_e eFrmLostMode; + MI_U32 u32EncFrmGaps; +} MI_VENC_ParamFrameLost_t; + +typedef struct MI_VENC_SuperFrameCfg_s +{ + MI_VENC_SuperFrmMode_e eSuperFrmMode; + MI_U32 u32SuperIFrmBitsThr; + MI_U32 u32SuperPFrmBitsThr; + MI_U32 u32SuperBFrmBitsThr; +} MI_VENC_SuperFrameCfg_t; + +typedef struct MI_VENC_ParamModH265e_s +{ + MI_U32 u32OneStreamBuffer; + MI_U32 u32H265eMiniBufMode; +} MI_VENC_ParamModH265e_t; + +typedef struct MI_VENC_ParamModJpege_s +{ + MI_U32 u32OneStreamBuffer; + MI_U32 u32JpegeMiniBufMode; +} MI_VENC_ParamModJpege_t; + +typedef struct MI_VENC_ModParam_s +{ + MI_VENC_ModType_e eVencModType; + union + { + //MI_VENC_ParamModVenc_t stVencModParam; //not defined yet + //MI_VENC_ParamModH264e_t stH264eModParam; //not defined yet + MI_VENC_ParamModH265e_t stH265eModParam; + MI_VENC_ParamModJpege_t stJpegeModParam; + }; +} MI_VENC_ModParam_t; + +typedef struct MI_VENC_InputSourceConfig_s +{ + MI_VENC_InputSrcBufferMode_e eInputSrcBufferMode; +}MI_VENC_InputSourceConfig_t; + +typedef struct MI_VENC_FrameHistoStaticInfo_s +{ + MI_U8 u8PicSkip; + MI_U16 u16PicType; + MI_U32 u32PicPoc; + MI_U32 u32PicSliNum; + MI_U32 u32PicNumIntra; + MI_U32 u32PicNumMerge; + MI_U32 u32PicNumSkip; + MI_U32 u32PicAvgCtuQp; + MI_U32 u32PicByte; + MI_U32 u32GopPicIdx; + MI_U32 u32PicNum; + MI_U32 u32PicDistLow; + MI_U32 u32PicDistHigh; +} MI_VENC_FrameHistoStaticInfo_t; + +typedef struct MI_VENC_AdvCustRcAttr_s +{ + MI_BOOL bEnableQPMap; + MI_BOOL bAbsQP; + MI_BOOL bEnableModeMap; + MI_BOOL bEnabelHistoStaticInfo; +} MI_VENC_AdvCustRcAttr_t; + +typedef struct MI_VENC_MdInfo_s +{ + MI_U16 u16SadRangeRatio[VENC_MAX_SAD_RANGE_NUM]; +} MI_VENC_MdInfo_t; + +typedef struct MI_VENC_SmartDetInfo_s +{ + MI_VENC_SmartDetType_e eSmartDetType; + union + { + MI_VENC_MdInfo_t stMdInfo; + MI_BOOL bRoiExist; + }; + MI_U8 u8ProtectFrmNum; +} MI_VENC_SmartDetInfo_t; + +typedef struct MI_VENC_IntraRefresh_s +{ + MI_BOOL bEnable; + MI_U32 u32RefreshLineNum; + MI_U32 u32ReqIQp; +}MI_VENC_IntraRefresh_t; + +typedef struct MI_VENC_InitParam_s +{ + MI_U32 u32MaxWidth; + MI_U32 u32MaxHeight; +}MI_VENC_InitParam_t; +#endif /* End of #ifndef __MI_VENC_DATATYPE_ */ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vg.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vg.h new file mode 100644 index 000000000..76cfcfd24 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vg.h @@ -0,0 +1,232 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +/* + * mi_vg.h + * Author: chiao.su + */ + +#ifndef MI_VG_H_ +#define MI_VG_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#define VG_MAJOR_VERSION 2 +#define VG_SUB_VERSION 3 +#define MACRO_TO_STR(macro) #macro +#define VG_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_vg_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_vg_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_vg_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_VG_API_VERSION VG_VERSION_STR(VG_MAJOR_VERSION,VG_SUB_VERSION) + +#define MAX_NUMBER 4 + +typedef enum _MI_VG_RET_E +{ + MI_VG_RET_SUCCESS = 0x00000000, /*VG Success*/ + MI_VG_RET_INIT_ERROR = 0x10000301, /*VG init error*/ + MI_VG_RET_IC_CHECK_ERROR = 0x10000302, /*VG platform check error*/ + MI_VG_RET_INVALID_USER_INFO_POINTER = 0x10000303, /*Invalid user information pointer*/ + MI_VG_RET_INVALID_FUNCTION_STATE = 0x10000304, /*Invalid function state*/ + MI_VG_RET_INVALID_OBJECT_THRESHOLD = 0x10000305, /*Invalid object threshold*/ + MI_VG_RET_INVALID_THRESHOLD_POINTER = 0x10000306, /*Invalid threshold pointer*/ + MI_VG_RET_INVALID_ENVIRONMENT_STATE = 0x10000307, /*Invalid environment state*/ + MI_VG_RET_INVALID_ENVIRONMENT_POINTER = 0x10000308, /*Invalid environment pointer*/ + MI_VG_RET_INVALID_LINE_NUMBER = 0x10000309, /*Invalid line number*/ + MI_VG_RET_INVALID_LINE_POINTER = 0x1000030A, /*Invalid line pointer*/ + MI_VG_RET_INVALID_LINE_COORDINATE = 0x1000030B, /*Invalid line coordinate*/ + MI_VG_RET_INVALID_LINE_COORDINATE_POINTER = 0x1000030C, /*Invalid line coordinate pointer*/ + MI_VG_RET_INVALID_LINE_MAGIC_NUMBER = 0x1000030D, /*Invalid line magic number*/ + MI_VG_RET_INVALID_REGION_COORDINATE_POINTER = 0x1000030E, /*Invalid region coordinate pointer*/ + MI_VG_RET_INVALID_REGION_MAGIC_NUMBER = 0x1000030F, /*Invalid region magic number*/ + MI_VG_RET_INVALID_REGION_COORDINATE = 0x10000310, /*Invalid region coordinate*/ + MI_VG_RET_INVALID_HANDLE = 0x10000311, /*Invalid VG handle*/ + MI_VG_RET_INVALID_HANDLE_MAGIC_NUMBER = 0x10000312, /*Invalid handle magic number*/ + MI_VG_RET_INVALID_INPUT_POINTER = 0x10000313, /*Invalid input pointer*/ + MI_VG_RET_OPERATE_ERROR = 0x10000314, /*VG operate error*/ + MI_VG_RET_INVALID_ALARM_POINTER = 0x10000315, /*Invalid alarm pointer*/ + MI_VG_RET_INVALID_DEBUG_POINTER = 0x10000316, /*Invalid debug pointer*/ + MI_VG_RET_INVALID_DETECT_PARAMETER_POINTER = 0x10000317, /*Invalid detect parameters pointer*/ + MI_VG_RET_INVALID_FUNCTION_SWITCH = 0x10000318, /*Invalid function switch*/ + MI_VG_RET_INVALID_DETECT_THRESHOLD = 0x10000319 /*Invalid detection threshold*/ +} MI_VG_RET; + +typedef enum _VgFunction +{ + VG_VIRTUAL_GATE = 2, + VG_REGION_INVASION = 3 +} VgFunction; + +typedef enum _VgRegion_Dir +{ + VG_REGION_ENTER = 0, + VG_REGION_LEAVING = 1, + VG_REGION_CROSS = 2 +} VgRegion_Dir; + +typedef enum _VgSize_Sensitively +{ + VG_SENSITIVELY_MIN = 0, + VG_SENSITIVELY_LOW = 1, + VG_SENSITIVELY_MIDDLE = 2, + VG_SENSITIVELY_HIGH = 3, + VG_SENSITIVELY_MAX = 4 +} VgSize_Sensitively; + +typedef enum _VgDirection_State +{ + VG_SPEC_DIRECTION_CLOSE = 0, + VG_SPEC_DIRECTION_OPEN = 1 +} VgDirection_State; + +typedef struct _VG_Point_t +{ + int32_t x; + int32_t y; +} MI_VG_Point_t; + +typedef struct _VG_Line_t +{ + MI_VG_Point_t px; //point x + MI_VG_Point_t py; //point y + MI_VG_Point_t pdx; //point direction x + MI_VG_Point_t pdy; //point direction y +} MI_VgLine_t; + +typedef struct _VG_Region_t +{ + MI_VG_Point_t p_one; //point one + MI_VG_Point_t p_two; //point two + MI_VG_Point_t p_three; //point three + MI_VG_Point_t p_four; //point four + + int32_t region_dir; //Region direction; + + int32_t spec_dir_state; +} MI_VgRegion_t; + +typedef struct _MI_VgSet_t +{ + //Common Information + float object_size_thd; + uint16_t line_number; + uint8_t indoor; + + //Line info + MI_VG_Point_t fp[MAX_NUMBER]; //First point + MI_VG_Point_t sp[MAX_NUMBER]; //Second point + MI_VG_Point_t fdp[MAX_NUMBER]; //First direction point + MI_VG_Point_t sdp[MAX_NUMBER]; //Second direction point + + //Function + uint8_t function_state; + + //Region info + MI_VG_Point_t first_p; //First point + MI_VG_Point_t second_p; //Second point + MI_VG_Point_t third_p; //Third point + MI_VG_Point_t fourth_p; //Fourth point + + //Region direction + uint8_t region_direction; + + //Magic_number + int32_t magic_number; + + int32_t region_spdir_state; +} MI_VgSet_t; + +typedef struct _MI_VgBoundingBox_t +{ + int32_t up; //Min y + int32_t down; //Max y + int32_t left; //Min x + int32_t right; //Max x +} MI_VgBoundingBox_t; + +typedef struct _MI_VgResult_t +{ + int32_t alarm[MAX_NUMBER]; + int32_t alarm_cnt; + MI_VgBoundingBox_t bounding_box[20]; +} MI_VgResult_t; + +typedef struct _MI_VgDetectThd_t +{ + uint8_t function_switch; + uint8_t detect_thd; +} MI_VgDetectThd; + +typedef struct _MI_VgDebug_t +{ + //Common Information + uint16_t background_state; + uint32_t version; //Modify date + uint32_t debug_object_size; + uint32_t debug_state; + + //Line info + MI_VG_Point_t dfp[MAX_NUMBER]; //Debug First point + MI_VG_Point_t dsp[MAX_NUMBER]; //Debug Second point + MI_VG_Point_t dfdp[MAX_NUMBER]; //Debug First direction point + MI_VG_Point_t dsdp[MAX_NUMBER]; //Debug Second direction point +} MI_VgDebug_t; + +typedef void* MI_VG_HANDLE; + +MI_VG_HANDLE MI_VG_Init(MI_VgSet_t* vg_user_info, uint16_t width, uint16_t height); + +MI_VG_RET MI_VG_Uninit(MI_VG_HANDLE vg_handle); + +MI_VG_RET MI_VG_Reset(MI_VG_HANDLE vg_handle); + +MI_VG_RET MI_VG_SetFunction(MI_VgSet_t* vg_user_info, uint8_t function_state); + +MI_VG_RET MI_VG_SetObjSizeThd(MI_VgSet_t* vg_user_info, float size_thd); + +MI_VG_RET MI_VG_GetObjSizeThd(MI_VgSet_t* vg_user_info, float* size_thd); + +MI_VG_RET MI_VG_SetScene(MI_VgSet_t* vg_user_info, int8_t scene); + +MI_VG_RET MI_VG_GetScene(MI_VgSet_t* vg_user_info, int8_t* scene); + +MI_VG_RET MI_VG_SetLineNumber(MI_VgSet_t* vg_user_info, uint16_t lineno); + +MI_VG_RET MI_VG_GetLineNumber(MI_VgSet_t* vg_user_info, uint16_t* lineno); + +MI_VG_RET MI_VG_SetLineAndDir(MI_VgSet_t* vg_user_info, MI_VgLine_t* line_coordinate, uint16_t lineno); + +MI_VG_RET MI_VG_GetLineAndDir(MI_VgSet_t* vg_user_info, MI_VgLine_t* line_coordinate, uint16_t lineno); + +MI_VG_RET MI_VG_SetRegionAndDir(MI_VgSet_t* vg_user_info, MI_VgRegion_t* region_coordinate); + +MI_VG_RET MI_VG_SetDetectThd(MI_VG_HANDLE vg_handle, MI_VgDetectThd* detect_parms); + +MI_VG_RET MI_VG_Run(MI_VG_HANDLE vg_handle, uint8_t* _ucMask); + +MI_VG_RET MI_VG_GetResult(MI_VG_HANDLE vg_handle, MI_VgResult_t *cross_alarm); + +MI_VG_RET MI_VG_GetDebugInfo(MI_VG_HANDLE vg_handle, MI_VgDebug_t *debug_info); + +#ifdef __cplusplus +} +#endif + +#endif /* MI_VG_H_ */ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vif.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vif.h new file mode 100644 index 000000000..c42507218 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vif.h @@ -0,0 +1,53 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_VIF_H_ +#define _MI_VIF_H_ + + +#include "mi_vif_datatype.h" + +#define VIF_MAJOR_VERSION 2 +#define VIF_SUB_VERSION 8 +#define MACRO_TO_STR(macro) #macro +#define VIF_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_vif_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_vif_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_vif_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_VIF_API_VERSION VIF_VERSION_STR(VIF_MAJOR_VERSION,VIF_SUB_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + +MI_S32 MI_VIF_SetDevAttr(MI_VIF_DEV u32VifDev, MI_VIF_DevAttr_t *pstDevAttr); +MI_S32 MI_VIF_GetDevAttr(MI_VIF_DEV u32VifDev, MI_VIF_DevAttr_t *pstDevAttr); +MI_S32 MI_VIF_EnableDev(MI_VIF_DEV u32VifDev); +MI_S32 MI_VIF_DisableDev(MI_VIF_DEV u32VifDev); +MI_S32 MI_VIF_SetChnPortAttr(MI_VIF_CHN u32VifChn, MI_VIF_PORT u32ChnPort, MI_VIF_ChnPortAttr_t *pstAttr); +MI_S32 MI_VIF_GetChnPortAttr(MI_VIF_CHN u32VifChn, MI_VIF_PORT u32ChnPort, MI_VIF_ChnPortAttr_t *pstAttr); +MI_S32 MI_VIF_EnableChnPort(MI_VIF_CHN u32VifChn, MI_VIF_PORT u32ChnPort); +MI_S32 MI_VIF_DisableChnPort(MI_VIF_CHN u32VifChn, MI_VIF_PORT u32ChnPort); +MI_S32 MI_VIF_Query(MI_VIF_CHN u32VifChn, MI_VIF_PORT u32ChnPort, MI_VIF_ChnPortStat_t *pstStat); +MI_S32 MI_VIF_SetDev2SnrPadMux(MI_VIF_Dev2SnrPadMuxCfg_t *pstVifDevMap, MI_U8 u8Length); +MI_S32 MI_VIF_GetDevStatus(MI_VIF_DEV u32Vifdev,MI_VIF_DevStatus_t *pstVifDevStatus); +MI_S32 MI_VIF_InitDev(MI_VIF_InitParam_t *pstInitParam); +MI_S32 MI_VIF_DeInitDev(void); + +#ifdef __cplusplus +} +#endif + +#endif///_MI_VIF_H_ + diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vif_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vif_datatype.h new file mode 100644 index 000000000..e525e7763 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vif_datatype.h @@ -0,0 +1,331 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_VIF_DATATYPE_H_ +#define _MI_VIF_DATATYPE_H_ + +#include "mi_sys_datatype.h" + +#pragma pack(push) +#pragma pack(4) + +typedef enum +{ + E_MI_VIF_ERR_INVALID_PORTID = E_MI_ERR_MAX + 1, + E_MI_VIF_ERR_FAILED_DEVNOTENABLE, /* device not enable*/ + E_MI_VIF_ERR_FAILED_DEVNOTDISABLE, /* device not disable*/ + E_MI_VIF_ERR_FAILED_PORTNOTENABLE, /* port not enable*/ + E_MI_VIF_ERR_FAILED_PORTNOTDISABLE, /* port not disable*/ + E_MI_VIF_ERR_CFG_TIMEOUT, /* config timeout*/ + E_MI_VIF_ERR_NORM_UNMATCH, /* video norm of ADC and VIU is unmatch*/ + E_MI_VIF_ERR_INVALID_WAYID, /* invlalid way ID */ + E_MI_VIF_ERR_INVALID_PHYCHNID, /* invalid phychn id*/ + E_MI_VIF_ERR_FAILED_NOTBIND, /* device or channel not bind */ + E_MI_VIF_ERR_FAILED_BINDED, /* device or channel not unbind */ +} MI_VIF_ErrCode_e; + +#define MI_VIF_SUCCESS (0) +#define MI_VIF_FAIL (1) + +#define MI_ERR_VIF_INVALID_DEVID MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_DEVID) +#define MI_ERR_VIF_INVALID_CHNID MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_CHNID) +#define MI_ERR_VIF_INVALID_PARA MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_ILLEGAL_PARAM) +#define MI_ERR_VIF_INVALID_NULL_PTR MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NULL_PTR) +#define MI_ERR_VIF_FAILED_NOTCONFIG MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_CONFIG) +#define MI_ERR_VIF_NOT_SUPPORT MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_SUPPORT) +#define MI_ERR_VIF_NOT_PERM MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_PERM) +#define MI_ERR_VIF_NOMEM MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOMEM) +#define MI_ERR_VIF_BUF_EMPTY MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUF_EMPTY) +#define MI_ERR_VIF_BUF_FULL MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUF_FULL) +#define MI_ERR_VIF_SYS_NOTREADY MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_SYS_NOTREADY) + +#define MI_ERR_VIF_BUSY MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BUSY) +#define MI_ERR_VIF_INVALID_PORTID MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_INVALID_PORTID)/* 0xA0108040*/ +#define MI_ERR_VIF_FAILED_DEVNOTENABLE MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_FAILED_DEVNOTENABLE)/* 0xA0108040*/ +#define MI_ERR_VIF_FAILED_DEVNOTDISABLE MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_FAILED_DEVNOTDISABLE)/* 0xA0108041*/ +#define MI_ERR_VIF_FAILED_PORTNOTENABLE MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_FAILED_PORTNOTENABLE)/* 0xA0108042*/ +#define MI_ERR_VIF_FAILED_PORTNOTDISABLE MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_FAILED_PORTNOTDISABLE)/* 0xA0108042*/ +#define MI_ERR_VIF_CFG_TIMEOUT MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_CFG_TIMEOUT)/* 0xA0108043*/ +#define MI_ERR_VIF_NORM_UNMATCH MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_NORM_UNMATCH)/* 0xA0108044*/ +#define MI_ERR_VIF_INVALID_WAYID MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_INVALID_WAYID)/* 0xA0108045*/ +#define MI_ERR_VIF_INVALID_PHYCHNID MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_INVALID_PHYCHNID)/* 0xA0108046*/ +#define MI_ERR_VIF_FAILED_NOTBIND MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_FAILED_NOTBIND)/* 0xA0108047*/ +#define MI_ERR_VIF_FAILED_BINDED MI_DEF_ERR(E_MI_MODULE_ID_VIF, E_MI_ERR_LEVEL_ERROR, E_MI_VIF_ERR_FAILED_BINDED)/* 0xA0108048*/ + +//typedef signed int MI_VIF_DEV; +typedef signed int MI_VIF_CHN; +typedef signed int MI_VIF_PORT; +typedef signed int MI_VIF_WAY; + +/* interface mode of video input */ +/* +BT 601: 16位数据传输;21芯;Y、U、V信号同时传输。并行数据,行场同步有单独输出; +BT 656: 8位数据传输; 9芯,不需要同步信号;串行视频传输;传输速率是601的2倍; + 先传Y,后传UV。656输出的是串行数据,行场同步信号嵌入在数据流中 + +656只是数据传输接口而已,可以说是作为601的一个传输方式。 +简单的说ITU-R BT.601是"演播室数字电视编码参数"标准,而ITU-R BT.656 则是ITU-R BT.601附件A中的数字接口标准, +用于主要数字视频设备(包括芯 片)之间采用27Mhz/s并口或243Mb/s串行接口的数字传输接口标准. + +601号建议 + + 它规定了取样频率与取样结构。 + 例如:在4:2:2等级的编码中,规定亮度信号和色差信号的取样频率分别为13.5MHZ和6.75MHZ , + 取样结构为正交结构,即按行、场、帧重复,每行中的R-Y和B-Y取样与奇次(1,3,5……)Y的取样同位置, + 即取样结构是固定的,取样点在电视屏幕上的相对位置不变。 + 它规定了编码方式。 + 对亮度信号和两个色差信号进行线性PCM编码,每个取样点取8比特量化。 + 同时,规定在数字编码时,不使用A/D转换的整个动态范围,只给亮度信号分配220个量化级, 黑电平对应于量化级16,白电平对应于量化级235。 + 为每个色差信号分配224个量化级,色差信号的零电平对应于量化级128。 + +以4:2:2编码标准为例,其比特流为:13.5×8+6.75×8×2 = 216Mb/S。 +若采用4:4:4编码方式,即对复合信号直接编码,其抽样频率取为13.3×8=106.4 Mb/S +*/ + +typedef enum +{ + /* + 输入数据的协议符合标准BT.656 协议,端口 数据输入模式为亮度色度复合模式,分量模 式为单分量。 + */ + E_MI_VIF_MODE_BT656, + /* + 如果是Sensor,则为VI_MODE_DIGITAL_CAMERA 输入数据的协议为Digital camera 协议, + 端口 数据输入模式为亮度色度复合模式,分量模 式为单分量 + */ + E_MI_VIF_MODE_DIGITAL_CAMERA, + /* + BT.1120 协议(BT.656+双分量),端口数据输入模式为亮度色度分离模式,分量模式为双分量。 + */ + E_MI_VIF_MODE_BT1120_STANDARD, + /* + BT.1120 interleave 模式,端口数据输入模式为亮度色度分离模式,分量模式为双分量。 + */ + E_MI_VIF_MODE_BT1120_INTERLEAVED, + E_MI_VIF_MODE_MIPI, + E_MI_VIF_MODE_MAX +} MI_VIF_IntfMode_e; + +typedef enum +{ + /* BT656 multiple ch mode */ + E_MI_VIF_WORK_MODE_1MULTIPLEX, + E_MI_VIF_WORK_MODE_2MULTIPLEX, + E_MI_VIF_WORK_MODE_4MULTIPLEX, + + /* RGB mode for MIPI/Parallel sensor */ + E_MI_VIF_WORK_MODE_RGB_REALTIME, + E_MI_VIF_WORK_MODE_RGB_FRAMEMODE, + E_MI_VIF_WORK_MODE_MAX +} MI_VIF_WorkMode_e; + + +typedef enum +{ + E_MI_VIF_FRAMERATE_FULL, + E_MI_VIF_FRAMERATE_HALF, + E_MI_VIF_FRAMERATE_QUARTER, + E_MI_VIF_FRAMERATE_OCTANT, + E_MI_VIF_FRAMERATE_THREE_QUARTERS, + E_MI_VIF_FRAMERATE_MAX +} MI_VIF_FrameRate_e; + +/* +输入数据顺序(仅支持 YUV 格式) + +VI_INPUT_DATA_VUVU YUV 数据通过分离模式输入时,C 分量的输入排列顺序为 VUVU。 +VI_INPUT_DATA_UVUV YUV 数据通过分离模式输入时,C 分量的输入排列顺序为 UVUV。 +VI_INPUT_DATA_UYVY YUV 数据通过复合模式输入时,顺序为UYVY。 +VI_INPUT_DATA_VYUY YUV 数据通过复合模式输入时,顺序为VYUY。 +VI_INPUT_DATA_YUYV YUV 数据通过复合模式输入时,顺序为YUYV。 +VI_INPUT_DATA_YVYU YUV 数据通过复合模式输入时,顺序为YVYU。 +*/ +typedef enum +{ + /*The input sequence of the second component(only contains u and v) in BT.1120 mode */ + E_MI_VIF_INPUT_DATA_VUVU = 0, + E_MI_VIF_INPUT_DATA_UVUV, + + /* The input sequence for yuv */ + E_MI_VIF_INPUT_DATA_UYVY = 0, + E_MI_VIF_INPUT_DATA_VYUY, + E_MI_VIF_INPUT_DATA_YUYV, + E_MI_VIF_INPUT_DATA_YVYU, + E_MI_VIF_INPUT_DATA_MAX +} MI_VIF_DataYuvSeq_e; + + +typedef enum +{ + // 时钟单沿模式,且VI 设备在上升沿采样 + E_MI_VIF_CLK_EDGE_SINGLE_UP, + // 时钟单沿模式,且VI 设备在下降沿采样 + E_MI_VIF_CLK_EDGE_SINGLE_DOWN, + // 前端送过来双沿数据时,VI 进行双沿采样 + E_MI_VIF_CLK_EDGE_DOUBLE, + E_MI_VIF_CLK_EDGE_MAX +} MI_VIF_ClkEdge_e; + + +typedef enum +{ + E_MI_VIF_BITORDER_NORMAL = 0, + E_MI_VIF_BITORDER_REVERSED +} MI_VIF_BitOrder_e; + +typedef enum +{ + E_MI_VIF_HDR_TYPE_OFF, + E_MI_VIF_HDR_TYPE_VC, //virtual channel mode HDR,vc0->long, vc1->short + E_MI_VIF_HDR_TYPE_DOL, + E_MI_VIF_HDR_TYPE_EMBEDDED, //compressed HDR mode + E_MI_VIF_HDR_TYPE_LI, //Line interlace HDR + E_MI_VIF_HDR_TYPE_MAX +} MI_VIF_HDRType_e; + +typedef enum +{ + E_MI_VIF_PIN_POLAR_POS, + E_MI_VIF_PIN_POLAR_NEG +} MI_VIF_Polar_e; + +typedef struct MI_VIF_SyncAttr_s +{ + MI_VIF_Polar_e eVsyncPolarity; + MI_VIF_Polar_e eHsyncPolarity; + MI_VIF_Polar_e ePclkPolarity; + MI_U32 VsyncDelay; + MI_U32 HsyncDelay; + MI_U32 PclkDelay; +} MI_VIF_SyncAttr_t; + +typedef enum +{ + E_MI_VIF_DEVICE_ID0 = 0x0001, + E_MI_VIF_DEVICE_ID1 = 0x0002, + E_MI_VIF_DEVICE_ID2 = 0x0004, + E_MI_VIF_DEVICE_ID3 = 0x0008, + E_MI_VIF_DEVICE_ID4 = 0x0010, + E_MI_VIF_DEVICE_ID5 = 0x0020, + E_MI_VIF_DEVICE_ID6 = 0x0040, + E_MI_VIF_DEVICE_ID7 = 0x0080, + E_MI_VIF_DEVICE_ID8 = 0x0100, + E_MI_VIF_DEVICE_ID9 = 0x0200, + E_MI_VIF_DEVICE_ID10 = 0x0400, + E_MI_VIF_DEVICE_ID11 = 0x0800, + E_MI_VIF_DEVICE_ID12 = 0x1000, + E_MI_VIF_DEVICE_ID13 = 0x2000, + E_MI_VIF_DEVICE_ID14 = 0x4000, + E_MI_VIF_DEVICE_ID15 = 0x8000, + E_MI_VIF_DEVICE_ID_MAX = 0xffff +} MI_VIF_DevId_e; + +typedef struct MI_VIF_DevAttr_s +{ + MI_VIF_IntfMode_e eIntfMode; + MI_VIF_WorkMode_e eWorkMode; + MI_VIF_HDRType_e eHDRType; + MI_VIF_ClkEdge_e eClkEdge; //BT656 + MI_VIF_DataYuvSeq_e eDataSeq; //mipi + MI_VIF_BitOrder_e eBitOrder;//adjust bit order layout BT656 + MI_VIF_SyncAttr_t stSyncAttr;//parallel, BT656 + MI_U32 u32DevStitchMask; //multi vif dev bitmask by MI_VIF_DevId_e +} MI_VIF_DevAttr_t; + +typedef struct MI_VIF_ChnPortAttr_s +{ + /* + 采集区域起始坐标用于配置需要采集的矩形图像相对于原始图像起始点的位置。 + stCapRect 的宽与高为静态属性, 其他项为动态属性;无次属性 + stCapRect 是针对原始图像进行裁剪; + stCapRect 中 s32X 和u32Width 必须 2 对齐; + s32Y 和u32Height 逐行采集时必须 2 对齐 + s32Y 和u32Height 隔行采集时必须 4 对齐 + */ + MI_SYS_WindowRect_t stCapRect; + + // stDestSize 的等于stCapRect,或者宽高都减少1/2 + MI_SYS_WindowSize_t stDestSize; + + /* + 抽场选择用于在原始图像为隔行输入时,用户可选择仅捕获其中的一场 + 为防止图像上下抖动现象,仅支持捕获两场或底场 + */ + MI_SYS_FieldType_e eCapSel; + + // 扫描模式用于在原始图像为隔行/逐行输入 + MI_SYS_FrameScanMode_e eScanMode; + + // 输出格式 enPixFormat 可以动态改变, 支持 semi-planar4:2:2 和 semi-planar4:2:0 + MI_SYS_PixelFormat_e ePixFormat; + + MI_VIF_FrameRate_e eFrameRate; + + // 如果设置 E_MI_VIF_WORK_MODE_RGB_FRAMEMODE, + // u32FrameModeLineCount表示VIF通知下一级的时机 + MI_U32 u32FrameModeLineCount; +} MI_VIF_ChnPortAttr_t; + +typedef struct MI_VIF_ChnPortStat_s +{ + // 通道是否使能 + MI_BOOL bEnable; + // 中断计数 + // can not support ? + MI_U32 u32IntCnt; + // 每10 秒的平均帧率,该值不一定精确 + MI_U32 u32FrameRate; + // 中断丢失计数,该结构体的中断丢失计数一直在增加,说明 VI 工作出现异常 + // can not support? + MI_U32 u32LostInt; + // 获取VB 失败计数 + MI_U32 u32VbFail; + // 图像宽度 + MI_U32 u32PicWidth; + // 图像高度 + MI_U32 u32PicHeight; +} MI_VIF_ChnPortStat_t; + +typedef enum +{ + E_MI_VIF_SNRPAD_ID_0 = 0, + E_MI_VIF_SNRPAD_ID_1 = 1, + E_MI_VIF_SNRPAD_ID_2 = 2, + E_MI_VIF_SNRPAD_ID_3 = 3, + E_MI_VIF_SNRPAD_ID_MAX, + E_MI_VIF_SNRPAD_ID_NA = 0xFF, +}MI_VIF_SNRPad_e; + +typedef struct MI_VIF_VIFDev2SnrPadMuxConf_s +{ + MI_VIF_SNRPad_e eSensorPadID; //sensor Pad id + MI_U32 u32PlaneID; //For HDR,0 is short exposure, 1 is long exposure +} MI_VIF_Dev2SnrPadMuxCfg_t; + +typedef struct MI_VIF_VIFDevStatus_s +{ + MI_VIF_Dev2SnrPadMuxCfg_t stDev2SensrPad; + MI_U32 bDevEn; +} MI_VIF_DevStatus_t; + +typedef struct MI_VIF_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_VIF_InitParam_t; + +#pragma pack(pop) + +#endif //_MI_VIF_DATATYPE_H_ + + diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vpe.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vpe.h new file mode 100644 index 000000000..7758095a5 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vpe.h @@ -0,0 +1,87 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_VPE_H_ +#define _MI_VPE_H_ + +#include "mi_vpe_datatype.h" + +#define VPE_MAJOR_VERSION 2 +#define VPE_SUB_VERSION 13 +#define MACRO_TO_STR(macro) #macro +#define VPE_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_vpe_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_vpe_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_vpe_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_VPE_API_VERSION VPE_VERSION_STR(VPE_MAJOR_VERSION,VPE_SUB_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + +MI_S32 MI_VPE_CreateChannel(MI_VPE_CHANNEL VpeCh, MI_VPE_ChannelAttr_t *pstVpeChAttr); +MI_S32 MI_VPE_DestroyChannel(MI_VPE_CHANNEL VpeCh); +MI_S32 MI_VPE_GetChannelAttr(MI_VPE_CHANNEL VpeCh, MI_VPE_ChannelAttr_t *pstVpeChAttr); +MI_S32 MI_VPE_SetChannelAttr(MI_VPE_CHANNEL VpeCh, MI_VPE_ChannelAttr_t *pstVpeChAttr); + +MI_S32 MI_VPE_StartChannel(MI_VPE_CHANNEL VpeCh); +MI_S32 MI_VPE_StopChannel(MI_VPE_CHANNEL VpeCh); + +MI_S32 MI_VPE_SetChannelParam(MI_VPE_CHANNEL VpeCh, MI_VPE_ChannelPara_t *pstVpeParam); +MI_S32 MI_VPE_GetChannelParam(MI_VPE_CHANNEL VpeCh, MI_VPE_ChannelPara_t *pstVpeParam); + +MI_S32 MI_VPE_SetChannelCrop(MI_VPE_CHANNEL VpeCh, MI_SYS_WindowRect_t *pstCropInfo); +MI_S32 MI_VPE_GetChannelCrop(MI_VPE_CHANNEL VpeCh, MI_SYS_WindowRect_t *pstCropInfo); +MI_S32 MI_VPE_GetChannelRegionLuma(MI_VPE_CHANNEL VpeCh, MI_VPE_RegionInfo_t *pstRegionInfo, MI_U32 *pu32LumaData,MI_S32 s32MilliSec); +MI_S32 MI_VPE_SetChannelRotation(MI_VPE_CHANNEL VpeCh, MI_SYS_Rotate_e eType); +MI_S32 MI_VPE_GetChannelRotation(MI_VPE_CHANNEL VpeCh, MI_SYS_Rotate_e *pType); + +MI_S32 MI_VPE_EnablePort(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort); +MI_S32 MI_VPE_DisablePort(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort); +MI_S32 MI_VPE_SetPortMode(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_VPE_PortMode_t *pstVpeMode); +MI_S32 MI_VPE_GetPortMode(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_VPE_PortMode_t *pstVpeMode); +MI_S32 MI_VPE_SetPortCrop(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_SYS_WindowRect_t *pstOutCropInfo); +MI_S32 MI_VPE_GetPortCrop(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_SYS_WindowRect_t *pstOutCropInfo); + +MI_S32 MI_VPE_SetPortShowPosition(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_SYS_WindowRect_t *pstPortPositionInfo); +MI_S32 MI_VPE_GetPortShowPosition(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_SYS_WindowRect_t *pstPortPositionInfo); + +MI_S32 MI_VPE_SkipFrame(MI_VPE_CHANNEL VpeCh, MI_U32 u32FrameNum); + +MI_S32 MI_VPE_LDCBegViewConfig(MI_VPE_CHANNEL VpeCh); +MI_S32 MI_VPE_LDCEndViewConfig(MI_VPE_CHANNEL VpeCh); +MI_S32 MI_VPE_LDCSetViewConfig(MI_VPE_CHANNEL VpeCh, void *pConfigAddr, MI_U32 u32ConfigSize); +MI_S32 MI_VPE_LDCSetBatchViewConfig(MI_VPE_CHANNEL VpeCh, MI_VPE_LdcConfig_t *pstCfg, MI_U32 u32CfgNum); + +MI_S32 MI_VPE_Alloc_IspDataBuf(MI_U32 u32Size,void **pUserVirAddr); +MI_S32 MI_VPE_Free_IspDataBuf(void *pUserBuf); + +MI_S32 MI_VPE_CreateMultiChannelStitch(MI_VPE_CHANNEL VpeCh, MI_VPE_MultiChannelStitchAttr_t *pstVpeChAttr); + +MI_S32 MI_VPE_InitDev(MI_VPE_InitParam_t *pstInitParam); +MI_S32 MI_VPE_DeInitDev(void); + +MI_S32 MI_VPE_CallBackTask_Register(MI_VPE_CallBackParam_t *pstCallBackParam); +MI_S32 MI_VPE_CallBackTask_Unregister(MI_VPE_CallBackParam_t *pstCallBackParam); + +MI_S32 MI_VPE_LoadPortZoomTable(MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_VPE_ZoomTable_t *pZoomTable); +MI_S32 MI_VPE_StartPortZoom (MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_VPE_ZoomAttr_t *pstZoomAttr); +MI_S32 MI_VPE_StopPortZoom (MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort); +MI_S32 MI_VPE_GetPortCurZoomAttr (MI_VPE_CHANNEL VpeCh, MI_VPE_PORT VpePort, MI_VPE_ZoomAttr_t *pstZoomAttr); + +#ifdef __cplusplus +} +#endif + +#endif///_MI_VPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vpe_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vpe_datatype.h new file mode 100644 index 000000000..7697fdc8b --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_vpe_datatype.h @@ -0,0 +1,294 @@ +/* SigmaStar trade secret */ +/* Copyright (c) [2019~2020] SigmaStar Technology. +All rights reserved. + +Unless otherwise stipulated in writing, any and all information contained +herein regardless in any format shall remain the sole proprietary of +SigmaStar and be kept in strict confidence +(SigmaStar Confidential Information) by the recipient. +Any unauthorized act including without limitation unauthorized disclosure, +copying, use, reproduction, sale, distribution, modification, disassembling, +reverse engineering and compiling of the contents of SigmaStar Confidential +Information is unlawful and strictly prohibited. SigmaStar hereby reserves the +rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ +#ifndef _MI_VPE_DATATYPE_H_ +#define _MI_VPE_DATATYPE_H_ +#include "mi_sys_datatype.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define MI_VPE_OK (0) +#define MI_ERR_VPE_INVALID_CHNID (0xA0078001) //The VPE channel ID is invalid. +#define MI_ERR_VPE_INVALID_PORTID (0xA0078002) //The VPE outport ID is invalid. +#define MI_ERR_VPE_ILLEGAL_PARAM (0xA0078003) //The VPE parameter is invalid. +#define MI_ERR_VPE_EXIST (0xA0078004) //A VPE channel is created. +#define MI_ERR_VPE_UNEXIST (0xA0078005) //No VPE channel is created. +#define MI_ERR_VPE_NULL_PTR (0xA0078006) //The pointer of the input parameter is null. +#define MI_ERR_VPE_NOT_SUPPORT (0xA0078008) //The operation is not supported. +#define MI_ERR_VPE_NOT_PERM (0xA0078009) //The operation is forbidden. +#define MI_ERR_VPE_NOMEM (0xA007800C) //The memory fails to be allocated. +#define MI_ERR_VPE_NOBUF (0xA007800D) //The buffer pool fails to be allocated. +#define MI_ERR_VPE_BUF_EMPTY (0xA007800E) //The picture queue is empty. +#define MI_ERR_VPE_NOTREADY (0xA0078010) //The VPE is not initialized. +#define MI_ERR_VPE_BUSY (0xA0078012) //The VPE is busy. + + +typedef MI_U32 MI_VPE_CHANNEL; +typedef MI_U32 MI_VPE_PORT; + +typedef enum +{ + E_MI_VPE_RUN_INVALID = 0x00, + E_MI_VPE_RUN_DVR_MODE = 0x01, + E_MI_VPE_RUN_CAM_TOP_MODE = 0x02, + E_MI_VPE_RUN_CAM_BOTTOM_MODE = 0x04, + E_MI_VPE_RUN_CAM_MODE = E_MI_VPE_RUN_CAM_TOP_MODE|E_MI_VPE_RUN_CAM_BOTTOM_MODE, + E_MI_VPE_RUN_REALTIME_TOP_MODE = 0x08, + E_MI_VPE_RUN_REALTIME_BOTTOM_MODE = 0x10, + E_MI_VPE_RUN_REALTIME_MODE = E_MI_VPE_RUN_REALTIME_TOP_MODE | E_MI_VPE_RUN_REALTIME_BOTTOM_MODE, + E_MI_VPE_RUNNING_MODE_MAX, +} MI_VPE_RunningMode_e; + +typedef enum +{ + E_MI_VPE_HDR_TYPE_OFF, + E_MI_VPE_HDR_TYPE_VC, //virtual channel mode HDR,vc0->long, vc1->short + E_MI_VPE_HDR_TYPE_DOL, + E_MI_VPE_HDR_TYPE_EMBEDDED, //compressed HDR mode + E_MI_VPE_HDR_TYPE_LI, //Line interlace HDR + E_MI_VPE_HDR_TYPE_MAX +} MI_VPE_HDRType_e; + +typedef enum +{ + E_MI_VPE_SENSOR_INVALID = 0, + E_MI_VPE_SENSOR0 = 0x1, + E_MI_VPE_SENSOR1 = 0x2, + E_MI_VPE_SENSOR2 = 0x4, + E_MI_VPE_SENSOR3 = 0x8, + E_MI_VPE_SENSOR4 = 0x10, + E_MI_VPE_SENSOR5 = 0x20, + E_MI_VPE_SENSOR6 = 0x40, + E_MI_VPE_SENSOR7 = 0x80, + E_MI_VPE_SENSOR_MAX +}MI_VPE_SensorChannel_e; + +typedef enum +{ + E_MI_VPE_3DNR_LEVEL_OFF, + E_MI_VPE_3DNR_LEVEL1, + E_MI_VPE_3DNR_LEVEL2, + E_MI_VPE_3DNR_LEVEL3, + E_MI_VPE_3DNR_LEVEL4, + E_MI_VPE_3DNR_LEVEL5, + E_MI_VPE_3DNR_LEVEL6, + E_MI_VPE_3DNR_LEVEL7, + E_MI_VPE_3DNR_LEVEL_NUM +}MI_VPE_3DNR_Level_e; + +typedef enum +{ + E_MI_VPE_ZOOM_LDC_NULL, + E_MI_VPE_ZOOM_LDC_PORT0 = 0X01, + E_MI_VPE_ZOOM_LDC_PORT1 = 0X02, + E_MI_VPE_ZOOM_LDC_PORT2 = 0X04, + E_MI_VPE_ZOOM_LDC_MAX = E_MI_VPE_ZOOM_LDC_PORT0| + E_MI_VPE_ZOOM_LDC_PORT1|E_MI_VPE_ZOOM_LDC_PORT2, +}MI_VPE_ChnPortMode_e; + +typedef enum +{ + E_MI_VPE_PORTSRC_FRAME = 0X0, + E_MI_VPE_PORTSRC_YUV_REALTIME = 0x01, + E_MI_VPE_PORTSRC_BAYER_REALTIME = 0x02, + E_MI_VPE_PORTSRC_MAX = 0xFF, +}MI_VPE_PortSource_e; + +typedef enum +{ + E_MI_VPE_OUTPUT_PORT0 = 0X01,//scl0 + E_MI_VPE_OUTPUT_PORT1 = 0X02,//scl1 + E_MI_VPE_OUTPUT_PORT2 = 0X04,//scl2 + E_MI_VPE_OUTPUT_PORT3 = 0X08,//isp dma/ldc + E_MI_VPE_OUTPUT_PORT4 = 0X10,//ir port + E_MI_VPE_OUTPUT_PORT5 = 0X20,//scl3 + E_MI_VPE_OUTPUT_PORT6 = 0X40,//scl4 + E_MI_VPE_OUTPUT_PORT7 = 0X80,//virtual port only src from bayer realtime + E_MI_VPE_PORT_ALL = 0xFF +}MI_VPE_OutputPortId_e; + +#define CHN_PORT_MODE(PortSrc, PortId) (PortId <<(8* PortSrc)) +/* +PortSrc from MI_VPE_PortSource_e +PortId from MI_VPE_OutputPortId_e +bit0~7 E_MI_VPE_PORTSRC_FRAME +bit8~15 E_MI_VPE_PORTSRC_YUV_REALTIME +bit16~23 E_MI_VPE_PORTSRC_BAYER_REALTIME +*/ + +typedef enum +{ + E_MI_VPE_SYNC3A_NONE = 0x00, + E_MI_VPE_SYNC3A_AE = 0x01, + E_MI_VPE_SYNC3A_AWB = 0x02, + E_MI_VPE_SYNC3A_IQ = 0x04 +}MI_VPE_SYNC3A_e; + +typedef struct MI_VPE_IspApiHeader_s +{ + MI_U32 u32HeadSize; //Size of MIIspApiHeader_t + MI_U32 u32DataLen; //Data length; + MI_U32 u32CtrlID; //Function ID + MI_U32 u32Channel; //Isp channel number + MI_S32 s32Ret; //Isp api retuen value +} MI_VPE_IspApiHeader_t; + +typedef struct MI_VPE_IspInitPara_s +{ + MI_U32 u32Revision; + MI_U32 u32Size; + MI_U8 u8Data[64]; +}MI_VPE_IspInitPara_t; + +typedef struct MI_VPE_ChannelAttr_s +{ + MI_U16 u16MaxW; + MI_U16 u16MaxH; + MI_SYS_PixelFormat_e ePixFmt; + MI_VPE_HDRType_e eHDRType; + MI_VPE_SensorChannel_e eSensorBindId; + + MI_BOOL bNrEn; + MI_BOOL bEdgeEn; + MI_BOOL bEsEn; + MI_BOOL bContrastEn; + MI_BOOL bUvInvert; + MI_BOOL bRotation; + MI_VPE_RunningMode_e eRunningMode; + MI_VPE_IspInitPara_t tIspInitPara; + MI_BOOL bEnLdc; // true port3 for ldc or for Isp(skip pass2) + MI_U32 u32ChnPortMode; +}MI_VPE_ChannelAttr_t; + +typedef struct MI_VPE_MultiChannelStitchAttr_s +{ + MI_U16 u16MaxW; + MI_U16 u16MaxH; + MI_SYS_PixelFormat_e ePixFmt; + MI_VPE_HDRType_e eHDRType; + MI_U32 u32StitchedSensorBitmap; //multi sensor bitmask by MI_VPE_SensorChannel_e + + MI_VPE_RunningMode_e eRunningMode; + MI_VPE_IspInitPara_t tIspInitPara; + MI_BOOL bEnLdc; + MI_U32 u32ChnPortMode; + MI_U32 u32MultiChannelNum; + MI_U32 u32Sync3AType; //sync 3a bitmask by MI_VPE_SYNC3A_e + MI_BOOL bForceOutputBufBeforeLDC; +}MI_VPE_MultiChannelStitchAttr_t; + + +typedef struct MI_VPE_PqParam_s +{ + MI_U8 u8NrcSfStr; //0 ~ 255; + MI_U8 u8NrcTfStr; //0 ~ 255 + MI_U8 u8NrySfStr; //0 ~ 255 + MI_U8 u8NryTfStr; //0 ~ 255 + MI_U8 u8NryBlendMotionTh; //0 ~ 15 + MI_U8 u8NryBlendStillTh; //0 ~ 15 + MI_U8 u8NryBlendMotionWei; //0 ~ 31 + MI_U8 u8NryBlendOtherWei; //0 ~ 31 + MI_U8 u8NryBlendStillWei; //0 ~ 31 + MI_U8 u8EdgeGain[6];//0~255 + MI_U8 u8Contrast;//0~255 +} MI_VPE_PqParam_t; + +typedef struct MI_VPE_ChannelPara_s +{ + MI_VPE_PqParam_t stPqParam; // only dvr use + MI_VPE_HDRType_e eHDRType; + MI_VPE_3DNR_Level_e e3DNRLevel; + MI_BOOL bMirror; + MI_BOOL bFlip; + MI_BOOL bWdrEn; //Wdr on/off not use + MI_BOOL bEnLdc; +} MI_VPE_ChannelPara_t; + +typedef struct MI_VPE_RegionInfo_s +{ + MI_SYS_WindowRect_t *pstWinRect; // region attribute + MI_U32 u32RegionNum; // count of the region +} MI_VPE_RegionInfo_t; + +/*Define attributes of Vpe port's work mode*/ +typedef struct MI_VPE_PortMode_s +{ + MI_U16 u16Width; // Width of target image + MI_U16 u16Height; // Height of target image + MI_BOOL bMirror; + MI_BOOL bFlip; + MI_SYS_PixelFormat_e ePixelFormat; // Pixel format of target image + MI_SYS_CompressMode_e eCompressMode; // Compression mode of the output +}MI_VPE_PortMode_t; + +typedef struct MI_VPE_InitParam_s +{ + MI_U32 u32DevId; + MI_U8 *u8Data; +} MI_VPE_InitParam_t; + +typedef MI_S32 (*MI_VPE_CALLBK_FUNC)(MI_U64 u64Data); + +typedef enum +{ + E_MI_VPE_CALLBACK_ISR, + E_MI_VPE_CALLBACK_MAX, +} MI_VPE_CallBackMode_e; + +typedef enum +{ + E_MI_VPE_IRQ_ISPVSYNC, + E_MI_VPE_IRQ_ISPFRAMEDONE, + E_MI_VPE_IRQ_MAX, +} MI_VPE_IrqType_e; + +typedef struct MI_VPE_CallBackParam_s +{ + MI_VPE_CallBackMode_e eCallBackMode; + MI_VPE_IrqType_e eIrqType; + MI_VPE_CALLBK_FUNC pfnCallBackFunc; + MI_U64 u64Data; +} MI_VPE_CallBackParam_t; + +typedef struct MI_VPE_ZoomEntry_s +{ + MI_SYS_WindowRect_t stCropWin; + MI_U8 u8ZoomSensorId; +} MI_VPE_ZoomEntry_t; + +typedef struct MI_VPE_ZoomTable_s +{ + MI_U32 u32EntryNum; + MI_VPE_ZoomEntry_t *pVirTableAddr; +} MI_VPE_ZoomTable_t; + +typedef struct MI_VPE_ZoomAttr_s +{ + MI_U32 u32FromEntryIndex; + MI_U32 u32ToEntryIndex; + MI_U32 u32CurEntryIndex; +} MI_VPE_ZoomAttr_t; + +typedef struct MI_VPE_LdcConfig_s +{ + void *pCfgAddr; + MI_U32 u32CfgSize; +} MI_VPE_LdcConfig_t; +#ifdef __cplusplus +} +#endif +#endif///_MI_VPE_DATATYPE_H_ diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_wlan.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_wlan.h new file mode 100644 index 000000000..2d4204929 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_wlan.h @@ -0,0 +1,421 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef _MI_WLAN_H_ +#define _MI_WLAN_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "mi_wlan_datatype.h" + +#define WLAN_MAJOR_VERSION 1 +#define WLAN_SUB_VERSION 0 +#define MACRO_TO_STR(macro) #macro +#define WLAN_VERSION_STR(major_version,sub_version) ({char *tmp = sub_version/100 ? \ + "mi_wlan_version_" MACRO_TO_STR(major_version)"." MACRO_TO_STR(sub_version) : sub_version/10 ? \ + "mi_wlan_version_" MACRO_TO_STR(major_version)".0" MACRO_TO_STR(sub_version) : \ + "mi_wlan_version_" MACRO_TO_STR(major_version)".00" MACRO_TO_STR(sub_version);tmp;}) +#define MI_WLAN_API_VERSION WLAN_VERSION_STR(DIVP_MAJOR_VERSION,DIVP_SUB_VERSION) + + + + +#define MI_WLAN_ERR_FAIL (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_FAILED)) +#define MI_WLAN_ERR_INVALID_DEVID (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INVALID_DEVID)) +#define MI_WLAN_ERR_ILLEGAL_PARAM (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_ILLEGAL_PARAM)) +#define MI_WLAN_ERR_NOT_SUPPORT (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_SUPPORT)) +#define MI_WLAN_ERR_MOD_INITED (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INITED)) +#define MI_WLAN_ERR_MOD_NOT_INIT (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_INIT)) +#define MI_WLAN_ERR_NOT_CONFIG (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NOT_CONFIG)) +#define MI_WLAN_ERR_INVAL_HANDLE (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_BADADDR)) +#define MI_WLAN_ERR_NULL_PTR (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_NULL_PTR)) +#define MI_WLAN_ERR_INITED (MI_DEF_ERR( E_MI_MODULE_ID_WLAN, E_MI_ERR_LEVEL_ERROR, E_MI_ERR_INITED)) + +/// WLAN max MAC len +#define MI_WLAN_MAX_MAC_LEN 32 +/// WLAN max SSID len +#define MI_WLAN_MAX_SSID_LEN 128 +/// WLAN max password len +#define MI_WLAN_MAX_PASSWD_LEN 40 +/// WLAN max AP number +#define MI_WLAN_MAX_APINFO_NUM 64 +/// WLAN max path len +#define MI_WLAN_MAX_FOLDERPATH_LEN 256 +/// WLAN interface len +#define MI_MAX_INTERFACE_NAME 64 +// WLAN BSSID len +#define MI_WLAN_BSSID_LEN 48 +// WLAN MAX hosts AP connected +#define MI_WLAN_MAX_HOSTS 64 +// WLAN MAX host name length +#define MI_WLAN_MAX_HOST_NAME_LEN 256 + +#define MI_RESULT MI_S32 + +// HANDLE indicates certain wifi connection +typedef MI_S32 WLAN_HANDLE; + + + +typedef enum +{ + /// WLAN module security key off + E_MI_WLAN_SECURITY_NONE = 1 << 0, + /// WLAN module security key unknow + E_MI_WLAN_SECURITY_UNKNOWTYPE = 1 << 1, + /// WLAN module security key WEP + E_MI_WLAN_SECURITY_WEP = 1 << 2, + /// WLAN module security key WPA + E_MI_WLAN_SECURITY_WPA = 1 << 3, + /// WLAN module security key WPA2 + E_MI_WLAN_SECURITY_WPA2 = 1 << 4, + /// WLAN module max + E_MI_WLAN_SECURITY_MAX = 0xff, +} MI_WLAN_Security_e; + + +typedef enum +{ + /// WLAN module encrypt type none + E_MI_WLAN_ENCRYPT_NONE = 1 << 0, + /// WLAN module encrypt type unknown + E_MI_WLAN_ENCRYPT_UNKNOWN = 1 << 1, + /// WLAN module encrypt type WEP + E_MI_WLAN_ENCRYPT_WEP = 1 << 2, + /// WLAN module encrypt type TKIP + E_MI_WLAN_ENCRYPT_TKIP = 1 << 3, + /// WLAN module encrypt type AES + E_MI_WLAN_ENCRYPT_AES = 1 << 4, + /// WLAN module max + E_MI_WLAN_ENCRYPT_MAX = 0xff, +} MI_WLAN_Encrypt_e; + + +typedef enum +{ + /// WLAN network infrastructure type + E_MI_WLAN_NETWORKTYPE_INFRA, + /// WLAN network AP type + E_MI_WLAN_NETWORKTYPE_AP, + /// WLAN network AdHoc type + E_MI_WLAN_NETWORKTYPE_ADHOC, + /// WLAN network Monitor type + E_MI_WLAN_NETWORKTYPE_MONITOR, + /// WLAN network mode master + E_MI_WLAN_NETWORKTYPE_MASTER, + /// WLAN network mode slave + E_MI_WLAN_NETWORKTYPE_SLAVE, + /// WLAN param max + E_MI_WLAN_NETWORKTYPE_MAX +} MI_WLAN_NetworkType_e; + + +typedef enum +{ + /// Authentication Suite PSK + E_MI_WLAN_AUTH_SUITE_PSK, + /// Authentication Suite unknown + E_MI_WLAN_AUTH_SUITE_UNKNOWN, + E_MI_WLAN_AUTH_SUITE_MAX + +} MI_WLAN_Authentication_Suite_e; + + + + +typedef enum +{ + /** + * WPA_DISCONNECTED - Disconnected state + */ + WPA_DISCONNECTED, + + /** + * WPA_INTERFACE_DISABLED - Interface disabled + */ + WPA_INTERFACE_DISABLED, + + /** + * WPA_INACTIVE - Inactive state (wpa_supplicant disabled) + */ + WPA_INACTIVE, + + /** + * WPA_SCANNING - Scanning for a network + */ + WPA_SCANNING, + + /** + * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID + */ + WPA_AUTHENTICATING, + + /** + * WPA_ASSOCIATING - Trying to associate with a BSS/SSID + */ + WPA_ASSOCIATING, + + /** + * WPA_ASSOCIATED - Association completed + */ + WPA_ASSOCIATED, + + /** + * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress + */ + WPA_4WAY_HANDSHAKE, + + /** + * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress + */ + WPA_GROUP_HANDSHAKE, + + /** + * WPA_COMPLETED - All authentication completed + */ + WPA_COMPLETED +} MI_WLAN_WPAStatus_e; + + +/// WLAN init parameter +typedef struct MI_WLAN_InitParams_s +{ + /// json description file of wifi dongle + MI_U8 au8JsonConfFilePath[MI_WLAN_MAX_FOLDERPATH_LEN]; + /// reserved + MI_U64 u64Reserved; +} MI_WLAN_InitParams_t; + + +/// WLAN open parameter +typedef struct MI_WLAN_OpenParam_s +{ + // WLAN network type + MI_WLAN_NetworkType_e eNetworkType; + // reserved + MI_BOOL bReserved; +} MI_WLAN_OpenParams_t; + + +/// WLAN connect info +typedef struct +{ + // WLan security mode + MI_WLAN_Security_e eSecurity; + // WLan SSID + MI_U8 au8SSId[MI_WLAN_MAX_SSID_LEN]; + // WLan password + MI_U8 au8Password[MI_WLAN_MAX_PASSWD_LEN]; + // WLAN connect overtime + MI_U32 OverTimeMs; +} MI_WLAN_ConnectParam_t; + + +typedef struct +{ + MI_U8 curLVL; + MI_U8 maxLVL; + MI_S8 signalSTR; +} MI_WLAN_Quality_t; + + +typedef struct +{ + // WLAN Security mode + MI_WLAN_Security_e eSecurity; + // WLAN Encryption type + MI_WLAN_Encrypt_e eGroupCipher; + // WLAN Encryption type + MI_WLAN_Encrypt_e ePairCipher; + // WLAN authenticationb suite + MI_WLAN_Authentication_Suite_e eAuthSuite; +} MI_WLAN_Cipher_t; + +/// WLAN ap info +typedef struct MI_WLAN_APInfo_s +{ + // WLAN CELL ID + MI_U16 u16CellId; + // WLAN Frequency GHz + MI_FLOAT fFrequency; + // WLAN Bitrate Mb/s + MI_FLOAT fBitRate; + // WLAN Quality + MI_WLAN_Quality_t stQuality; + // WLAN Encryption key on/off + MI_BOOL bEncryptKey; + // WLAN SSID + MI_U8 au8SSId[MI_WLAN_MAX_SSID_LEN]; + // WLAN Channel + MI_U8 u8Channel; + // WLAN MAC + MI_U8 au8Mac[MI_WLAN_MAX_MAC_LEN]; + // WLAN Encryption type + MI_WLAN_Encrypt_e eEncrypt; + // WLAN AP type (Infrastructure / Ad-Hoc) + MI_WLAN_NetworkType_e eMode; + // WLAN cipher kit + MI_WLAN_Cipher_t stCipher[2]; +} MI_WLAN_APInfo_t; + +/// WLAN ap info +typedef struct MI_WLAN_ScanParam_s +{ + // WLan set block mode + MI_BOOL bBlock; //reserved +} MI_WLAN_ScanParam_t; + +/// WLAN ap info +typedef struct MI_WLAN_ScanResult_s +{ + // WLan AP number + MI_WLAN_APInfo_t stAPInfo[MI_WLAN_MAX_APINFO_NUM]; + MI_U8 u8APNumber; +} MI_WLAN_ScanResult_t; + + +typedef struct MI_WLAN_Status_sta_s +{ + MI_U8 bssid[MI_WLAN_BSSID_LEN]; + MI_U32 freq; + MI_U8 ssid[MI_WLAN_MAX_SSID_LEN]; + MI_U16 id; + MI_WLAN_NetworkType_e mode; + MI_WLAN_Cipher_t stCipher; + MI_U8 key_mgmt[12]; + MI_WLAN_WPAStatus_e state; + MI_U8 address[MI_WLAN_BSSID_LEN]; + MI_U8 ip_address[16]; + MI_U32 channel; + MI_U32 RSSI; + MI_U8 Bandwidth[8]; +} MI_WLAN_Status_sta_t; + +typedef struct MI_WLAN_Status_host_s +{ + MI_U8 hostname[MI_WLAN_MAX_HOST_NAME_LEN]; + MI_U8 ipaddr[16]; + MI_U8 macaddr[18]; + MI_U64 connectedtime; + +} MI_WLAN_Status_host_t; + +typedef struct MI_WLAN_Status_ap_s +{ + MI_WLAN_Status_host_t astHosts[MI_WLAN_MAX_HOSTS]; + MI_U16 u16HostNum; +} MI_WLAN_Status_ap_t; + +typedef union MI_WLAN_Status_s +{ + MI_WLAN_Status_sta_t stStaStatus; + MI_WLAN_Status_ap_t stApStatus; +} MI_WLAN_Status_t; + + +//------------------------------------------------------------------------------ +/// @brief setup wlan init parameter , parse wifi config file and internel component +/// @param[in] *pstInitParams +/// @return MI_SUCCESS: success. +/// @return MI_WLAN_ERR_FAIL: init fail. +/// @return MI_WLAN_ERR_INITED: already inited. +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_Init(MI_WLAN_InitParams_t *pstInitParams); + +//------------------------------------------------------------------------------ +/// @brief do wlan deinit , deinit config file parser and internel component +/// @param none +/// @return MI_SUCCESS: success. +/// @return MI_WLAN_ERR_MOD_NOT_INIT: call MI_WLAN_Init first. +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_DeInit(void); + +//------------------------------------------------------------------------------ +/// @brief open wifi device +/// @param[in] *pstParam witch workmode wifi work on +/// @return MI_SUCCESS: success. +/// @return MI_WLAN_ERR_MOD_NOT_INIT: call MI_WLAN_Init first +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_Open(MI_WLAN_OpenParams_t *pstParam); + +//------------------------------------------------------------------------------ +/// @brief close wifi device +/// @param none. +/// @return MI_SUCCESS: success +/// @return MI_WLAN_ERR_NOT_CONFIG: Process success. +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_Close(void); + +//------------------------------------------------------------------------------ +/// @brief connect wifi service +/// +/// infra mode : connect to certain wifi network +/// ap mode: start dns hdcp service and wait hosts to connect +/// @param[in/out] hWLan wlan handle. +/// (<0)indicates a new connection and will be assigned a sensible ID if connecton set up +/// (>0)indicates an set up connection +/// @param[in] *pstConnectParam :. +/// infra mode:contains nessesarry information to establish a sta connection +/// @return MI_SUCCESS: connect success. +/// @return MI_WLAN_ERR_MOD_NOT_INIT: open wlan device first +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_Connect(WLAN_HANDLE *hWLan, MI_WLAN_ConnectParam_t *pstConnectParam); + +//------------------------------------------------------------------------------ +/// @brief disconnect wlan +/// @param[in] hWLan wlan handle. +/// @return MI_SUCCESS: Process success. +/// @return MI_WLAN_ERR_NOT_CONFIG: set up a wlan connection first +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_Disconnect(WLAN_HANDLE hWLan); + +//------------------------------------------------------------------------------ +/// @brief scan ap info +/// @param[in] *pstParam info param. //reserved +/// @param[out] *pstResult result. +/// @return MI_SUCCESS: success. +/// @return MI_WLAN_ERR_NOT_CONFIG: open wlan first +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_Scan(MI_WLAN_ScanParam_t *pstParam, MI_WLAN_ScanResult_t *pstResult); + +//------------------------------------------------------------------------------ +/// @brief set wlan debug level +/// @param[in] eDgbLevel debug level. +/// @return MI_OK: Process success. +/// @return MI_ERR_FAILED: Process failed +//------------------------------------------------------------------------------ +//MI_RESULT MI_WLAN_SetDebugLevel(MI_DBG_LEVEL_e eDgbLevel); + +//------------------------------------------------------------------------------ +/// @brief get current wlan status +/// @param[in] the struct to store wlan status +/// @return MI_SUCCESS: Process success. +/// @return MI_WLAN_ERR_NOT_CONFIG: open wlan first +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_GetStatus(MI_WLAN_Status_t *status); + +//------------------------------------------------------------------------------ +/// @brief get wlan chip version +/// @return MI_OK: Process success +/// @return MI_ERR_FAILED: Process failed +//------------------------------------------------------------------------------ +MI_RESULT MI_WLAN_GetWlanChipVersion(MI_U8 *ChipVersion); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_wlan_datatype.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_wlan_datatype.h new file mode 100644 index 000000000..e19bf39a9 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/mi_wlan_datatype.h @@ -0,0 +1,73 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + +#ifndef __MI_WLAN_DATATYPE_H__ +#define __MI_WLAN_DATATYPE_H__ +#ifdef __cplusplus +extern "C" { +#endif + +#define DBG_LEVEL_FATAL (1) +#define DBG_LEVEL_ERROR (2) +#define DBG_LEVEL_WARN (3) +#define DBG_LEVEL_INFO (4) +#define DBG_LEVEL_DEBUG (5) +#define DBG_LEVEL_ENTRY (6) + +#define DBG_LEVEL DBG_LEVEL_WARN + +#define COLOR_NONE "\033[0m" +#define COLOR_BLACK "\033[0;30m" +#define COLOR_BLUE "\033[0;34m" +#define COLOR_GREEN "\033[0;32m" +#define COLOR_CYAN "\033[0;36m" +#define COLOR_RED "\033[0;31m" +#define COLOR_YELLOW "\033[1;33m" +#define COLOR_WHITE "\033[1;37m" + +#define DBG_ENTRY(fmt, args...) ({do{if(DBG_LEVEL>=DBG_LEVEL_ENTRY){printf(COLOR_CYAN"[WLAN_ENTRY]:%s[%d]: ", __FUNCTION__,__LINE__);printf(fmt, ##args);printf(COLOR_NONE);}}while(0);}) +#define DBG_DEBUG(fmt, args...) ({do{if(DBG_LEVEL>=DBG_LEVEL_DEBUG){printf(COLOR_WHITE"[WLAN_BDG]:%s[%d]: ", __FUNCTION__,__LINE__);printf(fmt, ##args);printf(COLOR_NONE);}}while(0);}) +#define DBG_INFO(fmt, args...) ({do{if(DBG_LEVEL>=DBG_LEVEL_INFO) {printf(COLOR_GREEN"[WLAN_INFO]:%s[%d]: ", __FUNCTION__,__LINE__);printf(fmt, ##args);printf(COLOR_NONE);}}while(0);}) +#define DBG_WRN(fmt, args...) ({do{if(DBG_LEVEL>=DBG_LEVEL_WARN) {printf(COLOR_YELLOW"[WLAN_WRN]:%s[%d]: ", __FUNCTION__,__LINE__);printf(fmt, ##args);printf(COLOR_NONE);}}while(0);}) +#define DBG_ERR(fmt, args...) ({do{if(DBG_LEVEL>=DBG_LEVEL_ERROR){printf(COLOR_RED"[WLAN_ERR]:%s[%d]: ", __FUNCTION__,__LINE__);printf(fmt, ##args);printf(COLOR_NONE);}}while(0);}) +#define DBG_FATAL(fmt, args...) ({do{if(DBG_LEVEL>=DBG_LEVEL_FATAL){printf(COLOR_RED"[WLAN_FATAL]:%s[%d]: ", __FUNCTION__,__LINE__);printf(fmt, ##args);printf(COLOR_NONE);}}while(0);}) + + + +typedef enum +{ + E_WLAN_CMD_INIT = 0, + E_WLAN_CMD_OPEN, + E_WLAN_CMD_CLOSE, + E_WLAN_CMD_DEINIT, + E_WLAN_CMD_SCAN, + E_WLAN_CMD_CONNECT, + E_WLAN_CMD_CONNECT_addNetWork, + E_WLAN_CMD_DISCONNECT, + E_WLAN_CMD_STATUS, + E_WLAN_CMD_VERSION, + E_WLAN_CMD_CHANNEL, + E_WLAN_CMD_NUM +} E_WLAN_CMD; + + + + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/ssnn.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/ssnn.h new file mode 100644 index 000000000..70ec5b095 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/ssnn.h @@ -0,0 +1,74 @@ +#ifndef _SSNN_H +#define _SSNN_H + +#ifdef __cplusplus +extern "C" { +#endif +// ================================================================================================== +// Structure Definition +// ================================================================================================== + +typedef struct +{ + // == Model-dependent settings == // + int target_height; + int target_width; + + // == General settings == // + float prob_thresh; + float nms_thresh; + int num_threads; + int max_detection; + int init_network_index; +}network_config; + +typedef struct +{ + short int x_min, y_min; // top-left corner + short int x_max, y_max; // bottom-right corner + short int class_idx; + float prob; +}BBox; + +typedef struct +{ + network_config *cfg; + void *net; + BBox *boxes; // Only for detector + float *probs; // Only for classifier + float *feature; // Only for feature extractor + int num_detection; +}NetworkHandle; + +// ================================================================================================== +// Enumerations +// ================================================================================================== + +enum E_NETWORK_TYPE +{ + CLASSIFIER, + DETECTOR, + FEATURE +}; + +// ================================================================================================== +// API +// ================================================================================================== + +int Init_Network(NetworkHandle **phandle, network_config *cfg); +void Release_Network(NetworkHandle **phandle); +int Forward_Network(NetworkHandle *handle, unsigned char *data, int height, int width, int color); +int Get_Detection(NetworkHandle *handle, int img_height, int img_width); // Only for detector +int Get_Prob(NetworkHandle *handle); // Only for classifier +int Get_Feature(NetworkHandle *handle); // Only for feature extractor +int Change_Model(NetworkHandle *handle, int network_index); +int Get_Num_Classes(NetworkHandle *handle); +int Get_Network_Type(NetworkHandle *handle); +int Get_Size_Alignment(NetworkHandle *handle); +int Get_Feature_Size(NetworkHandle *handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/333DE/lib/mi_libs/include/sstarFb.h b/code/application/sifarsdk/333DE/lib/mi_libs/include/sstarFb.h new file mode 100644 index 000000000..baa4ceb32 --- /dev/null +++ b/code/application/sifarsdk/333DE/lib/mi_libs/include/sstarFb.h @@ -0,0 +1,220 @@ +/* Copyright (c) 2018-2019 Sigmastar Technology Corp. + All rights reserved. + + Unless otherwise stipulated in writing, any and all information contained + herein regardless in any format shall remain the sole proprietary of + Sigmastar Technology Corp. and be kept in strict confidence + (��Sigmastar Confidential Information��) by the recipient. + Any unauthorized act including without limitation unauthorized disclosure, + copying, use, reproduction, sale, distribution, modification, disassembling, + reverse engineering and compiling of the contents of Sigmastar Confidential + Information is unlawful and strictly prohibited. Sigmastar hereby reserves the + rights to any and all damages, losses, costs and expenses resulting therefrom. +*/ + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// @file sstarFb.h +/// @brief Sigmastar graphic Interface header file +/// @author Sigmastar Semiconductor Inc. +/// @attention +/// +/////////////////////////////////////////////////////////////////////////////////////////////////// +#ifndef _UAPI_SSTAR_FB_GRAPHIC_H +#define _UAPI_SSTAR_FB_GRAPHIC_H + +#include +#include "mi_common_datatype.h" + +//------------------------------------------------------------------------------------------------- +// Type and Structure +//------------------------------------------------------------------------------------------------- +typedef enum +{ + //E_DRV_FB_GOP_COLOR_RGB565 + E_MI_FB_COLOR_FMT_RGB565 = 1, + //E_DRV_FB_GOP_COLOR_ARGB4444 + E_MI_FB_COLOR_FMT_ARGB4444 = 2, + //E_DRV_FB_GOP_COLOR_ARGB8888 + E_MI_FB_COLOR_FMT_ARGB8888 = 5, + //E_DRV_FB_GOP_COLOR_ARGB1555 + E_MI_FB_COLOR_FMT_ARGB1555 = 6, + //E_DRV_FB_GOP_COLOR_YUV422 + E_MI_FB_COLOR_FMT_YUV422 = 9, + //E_DRV_FB_GOP_COLOR_I8 + E_MI_FB_COLOR_FMT_I8 = 4, + //E_DRV_FB_GOP_COLOR_I4 + E_MI_FB_COLOR_FMT_I4 = 13, + //E_DRV_FB_GOP_COLOR_I2 + E_MI_FB_COLOR_FMT_I2 = 14, + //E_DRV_FB_GOP_COLOR_INVALID + E_MI_FB_COLOR_FMT_INVALID = 12, +} MI_FB_ColorFmt_e; + +typedef enum +{ + E_MI_FB_DISPLAYLAYER_ATTR_MASK_DISP_POS = 0x1, + E_MI_FB_DISPLAYLAYER_ATTR_MASK_DISP_SIZE = 0x2, + E_MI_FB_DISPLAYLAYER_ATTR_MASK_BUFFER_SIZE = 0x4, + E_MI_FB_DISPLAYLAYER_ATTR_MASK_SCREEN_SIZE = 0x8, + E_MI_FB_DISPLAYLAYER_ATTR_MASK_PREMUL = 0x10, + E_MI_FB_DISPLAYLAYER_ATTR_MASK_COLOR_FMB = 0x20, + E_MI_FB_DISPLAYLAYER_ATTR_MASK_OUTPUT_COLORSPACE = 0x40, + E_MI_FB_DISPLAYLAYER_ATTR_MASK_DST_DISP = 0x80, +} MI_FB_DisplayLayerAttrMaskbit_e; + +typedef struct MI_FB_GlobalAlpha_s +{ + MI_BOOL bAlphaEnable;/* alpha enable flag */ + /* alpha channel enable flag + TRUE: alpha set to pixel alpha + FALSE:aplha set to global alpha + */ + MI_BOOL bAlphaChannel; + MI_U8 u8Alpha0; /*alpha0 value*/ + MI_U8 u8Alpha1; /*alpha1 value*/ + MI_U8 u8GlobalAlpha;/* global alpha value */ + MI_U8 u8Reserved; /* reserved*/ +} MI_FB_GlobalAlpha_t; + +typedef struct MI_FB_ColorKey_s +{ + MI_BOOL bKeyEnable; + MI_U8 u8Red; + MI_U8 u8Green; + MI_U8 u8Blue; +} MI_FB_ColorKey_t; + +typedef struct MI_FB_Rectangle_s +{ + MI_U16 u16Xpos; + MI_U16 u16Ypos; + MI_U16 u16Width; + MI_U16 u16Height; +} MI_FB_Rectangle_t; + +typedef enum +{ + //DRV_FB_GOPOUT_RGB + E_MI_FB_OUTPUT_RGB = 0, + //DRV_FB_GOPOUT_YUV + E_MI_FB_OUTPUT_YUV = 1, +} MI_FB_OutputColorSpace_e; + +typedef enum +{ + //E_DRV_FB_GOP_DST_IP0 + E_MI_FB_DST_IP0 = 0, + //E_DRV_FB_GOP_DST_IP0_SUB + E_MI_FB_DST_IP0_SUB = 1, + //E_DRV_FB_GOP_DST_MIXER2VE + E_MI_FB_DST_MIXER2VE = 2, + //E_DRV_FB_GOP_DST_OP0 + E_MI_FB_DST_OP0 = 3, + //E_DRV_FB_GOP_DST_VOP + E_MI_FB_DST_VOP = 4, + //E_DRV_FB_GOP_DST_IP1 + E_MI_FB_DST_IP1 = 5, + //E_DRV_FB_GOP_DST_IP1_SUB + E_MI_FB_DST_IP1_SUB = 6, + //E_DRV_FB_GOP_DST_MIXER2OP + E_MI_FB_DST_MIXER2OP = 7, + //E_DRV_FB_GOP_DST_VOP_SUB + E_MI_FB_DST_VOP_SUB = 8, + //E_DRV_FB_GOP_DST_FRC + E_MI_FB_DST_FRC = 9, + //E_DRV_FB_GOP_DST_VE + E_MI_FB_DST_VE = 10, + //E_DRV_FB_GOP_DST_BYPASS + E_MI_FB_DST_BYPASS = 11, + //E_DRV_FB_GOP_DST_OP1 + E_MI_FB_DST_OP1 = 12, + //E_DRV_FB_GOP_DST_MIXER2OP1 + E_MI_FB_DST_MIXER2OP1 = 13, + //E_DRV_FB_GOP_DST_DIP + E_MI_FB_DST_DIP = 14, + //E_DRV_FB_GOP_DST_GOPScaling + E_MI_FB_DST_GOPScaling = 15, + //E_DRV_FB_GOP_DST_OP_DUAL_RATE + E_MI_FB_DST_OP_DUAL_RATE = 16, + //E_DRV_FB_GOP_DST_INVALID + E_MI_FB_DST_INVALID = 17, +} MI_FB_DstDisplayplane_e; + +typedef struct MI_FB_DisplayLayerAttr_s +{ + MI_U32 u32Xpos; /**the x pos of orign point in screen.Meaning for stretchwindow posx*/ + MI_U32 u32YPos; /**the y pos of orign point in screen.Meaning for stretchwindow posy*/ + MI_U32 u32dstWidth; /**display buffer dest with in screen.Meaning for stretch window dst width*/ + MI_U32 u32dstHeight; /**display buffer dest hight in screen.Meaning for stretch window dst height*/ + MI_U32 u32DisplayWidth; /**the width of display buf in fb.Meaning for OSD resolution width */ + MI_U32 u32DisplayHeight; /**the height of display buf in fb.Meaning for OSD resolution height*/ + MI_U32 u32ScreenWidth; /**the width of screen.Meaning for timing width.Meaning for timing height*/ + MI_U32 u32ScreenHeight; /** the height of screen */ + MI_BOOL bPreMul; /**the data drawed in buffer whether is premultiply alpha or not*/ + MI_FB_ColorFmt_e eFbColorFmt; /**the color format of framebuffer*/ + MI_FB_OutputColorSpace_e eFbOutputColorSpace; /**output color space*/ + MI_FB_DstDisplayplane_e eFbDestDisplayPlane; /**destination displayplane*/ + MI_U32 u32SetAttrMask; /** display attribute modify mask*/ +} MI_FB_DisplayLayerAttr_t; + +typedef struct MI_FB_CursorImage_s +{ + MI_U32 u32Width; /**width, unit pixel*/ + MI_U32 u32Height; /**Height, unit pixel*/ + MI_U32 u32Pitch; /**Pitch, unit pixel*/ + MI_FB_ColorFmt_e eColorFmt; /**Color format*/ +#ifndef __KERNEL__ + const char *data; /**Image raw data*/ +#else + const char __user *data; /**Image raw data*/ +#endif +} MI_FB_CursorImage_t; + +typedef enum +{ + E_MI_FB_CURSOR_ATTR_MASK_ICON = 0x1, + E_MI_FB_CURSOR_ATTR_MASK_POS = 0x2, + E_MI_FB_CURSOR_ATTR_MASK_ALPHA = 0x4, + E_MI_FB_CURSOR_ATTR_MASK_SHOW = 0x8, + E_MI_FB_CURSOR_ATTR_MASK_HIDE = 0x10, + E_MI_FB_CURSOR_ATTR_MASK_COLORKEY = 0x20, + E_MI_FB_CURSOR_ATTR_MASK = 0x3F +} MI_FB_CursorAttrMaskbit_e; + +typedef struct MI_FB_CursorAttr_s +{ + MI_U32 u32XPos; + MI_U32 u32YPos; + MI_U32 u32HotSpotX; + MI_U32 u32HotSpotY; + MI_FB_GlobalAlpha_t stAlpha; + MI_FB_ColorKey_t stColorKey; + MI_BOOL bShown; + MI_FB_CursorImage_t stCursorImageInfo; + MI_U16 u16CursorAttrMask; +} MI_FB_CursorAttr_t; +//------------------------------------------------------------------------------------------------- +// Macro and Define +//------------------------------------------------------------------------------------------------- +#define FB_IOC_MAGIC 'F' + +#define FBIOGET_SCREEN_LOCATION _IOR(FB_IOC_MAGIC, 0x60, MI_FB_Rectangle_t) +#define FBIOSET_SCREEN_LOCATION _IOW(FB_IOC_MAGIC, 0x61, MI_FB_Rectangle_t) + +#define FBIOGET_SHOW _IOR(FB_IOC_MAGIC, 0x62, MI_BOOL) +#define FBIOSET_SHOW _IOW(FB_IOC_MAGIC, 0x63, MI_BOOL) + +#define FBIOGET_GLOBAL_ALPHA _IOR(FB_IOC_MAGIC, 0x64, MI_FB_GlobalAlpha_t) +#define FBIOSET_GLOBAL_ALPHA _IOW(FB_IOC_MAGIC, 0x65, MI_FB_GlobalAlpha_t) + +#define FBIOGET_COLORKEY _IOR(FB_IOC_MAGIC, 0x66, MI_FB_ColorKey_t) +#define FBIOSET_COLORKEY _IOW(FB_IOC_MAGIC, 0x67, MI_FB_ColorKey_t) + +#define FBIOGET_DISPLAYLAYER_ATTRIBUTES _IOR(FB_IOC_MAGIC, 0x68, MI_FB_DisplayLayerAttr_t) +#define FBIOSET_DISPLAYLAYER_ATTRIBUTES _IOW(FB_IOC_MAGIC, 0x69, MI_FB_DisplayLayerAttr_t) + +#define FBIOGET_CURSOR_ATTRIBUTE _IOR(FB_IOC_MAGIC, 0x70, MI_FB_CursorAttr_t) +#define FBIOSET_CURSOR_ATTRIBUTE _IOW(FB_IOC_MAGIC, 0x71, MI_FB_CursorAttr_t) + +#endif diff --git a/code/application/sifarsdk/333DE/test/CMakeLists.txt b/code/application/sifarsdk/333DE/test/CMakeLists.txt new file mode 100644 index 000000000..be94652a1 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/CMakeLists.txt @@ -0,0 +1,8 @@ + +# cmake_minimum_required(VERSION 2.8.0) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TEST_LINUX_MOCK}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TEST_LINUX_MOCK}") + +add_subdirectory(application) +add_subdirectory(component) +add_subdirectory(hal) \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/application/CMakeLists.txt b/code/application/sifarsdk/333DE/test/application/CMakeLists.txt new file mode 100644 index 000000000..c3b1f9188 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/CMakeLists.txt @@ -0,0 +1,9 @@ + +# cmake_minimum_required(VERSION 2.8.0) +#Compile gtest for test code. +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TEST_LINUX_MOCK}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TEST_LINUX_MOCK}") +add_subdirectory(main) +add_subdirectory(NetworkManager) + + diff --git a/code/application/sifarsdk/333DE/test/application/NetworkManager/CMakeLists.txt b/code/application/sifarsdk/333DE/test/application/NetworkManager/CMakeLists.txt new file mode 100644 index 000000000..00d9acb26 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/NetworkManager/CMakeLists.txt @@ -0,0 +1,40 @@ + +set(EXECUTABLE_OUTPUT_PATH ${TEST_OUTPUT_PATH}/bin) + +include_directories( + ./src + ${APPLICATION_SOURCE_PATH}/StateManager/include + ${APPLICATION_SOURCE_PATH}/StateManager/src + ${APPLICATION_SOURCE_PATH}/NetworkManager/include + ${COMPONENT_SOURCE_PATH}/StateMachineManager/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/DualCoreManager/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${HAL_SOURCE_PATH}/include + ${HAL_SOURCE_PATH} + ${TEST_SOURCE_PATH}/test_common + ${PLATFORM_PATH}/hal/include + ${PLATFORM_PATH}/hal + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googletest/include + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/include +) + +link_directories( + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${LIBS_OUTPUT_PATH} +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) +aux_source_directory(./src SRC_FILES) +aux_source_directory(${TEST_SOURCE_PATH}/test_common SRC_FILES) + + +set(TARGET_NAME NetworkManager333DETest) +add_executable(${TARGET_NAME} ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} NetworkManager HalChipBoard gtest gmock ${TEST_LINK_LIB} pthread ReturnCode Log) \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/application/NetworkManager/main.cpp b/code/application/sifarsdk/333DE/test/application/NetworkManager/main.cpp new file mode 100644 index 000000000..fb1d91b4c --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/NetworkManager/main.cpp @@ -0,0 +1,9 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/application/NetworkManager/src/NetworkManager333DETest.cpp b/code/application/sifarsdk/333DE/test/application/NetworkManager/src/NetworkManager333DETest.cpp new file mode 100644 index 000000000..7df0ff2d0 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/NetworkManager/src/NetworkManager333DETest.cpp @@ -0,0 +1,164 @@ + +#include "INetworkManager.h" +#include "IPeripheralManager.h" +#include "IHal.h" +#include "IHal333DE.h" +#include "Hal333DE.h" +#include "Log.h" +#include "TestCommon.h" +#include +#include +#include +#include +namespace NetworkManager333DETest +{ + class Hal333DEMock : public Hal333DE + { + public: + Hal333DEMock() = default; + virtual ~Hal333DEMock() = default; + void CheckAllPins(void) override + { + // For test in ubuntu, do not pirntf the error log. + } + }; + // ../out/test/bin/NetworkManager333DETest --gtest_filter=NetworkManager333DETest.Demo + // This demo run in ubuntu. + TEST(NetworkManager333DETest, Demo) + { + InitLog(LOG_EASYLOGGING, nullptr); + Hal333DEMakePtrOverride(); + std::shared_ptr hal = std::make_shared(); + CreateHalModuleInstance(); + IHal::GetInstance(&hal); + CreatePeripheralManager(); + CreateNetworkManagerModule(); + IHal::GetInstance()->Init(); + IPeripheralManager::GetInstance()->Init(); + RETURN_CODE code = INetworkManager::GetInstance()->Init(); + if (!code->IsCodeOK()) + { + LogError("init failed.\n"); + code->PrintStringCode(); + } + else + { + LogInfo("init succeed.\n"); + INetworkManager::GetInstance()->LinkNetworkInit(); + ITestCommon::GetInstance()->IUsleep(1000 * 15); + } + EXPECT_TRUE(code->IsCodeOK()) << TEST_REPORT_TIPS << "State manager init failed."; + + UnInitLog(); + INetworkManager::GetInstance()->UnInit(); + } + // ../out/test/bin/NetworkManager333DETest --gtest_filter=NetworkManager333DETest.Demo2 + // This demo run on board. + TEST(NetworkManager333DETest, Demo2) + { + InitLog(LOG_EASYLOGGING, nullptr); + Hal333DEMakePtrOverride(); + CreateHalModuleInstance(); + CreatePeripheralManager(); + CreateNetworkManagerModule(); + IHal::GetInstance()->Init(); + IPeripheralManager::GetInstance()->Init(); + RETURN_CODE code = INetworkManager::GetInstance()->Init(); + if (!code->IsCodeOK()) + { + LogError("init failed.\n"); + code->PrintStringCode(); + } + else + { + LogInfo("init succeed.\n"); + INetworkManager::GetInstance()->LinkNetworkInit(); + ITestCommon::GetInstance()->IUsleep(1000 * 60); + } + EXPECT_TRUE(code->IsCodeOK()) << TEST_REPORT_TIPS << "State manager init failed."; + + UnInitLog(); + INetworkManager::GetInstance()->UnInit(); + } + // ../out/test/bin/NetworkManager333DETest --gtest_filter=NetworkManager333DETest.Demo3 + // This demo run in ubuntu. + TEST(NetworkManager333DETest, Demo3) + { + InitLog(LOG_EASYLOGGING, nullptr); + Hal333DEMakePtrOverride(); + std::shared_ptr hal = std::make_shared(); + CreateHalModuleInstance(); + IHal::GetInstance(&hal); + CreatePeripheralManager(); + CreateNetworkManagerModule(); + IHal::GetInstance()->Init(); + IPeripheralManager::GetInstance()->Init(); + RETURN_CODE code = INetworkManager::GetInstance()->Init(); + if (!code->IsCodeOK()) + { + LogError("init failed.\n"); + code->PrintStringCode(); + } + else + { + LogInfo("init succeed.\n"); + INetworkManager::GetInstance()->RegisterNetwork(RegisterNetworkType::MANUAL); + ITestCommon::GetInstance()->IUsleep(1000 * 10); + } + EXPECT_TRUE(code->IsCodeOK()) << TEST_REPORT_TIPS << "State manager init failed."; + + UnInitLog(); + INetworkManager::GetInstance()->UnInit(); + } + // ../out/test/bin/NetworkManager333DETest --gtest_filter=NetworkManager333DETest.Demo4 + // This demo run on board. + TEST(NetworkManager333DETest, Demo4) + { + InitLog(LOG_EASYLOGGING, nullptr); + Hal333DEMakePtrOverride(); + CreateHalModuleInstance(); + CreatePeripheralManager(); + CreateNetworkManagerModule(); + IHal::GetInstance()->Init(); + IPeripheralManager::GetInstance()->Init(); + RETURN_CODE code = INetworkManager::GetInstance()->Init(); + if (!code->IsCodeOK()) + { + LogError("init failed.\n"); + code->PrintStringCode(); + } + else + { + LogInfo("init succeed.\n"); + INetworkManager::GetInstance()->LinkNetworkInit(); + ITestCommon::GetInstance()->IUsleep(1000 * 10); + INetworkManager::GetInstance()->RegisterNetwork(RegisterNetworkType::MANUAL); + ITestCommon::GetInstance()->IUsleep(1000 * 10); + NetworkParameter param; + INetworkManager::GetInstance()->GetParameter(param); + LogInfo("imei = %s, iccid = %s\n", param.mIMEI.c_str(), param.mIccid.c_str()); + AuthRequestDataIn dataIn("acenter.wuyuantech.com", param.mIMEI, param.mIccid); + AuthRequestDataOut dataOut; + INetworkManager::GetInstance()->AuthRequest(dataIn, dataOut); + LogInfo("acm ip = %s\n", dataOut.mAcmIP.c_str()); + std::shared_ptr acmServers = std::make_shared(); + AcmServersData acm; + acm.mIMEI = param.mIMEI; + acm.mIccid = param.mIccid; + acm.mAcmIP = dataOut.mAcmIP; + acm.mSignalLevel = NetworkSignal::LEVEL_3; + acm.mServiceProvider = "CHN-CT"; + acm.FcTemper = 83; + acm.BatRemainCap = 100; + acm.mModuleSubVersion = "ASFDSFDSGDFGFGF"; + INetworkManager::GetInstance()->GetAcmServersHandle(acmServers, acm); + AcmLoginResult acmOut; + acmServers->Login(acmOut); + ITestCommon::GetInstance()->IUsleep(1000 * 600); + } + EXPECT_TRUE(code->IsCodeOK()) << TEST_REPORT_TIPS << "State manager init failed."; + + UnInitLog(); + INetworkManager::GetInstance()->UnInit(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/application/main/CMakeLists.txt b/code/application/sifarsdk/333DE/test/application/main/CMakeLists.txt new file mode 100644 index 000000000..3d3a37005 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/main/CMakeLists.txt @@ -0,0 +1,49 @@ + +set(EXECUTABLE_OUTPUT_PATH ${TEST_OUTPUT_PATH}/bin) +include_directories( + ./src + ${APPLICATION_SOURCE_PATH}/StateManager/include + ${APPLICATION_SOURCE_PATH}/main/src + # ${APPLICATION_SOURCE_PATH}/StateManager/src + ${COMPONENT_SOURCE_PATH}/StateMachineManager/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/DualCoreManager/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/McuManager/src + ${COMPONENT_SOURCE_PATH}/Config/src + # ${COMPONENT_SOURCE_PATH}/Config/src/src_c/include + ${HAL_SOURCE_PATH}/include + ${HAL_SOURCE_PATH} + ${TEST_SOURCE_PATH}/test_utils + ${TEST_SOURCE_PATH}/test_utils/linux_mock + ${PLATFORM_PATH}/hal/include + ${PLATFORM_PATH}/hal + ${PLATFORM_PATH}/application/main/src + ${MAIN_INCLUDE_PATH} + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googletest/include + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/include +) + +link_directories( + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${LIBS_OUTPUT_PATH} +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) +aux_source_directory(./src SRC_FILES) +# aux_source_directory(${APPLICATION_SOURCE_PATH}/main/src SRC_FILES) +aux_source_directory(${PLATFORM_PATH}/application/main/src SRC_FILES) +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) +aux_source_directory(./linux_mock SRC_FILES) +endif() + + +set(TARGET_NAME 333DEMainTest) +add_executable(${TARGET_NAME} ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} HalChipBoard StateManager testUtils Config gtest gmock pthread ReturnCode Log) \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/application/main/linux_mock/LinuxMockMainTest2.cpp b/code/application/sifarsdk/333DE/test/application/main/linux_mock/LinuxMockMainTest2.cpp new file mode 100644 index 000000000..664e8588a --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/main/linux_mock/LinuxMockMainTest2.cpp @@ -0,0 +1,372 @@ +#include "ChipBoardMainThread.h" +#include "TestTimeOut.h" +#include "Hal333DE.h" +#include "Log.h" +#include "IDualCoreManager.h" +#include "IStateManager.h" +#include "LinuxApiTest.h" +#include "LinuxApiTestForUsb.h" +#include "LinuxApiTestForMcu.h" +#include "NetworkModule333DE.h" +#include "Hal333DEMakePtr.h" +#include "NetworkModuleMock.h" +#include +#include +#include +#include +extern const char *GPIO_EXPORT; +extern const char *GPIO_EXPORT_MODE; +extern const char *OPEN_GPIO_7; +extern const char *OPEN_GPIO_6; +extern const char *OPEN_GPIO_66; +extern const char *OPEN_GPIO_69; +extern const char *OPEN_GPIO_pir; +extern const char *GPIO_DIR_MODE; +extern const char *GPIO_UNEXPORT; +namespace LinuxMockMainTest2 +{ + using KeyPressingFunc = std::function; + using GpioInputFunc = std::function; + const std::string GPIO_INPUT_HIGHT = "1"; + const std::string GPIO_INPUT_LOW = "0"; + class LinuxMockMainTest2 : public testing::Test + { + public: + LinuxMockMainTest2() + : mFileExport_v2(GPIO_EXPORT, GPIO_EXPORT_MODE), + mFileKeyGpio_7(OPEN_GPIO_7, GPIO_DIR_MODE), + mFileKeyGpio_6(OPEN_GPIO_6, GPIO_DIR_MODE), + mFileKeyGpio_66(OPEN_GPIO_66, GPIO_DIR_MODE), + mFileKeyGpio_69(OPEN_GPIO_69, GPIO_DIR_MODE), + mFileKeyGpio_pir(OPEN_GPIO_pir, GPIO_DIR_MODE) + { + mKeyFiles[SfKeyDefine::KEY_PIN_RESET] = &mFileKeyGpio_69; + mKeyFiles[SfKeyDefine::KEY_PIN_SYNC] = &mFileKeyGpio_7; + mKeyFiles[SfKeyDefine::KEY_PIN_FORMAT] = &mFileKeyGpio_66; + mKeyFiles[SfKeyDefine::KEY_PIN_DATAREADY] = &mFileKeyGpio_6; + mKeyPressingFunc[SfKeyDefine::KEY_PIN_SYNC] = std::bind(&LinuxMockMainTest2::MockPress_KeySyns, this, std::placeholders::_1); + mGpioInputFunc[GpioPin::PIR] = std::bind(&LinuxMockMainTest2::MockInput_Pir, this, std::placeholders::_1); + } + ~LinuxMockMainTest2() = default; + static void SetUpTestCase() + { + InitLog(LOG_EASYLOGGING, nullptr); + } + static void TearDownTestCase() + { + UnInitLog(); + } + virtual void SetUp() + { + mLinuxApiMock = std::make_shared(); + std::shared_ptr tmp = mLinuxApiMock; + LinuxApiMock::GetInstance(&tmp); + LinuxApiTest::DefaultApiInit(mLinuxApiMock); + GpioKeyInit(mLinuxApiMock); + LinuxApiTestForUsb::LinuxApiInit(mLinuxApiMock); + LinuxApiTestForMcu::LinuxApiInit(mLinuxApiMock); + } + virtual void TearDown() + { + std::shared_ptr tmpMain = std::make_shared(); + MainThread::GetInstance(&tmpMain); + mMainThread.reset(); + std::shared_ptr tmpLinux = std::make_shared(); + LinuxApiMock::GetInstance(&tmpLinux); + mLinuxApiMock.reset(); + } + + private: + void GpioKeyInit(std::shared_ptr &test) + { + auto fileExportOpen = [=](void) + { + // LogInfo("fopen export file.\n"); + mFileExport_v2.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(GPIO_EXPORT, GPIO_EXPORT_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileExportOpen)), ::testing::Return((FILE *)(&mFileExport_v2)))); + EXPECT_CALL(*test.get(), fopen(GPIO_UNEXPORT, GPIO_EXPORT_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileExportOpen)), ::testing::Return((FILE *)(&mFileExport_v2)))); + auto fileFclose = [=](FILE *file) + { + // LogInfo("fclose file.\n"); + ((FILE_Mock *)file)->FileClose(); + }; + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileExport_v2))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + + auto fileGpio_7_Open = [=](void) + { + // LogInfo("fopen fileGpio_7_Open file.\n"); + mFileKeyGpio_7.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_7, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_7_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_7)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + + auto fileGpio_6_Open = [=](void) + { + // LogInfo("fopen fileGpio_6_Open file.\n"); + mFileKeyGpio_6.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_6, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_6_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_6)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_6))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_6))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_LOW), ::testing::Return(1))); + + auto fileGpio_66_Open = [=](void) + { + // LogInfo("fopen fileGpio_66_Open file.\n"); + mFileKeyGpio_66.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_66, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_66_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_66)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_66))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_66))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + + auto fileGpio_69_Open = [=](void) + { + // LogInfo("fopen fileGpio_6_Open file.\n"); + mFileKeyGpio_69.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_69, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_69_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_69)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + + auto fileGpio_pir_Open = [=](void) + { + // LogInfo("fopen fileGpio_pir_Open file.\n"); + mFileKeyGpio_pir.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_pir, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_pir_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_pir)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + } + + public: + void MockPressKey(const SfKeyDefine &key, const unsigned int &pressingTimeMs) + { + mKeyPressingFunc[key](pressingTimeMs); + } + void MockGpioInput(const GpioPin &gpio, const unsigned int &pressingTimeMs) + { + mGpioInputFunc[gpio](pressingTimeMs); + } + void MockPress_KeyReset(const unsigned int &pressingTimeMs) + { + auto timerThread = [](LinuxMockMainTest2 *test, const unsigned int &pressingTimeMs) + { + test->MockPress_KeyResetThread(pressingTimeMs); + }; + std::thread timer(timerThread, this, pressingTimeMs); + timer.detach(); + } + void MockPress_KeyResetThread(const unsigned int &pressingTimeMs) + { + LogInfo("Key reset pressed.\n"); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_LOW), ::testing::Return(1))); + std::this_thread::sleep_for(std::chrono::milliseconds(pressingTimeMs)); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + LogInfo("Key reset unpressed.\n"); + } + void MockPress_KeySyns(const unsigned int &pressingTimeMs) + { + auto timerThread = [](LinuxMockMainTest2 *test, const unsigned int &pressingTimeMs) + { + test->MockPress_KeySynsThread(pressingTimeMs); + }; + std::thread timer(timerThread, this, pressingTimeMs); + timer.detach(); + } + void MockPress_KeySynsThread(const unsigned int &pressingTimeMs) + { + LogInfo("Key syns pressed.\n"); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_LOW), ::testing::Return(1))); + std::this_thread::sleep_for(std::chrono::milliseconds(pressingTimeMs)); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + LogInfo("Key syns unpressed.\n"); + } + void MockInput_Pir(const unsigned int &pressingTimeMs) + { + auto timerThread = [](LinuxMockMainTest2 *test, const unsigned int &pressingTimeMs) + { + test->MockInput_PirThread(pressingTimeMs); + }; + std::thread timer(timerThread, this, pressingTimeMs); + timer.detach(); + } + void MockInput_PirThread(const unsigned int &pressingTimeMs) + { + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_LOW), ::testing::Return(1))); + std::this_thread::sleep_for(std::chrono::milliseconds(pressingTimeMs)); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + } + + public: + std::shared_ptr mMainThread; + std::shared_ptr mLinuxApiMock; + + private: + // std::shared_ptr mLinuxApiMock; + FILE_Mock mFileExport_v2; + FILE_Mock mFileKeyGpio_7; + FILE_Mock mFileKeyGpio_6; + FILE_Mock mFileKeyGpio_66; + FILE_Mock mFileKeyGpio_69; + FILE_Mock mFileKeyGpio_pir; + std::map mKeyFiles; + std::map mKeyPressingFunc; + std::map mGpioInputFunc; + }; + class NetworkModuleMock2 : public NetworkModule333DE + { + public: + NetworkModuleMock2() = default; + virtual ~NetworkModuleMock2() = default; + MOCK_METHOD0(GetUsbNode, SF_SERIAL_DATA_FRAME_TYPE_S(void)); + }; + class IHalMock : public Hal333DE + { + public: + IHalMock() = default; + ~IHalMock() = default; + // MOCK_METHOD2(GetCameraHal, RETURN_CODE(const CameraType &, std::shared_ptr &)); + MOCK_METHOD0(GetMcuDeviceInformation, const McuDeviceInformation(void)); + }; + class Hal333DEMakePtrMock : public Hal333DEMakePtr + { + public: + Hal333DEMakePtrMock(std::shared_ptr &IHal) + { + mIHal = IHal; + } + virtual ~Hal333DEMakePtrMock() = default; + MOCK_METHOD1(CreateNetworkModuleHandle, RETURN_CODE(std::shared_ptr &)); + MOCK_METHOD1(CreateHalModuleInstance, RETURN_CODE(std::shared_ptr &)); + + public: + void DefaultMock(void) + { + EXPECT_CALL(*this, CreateNetworkModuleHandle(::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + EXPECT_CALL(*this, CreateHalModuleInstance(::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(mIHal), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + } + + private: + std::shared_ptr mIHal; + }; + // ../out/test/bin/333DEMainTest --gtest_filter=LinuxMockMainTest2.MainStart + TEST_F(LinuxMockMainTest2, MainStart) + { + class MainThreadTest : public ChipBoardMainThread + { + public: + MainThreadTest() = default; + ~MainThreadTest() + { + } + RETURN_CODE Init(void) override + { + // int result = -1; + // constexpr int CMD_BUF_LENGTH = 1024; + // char cmd[CMD_BUF_LENGTH] = {0}; + ChipBoardMainThread::Init(); + // const char *file = IHal::GetInstance()->GetConfigFilePath(); + // const char *ststaticsticsFile = IHal::GetInstance()->GetStstaticsticsFilePath(); + // snprintf(cmd, CMD_BUF_LENGTH, "rm -f %s %s", file, ststaticsticsFile); + // result = system(cmd); + // LogInfo("rm file result = %d\n", result); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + RETURN_CODE UnInit(void) override + { + // int result = -1; + // constexpr int CMD_BUF_LENGTH = 1024; + // char cmd[CMD_BUF_LENGTH] = {0}; + ChipBoardMainThread::UnInit(); + mNetworkMock.reset(); + // mMcuDeviceMock.reset(); + mHalMock.reset(); + // std::shared_ptr tmp = std::make_shared(); + // DualCoreManagerMakePtr::GetInstance(&tmp); + // std::shared_ptr tmp2 = std::make_shared(); + // HalX86MakePtr::GetInstance(&tmp2); + // const char *file = IHal::GetInstance()->GetConfigFilePath(); + // const char *ststaticsticsFile = IHal::GetInstance()->GetStstaticsticsFilePath(); + // snprintf(cmd, CMD_BUF_LENGTH, "rm -f %s %s", file, ststaticsticsFile); + // result = system(cmd); + // LogInfo("rm file result = %d\n", result); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + void CustomizationInit(void) override + { + // std::shared_ptr mcuManagerMakePtrMock = std::make_shared(); + // McuManagerMakePtr::GetInstance(&mcuManagerMakePtrMock); + // std::shared_ptr mcuManager = std::make_shared(); + // EXPECT_CALL(*(std::dynamic_pointer_cast(mcuManagerMakePtrMock)).get(), CreateMcuManager(::testing::_)) + // .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(mcuManager), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + // mMcuDeviceMock = std::make_shared(); + // EXPECT_CALL(*mMcuDeviceMock.get(), GetStartupMode()) + // .Times(1) + // .WillRepeatedly(::testing::DoAll(::testing::Return(static_cast(StartupMode::STARTUP_MODE_ONKEY)))); + // EXPECT_CALL(*(std::dynamic_pointer_cast(mcuManager)).get(), GetMcuDevice(::testing::_)) + // .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(mMcuDeviceMock), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + + mHalMock = std::make_shared(); + EXPECT_CALL(*mHalMock.get(), GetMcuDeviceInformation()) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::Return(gMcuInfoMock))); + // mCameraHalMock = std::make_shared(); + // EXPECT_CALL(*(std::dynamic_pointer_cast(mHalMock)).get(), GetCameraHal(CameraType::MAIN_CAMERA, ::testing::_)) + // .Times(1) + // .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<1>(mCameraHalMock), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + + std::shared_ptr hal = mHalMock; + std::shared_ptr halMakePtrMock = std::make_shared(hal); + std::shared_ptr tmp = std::dynamic_pointer_cast(halMakePtrMock); + tmp->DefaultMock(); + HalX86MakePtr::GetInstance(&halMakePtrMock); + + mNetworkMock = std::make_shared(); + EXPECT_CALL(*mNetworkMock.get(), GetUsbNode()) + .WillRepeatedly(::testing::DoAll(::testing::Return(networkModuleDefaultNode))); + EXPECT_CALL(*(std::dynamic_pointer_cast(halMakePtrMock)).get(), CreateNetworkModuleHandle(::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(mNetworkMock), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + } + + private: + std::shared_ptr mNetworkMock; + // std::shared_ptr mMcuDeviceMock; + std::shared_ptr mHalMock; + }; + mMainThread = std::make_shared(); + MainThread::GetInstance(&mMainThread); + MainThread::GetInstance()->Init(); + constexpr int TIME_OUT_MS = 10000; + std::shared_ptr timer = std::make_shared(TIME_OUT_MS); + timer->StartTimer(); + MainThread::GetInstance()->Runing(); + MainThread::GetInstance()->UnInit(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/application/main/main.cpp b/code/application/sifarsdk/333DE/test/application/main/main.cpp new file mode 100644 index 000000000..fb1d91b4c --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/main/main.cpp @@ -0,0 +1,9 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/application/main/src/mainTest.cpp b/code/application/sifarsdk/333DE/test/application/main/src/mainTest.cpp new file mode 100644 index 000000000..247f99ea9 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/main/src/mainTest.cpp @@ -0,0 +1,25 @@ +#include "ChipBoardMainThread.h" +#include "TestTimeOut.h" +#include "Hal333DE.h" +#include "Log.h" +#include "IDualCoreManager.h" +#include "IStateManager.h" +#include +#include +#include +#include +namespace mainTest +{ + // ../out/test/bin/333DEMainTest --gtest_filter=mainTest.Demo + TEST(mainTest, Demo) + { + std::shared_ptr mainThread = std::make_shared(); + MainThread::GetInstance(&mainThread); + MainThread::GetInstance()->Init(); + constexpr int TIME_OUT_MS = 1000 * 40; + std::shared_ptr timer = std::make_shared(TIME_OUT_MS); + timer->StartTimer(); + MainThread::GetInstance()->Runing(); + MainThread::GetInstance()->UnInit(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/application/main/src/mainTest2.cpp b/code/application/sifarsdk/333DE/test/application/main/src/mainTest2.cpp new file mode 100644 index 000000000..12ecbf1da --- /dev/null +++ b/code/application/sifarsdk/333DE/test/application/main/src/mainTest2.cpp @@ -0,0 +1,403 @@ +#include "ChipBoardMainThread.h" +#include "TestTimeOut.h" +#include "Hal333DE.h" +#include "Log.h" +#include "IDualCoreManager.h" +#include "IStateManager.h" +#include "McuDevice.h" +#include "McuManagerMakePtr.h" +#include "KeyContrl.h" +#include "IConfigCpp.h" +#include +#include +#include +#include +namespace mainTest2 +{ + constexpr int KEY_CLICK_PRESSING_TIME_MS = 200; + + // static Param REAL_PARAM; + class mainTest2 : public testing::Test + { + public: + mainTest2() = default; + ~mainTest2() = default; + static void SetUpTestCase() + { + InitLog(LOG_EASYLOGGING, nullptr); + } + static void TearDownTestCase() + { + UnInitLog(); + } + virtual void SetUp() + { + } + virtual void TearDown() + { + // MainThread::GetInstance()->DestoryAllModules(); + } + + public: + }; + class McuDeviceTest : public McuDevice + { + public: + McuDeviceTest() = default; + virtual ~McuDeviceTest() = default; + unsigned char GetStartupMode(void) override + { + McuDevice::GetStartupMode(); + return MockGetStartupMode(); + } + virtual unsigned char MockGetStartupMode(void) + { + return 0; + } + }; + class VMcuDeviceMock : public McuDeviceTest + { + public: + VMcuDeviceMock() = default; + ~VMcuDeviceMock() = default; + MOCK_METHOD0(MockGetStartupMode, unsigned char(void)); + }; + class McuManagerMakePtrMock : public McuManagerMakePtr + { + public: + McuManagerMakePtrMock() = default; + ~McuManagerMakePtrMock() = default; + MOCK_METHOD1(CreateMcuDevice, RETURN_CODE(std::shared_ptr &)); + }; + class Hal333DEMakePtrMock : public Hal333DEMakePtr + { + public: + Hal333DEMakePtrMock() = default; + ~Hal333DEMakePtrMock() = default; + MOCK_METHOD2(CreateGpioKeyContrlInstance, RETURN_CODE(const SfKeyDefine &, std::shared_ptr &)); + }; + class IConfigCppMock : public IConfigCpp + { + public: + IConfigCppMock() = default; + ~IConfigCppMock() = default; + MOCK_METHOD1(GetParam, const Param(const PARAM_NAME &)); + }; + class KeyContrlMock : public KeyContrl + { + public: + KeyContrlMock(const SfKeyDefine &key, const SF_KEY_PIN_E &pin, const SF_BOOL &valueMeansKeyUp) : KeyContrl(key, pin, valueMeansKeyUp), mKey(key) + { + mEventContext = nullptr; + mKeyMonitor = std::make_shared(); + } + ~KeyContrlMock() = default; + void SetKeyEventMonitor(std::shared_ptr monitor, void *context) override + { + KeyContrl::SetKeyEventMonitor(monitor, context); + mKeyMonitor = monitor; + mEventContext = context; + } + void MockKeyPressing(const unsigned int &pressingTimeMs) + { + auto pressThread = [](KeyContrlMock *test, const unsigned int &pressingTimeMs) + { + test->MockKeyPress(pressingTimeMs); + }; + std::thread press(pressThread, this, pressingTimeMs); + press.detach(); + } + void MockKeyPress(const unsigned int &pressingTimeMs) + { + auto monitor = mKeyMonitor.lock(); + if (!mKeyMonitor.expired()) // mKeyMonitor is available. + { + monitor->HalKeyEventHappened(mKey, SfKeyEvent::KEY_EVENT_PRESSED, mEventContext); + std::this_thread::sleep_for(std::chrono::milliseconds(pressingTimeMs)); + monitor->HalKeyEventHappened(mKey, SfKeyEvent::KEY_EVENT_UN_PRESSED, mEventContext); + } + } + + private: + const SfKeyDefine mKey; + std::weak_ptr mKeyMonitor; + void *mEventContext; + }; + // ../out/test/bin/333DEMainTest --gtest_filter=mainTest2.Demo + TEST_F(mainTest2, Demo) + { + class MainThreadTest : public ChipBoardMainThread + { + public: + MainThreadTest() = default; + ~MainThreadTest() + { + } + RETURN_CODE Init(void) override + { + ChipBoardMainThread::Init(); + Param cameraMode; + cameraMode.numberUInt = 2; + SetParam(cameraMode, PARAM_CAMERA_MODE); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + RETURN_CODE UnInit(void) override + { + ChipBoardMainThread::UnInit(); + mMcuDeviceMock.reset(); + mMcuManagerMakePtrMock.reset(); + mHal333DEMakePtrMock.reset(); + mKeyReset.reset(); + mKeySync.reset(); + mConfigCppMock.reset(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + void CustomizationInit(void) override + { + ChipBoardMainThread::CustomizationInit(); + + mKeyReset = std::make_shared(SfKeyDefine::KEY_PIN_RESET, SF_KEY_PIN_RESET, HIGHT_MEANS_KEY_UP); + mKeySync = std::make_shared(SfKeyDefine::KEY_PIN_SYNC, SF_KEY_PIN_SYNC, HIGHT_MEANS_KEY_UP); + mMcuDeviceMock = std::make_shared(); + mMcuManagerMakePtrMock = std::make_shared(); + mHal333DEMakePtrMock = std::make_shared(); + mConfigCppMock = std::make_shared(); + + auto CreateGpioKeyContrlInstanceReal = [=](const SfKeyDefine &key, std::shared_ptr &contrl) + { + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->Hal333DEMakePtr::CreateGpioKeyContrlInstance(key, contrl); + }; + HalX86MakePtr::GetInstance(&mHal333DEMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1>(::testing::Invoke(CreateGpioKeyContrlInstanceReal)), + ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + // auto GetParamReal = [=](const PARAM_NAME &name) + // { + // memset(&REAL_PARAM, 0, sizeof(Param)); + // REAL_PARAM = std::dynamic_pointer_cast(IConfigCpp::GetInstance())->ConfigCpp::GetParam(name); + // LogInfo("================================== %s\n", REAL_PARAM.str); + // }; + // IConfigCpp::GetInstance(&mConfigCppMock); + // EXPECT_CALL(*(std::dynamic_pointer_cast(mConfigCppMock)).get(), GetParam(::testing::_)) + // .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(GetParamReal)), + // ::testing::ReturnPointee(&REAL_PARAM))); + + EXPECT_CALL(*mMcuDeviceMock.get(), MockGetStartupMode()) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::Return(static_cast(StartupMode::STARTUP_MODE_PIR)))); + + McuManagerMakePtr::GetInstance(&mMcuManagerMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mMcuManagerMakePtrMock)).get(), CreateMcuDevice(::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(mMcuDeviceMock), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + + HalX86MakePtr::GetInstance(&mHal333DEMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_RESET, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<1>(mKeyReset), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_SYNC, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<1>(mKeySync), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + } + void MockKeySyncPressing(const unsigned int &pressingTimeMs) + { + std::dynamic_pointer_cast(mKeySync)->MockKeyPressing(pressingTimeMs); + } + + private: + std::shared_ptr mMcuDeviceMock; + std::shared_ptr mMcuManagerMakePtrMock; + std::shared_ptr mHal333DEMakePtrMock; + std::shared_ptr mKeyReset; + std::shared_ptr mKeySync; + std::shared_ptr mConfigCppMock; + }; + std::shared_ptr mainThread = std::make_shared(); + MainThread::GetInstance(&mainThread); + MainThread::GetInstance()->Init(); + constexpr int TIME_OUT_MS = 1000 * 120; + std::shared_ptr timer = std::make_shared(TIME_OUT_MS); + timer->StartTimer(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 60)); + // std::dynamic_pointer_cast(mainThread)->MockKeySyncPressing(KEY_CLICK_PRESSING_TIME_MS); + MainThread::GetInstance()->Runing(); + MainThread::GetInstance()->UnInit(); + } + // ../out/test/bin/333DEMainTest --gtest_filter=mainTest2.Demo2 + TEST_F(mainTest2, Demo2) + { + class MainThreadTest : public ChipBoardMainThread + { + public: + MainThreadTest() = default; + ~MainThreadTest() + { + } + RETURN_CODE Init(void) override + { + ChipBoardMainThread::Init(); + Param cameraMode; + cameraMode.numberUInt = 2; + SetParam(cameraMode, PARAM_CAMERA_MODE); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + RETURN_CODE UnInit(void) override + { + ChipBoardMainThread::UnInit(); + mMcuDeviceMock.reset(); + mMcuManagerMakePtrMock.reset(); + mHal333DEMakePtrMock.reset(); + mKeyReset.reset(); + mKeySync.reset(); + mConfigCppMock.reset(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + void CustomizationInit(void) override + { + ChipBoardMainThread::CustomizationInit(); + + mKeyReset = std::make_shared(SfKeyDefine::KEY_PIN_RESET, SF_KEY_PIN_RESET, HIGHT_MEANS_KEY_UP); + mKeySync = std::make_shared(SfKeyDefine::KEY_PIN_SYNC, SF_KEY_PIN_SYNC, HIGHT_MEANS_KEY_UP); + mMcuDeviceMock = std::make_shared(); + mMcuManagerMakePtrMock = std::make_shared(); + mHal333DEMakePtrMock = std::make_shared(); + mConfigCppMock = std::make_shared(); + + auto CreateGpioKeyContrlInstanceReal = [=](const SfKeyDefine &key, std::shared_ptr &contrl) + { + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->Hal333DEMakePtr::CreateGpioKeyContrlInstance(key, contrl); + }; + HalX86MakePtr::GetInstance(&mHal333DEMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1>(::testing::Invoke(CreateGpioKeyContrlInstanceReal)), + ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + + EXPECT_CALL(*mMcuDeviceMock.get(), MockGetStartupMode()) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::Return(static_cast(StartupMode::STARTUP_MODE_ONKEY)))); + + McuManagerMakePtr::GetInstance(&mMcuManagerMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mMcuManagerMakePtrMock)).get(), CreateMcuDevice(::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(mMcuDeviceMock), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + + HalX86MakePtr::GetInstance(&mHal333DEMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_RESET, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<1>(mKeyReset), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_SYNC, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<1>(mKeySync), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + } + void MockKeySyncPressing(const unsigned int &pressingTimeMs) + { + std::dynamic_pointer_cast(mKeySync)->MockKeyPressing(pressingTimeMs); + } + + private: + std::shared_ptr mMcuDeviceMock; + std::shared_ptr mMcuManagerMakePtrMock; + std::shared_ptr mHal333DEMakePtrMock; + std::shared_ptr mKeyReset; + std::shared_ptr mKeySync; + std::shared_ptr mConfigCppMock; + }; + std::shared_ptr mainThread = std::make_shared(); + MainThread::GetInstance(&mainThread); + MainThread::GetInstance()->Init(); + constexpr int TIME_OUT_MS = 1000 * 120; + std::shared_ptr timer = std::make_shared(TIME_OUT_MS); + timer->StartTimer(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 60)); + // std::dynamic_pointer_cast(mainThread)->MockKeySyncPressing(KEY_CLICK_PRESSING_TIME_MS); + MainThread::GetInstance()->Runing(); + MainThread::GetInstance()->UnInit(); + } + // ../out/test/bin/333DEMainTest --gtest_filter=mainTest2.Demo3 + TEST_F(mainTest2, Demo3) + { + class MainThreadTest : public ChipBoardMainThread + { + public: + MainThreadTest() = default; + ~MainThreadTest() + { + } + RETURN_CODE Init(void) override + { + ChipBoardMainThread::Init(); + Param cameraMode; + cameraMode.numberUInt = 2; + SetParam(cameraMode, PARAM_CAMERA_MODE); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + RETURN_CODE UnInit(void) override + { + ChipBoardMainThread::UnInit(); + mMcuDeviceMock.reset(); + mMcuManagerMakePtrMock.reset(); + mHal333DEMakePtrMock.reset(); + mKeyReset.reset(); + mKeySync.reset(); + mConfigCppMock.reset(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + void CustomizationInit(void) override + { + ChipBoardMainThread::CustomizationInit(); + + mKeyReset = std::make_shared(SfKeyDefine::KEY_PIN_RESET, SF_KEY_PIN_RESET, HIGHT_MEANS_KEY_UP); + mKeySync = std::make_shared(SfKeyDefine::KEY_PIN_SYNC, SF_KEY_PIN_SYNC, HIGHT_MEANS_KEY_UP); + mMcuDeviceMock = std::make_shared(); + mMcuManagerMakePtrMock = std::make_shared(); + mHal333DEMakePtrMock = std::make_shared(); + mConfigCppMock = std::make_shared(); + + auto CreateGpioKeyContrlInstanceReal = [=](const SfKeyDefine &key, std::shared_ptr &contrl) + { + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->Hal333DEMakePtr::CreateGpioKeyContrlInstance(key, contrl); + }; + HalX86MakePtr::GetInstance(&mHal333DEMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1>(::testing::Invoke(CreateGpioKeyContrlInstanceReal)), + ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + + EXPECT_CALL(*mMcuDeviceMock.get(), MockGetStartupMode()) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::Return(static_cast(StartupMode::STARTUP_MODE_RING)))); + + McuManagerMakePtr::GetInstance(&mMcuManagerMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mMcuManagerMakePtrMock)).get(), CreateMcuDevice(::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(mMcuDeviceMock), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + + HalX86MakePtr::GetInstance(&mHal333DEMakePtrMock); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_RESET, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<1>(mKeyReset), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + EXPECT_CALL(*(std::dynamic_pointer_cast(mHal333DEMakePtrMock)).get(), CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_SYNC, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<1>(mKeySync), ::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + } + void MockKeySyncPressing(const unsigned int &pressingTimeMs) + { + std::dynamic_pointer_cast(mKeySync)->MockKeyPressing(pressingTimeMs); + } + + private: + std::shared_ptr mMcuDeviceMock; + std::shared_ptr mMcuManagerMakePtrMock; + std::shared_ptr mHal333DEMakePtrMock; + std::shared_ptr mKeyReset; + std::shared_ptr mKeySync; + std::shared_ptr mConfigCppMock; + }; + std::shared_ptr mainThread = std::make_shared(); + MainThread::GetInstance(&mainThread); + MainThread::GetInstance()->Init(); + constexpr int TIME_OUT_MS = 1000 * 120; + std::shared_ptr timer = std::make_shared(TIME_OUT_MS); + timer->StartTimer(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 60)); + // std::dynamic_pointer_cast(mainThread)->MockKeySyncPressing(KEY_CLICK_PRESSING_TIME_MS); + MainThread::GetInstance()->Runing(); + MainThread::GetInstance()->UnInit(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/component/CMakeLists.txt b/code/application/sifarsdk/333DE/test/component/CMakeLists.txt new file mode 100644 index 000000000..cd3123759 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/component/CMakeLists.txt @@ -0,0 +1,9 @@ + +# cmake_minimum_required(VERSION 2.8.0) +#Compile gtest for test code. +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TEST_LINUX_MOCK}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TEST_LINUX_MOCK}") +add_subdirectory(PeripheralManager) +add_subdirectory(McuManager) + + diff --git a/code/application/sifarsdk/333DE/test/component/McuManager/CMakeLists.txt b/code/application/sifarsdk/333DE/test/component/McuManager/CMakeLists.txt new file mode 100644 index 000000000..67ed3d588 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/component/McuManager/CMakeLists.txt @@ -0,0 +1,37 @@ +include(${CMAKE_SOURCE_DIR}/build/independent_source.cmake) +set(EXECUTABLE_OUTPUT_PATH ${TEST_OUTPUT_PATH}/bin) + +include_directories( + ./src + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/McuManager/include + ${HAL_SOURCE_PATH}/include + ${PLATFORM_PATH}/hal/include + ${PLATFORM_PATH}/hal + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googletest/include + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/include +) + +link_directories( + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${LIBS_OUTPUT_PATH} +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME McuManager333DETest) +add_executable(${TARGET_NAME} ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} McuManager gtest gmock pthread ${TEST_LINK_LIB} HalChipBoard ReturnCode Log) +if(${COVERAGE_ON} MATCHES "true") + target_link_libraries(${TARGET_NAME} gcov) +endif() \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/component/McuManager/mainTest.cpp b/code/application/sifarsdk/333DE/test/component/McuManager/mainTest.cpp new file mode 100644 index 000000000..fb1d91b4c --- /dev/null +++ b/code/application/sifarsdk/333DE/test/component/McuManager/mainTest.cpp @@ -0,0 +1,9 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/component/McuManager/src/IMcuManager333DETest.cpp b/code/application/sifarsdk/333DE/test/component/McuManager/src/IMcuManager333DETest.cpp new file mode 100644 index 000000000..1c853ee7b --- /dev/null +++ b/code/application/sifarsdk/333DE/test/component/McuManager/src/IMcuManager333DETest.cpp @@ -0,0 +1,36 @@ +#include "IMcuManager.h" +#include "IHal.h" +#include "IHal333DE.h" +#include "Log.h" +#include +#include +#include +namespace IMcuManager333DETest +{ + // ../out/test/bin/McuManager333DETest --gtest_filter=IMcuManager333DETest.Demo + TEST(IMcuManager333DETest, Demo) + { + InitLog(LOG_EASYLOGGING, nullptr); + Hal333DEMakePtrOverride(); + CreateHalModuleInstance(); // Create the instance of chip, called in main function. + CreateMcuManager(); + IHal::GetInstance()->Init(); + IMcuManager::GetInstance()->Init(); + std::shared_ptr mcuDevice; + IMcuManager::GetInstance()->GetMcuDevice(mcuDevice); + unsigned char mode = -1; + if (mcuDevice) + { + mode = mcuDevice->GetStartupMode(); + LogInfo("GetStartupMode = %d\n", mode); + } + else + { + LogError("nullptr pointer.\n"); + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + IMcuManager::GetInstance()->UnInit(); + IHal::GetInstance()->UnInit(); + UnInitLog(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/component/McuManager/src/IMcuManagerTest.cpp b/code/application/sifarsdk/333DE/test/component/McuManager/src/IMcuManagerTest.cpp new file mode 100644 index 000000000..7c72d654f --- /dev/null +++ b/code/application/sifarsdk/333DE/test/component/McuManager/src/IMcuManagerTest.cpp @@ -0,0 +1,17 @@ +#include "IMcuManager.h" +#include "Log.h" +#include +#include +namespace IMcuManagerTest +{ + // ../out/test/bin/McuManagerTest --gtest_filter=IMcuManagerTest.Demo + TEST(IMcuManagerTest, Demo) + { + InitLog(LOG_EASYLOGGING, nullptr); + CreateMcuManager(); + IMcuManager::GetInstance()->Init(); + // HttpTest test; + // test.Create(); + UnInitLog(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/component/PeripheralManager/CMakeLists.txt b/code/application/sifarsdk/333DE/test/component/PeripheralManager/CMakeLists.txt new file mode 100644 index 000000000..74704ab37 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/component/PeripheralManager/CMakeLists.txt @@ -0,0 +1,44 @@ + +set(EXECUTABLE_OUTPUT_PATH ${TEST_OUTPUT_PATH}/bin) + +include_directories( + ./src + ${APPLICATION_SOURCE_PATH}/StateManager/include + ${APPLICATION_SOURCE_PATH}/StateManager/src + ${APPLICATION_SOURCE_PATH}/NetworkManager/include + ${COMPONENT_SOURCE_PATH}/StateMachineManager/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/DualCoreManager/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${HAL_SOURCE_PATH}/include + ${HAL_SOURCE_PATH} + ${TEST_SOURCE_PATH}/test_utils + ${TEST_SOURCE_PATH}/test_utils/linux_mock + ${PLATFORM_PATH}/hal/include + ${PLATFORM_PATH}/hal + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googletest/include + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/include +) + +link_directories( + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${LIBS_OUTPUT_PATH} +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) +aux_source_directory(./src SRC_FILES) +# aux_source_directory(${TEST_SOURCE_PATH}/test_common SRC_FILES) +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) +aux_source_directory(./src/linux_mock SRC_FILES) +endif() + + +set(TARGET_NAME PeripheralManager333DETest) +add_executable(${TARGET_NAME} ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} NetworkManager HalChipBoard gtest gmock ${TEST_LINK_LIB} pthread ReturnCode Log) \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/component/PeripheralManager/main.cpp b/code/application/sifarsdk/333DE/test/component/PeripheralManager/main.cpp new file mode 100644 index 000000000..fb1d91b4c --- /dev/null +++ b/code/application/sifarsdk/333DE/test/component/PeripheralManager/main.cpp @@ -0,0 +1,9 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/component/PeripheralManager/src/linux_mock/PeripheralManagerTest.cpp b/code/application/sifarsdk/333DE/test/component/PeripheralManager/src/linux_mock/PeripheralManagerTest.cpp new file mode 100644 index 000000000..ae4496eb6 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/component/PeripheralManager/src/linux_mock/PeripheralManagerTest.cpp @@ -0,0 +1,294 @@ + +#include "Log.h" +#include "Hal333DEMakePtr.h" +#include "IHal333DE.h" +#include "LinuxApiMock.h" +#include "LinuxApiTest.h" +#include "IPeripheralManager.h" +#include +#include +#include +#include +extern const char *GPIO_EXPORT; +extern const char *GPIO_EXPORT_MODE; +extern const char *OPEN_GPIO_7; +extern const char *OPEN_GPIO_6; +extern const char *OPEN_GPIO_66; +extern const char *OPEN_GPIO_69; +extern const char *OPEN_GPIO_pir; +extern const char *GPIO_DIR_MODE; +extern const char *GPIO_UNEXPORT; +namespace PeripheralManager333DETest +{ + using KeyPressingFunc = std::function; + using GpioInputFunc = std::function; + const std::string GPIO_INPUT_HIGHT = "1"; + const std::string GPIO_INPUT_LOW = "0"; + class PeripheralManager333DETest : public testing::Test + { + public: + PeripheralManager333DETest() + : mFileExport_v2(GPIO_EXPORT, GPIO_EXPORT_MODE), + mFileKeyGpio_7(OPEN_GPIO_7, GPIO_DIR_MODE), + mFileKeyGpio_6(OPEN_GPIO_6, GPIO_DIR_MODE), + mFileKeyGpio_66(OPEN_GPIO_66, GPIO_DIR_MODE), + mFileKeyGpio_69(OPEN_GPIO_69, GPIO_DIR_MODE), + mFileKeyGpio_pir(OPEN_GPIO_pir, GPIO_DIR_MODE) + { + mKeyFiles[SfKeyDefine::KEY_PIN_RESET] = &mFileKeyGpio_69; + mKeyFiles[SfKeyDefine::KEY_PIN_SYNC] = &mFileKeyGpio_7; + mKeyFiles[SfKeyDefine::KEY_PIN_FORMAT] = &mFileKeyGpio_66; + mKeyFiles[SfKeyDefine::KEY_PIN_DATAREADY] = &mFileKeyGpio_6; + mKeyPressingFunc[SfKeyDefine::KEY_PIN_SYNC] = std::bind(&PeripheralManager333DETest::MockPress_KeySyns, this, std::placeholders::_1); + mGpioInputFunc[GpioPin::PIR] = std::bind(&PeripheralManager333DETest::MockInput_Pir, this, std::placeholders::_1); + } + ~PeripheralManager333DETest() = default; + static void SetUpTestCase() + { + InitLog(LOG_EASYLOGGING, nullptr); + Hal333DEMakePtrOverride(); + } + static void TearDownTestCase() + { + UnInitLog(); + } + virtual void SetUp() + { + std::shared_ptr tmp = std::make_shared(); + LinuxApiTest::DefaultApiInit(tmp); + GpioKeyInit(tmp); + mLinuxApiMock = tmp; + LinuxApiMock::GetInstance(&mLinuxApiMock); + CreatePeripheralManager(); + CreateHalModuleInstance(); + IHal::GetInstance()->Init(); + IPeripheralManager::GetInstance()->Init(); + } + virtual void TearDown() + { + IPeripheralManager::GetInstance()->UnInit(); + IHal::GetInstance()->UnInit(); + mLinuxApiMock = std::make_shared(); + LinuxApiMock::GetInstance(&mLinuxApiMock); + mLinuxApiMock.reset(); + } + + private: + void GpioKeyInit(std::shared_ptr &test) + { + auto fileExportOpen = [=](void) + { + // LogInfo("fopen export file.\n"); + mFileExport_v2.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(GPIO_EXPORT, GPIO_EXPORT_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileExportOpen)), ::testing::Return((FILE *)(&mFileExport_v2)))); + EXPECT_CALL(*test.get(), fopen(GPIO_UNEXPORT, GPIO_EXPORT_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileExportOpen)), ::testing::Return((FILE *)(&mFileExport_v2)))); + auto fileFclose = [=](FILE *file) + { + // LogInfo("fclose file.\n"); + ((FILE_Mock *)file)->FileClose(); + }; + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileExport_v2))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + + auto fileGpio_7_Open = [=](void) + { + // LogInfo("fopen fileGpio_7_Open file.\n"); + mFileKeyGpio_7.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_7, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_7_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_7)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + + auto fileGpio_6_Open = [=](void) + { + // LogInfo("fopen fileGpio_6_Open file.\n"); + mFileKeyGpio_6.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_6, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_6_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_6)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_6))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_6))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_LOW), ::testing::Return(1))); + + auto fileGpio_66_Open = [=](void) + { + // LogInfo("fopen fileGpio_66_Open file.\n"); + mFileKeyGpio_66.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_66, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_66_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_66)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_66))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_66))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + + auto fileGpio_69_Open = [=](void) + { + // LogInfo("fopen fileGpio_6_Open file.\n"); + mFileKeyGpio_69.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_69, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_69_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_69)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + + auto fileGpio_pir_Open = [=](void) + { + // LogInfo("fopen fileGpio_pir_Open file.\n"); + mFileKeyGpio_pir.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_pir, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_pir_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_pir)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + } + + public: + void MockPressKey(const SfKeyDefine &key, const unsigned int &pressingTimeMs) + { + mKeyPressingFunc[key](pressingTimeMs); + } + void MockGpioInput(const GpioPin &gpio, const unsigned int &pressingTimeMs) + { + mGpioInputFunc[gpio](pressingTimeMs); + } + void MockPress_KeyReset(const unsigned int &pressingTimeMs) + { + auto timerThread = [](PeripheralManager333DETest *test, const unsigned int &pressingTimeMs) + { + test->MockPress_KeyResetThread(pressingTimeMs); + }; + std::thread timer(timerThread, this, pressingTimeMs); + timer.detach(); + } + void MockPress_KeyResetThread(const unsigned int &pressingTimeMs) + { + LogInfo("Key reset pressed.\n"); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_LOW), ::testing::Return(1))); + std::this_thread::sleep_for(std::chrono::milliseconds(pressingTimeMs)); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + LogInfo("Key reset unpressed.\n"); + } + void MockPress_KeySyns(const unsigned int &pressingTimeMs) + { + auto timerThread = [](PeripheralManager333DETest *test, const unsigned int &pressingTimeMs) + { + test->MockPress_KeySynsThread(pressingTimeMs); + }; + std::thread timer(timerThread, this, pressingTimeMs); + timer.detach(); + } + void MockPress_KeySynsThread(const unsigned int &pressingTimeMs) + { + LogInfo("Key syns pressed.\n"); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_LOW), ::testing::Return(1))); + std::this_thread::sleep_for(std::chrono::milliseconds(pressingTimeMs)); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + LogInfo("Key syns unpressed.\n"); + } + void MockInput_Pir(const unsigned int &pressingTimeMs) + { + auto timerThread = [](PeripheralManager333DETest *test, const unsigned int &pressingTimeMs) + { + test->MockInput_PirThread(pressingTimeMs); + }; + std::thread timer(timerThread, this, pressingTimeMs); + timer.detach(); + } + void MockInput_PirThread(const unsigned int &pressingTimeMs) + { + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_LOW), ::testing::Return(1))); + std::this_thread::sleep_for(std::chrono::milliseconds(pressingTimeMs)); + EXPECT_CALL(*(std::dynamic_pointer_cast(mLinuxApiMock)).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + } + + private: + std::shared_ptr mLinuxApiMock; + FILE_Mock mFileExport_v2; + FILE_Mock mFileKeyGpio_7; + FILE_Mock mFileKeyGpio_6; + FILE_Mock mFileKeyGpio_66; + FILE_Mock mFileKeyGpio_69; + FILE_Mock mFileKeyGpio_pir; + std::map mKeyFiles; + std::map mKeyPressingFunc; + std::map mGpioInputFunc; + }; + class PeripheralMonitor : public VKeyMonitor, public std::enable_shared_from_this + { + public: + PeripheralMonitor() = default; + ~PeripheralMonitor() = default; + void Init(void) + { + IPeripheralManager::GetInstance()->SetKeyMonitor(shared_from_this()); + } + MOCK_METHOD3(KeyActionHappened, RETURN_CODE(const SfKeyDefine &, const SfKeyAction &, const unsigned int)); + // RETURN_CODE KeyActionHappened(const SfKeyDefine &key, const SfKeyAction &event, const unsigned int holdTimeMs) override + // { + // LogInfo("PeripheralMonitor::KeyActionHappened, event = %d, hold time = %d\n", static_cast(event), holdTimeMs); + // return VReturnCode::NewCode(VReturnCodeDefine::OK); + // } + }; + // ../out/test/bin/PeripheralManager333DETest --gtest_filter=PeripheralManager333DETest.KeyPressing + TEST_F(PeripheralManager333DETest, KeyPressing) + { + LogInfo("KeyPressing.\n"); + std::shared_ptr moniter = std::make_shared(); + EXPECT_CALL(*moniter.get(), KeyActionHappened(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + moniter->Init(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + constexpr int PRESSING_TIME_MS = 300; + MockPressKey(SfKeyDefine::KEY_PIN_SYNC, PRESSING_TIME_MS); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + LogInfo("KeyPressing. end.\n"); + moniter.reset(); + } + class GpioMonitor : public VGpioMonitor, public std::enable_shared_from_this + { + public: + GpioMonitor() = default; + ~GpioMonitor() = default; + void Init(void) + { + IPeripheralManager::GetInstance()->SetGpioMonitor(shared_from_this()); + } + MOCK_METHOD2(InputTransform, RETURN_CODE(const GpioDevice &, const DeviceInput &)); + }; + // ../out/test/bin/PeripheralManager333DETest --gtest_filter=PeripheralManager333DETest.PirGpio + TEST_F(PeripheralManager333DETest, PirGpio) + { + std::shared_ptr moniter = std::make_shared(); + EXPECT_CALL(*moniter.get(), InputTransform(::testing::_, DeviceInput::INVALID)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + EXPECT_CALL(*moniter.get(), InputTransform(::testing::_, DeviceInput::VALID)) + .Times(1) + .WillRepeatedly(::testing::DoAll(::testing::Return(VReturnCode::NewCode(VReturnCodeDefine::OK)))); + moniter->Init(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + constexpr int INPUTING_TIME_MS = 300; + MockGpioInput(GpioPin::PIR, INPUTING_TIME_MS); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + moniter.reset(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/hal/CMakeLists.txt b/code/application/sifarsdk/333DE/test/hal/CMakeLists.txt new file mode 100644 index 000000000..79b28fa25 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/hal/CMakeLists.txt @@ -0,0 +1,38 @@ + +set(EXECUTABLE_OUTPUT_PATH ${TEST_OUTPUT_PATH}/bin) +include_directories( + ./src + ${HAL_SOURCE_PATH} + ${HAL_SOURCE_PATH}/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${TEST_SOURCE_PATH}/test_common + ${TEST_SOURCE_PATH}/test_utils + ${TEST_SOURCE_PATH}/test_utils/linux_mock + ${PLATFORM_PATH}/hal/include + ${PLATFORM_PATH}/hal + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googletest/include + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/include +) + +link_directories( + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/lib + ${LIBS_OUTPUT_PATH} +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) +aux_source_directory(./src SRC_FILES) +aux_source_directory(${TEST_SOURCE_PATH}/test_common SRC_FILES) +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) +aux_source_directory(./src/linux_mock SRC_FILES) +endif() + + +set(TARGET_NAME Hal333DETest) +add_executable(${TARGET_NAME} ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} HalChipBoard gtest gmock ${TEST_LINK_LIB} pthread ReturnCode Log) \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/hal/main.cpp b/code/application/sifarsdk/333DE/test/hal/main.cpp new file mode 100644 index 000000000..fb1d91b4c --- /dev/null +++ b/code/application/sifarsdk/333DE/test/hal/main.cpp @@ -0,0 +1,9 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/hal/src/Hal333DETest.cpp b/code/application/sifarsdk/333DE/test/hal/src/Hal333DETest.cpp new file mode 100644 index 000000000..e3d4042da --- /dev/null +++ b/code/application/sifarsdk/333DE/test/hal/src/Hal333DETest.cpp @@ -0,0 +1,159 @@ + +#include "Log.h" +#include "Hal333DE.h" +#include "IHal333DE.h" +#include "TestCommon.h" +#include +#include +#include +#include +namespace Hal333DETest +{ + class Hal333DETest : public testing::Test + { + public: + Hal333DETest() = default; + ~Hal333DETest() = default; + static void SetUpTestCase() + { + InitLog(LOG_EASYLOGGING, nullptr); + } + static void TearDownTestCase() + { + UnInitLog(); + } + virtual void SetUp() + { + } + virtual void TearDown() + { + } + }; + // This demo demonstrates how to control the LED light of a chip. + // ../out/test/bin/Hal333DETest --gtest_filter=Hal333DETest.DemoForLed + TEST(Hal333DETest, DemoForLed) + { + InitLog(LOG_EASYLOGGING, nullptr); + std::shared_ptr makePtr = std::make_shared(); + HalX86MakePtr::GetInstance(&makePtr); + + CreateHalModuleInstance(); // Create the instance of chip, called in main function. + IHal::GetInstance()->Init(); // Init chip + std::shared_ptr ledTest = std::make_shared(); + IHal::GetInstance()->GetLedContrlHandle(SfLedIndex::SF_LED_BAT, ledTest); // Get the handle for contrling the led. + ledTest->SetLedState(SfLedState::SF_LED_STATE_GREEN); // Contrl the led. + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 5)); + ledTest->SetLedState(SfLedState::SF_LED_STATE_RED); // Contrl the led. + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 5)); + ledTest->SetLedState(SfLedState::SF_LED_STATE_YELLOW); // Contrl the led. + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 5)); + IHal::GetInstance()->UnInit(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + UnInitLog(); + } + class KeyMonitorTest : public VKeyEventMonitor + { + public: + KeyMonitorTest() = default; + ~KeyMonitorTest() = default; + void HalKeyEventHappened(const SfKeyDefine &key, const SfKeyEvent &event, void *context) override + { + if (SfKeyEvent::KEY_EVENT_PRESSED == event) + { + LogInfo("Key event happened. key pressed.\n"); + } + if (SfKeyEvent::KEY_EVENT_UN_PRESSED == event) + { + LogInfo("Key event happened. key unpressed.\n"); + } + } + }; + // This demo demonstrates how to capture key events. + // ../out/test/bin/Hal333DETest --gtest_filter=Hal333DETest.DemoForKey + TEST(Hal333DETest, DemoForKey) + { + InitLog(LOG_EASYLOGGING, nullptr); + std::shared_ptr makePtr = std::make_shared(); + HalX86MakePtr::GetInstance(&makePtr); + + CreateHalModuleInstance(); // Create the instance of chip, called in main function. + IHal::GetInstance()->Init(); // Init chip + std::shared_ptr keyTest = std::make_shared(); + IHal::GetInstance()->GetKeyContrlHandle(SfKeyDefine::KEY_PIN_SYNC, keyTest); + std::shared_ptr keyMonitor = std::make_shared(); + keyTest->SetKeyEventMonitor(keyMonitor, nullptr); // Use callback function to capture the key events. + + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 60)); + IHal::GetInstance()->UnInit(); // UnInit chip + UnInitLog(); + } + // ../out/test/bin/Hal333DETest --gtest_filter=Hal333DETest.DemoForNetworkModule + TEST(Hal333DETest, DemoForNetworkModule) + { + InitLog(LOG_EASYLOGGING, nullptr); + // std::shared_ptr makePtr = std::make_shared(); + // HalX86MakePtr::GetInstance(&makePtr); + + Hal333DEMakePtrOverride(); + CreateHalModuleInstance(); // Create the instance of chip, called in main function. + IHal::GetInstance()->Init(); // Init chip + std::shared_ptr network = std::make_shared(); + IHal::GetInstance()->GetNetworkHardware(network); + RETURN_CODE code = network->IsHardwareSupport(); + if (code->IsCodeOK()) + { + LogInfo("Module is supported."); + } + IHal::GetInstance()->UnInit(); // UnInit chip + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + UnInitLog(); + } + class CameraOwnerTest : public VCameraHalOwner + { + public: + CameraOwnerTest() = default; + ~CameraOwnerTest() = default; + void CameraFinshTask(const std::vector &files) override + { + } + void SpontaneousTaskFromCamera(const std::vector &files) override + { + } + int AudioStream_write(const char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp) override + { + return 0; + } + int VideoStream_write(char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp, const unsigned int &key_frame) override + { + return 0; + } + }; + // ../out/test/bin/Hal333DETest --gtest_filter=Hal333DETest.DemoForCamera + TEST(Hal333DETest, DemoForCamera) + { + InitLog(LOG_EASYLOGGING, nullptr); + + Hal333DEMakePtrOverride(); + CreateHalModuleInstance(); // Create the instance of chip, called in main function. + IHal::GetInstance()->Init(); // Init chip + std::shared_ptr camera; + std::shared_ptr Owner = std::make_shared(); + IHal::GetInstance()->GetCameraHal(CameraType::MAIN_CAMERA, camera); + if (camera) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + camera->SetCameraOwner(Owner); + constexpr int IS_NIGHT = 0; + CameraTaskData data(CameraTaskType::PICTURE, IS_NIGHT, NOT_MULTI_SHOT); + camera->StartSingleTask(data); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 60)); + } + + IHal::GetInstance()->UnInit(); // UnInit chip + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + UnInitLog(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/hal/src/linux_mock/GpioInputHandleTest.cpp b/code/application/sifarsdk/333DE/test/hal/src/linux_mock/GpioInputHandleTest.cpp new file mode 100644 index 000000000..5d886afcd --- /dev/null +++ b/code/application/sifarsdk/333DE/test/hal/src/linux_mock/GpioInputHandleTest.cpp @@ -0,0 +1,149 @@ +#include "Log.h" +#include "IHalCommon.h" +#include "Hal333DEMakePtr.h" +#include "IHal333DE.h" +#include "LinuxApiMock.h" +#include "LinuxApiTest.h" +#include "GpioInputHandle.h" +#include +#include +#include +#include + +extern const char *GPIO_EXPORT; +extern const char *GPIO_EXPORT_MODE; +extern const char *GPIO_DIR_MODE; +extern const char *GPIO_UNEXPORT; +extern const char *OPEN_GPIO_pir; + +namespace GpioInputHandleTest +{ + const std::string GPIO_INPUT_HIGHT = "1"; + const std::string GPIO_INPUT_LOW = "0"; + class GpioInputHandleTest : public testing::Test + { + public: + GpioInputHandleTest() + : mFileExport_v2(GPIO_EXPORT, GPIO_EXPORT_MODE), + mFileKeyGpio_pir(OPEN_GPIO_pir, GPIO_DIR_MODE) + { + } + ~GpioInputHandleTest() = default; + static void SetUpTestCase() + { + InitLog(LOG_EASYLOGGING, nullptr); + Hal333DEMakePtrOverride(); + } + static void TearDownTestCase() + { + UnInitLog(); + } + virtual void SetUp() + { + std::shared_ptr tmp = std::make_shared(); + LinuxApiTest::DefaultApiInit(tmp); + GpioKeyInit(tmp); + mLinuxApiMock = tmp; + LinuxApiMock::GetInstance(&mLinuxApiMock); + } + virtual void TearDown() + { + mLinuxApiMock = std::make_shared(); + LinuxApiMock::GetInstance(&mLinuxApiMock); + } + void SetGpioInput(const GpioPin &gpio, const std::string &input) + { + switch (gpio) + { + case GpioPin::PIR: + { + EXPECT_CALL(*std::dynamic_pointer_cast(mLinuxApiMock).get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(input), ::testing::Return(1))); + } + break; + + default: + break; + } + } + + private: + void GpioKeyInit(std::shared_ptr &test) + { + auto fileExportOpen = [=](void) + { + // LogInfo("fopen export file.\n"); + mFileExport_v2.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(GPIO_EXPORT, GPIO_EXPORT_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileExportOpen)), ::testing::Return((FILE *)(&mFileExport_v2)))); + EXPECT_CALL(*test.get(), fopen(GPIO_UNEXPORT, GPIO_EXPORT_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileExportOpen)), ::testing::Return((FILE *)(&mFileExport_v2)))); + auto fileFclose = [=](FILE *file) + { + // LogInfo("fclose file.\n"); + ((FILE_Mock *)file)->FileClose(); + }; + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileExport_v2))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + + auto fileGpio_pir_Open = [=](void) + { + // LogInfo("fopen fileGpio_pir_Open file.\n"); + mFileKeyGpio_pir.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_pir, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_pir_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_pir)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_pir))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(GPIO_INPUT_HIGHT), ::testing::Return(1))); + } + + private: + std::shared_ptr mLinuxApiMock; + FILE_Mock mFileExport_v2; + FILE_Mock mFileKeyGpio_pir; + }; + class GpioMonitorTest : public VGpioInputMonitor + { + public: + GpioMonitorTest() + { + } + ~GpioMonitorTest() + { + } + void InputTransform(const GpioPin &device, const GpioInputValue &value, void *context) override + { + LogInfo("InputTransform.\n"); + } + }; + // ../out/test/bin/Hal333DETest --gtest_filter=GpioInputHandleTest.Demo + TEST_F(GpioInputHandleTest, Demo) + { + auto gpioHandle = std::make_shared(); + auto monitor = std::make_shared(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioInputInstance(GpioPin::PIR, gpioHandle); + LogInfo("Start test.\n"); + gpioHandle->Init(); + gpioHandle->SetInputMonitor(monitor, nullptr); + std::dynamic_pointer_cast(gpioHandle) + ->CheckInputValue(); + gpioHandle->UnInit(); + } + // ../out/test/bin/Hal333DETest --gtest_filter=GpioInputHandleTest.Demo2 + TEST_F(GpioInputHandleTest, Demo2) + { + auto gpioHandle = std::make_shared(); + auto monitor = std::make_shared(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioInputInstance(GpioPin::PIR, gpioHandle); + LogInfo("Start test.\n"); + gpioHandle->Init(); + gpioHandle->SetInputMonitor(monitor, nullptr); + SetGpioInput(GpioPin::PIR, GPIO_INPUT_LOW); + std::dynamic_pointer_cast(gpioHandle) + ->CheckInputValue(); + gpioHandle->UnInit(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/333DE/test/hal/src/linux_mock/KeyContrlTest.cpp b/code/application/sifarsdk/333DE/test/hal/src/linux_mock/KeyContrlTest.cpp new file mode 100644 index 000000000..65d91f191 --- /dev/null +++ b/code/application/sifarsdk/333DE/test/hal/src/linux_mock/KeyContrlTest.cpp @@ -0,0 +1,202 @@ +#include "Log.h" +#include "IHalCommon.h" +#include "Hal333DEMakePtr.h" +#include "IHal333DE.h" +#include "LinuxApiMock.h" +#include "LinuxApiTest.h" +#include "KeyContrl.h" +#include +#include +#include +#include + +extern const char *GPIO_EXPORT; +extern const char *GPIO_EXPORT_MODE; +extern const char *OPEN_GPIO_7; +extern const char *OPEN_GPIO_6; +extern const char *OPEN_GPIO_66; +extern const char *OPEN_GPIO_69; +extern const char *GPIO_DIR_MODE; +extern const char *GPIO_UNEXPORT; + +namespace KeyContrlTest +{ + class KeyContrlTest : public testing::Test + { + public: + KeyContrlTest() + : mFileExport_v2(GPIO_EXPORT, GPIO_EXPORT_MODE), + mFileKeyGpio_7(OPEN_GPIO_7, GPIO_DIR_MODE), + mFileKeyGpio_6(OPEN_GPIO_6, GPIO_DIR_MODE), + mFileKeyGpio_66(OPEN_GPIO_66, GPIO_DIR_MODE), + mFileKeyGpio_69(OPEN_GPIO_69, GPIO_DIR_MODE) + { + } + ~KeyContrlTest() = default; + static void SetUpTestCase() + { + InitLog(LOG_EASYLOGGING, nullptr); + Hal333DEMakePtrOverride(); + } + static void TearDownTestCase() + { + UnInitLog(); + } + virtual void SetUp() + { + std::shared_ptr tmp = std::make_shared(); + LinuxApiTest::DefaultApiInit(tmp); + GpioKeyInit(tmp); + mLinuxApiMock = tmp; + LinuxApiMock::GetInstance(&mLinuxApiMock); + } + virtual void TearDown() + { + mLinuxApiMock = std::make_shared(); + LinuxApiMock::GetInstance(&mLinuxApiMock); + } + + private: + void GpioKeyInit(std::shared_ptr &test) + { + auto fileExportOpen = [=](void) + { + // LogInfo("fopen export file.\n"); + mFileExport_v2.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(GPIO_EXPORT, GPIO_EXPORT_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileExportOpen)), ::testing::Return((FILE *)(&mFileExport_v2)))); + EXPECT_CALL(*test.get(), fopen(GPIO_UNEXPORT, GPIO_EXPORT_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileExportOpen)), ::testing::Return((FILE *)(&mFileExport_v2)))); + auto fileFclose = [=](FILE *file) + { + // LogInfo("fclose file.\n"); + ((FILE_Mock *)file)->FileClose(); + }; + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileExport_v2))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + + auto fileGpio_7_Open = [=](void) + { + // LogInfo("fopen fileGpio_7_Open file.\n"); + mFileKeyGpio_7.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_7, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_7_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_7)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_7))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>("1"), ::testing::Return(1))); + + auto fileGpio_6_Open = [=](void) + { + // LogInfo("fopen fileGpio_6_Open file.\n"); + mFileKeyGpio_6.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_6, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_6_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_6)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_6))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_6))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>("0"), ::testing::Return(1))); + + auto fileGpio_66_Open = [=](void) + { + // LogInfo("fopen fileGpio_66_Open file.\n"); + mFileKeyGpio_66.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_66, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_66_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_66)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_66))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_66))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>("1"), ::testing::Return(1))); + + auto fileGpio_69_Open = [=](void) + { + // LogInfo("fopen fileGpio_6_Open file.\n"); + mFileKeyGpio_69.FileFopen(); + }; + EXPECT_CALL(*test.get(), fopen(OPEN_GPIO_69, GPIO_DIR_MODE)) + .WillRepeatedly(::testing::DoAll((::testing::Invoke(fileGpio_69_Open)), ::testing::Return((FILE *)(&mFileKeyGpio_69)))); + EXPECT_CALL(*test.get(), fclose((FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(fileFclose)), ::testing::Return(SUCCESSFUL))); + EXPECT_CALL(*test.get(), fread(::testing::_, ::testing::_, ::testing::_, (FILE *)(&mFileKeyGpio_69))) + .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>("1"), ::testing::Return(1))); + } + + private: + std::shared_ptr mLinuxApiMock; + FILE_Mock mFileExport_v2; + FILE_Mock mFileKeyGpio_7; + FILE_Mock mFileKeyGpio_6; + FILE_Mock mFileKeyGpio_66; + FILE_Mock mFileKeyGpio_69; + }; + class KeyManagerTest : public VKeyEventMonitor//, public std::enable_shared_from_this + { + public: + KeyManagerTest() + { + } + ~KeyManagerTest() + { + } + void HalKeyEventHappened(const SfKeyDefine &key, const SfKeyEvent &event, void *context) override + { + LogInfo("HalKeyEventHappened.\n"); + } + // bool IsKeyPressing(void) override + // { + // return false; + // } + }; + // ../out/test/bin/Hal333DETest --gtest_filter=KeyContrlTest.Init + TEST_F(KeyContrlTest, Init) + { + auto keyHandle = std::make_shared(); + auto monitor = std::make_shared(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_SYNC, keyHandle); + LogInfo("Start test.\n"); + keyHandle->Init(); + keyHandle->SetKeyEventMonitor(monitor, nullptr); + std::dynamic_pointer_cast(keyHandle)->CheckKeyValue(); + keyHandle->UnInit(); + } + // ../out/test/bin/Hal333DETest --gtest_filter=KeyContrlTest.Init2 + TEST_F(KeyContrlTest, Init2) + { + auto keyHandle = std::make_shared(); + auto monitor = std::make_shared(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_DATAREADY, keyHandle); + LogInfo("Start test.\n"); + keyHandle->Init(); + keyHandle->SetKeyEventMonitor(monitor, nullptr); + std::dynamic_pointer_cast(keyHandle)->CheckKeyValue(); + keyHandle->UnInit(); + } + // ../out/test/bin/Hal333DETest --gtest_filter=KeyContrlTest.Init3 + TEST_F(KeyContrlTest, Init3) + { + auto keyHandle = std::make_shared(); + auto monitor = std::make_shared(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_FORMAT, keyHandle); + LogInfo("Start test.\n"); + keyHandle->Init(); + keyHandle->SetKeyEventMonitor(monitor, nullptr); + std::dynamic_pointer_cast(keyHandle)->CheckKeyValue(); + keyHandle->UnInit(); + } + // ../out/test/bin/Hal333DETest --gtest_filter=KeyContrlTest.Init4 + TEST_F(KeyContrlTest, Init4) + { + auto keyHandle = std::make_shared(); + auto monitor = std::make_shared(); + std::dynamic_pointer_cast(HalX86MakePtr::GetInstance())->CreateGpioKeyContrlInstance(SfKeyDefine::KEY_PIN_RESET, keyHandle); + LogInfo("Start test.\n"); + keyHandle->Init(); + keyHandle->SetKeyEventMonitor(monitor, nullptr); + std::dynamic_pointer_cast(keyHandle)->CheckKeyValue(); + keyHandle->UnInit(); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/CMakeLists.txt b/code/application/sifarsdk/CMakeLists.txt new file mode 100755 index 000000000..7b61f0165 --- /dev/null +++ b/code/application/sifarsdk/CMakeLists.txt @@ -0,0 +1,137 @@ +cmake_minimum_required(VERSION 3.5.1) +include(build/global_config.cmake) + +project(app) + +message("platform = ${TARGET_PLATFORM}") +message("platform PATH = ${PLATFORM_PATH}") + +# Gdb debug +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) + message("---------------------------Debug mode.-----------------------") + SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb") + SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") + # asan + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=leak -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined") +else() + message("---------------------------Release mode.-----------------------") + SET(CMAKE_BUILD_TYPE "Release") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os") +endif() + +if(${COVERAGE_ON} MATCHES "true") + message("you choose to build gcno file") + add_definitions("-fprofile-arcs") + add_definitions("-ftest-coverage") +endif() + +# 查看是工具链支持情况 +include(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14) + +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) +# execute_process(COMMAND sh build_lvgl_for_cmakelist.sh ${TARGET_PLATFORM} ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/lvglLinux-x86/) +# add_subdirectory(external/lvglLinux-x86) +endif() + +link_directories( + ${DEPENDENCY_LIBS_PATH}/live/${LIVE_PLATFORM_SRC_PATH} +) +string(COMPARE EQUAL "${PLATFORM_PATH}" "" value) +message("The platform path is ${PLATFORM_PATH}.") +if (value EQUAL 0) #变量被设置了 +message("build chip board libs.") +link_directories( + # ${DEPENDENCY_LIBS_PATH}/live/${LIVE_PLATFORM_SRC_PATH} +) +endif() + +#Add macro definition +add_definitions(-DCONFIG_FILE_PATH=\"${CONFIG_FILE_PATH}\") +add_definitions(-DCONFIG_FILE_STATIC_PATH=\"${CONFIG_FILE_STATIC_PATH}\") +add_definitions(-DSF_DCF_EXT_PHOTO=\"${SF_DCF_EXT_PHOTO}\") +add_definitions(-DSF_DCF_EXT_MOV=\"${SF_DCF_EXT_MOV}\") +add_definitions(-DSF_SD_ROOT=\"${SF_SD_ROOT}\") +add_definitions(-DSF_DCF_DIR_NAME_SUFFIX=\"${SF_DCF_DIR_NAME_SUFFIX}\") +add_definitions(-DSF_DCF_ROOT_DIR_NAME=\"${SF_DCF_ROOT_DIR_NAME}\") +add_definitions(-DSF_DCF_THM_DIR_NAME=\"${SF_DCF_THM_DIR_NAME}\") +add_definitions(-DSF_DCF_FILE_NAME_PREFIX=\"${SF_DCF_FILE_NAME_PREFIX}\") + +# Config message of libs on board +# unset(MAIN_INCLUDE_PATH CACHE) +# set(MAIN_INCLUDE_PATH "" CACHE STRING INTERNAL) +# unset(MAIN_SRC_FILE CACHE) +# set(MAIN_SRC_FILE "" CACHE STRING INTERNAL) +# unset(MAIN_LINK_LIB CACHE) +# set(MAIN_LINK_LIB "" CACHE STRING INTERNAL) + +# Config message of main thread +unset(MAIN_INCLUDE_PATH CACHE) +set(MAIN_INCLUDE_PATH "" CACHE STRING INTERNAL) +unset(MAIN_SRC_FILE CACHE) +set(MAIN_SRC_FILE "" CACHE STRING INTERNAL) +unset(MAIN_LINK_LIB CACHE) +set(MAIN_LINK_LIB "" CACHE STRING INTERNAL) + +# Config message for test code. +unset(TEST_LINK_LIB CACHE) +set(TEST_LINK_LIB "" CACHE STRING INTERNAL) +unset(TEST_LINUX_MOCK CACHE) +set(TEST_LINUX_MOCK "" CACHE STRING INTERNAL) +# if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) +set(TEST_LINK_LIB "testUtils" CACHE STRING INTERNAL FORCE) +# endif() +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) + set(TEST_LINUX_MOCK "-Wl,--wrap=fopen,--wrap=fprintf_gpio,--wrap=fprintf_dir" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=tcgetattr" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=tcsetattr" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=gethostbyname" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=connect" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=socket" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=select" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=linux_open" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=linux_read" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=linux_write" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=linux_close" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=linux_fclose" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=linux_fread" CACHE STRING INTERNAL FORCE) + set(TEST_LINUX_MOCK "${TEST_LINUX_MOCK},--wrap=linux_fcntl" CACHE STRING INTERNAL FORCE) +endif() + +# 添加编译目录 +add_subdirectory(application) +add_subdirectory(component) +add_subdirectory(hal) +# add_subdirectory(customization) + +string(COMPARE EQUAL "${PLATFORM_PATH}" "" value) +message("The platform path is ${PLATFORM_PATH}.") +if (value EQUAL 0) #变量被设置了 +message("build chip board code.") +add_subdirectory(${PLATFORM_PATH}) +endif() + +message("MAIN_INCLUDE_PATH = ${MAIN_INCLUDE_PATH}") +message("MAIN_SRC_FILE = ${MAIN_SRC_FILE}") +message("MAIN_LINK_LIB = ${MAIN_LINK_LIB}") +add_subdirectory(test) + +add_custom_target( + SifarSDK_libs + COMMAND echo "Build SifarSDK." + COMMAND rm -rf ${LIBS_OUTPUT_PATH}/include + COMMAND rm -rf ${LIBS_OUTPUT_PATH}/readme + COMMAND mkdir ${LIBS_OUTPUT_PATH}/include + COMMAND mkdir ${LIBS_OUTPUT_PATH}/readme + # COMMAND arm-linux-gnueabihf-9.1.0-strip ${EXEC_OUTPUT_PATH}/* + COMMAND make ConfigOutput + COMMAND make FtpManagerOutput + WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/cmake-shell-linux/ +) + + diff --git a/code/application/sifarsdk/Makefile b/code/application/sifarsdk/Makefile new file mode 100644 index 000000000..80fcb5d7f --- /dev/null +++ b/code/application/sifarsdk/Makefile @@ -0,0 +1,21 @@ +gmock: + $(MAKE) -C external/gtest all +gmock_clean: + $(MAKE) -C external/gtest clean +cmake: + $(MAKE) -C build/cmake all +cmake_clean: + $(MAKE) -C build/cmake clean +all:cmake + $(MAKE) -C cmake-shell-linux all +clean: + $(MAKE) -C cmake-shell-linux clean + @rm -rf external/gtest/googletest-release-1.11.0 \ + external/lvglLinux-x86/lv_sim_vscode_sdl \ + external/openssl/openssl-1.1.1s \ + external/openssl/build \ + external/curl/curl-8.1.2 \ + out \ + cmake-shell-linux + + diff --git a/code/application/sifarsdk/README.md b/code/application/sifarsdk/README.md new file mode 100644 index 000000000..1ee0667d7 --- /dev/null +++ b/code/application/sifarsdk/README.md @@ -0,0 +1,54 @@ +# 1. 项目名称:SifarSDK project + +## 1.1. 前言 +   面向工程师的技术文档均使用markdown编辑,不熟悉markdown的工程师可参考/doc/markdown_user_guide.md文档搭建阅读和修改环境。 + +## 1.2. 项目简介 + +   基于相机业务的跨芯片平台SDK,适用于任何**Linux系统**平台的芯片。 + +## 1.3. 目录介绍: +* **doc:设计文档相关,首要阅读**; +* build:源码构建编译配置文件; +* 333DE:芯片平台代码; +* at-command:AT指令差异化代码; +* external:第三方开源库; +* application:应用层代码; +* component:组件层相关代码; +* hal:硬件适配层相关代码; +* customization:一个客制化的demo; +* test:自动化测试相关代码; +* CMakeLists.txt:此目录的CMakeLists.txt是整个项目构建的起始文件,可根据此文件去跟踪构建的源码文件都有哪些目录的哪些文件。 + +## 1.4. main函数说明 +   由于SifarSDK会构建多个Test可执行文件,存在多个main函数文件。不同的平台和项目可按需重新构建各自的/application/main/线程目录,对mian线程启动的初始化进行重载。 + +SifarSDK的main函数详见:./application/main/main.cpp + +## 1.5. 编译: + +### 1.5.1. SifarSDK开发环境配置 +* SifarSDK默认使用Linux的gcc编译,此时可直接执行编译命令; +* 如果是Linux之前的其它芯片平台,详见开发文档:/doc/hunting_camera_design.md + +### 1.5.2. 编译命令 + +在项目根目录下执行命令: +``` +make cmake +cd cmake-shell-linux/ +make +``` +编译完成后在生成out目录并存放所有的可执行文件,可执行文件可直接在Ubuntu系统运行。 + +### 1.5.3. SifarSDK输出组件库 + +在项目根目录下执行命令: +``` +make cmake +cd cmake-shell-linux/ +make SifarSDK_libs +``` +执行上述命令时,out/libs目录下会生成include和readme两个目录: +include:组件库需要依赖的头文件; +readme:组件库的使用方法,文件名以README_xxx.md格式命名,xxx为库名称; \ No newline at end of file diff --git a/code/application/sifarsdk/application/CMakeLists.txt b/code/application/sifarsdk/application/CMakeLists.txt new file mode 100644 index 000000000..944e67ab3 --- /dev/null +++ b/code/application/sifarsdk/application/CMakeLists.txt @@ -0,0 +1,7 @@ + +# cmake_minimum_required(VERSION 2.8.0) +add_subdirectory(main) +add_subdirectory(StateManager) +add_subdirectory(NetworkManager) + + diff --git a/code/application/sifarsdk/application/NetworkManager/CMakeLists.txt b/code/application/sifarsdk/application/NetworkManager/CMakeLists.txt new file mode 100644 index 000000000..2733b720c --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/CMakeLists.txt @@ -0,0 +1,42 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ./src/signatureMng/inc + ${APPLICATION_SOURCE_PATH}/StateManager/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/cJSON/include + ${COMPONENT_SOURCE_PATH}/base64/include + ${COMPONENT_SOURCE_PATH}/utils/include + ${COMPONENT_SOURCE_PATH}/SignatureManager/include + ${COMPONENT_SOURCE_PATH}/SystemTime/include + ${COMPONENT_SOURCE_PATH}/FileManager/include + ${COMPONENT_SOURCE_PATH}/DualCoreManager/include + ${COMPONENT_SOURCE_PATH}/HttpBase/include + ${COMPONENT_SOURCE_PATH}/Config/include + # ${COMPONENT_SOURCE_PATH}/StateMachineManager/include + ${COMPONENT_SOURCE_PATH}/DualCoreManager/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) +aux_source_directory(./src/signatureMng/src SRC_FILES) + +set(TARGET_NAME NetworkManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} StateManager SignatureManager StateMachineManager PeripheralManager DualCoreManager SystemTime FileManager cJSON base64 utils HttpBase ReturnCode Log) + diff --git a/code/application/sifarsdk/application/NetworkManager/include/INetworkManager.h b/code/application/sifarsdk/application/NetworkManager/include/INetworkManager.h new file mode 100644 index 000000000..543508361 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/include/INetworkManager.h @@ -0,0 +1,284 @@ +#ifndef I_NETWORK_MANAGER_H +#define I_NETWORK_MANAGER_H +#include "VReturnCode.h" +#include "IHalCommon.h" // TODO: It't better not include IHalCommon.h +#include +#include +enum class RegisterNetworkType +{ + MANUAL = 0, + AUTO, + END +}; +class AuthRequestDataIn +{ +public: + AuthRequestDataIn(const std::string &webIP, const std::string &imei, const std::string &iccid) + : mWebIP(webIP), mIMEI(imei), mIccid(iccid) + { + } + ~AuthRequestDataIn() + { + } + const std::string mWebIP; + const std::string mIMEI; + const std::string mIccid; +}; +class AuthRequestDataOut +{ +public: + AuthRequestDataOut() + { + } + ~AuthRequestDataOut() + { + } + std::string mAcmIP; +}; +enum class NetworkSignal +{ + LEVEL_0 = 0, + LEVEL_1, + LEVEL_2, + LEVEL_3, + LEVEL_4, + END +}; +class NetworkParameter +{ +public: + NetworkParameter() + { + mSignalLevel = NetworkSignal::END; + } + ~NetworkParameter() + { + } + // std::string mWebIP; + std::string mIMEI; + std::string mIccid; + std::string mAcmIP; + std::string mServiceProvider; + std::string mModuleSubVersion; + NetworkSignal mSignalLevel; +}; +class SubscribeMessage +{ +public: + SubscribeMessage(const SF_FILE_TYPE_E &fileTye, const std::string &targetFileName) + : mFileTye(fileTye), mTargetFileName(targetFileName) + { + } + ~SubscribeMessage() + { + } + SubscribeMessage &operator=(const SubscribeMessage &value) + { + return *this; + } + const SF_FILE_TYPE_E mFileTye; // TODO: It't better not include IHalCommon.h + const std::string mTargetFileName; + // const std::string mHDFilePath; +}; +class UploadFileData +{ +public: + UploadFileData(const SF_FILE_TYPE_E &fileType, const std::string &fileName, const std::string &filePath) + : enFileTye(fileType), thumbfileName(fileName), thumbfilePath(filePath) //, thumbfileSize(fileSize) + { + thumbfileSize = 0; + } + ~UploadFileData() + { + } + UploadFileData &operator=(const UploadFileData &value) + { + return *this; + } + const SF_FILE_TYPE_E enFileTye; // TODO: It't better not include IHalCommon.h + const std::string thumbfileName; + const std::string thumbfilePath; + unsigned int thumbfileSize; + std::string mSendFileWithTime; + std::string mBindFile; +}; +class AcmServersData +{ +public: + AcmServersData() + { + SdTotalFile = 0; + FcTemper = 0; + BatRemainCap = 0; + mSignalLevel = NetworkSignal::END; + mMcuVersion = 0; + mMcuSubVersion = 0; + mStartupMode = 0; + } + ~AcmServersData() + { + } + std::string mIMEI; + std::string mIccid; + std::string mModuleSubVersion; + std::string mServiceProvider; + std::string mAcmIP; + std::string mAppVersion; + unsigned short mMcuVersion; + unsigned char mMcuSubVersion; + unsigned short SdTotalFile; + unsigned char FcTemper; + unsigned char BatRemainCap; + // UINT8 netGeneration; + // UINT8 SimSignal; + NetworkSignal mSignalLevel; + unsigned char mStartupMode; +}; +typedef struct HttpTime +{ + unsigned short Year; + unsigned short Mon; + unsigned short Day; + unsigned short Hour; + unsigned short Min; + unsigned short Sec; +} HttpTime; +enum class SdFormatValue +{ + DO_NOT_NEED_TO_FORMAT = 0, + NEED_TO_FORMAT = 1, + END +}; +enum class DeviceReset +{ + DO_NOT_NEED_TO_RESET = 0, + NEED_TO_RESET, + END +}; +class AcmLoginResult +{ +public: + AcmLoginResult() + { + DateStyle = 0; + TimeZone = 0; + bindFlag = 0; + PicPlan = 0; + Did = 0; + AlivePort = 0; + UploadMode = 0; + mIsLogin = false; + mSyncConfig = false; + mSdFormat = SdFormatValue::END; + mDeviceReset = DeviceReset::END; + } + ~AcmLoginResult() + { + } + unsigned char DateStyle; + unsigned char SendMaxNum; + unsigned char bindFlag; + unsigned char UploadMode; + signed int Did; + signed int AlivePort; + char PicPlan; + char TimeZone; + HttpTime httpTime; + std::string AcmIP; + std::string AliveIp; + std::string Token; + std::string BindAccount; + std::string Uuid; + std::string szIP; + std::string szBucket; + std::string szUsername; + std::string szPassword; + std::string mOtaUrl; + bool mIsLogin; + bool mSyncConfig; + SdFormatValue mSdFormat; + DeviceReset mDeviceReset; + std::vector mSubscribleFiles; +}; +class FileServersData +{ +public: + FileServersData(const AcmLoginResult &data, const std::string imei) : mData(data), mIMEI(imei) + { + } + ~FileServersData() + { + } + const AcmLoginResult mData; + const std::string mIMEI; + std::string mIP; +}; +enum class UploadResult +{ + SUCCEED = 0, + FAILED, + END +}; +class VUploadTask +{ +public: + VUploadTask() = default; + virtual ~VUploadTask() = default; + virtual void UploadResultResponse(const UploadFileData &file, const UploadResult &result) {} + virtual const std::vector GetFiles(void) + { + std::vector files; + return files; + } +}; +class VFileServersHandle +{ +public: + VFileServersHandle() = default; + virtual ~VFileServersHandle() = default; + virtual RETURN_CODE UploadFiles(const std::shared_ptr &task) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE StopUploading(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +class FileResult +{ +public: + FileResult(const UploadFileData &file, const UploadResult &result) + : mFile(file), mResult(result) + { + } + ~FileResult() + { + } + const UploadFileData mFile; + const UploadResult mResult; +}; +class VAcmServersHandle +{ +public: + VAcmServersHandle() = default; + virtual ~VAcmServersHandle() = default; + virtual RETURN_CODE Login(AcmLoginResult &dataOut) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SyncConfig(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetLoginDate(AcmLoginResult &data) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SendFileResult(const std::vector &results) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +class INetworkManager +{ +public: + INetworkManager() = default; + virtual ~INetworkManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE NetworkHardwareIsWorking(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE LinkNetworkInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE AuthRequest(const AuthRequestDataIn &dataIn, AuthRequestDataOut &dataOut) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE RegisterNetwork(const RegisterNetworkType &type) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetParameter(NetworkParameter ¶m) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetFileServersHandle(std::shared_ptr &servers, const FileServersData &data) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetAcmServersHandle(std::shared_ptr &servers, const AcmServersData &data) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetAcmServersHandle(std::shared_ptr &servers) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE KeepAliveWithLiveServers(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreateNetworkManagerModule(void); +#endif // !I_NETWORK_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandle.cpp b/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandle.cpp new file mode 100644 index 000000000..4ce5b2c80 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandle.cpp @@ -0,0 +1,1346 @@ +#include "ACMServersHandle.h" +#include "IPeripheralManager.h" +#include "IDualCoreManager.h" +#include "Log.h" +#include "IConfig.h" +#include +constexpr int SF_HTTP_RECV_MAX = 4096; +ACMServersHandle::ACMServersHandle(const AcmServersData &data) : HttpServers(data.mAcmIP), mData(data) +{ + mServersVersion = "v1"; + memset(&stLoginAcmResponse, 0, sizeof(LOGIN_ACM_RESPONSE_S)); + memset(&SubReportFileAttr, 0, sizeof(SF_REPORT_FILE_ATTR_S)); +} +SINT32 ACMServersHandle::GetDomainName(const char *url, char *host) +{ + char *pA = nullptr; + char *pB = nullptr; + memset(host, 0, strlen(host)); + + if (!(*url)) + return -1; + pA = (char *)url; + if (!strncmp(pA, "http://", strlen("http://"))) + pA = (char *)(url + strlen("http://")); + else if (!strncmp(pA, "https://", strlen("https://"))) + pA = (char *)(url + strlen("https://")); + pB = strchr(pA, '/'); + if (pB) + { + memcpy(host, pA, strlen(pA) - strlen(pB)); + host[strlen(pA) - strlen(pB)] = 0; + } + else + { + memcpy(host, pA, strlen(pA)); + host[strlen(pA)] = 0; + } + // LogInfo("host = %s\n", host); + return 0; +} +RETURN_CODE ACMServersHandle::Login(AcmLoginResult &dataOut) +{ + char RecvBuf[SF_HTTP_RECV_MAX] = {0}; + std::string packet; + HttpServers::Create(); + LoginPacketGrouping(mData, packet); + LogInfo("Login packet = %s\n", packet.c_str()); + Transfer(packet, RecvBuf, SF_HTTP_RECV_MAX); + LogInfo("Recv buf = %s\n", RecvBuf); + LoginRecvAnalysis(RecvBuf, dataOut); + mLoginResponse = dataOut; + SystemTime time; + TypeConversionOfTime(dataOut.httpTime, time); + SetSystemTime(time); + IDualCoreManager::GetInstance()->SetMcuTime(); + HttpServers::Close(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE ACMServersHandle::SyncConfig(void) +{ + char RecvBuf[SF_HTTP_RECV_MAX] = {0}; + std::string packet; + HttpServers::Create(); + sf_net_packetgrouping_sync(mLoginResponse, packet, SYNC_DOWNLOAD_FROM_SERVERS); + LogInfo("SyncConfig packet = %s\n", packet.c_str()); + Transfer(packet, RecvBuf, SF_HTTP_RECV_MAX); + LogInfo("Recv buf = %s\n", RecvBuf); + SyncResult dataOut; + SyncFileAnlysis(RecvBuf, dataOut); + // TODO: save config. + if (SYNC_UPLOAD_TO_SERVERS == dataOut.ParaSync) + { + sf_net_packetgrouping_sync(mLoginResponse, packet, SYNC_UPLOAD_TO_SERVERS); + memset(RecvBuf, 0, SF_HTTP_RECV_MAX); + LogInfo("SyncConfig packet = %s\n", packet.c_str()); + Transfer(packet, RecvBuf, SF_HTTP_RECV_MAX); + LogInfo("Recv buf = %s\n", RecvBuf); + SyncFileAnlysis(RecvBuf, dataOut); + } + HttpServers::Close(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +SINT32 ACMServersHandle::sf_net_packetgrouping_sync(const AcmLoginResult &loginData, std::string &packet, const unsigned int &modiyFlay) +{ + std::stringstream packetOut; + cJSON *root = nullptr; + root = MallocPacketOfSync(loginData, modiyFlay); + if (!root) + { + LogError("MallocPacketOfSync failed.\n"); + return SF_FAILURE; + } + char *devparam = cJSON_Print(root); + cJSON_Delete(root); + // Param sync = GetParam(PARAM_PARAM_SYNC); + packetOut << "POST /AcmService/acmhttp/" << mServersVersion << "/syncConfig?modifyFlag=" + << modiyFlay << " HTTP/1.1\r\n" + << "Host:" << mData.mAcmIP << "\r\n" + << "token:" << loginData.Token << "\r\n" + << "Connection: keep-alive\r\n" + << "Content-Length: " << strlen(devparam) << "\r\n" + << "Content-Type: application/json\r\n\r\n" + << devparam; + // packetOut << "POST /AcmService/acmhttp/" << mServersVersion << "/syncConfig" + // << sync.numberUInt << " HTTP/1.1\r\n" + // << "Host:" << mData.mAcmIP << "\r\n" + // << "token:" << loginData.Token << "\r\n" + // << "Connection: keep-alive\r\n" + // << "Content-Length: " << strlen(devparam) << "\r\n" + // << "Content-Type: application/json\r\n\r\n" + // << devparam; + free(devparam); + packet = packetOut.str(); + return SF_SUCCESS; +} +cJSON *ACMServersHandle::MallocPacketOfSync(const AcmLoginResult &loginData, const unsigned int &modiyFlay) +{ + UINT16 param = 0; + SF_CHAR time[16] = {0}; + SF_CHAR workTimerWeekStr[10] = {0}; + SF_CHAR gpsStr[32] = {0}; + cJSON *root = nullptr; + Param videoLength; + Param did = GetParam(PARAM_DID); + Param batteryTpye = GetParam(PARAM_BATTERY_TYPE); + Param cameraMode = GetParam(PARAM_CAMERA_MODE); + Param flashLed = GetParam(PARAM_FLASH_LED); + Param sdLoop = GetParam(PARAM_SD_LOOP); + Param pirSwitch = GetParam(PARAM_PIR_SWITCH); + Param stampSwitch = GetParam(PARAM_STAMP_SWITCH); + Param imageSize = GetParam(PARAM_IMAGE_SIZE); + Param multiShot = GetParam(PARAM_NAME_MULTI_SHOT); + Param digitPirSensitivity = GetParam(PARAM_PIR_SENSITIVITY); + + Param videoSize = GetParam(PARAM_VIDEO_SIZE); + + root = cJSON_CreateObject(); + cJSON_AddNumberToObject(root, "did", loginData.Did); + cJSON_AddNumberToObject(root, "batteryType", batteryTpye.numberUInt); + cJSON_AddNumberToObject(root, "video", cameraMode.numberUInt + 1); + cJSON_AddNumberToObject(root, "ledNumber", flashLed.numberUInt); + cJSON_AddNumberToObject(root, "sdcycleFlag", sdLoop.numberUInt); + cJSON_AddNumberToObject(root, "pirswitch", pirSwitch.numberUInt); + cJSON_AddNumberToObject(root, "stamp", stampSwitch.numberUInt); + cJSON_AddNumberToObject(root, "image", imageSize.numberUInt); + cJSON_AddNumberToObject(root, "multishot", multiShot.numberUInt); + cJSON_AddNumberToObject(root, "sdFormat", static_cast(loginData.mSdFormat)); + cJSON_AddNumberToObject(root, "devResetCommand", static_cast(loginData.mDeviceReset)); + cJSON_AddNumberToObject(root, "modifyFlag", modiyFlay); + + // /*0:1080P, 1:720P, 2:480P*/ + cJSON_AddNumberToObject(root, "videoSize", videoSize.numberUInt + 1); + if (videoSize.numberUInt == SF_VIDEO_SIZE_1080) + { + constexpr int VIDEO_LENGTH_S = 10; + videoLength.numberUInt = VIDEO_LENGTH_S; + } + else if (videoSize.numberUInt == SF_VIDEO_SIZE_720) + { + constexpr int VIDEO_LENGTH_S = 20; + videoLength.numberUInt = VIDEO_LENGTH_S; + } + else if (videoSize.numberUInt == SF_VIDEO_SIZE_WVGA) + { + constexpr int VIDEO_LENGTH_S = 30; + videoLength.numberUInt = VIDEO_LENGTH_S; + } + SetParam(videoLength, PARAM_VIDEO_LENGTH); + + cJSON_AddNumberToObject(root, "videoLength", videoLength.numberUInt); + cJSON_AddNumberToObject(root, "pirsentivity", digitPirSensitivity.numberUInt); + + Param pirdelaySwitch = GetParam(PARAM_PIR_DELAY_SWITCH); + Param pirdelayTime = GetParam(PARAM_PIR_DELAY_TIME); + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "delayFlag", pirdelaySwitch.numberUInt); + sprintf(time, "%02d%02d%02d", pirdelayTime.time.Hour, pirdelayTime.time.Min, pirdelayTime.time.Sec); + cJSON_AddStringToObject(root, "delayValue", time); + Param timelapseSwitch = GetParam(PARAM_TIMELAPSE_SWITCH); + Param timeLapseTime = GetParam(PARAM_TIMELAPSE_TIME); + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "timelapseFlag", timelapseSwitch.numberUInt); + sprintf(time, "%02d%02d%02d", timeLapseTime.time.Hour, timeLapseTime.time.Min, timeLapseTime.time.Sec); + cJSON_AddStringToObject(root, "timelapseValue", time); + Param workTime1Switch = GetParam(PARAM_WORK_TIME_1_SWITCH); + Param workTime2Switch = GetParam(PARAM_WORK_TIME_2_SWITCH); + Param workTime = GetParam(PARAM_WORK_TIME); + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "timerFlag", workTime1Switch.numberUInt); + sprintf(time, "%02d%02d-%02d%02d", workTime.workTime[0].StartTime.Hour, workTime.workTime[0].StartTime.Min, workTime.workTime[0].StopTime.Hour, workTime.workTime[0].StopTime.Min); + cJSON_AddStringToObject(root, "timerValue", time); + + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "timerFlag2", workTime2Switch.numberUInt); + sprintf(time, "%02d%02d-%02d%02d", workTime.workTime[1].StartTime.Hour, workTime.workTime[1].StartTime.Min, workTime.workTime[1].StopTime.Hour, workTime.workTime[1].StopTime.Min); + cJSON_AddStringToObject(root, "timerValue2", time); + + debug_remotecontrol_packet(); + char stringGPS[21] = {0}; + packet_gps_parse(stringGPS); + Param gpsFlag = GetParam(PARAM_GPS_FLAG); + cJSON_AddNumberToObject(root, "gpsFlag", gpsFlag.numberUInt); + cJSON_AddStringToObject(root, "gps", stringGPS); + Param gprsMode = GetParam(PARAM_GPRS_MODE); + cJSON_AddNumberToObject(root, "smsctrl", gprsMode.numberUInt); + Param dailyReportSwitch = GetParam(PARAM_DAILY_REPORT_SWITCH); + Param dailyReportTime = GetParam(PARAM_DAILY_REPORT_TIME); + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "dailyreportFlag", dailyReportSwitch.numberUInt); + sprintf(time, "%02d%02d", dailyReportTime.time.Hour, dailyReportTime.time.Min); + cJSON_AddStringToObject(root, "dailyreportValue", time); + + return root; +} +SINT32 ACMServersHandle::packet_gps_parse(char *pstring) +{ + Param Latitude = GetParam(PARAM_LATITUDE); + Param Longitude = GetParam(PARAM_LONGITUDE); + *pstring++ = Latitude.str[9]; + *pstring++ = Latitude.str[0]; + *pstring++ = Latitude.str[1]; + *pstring++ = '.'; + *pstring++ = Latitude.str[2]; + *pstring++ = Latitude.str[3]; + *pstring++ = '.'; + *pstring++ = Latitude.str[5]; + *pstring++ = Latitude.str[6]; + *pstring++ = '-'; + + *pstring++ = Longitude.str[10]; + *pstring++ = Longitude.str[0]; + *pstring++ = Longitude.str[1]; + *pstring++ = Longitude.str[2]; + *pstring++ = '.'; + *pstring++ = Longitude.str[3]; + *pstring++ = Longitude.str[4]; + *pstring++ = '.'; + *pstring++ = Longitude.str[6]; + *pstring++ = Longitude.str[7]; + *pstring++ = '\0'; + return SF_SUCCESS; +} +SINT32 ACMServersHandle::debug_remotecontrol_packet(void) +{ + Param gprsMode = GetParam(PARAM_GPRS_MODE); + Param dailyReportSwitch = GetParam(PARAM_DAILY_REPORT_SWITCH); + Param dailyReportTime = GetParam(PARAM_DAILY_REPORT_TIME); + if (gprsMode.numberUInt == 0) + { + dailyReportSwitch.numberUInt = 0; + dailyReportTime.time.Hour = 24; + dailyReportTime.time.Min = 0; + } + else if (gprsMode.numberUInt == 1) + { + dailyReportSwitch.numberUInt = 0; + dailyReportTime.time.Hour = 0; + dailyReportTime.time.Min = 0; + } + else if (gprsMode.numberUInt == 2) + { + dailyReportSwitch.numberUInt = 1; + dailyReportTime.time.Hour = 0; + dailyReportTime.time.Min = 30; + } + else if (gprsMode.numberUInt == 3) + { + dailyReportSwitch.numberUInt = 1; + dailyReportTime.time.Hour = 1; + dailyReportTime.time.Min = 0; + } + else if (gprsMode.numberUInt == 4) + { + dailyReportSwitch.numberUInt = 1; + dailyReportTime.time.Hour = 2; + dailyReportTime.time.Min = 0; + } + else if (gprsMode.numberUInt == 5) + { + dailyReportSwitch.numberUInt = 1; + dailyReportTime.time.Hour = 3; + dailyReportTime.time.Min = 0; + } + else if (gprsMode.numberUInt == 6) + { + dailyReportSwitch.numberUInt = 1; + dailyReportTime.time.Hour = 4; + dailyReportTime.time.Min = 0; + } + else if (gprsMode.numberUInt == 7) + { + dailyReportSwitch.numberUInt = 1; + dailyReportTime.time.Hour = 6; + dailyReportTime.time.Min = 0; + } + else if (gprsMode.numberUInt == 8) + { + dailyReportSwitch.numberUInt = 1; + dailyReportTime.time.Hour = 12; + dailyReportTime.time.Min = 0; + } + else if (gprsMode.numberUInt == 9) + { + dailyReportSwitch.numberUInt = 1; + dailyReportTime.time.Hour = 24; + dailyReportTime.time.Min = 0; + } + return SF_SUCCESS; +} +RETURN_CODE ACMServersHandle::GetLoginDate(AcmLoginResult &data) +{ + data = mLoginResponse; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE ACMServersHandle::SendFileResult(const std::vector &results) +{ + char RecvBuf[SF_HTTP_RECV_MAX] = {0}; + std::string packet; + HttpServers::Create(); + FilesUploadedGrouping(mLoginResponse, results, packet); + LogInfo("Upload packet = %s\n", packet.c_str()); + Transfer(packet, RecvBuf, SF_HTTP_RECV_MAX); + LogInfo("Recv buf = %s\n", RecvBuf); + // SyncResult result; + SendFilesAnlysis(RecvBuf); + HttpServers::Close(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +SINT32 ACMServersHandle::Transfer(const std::string &sendData, char *recvBuf, const unsigned int &recvBufLength) +{ + SINT32 s32ret = 0; + if (!recvBuf) + { + LogError("Nullptr pointer.\n"); + return SF_FAILURE; + } + s32ret = HttpServers::Send(sendData.c_str(), sendData.length()); + s32ret = HttpServers::Rece(recvBuf, recvBufLength); + LogInfo("datasize = %d\n", s32ret); + if (s32ret <= 0) + return SF_FAILURE; + return SF_SUCCESS; +} +SINT32 ACMServersHandle::LoginRecvAnalysis(char *recvData, AcmLoginResult &dataOut) +{ + char *p = nullptr; + char *p1 = nullptr; + char *p2 = nullptr; + cJSON *json = nullptr; + cJSON *first = nullptr; + cJSON *second = nullptr; + cJSON *subListItem = nullptr; + SINT32 ret = SF_SUCCESS; + UINT16 index = 0; + UINT16 i = 0; + UINT16 declen = 0; + char buf[256] = {0}; + SF_CHAR decode_tempStr[128] = {0}; + SF_REPORT_FILE_ATTR_S *pSubReportFileAttr = &SubReportFileAttr; + ret = ResponseStatusCode(recvData); + if (ret == SF_FAILURE) + { + LogError("Recv error.\n"); + dataOut.mIsLogin = false; + // return SF_DATA_ERROR_REQUEST; // TODO: + return SF_FAILURE; + } + dataOut.mIsLogin = true; + + p = strchr(recvData, '{'); + json = cJSON_Parse(p); + if (!json) + { + LogError("Error before: [%s]\n", cJSON_GetErrorPtr()); + cJSON_Delete(json); + // return SF_DATA_ERROR_DATA_FORMAT; + return SF_FAILURE; + } + + first = cJSON_GetObjectItem(json, "code"); + first = cJSON_GetObjectItem(json, "errCode"); + LogInfo("...errCode = %d\n", first->valueint); + dataOut.bindFlag = USER_BIND; + if (first->valueint != 0) + { + // data_error_collection(first->valueint); // TODO: + + if (first->valueint == 10012 || first->valueint == 20013 || first->valueint == 20002) + { + dataOut.PicPlan = 0; + } + + if (first->valueint == 20002 || first->valueint == 20011) + { + dataOut.bindFlag = USER_NOT_BIND; + } + cJSON_Delete(json); + return SF_FAILURE; + } + + first = cJSON_GetObjectItem(json, "msg"); + LogInfo("...msg = %s\n", first->valuestring); + first = cJSON_GetObjectItem(json, "data"); + + second = cJSON_GetObjectItem(first, "serverIp"); + if (second->valuestring != nullptr) + { + dataOut.AcmIP = second->valuestring; + cJSON_Delete(json); + // return SF_DATA_ERROR_IP_CHANGE; // TODO: return? + return SF_FAILURE; + } + + second = cJSON_GetObjectItem(first, "devResetCommand"); + if (second != nullptr) + { + constexpr int NEED_TO_RESET = 1; + stLoginAcmResponse.devResetCommand = second->valueint; + LogInfo(".devResetCommand = %d\n", stLoginAcmResponse.devResetCommand); + dataOut.mDeviceReset = NEED_TO_RESET == second->valueint + ? DeviceReset::NEED_TO_RESET + : DeviceReset::DO_NOT_NEED_TO_RESET; + } + + second = cJSON_GetObjectItem(first, "did"); + if (second != nullptr) + { + dataOut.Did = second->valueint; + LogInfo(".did = %d\n", dataOut.Did); + } + + second = cJSON_GetObjectItem(first, "downloadUrl"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.downloadUrl, '\0', sizeof(stLoginAcmResponse.downloadUrl)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.downloadUrl, buf, declen); + dataOut.mOtaUrl = stLoginAcmResponse.downloadUrl; + LogInfo(".downloadUrl = %s\n", stLoginAcmResponse.downloadUrl); + } + + second = cJSON_GetObjectItem(first, "dateFormat"); + if (second != nullptr) + { + dataOut.DateStyle = second->valueint; + } + + second = cJSON_GetObjectItem(first, "hdCommand"); + if (second != nullptr) + { + stLoginAcmResponse.hdCommand = second->valueint; + LogInfo(".hdCommand = %d\n", stLoginAcmResponse.hdCommand); + } + + // sub hd pic + if ((stLoginAcmResponse.hdCommand > 0) && (stLoginAcmResponse.hdCommand < 100)) + { + std::vector allUploadFiles; + second = cJSON_GetObjectItem(first, "hdPhototVOList"); + i = pSubReportFileAttr->filecnt; + for (index = 0; index < stLoginAcmResponse.hdCommand; index++) + { + subListItem = cJSON_GetArrayItem(second, index); + { + pSubReportFileAttr->stSendFileAttr[i].enFileTye = (SF_FILE_TYPE_E)cJSON_GetObjectItem(subListItem, "fileType")->valueSINT32; + sprintf(pSubReportFileAttr->stSendFileAttr[i].SubFileName, "%s", cJSON_GetObjectItem(subListItem, "fileName")->valuestring); + LogInfo("enFileTye:%d, SubFileName:%s\n", pSubReportFileAttr->stSendFileAttr[i].enFileTye, + pSubReportFileAttr->stSendFileAttr[i].SubFileName); + i++; + pSubReportFileAttr->filecnt = i; + } + SubscribeMessage uploadFile((SF_FILE_TYPE_E)cJSON_GetObjectItem(subListItem, "fileType")->valueSINT32, + cJSON_GetObjectItem(subListItem, "fileName")->valuestring); + allUploadFiles.push_back(uploadFile); + } + LogInfo("filecnt:%d\n", pSubReportFileAttr->filecnt); + dataOut.mSubscribleFiles = allUploadFiles; + } + + char AliveIp[32] = {0}; + second = cJSON_GetObjectItem(first, "ip"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.ip, '\0', sizeof(stLoginAcmResponse.ip)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.ip, buf, declen); + p1 = stLoginAcmResponse.ip; + p2 = strchr(stLoginAcmResponse.ip, ':'); + dataOut.AlivePort = atoi(p2 + 1); + // memcpy(pStaticParam->AliveIp, p1, p2 - p1); // TODO: + } + + second = cJSON_GetObjectItem(first, "name"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.name, '\0', sizeof(stLoginAcmResponse.name)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.name, buf, declen); + LogInfo(".name = %s\n", stLoginAcmResponse.name); + } + + second = cJSON_GetObjectItem(first, "offset"); + if (second != nullptr) + { + stLoginAcmResponse.offset = second->valueint; + dataOut.TimeZone = stLoginAcmResponse.offset / 1000 / 3600; + LogInfo(".TimeZone = %d\n", dataOut.TimeZone); + } + + second = cJSON_GetObjectItem(first, "otaCommand"); + if (second != nullptr) + { + stLoginAcmResponse.otaCommand = second->valueint; + LogInfo(".otaCommand = %d\n", stLoginAcmResponse.otaCommand); + } + + second = cJSON_GetObjectItem(first, "passwd"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.passwd, '\0', sizeof(stLoginAcmResponse.passwd)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.passwd, buf, declen); + LogInfo(".passwd = %s\n", stLoginAcmResponse.passwd); + } + + second = cJSON_GetObjectItem(first, "port"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.port, '\0', sizeof(stLoginAcmResponse.port)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.port, buf, declen); + LogInfo(".port = %s\n", stLoginAcmResponse.port); + } + + second = cJSON_GetObjectItem(first, "sdFormatCommand"); + if (second != nullptr) + { + constexpr int NEED_TO_FORMAT = 1; + stLoginAcmResponse.sdFormatCommand = second->valueint; + LogInfo(".sdFormatCommand = %d\n", stLoginAcmResponse.sdFormatCommand); + dataOut.mSdFormat = NEED_TO_FORMAT == second->valueint + ? SdFormatValue::NEED_TO_FORMAT + : SdFormatValue::DO_NOT_NEED_TO_FORMAT; + } + + second = cJSON_GetObjectItem(first, "synConfigCommand"); + if (second != nullptr) + { + stLoginAcmResponse.synConfigCommand = second->valueint; + LogInfo(".synConfigCommand = %d\n", stLoginAcmResponse.synConfigCommand); + constexpr int NEET_TO_SYNC_CONFIG = 1; + dataOut.mSyncConfig = second->valueint == NEET_TO_SYNC_CONFIG ? true : false; + } + + second = cJSON_GetObjectItem(first, "serverIp"); + if (second->valuestring != nullptr) + { + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.serverIp, buf, declen); + stLoginAcmResponse.RegionalChange = 1; + LogInfo(".serverIp = %s\n", stLoginAcmResponse.serverIp); + } + + second = cJSON_GetObjectItem(first, "token"); + if (second->valuestring != nullptr) + { + dataOut.Token = second->valuestring; + LogInfo(".token = %s\n", dataOut.Token.c_str()); + } + + second = cJSON_GetObjectItem(first, "leftOverPic"); + if (second != nullptr) + { + stLoginAcmResponse.leftOverPic = second->valueint; + LogInfo(".leftOverPic = %d\n", stLoginAcmResponse.leftOverPic); + if (stLoginAcmResponse.leftOverPic > 0) + dataOut.PicPlan = 1; + else + dataOut.PicPlan = 0; + } + + second = cJSON_GetObjectItem(first, "uploadType"); + if (second != nullptr) + { + dataOut.UploadMode = second->valueint; + LogInfo(".uploadtype = %d\n", dataOut.UploadMode); + } + + second = cJSON_GetObjectItem(first, "url"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.url, '\0', sizeof(stLoginAcmResponse.url)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.url, buf, declen); + LogInfo(".url = %s\n", stLoginAcmResponse.url); + } + + second = cJSON_GetObjectItem(first, "userEmail"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.userEmail, '\0', sizeof(stLoginAcmResponse.userEmail)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.userEmail, buf, declen); + dataOut.BindAccount = stLoginAcmResponse.userEmail; + + LogInfo(".userEmail = %s\n", stLoginAcmResponse.userEmail); + } + + second = cJSON_GetObjectItem(first, "uuid"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.uuid, '\0', sizeof(stLoginAcmResponse.uuid)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.uuid, buf, declen); + dataOut.Uuid = stLoginAcmResponse.uuid; + LogInfo(".uuids = %s\n", stLoginAcmResponse.uuid); + } + + second = cJSON_GetObjectItem(first, "date"); + if (second->valuestring != nullptr) + { + memcpy(stLoginAcmResponse.date, second->valuestring, strlen(second->valuestring)); + LogInfo(".date = %s\n", stLoginAcmResponse.date); + } + + second = cJSON_GetObjectItem(first, "maxNumberDay"); + if (second != nullptr) + { + dataOut.SendMaxNum = second->valueint; + LogInfo(".maxNumberDay = %d\n", dataOut.SendMaxNum); + } + + second = cJSON_GetObjectItem(first, "getPic"); + if (second != nullptr) + { + stLoginAcmResponse.getPic = second->valueint; + LogInfo(".getPic = %d\n", stLoginAcmResponse.getPic); + } + + second = cJSON_GetObjectItem(first, "mqttEndpoint"); + if (second != nullptr && second->valuestring != nullptr && strlen(second->valuestring) > 0) + { + // mqtt ip is public.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883 + // memset(pStaticParam->MQTTIp, '\0', sizeof(pStaticParam->MQTTIp)); + Param MQTTIp; + Param MQTTPort; + memset(&MQTTIp, 0, sizeof(Param)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + p1 = buf; + p2 = strchr(buf, ':'); + memcpy(MQTTIp.str, p1, p2 - p1); + MQTTPort.numberInt = atoi(p2 + 1); + LogInfo("mqtt ip is %s\n", MQTTIp.str); + LogInfo("mqtt port is %d\n", MQTTPort.numberInt); + } + + second = cJSON_GetObjectItem(first, "p2pId"); + if (second != nullptr && second->valuestring != nullptr && strlen(second->valuestring) > 0) + { + memset(stLoginAcmResponse.p2pId, '\0', sizeof(stLoginAcmResponse.p2pId)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.p2pId, buf, declen); + LogInfo("...p2p id = %s\n", stLoginAcmResponse.p2pId); + // memcpy(gstSFLiveAccount.product_key, stLoginAcmResponse.p2pId, strlen(stLoginAcmResponse.p2pId)); + Param p2pId; + memset(&p2pId, 0, sizeof(Param)); + memcpy(p2pId.str, stLoginAcmResponse.p2pId, declen); + SetParam(p2pId, PARAM_P2P_ID); + } + + second = cJSON_GetObjectItem(first, "p2pName"); + if (second != nullptr && second->valuestring != nullptr && strlen(second->valuestring) > 0) + { + memset(stLoginAcmResponse.p2pName, '\0', sizeof(stLoginAcmResponse.p2pName)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.p2pName, buf, declen); + LogInfo("...p2p name = %s\n", stLoginAcmResponse.p2pName); + // memcpy(gstSFLiveAccount.device_name, stLoginAcmResponse.p2pName, strlen(stLoginAcmResponse.p2pName)); + Param p2pName; + memset(&p2pName, 0, sizeof(Param)); + memcpy(p2pName.str, stLoginAcmResponse.p2pName, declen); + SetParam(p2pName, PARAM_P2P_NAME); + } + + second = cJSON_GetObjectItem(first, "p2pSecret"); + if (second != nullptr && second->valuestring != nullptr && strlen(second->valuestring) > 0) + { + memset(stLoginAcmResponse.p2pSecret, '\0', sizeof(stLoginAcmResponse.p2pSecret)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.p2pSecret, buf, declen); + LogInfo("...p2p secret = %s\n", stLoginAcmResponse.p2pSecret); + // memcpy(gstSFLiveAccount.device_secret, stLoginAcmResponse.p2pSecret, strlen(stLoginAcmResponse.p2pSecret)); + Param p2pSecret; + memset(&p2pSecret, 0, sizeof(Param)); + memcpy(p2pSecret.str, stLoginAcmResponse.p2pSecret, declen); + SetParam(p2pSecret, PARAM_P2P_SECRET); + } + + dataOut.szIP = stLoginAcmResponse.url; + dataOut.szBucket = stLoginAcmResponse.port; + dataOut.szUsername = stLoginAcmResponse.name; + dataOut.szPassword = stLoginAcmResponse.passwd; + + /**/ + // HttpTime httpTime; + char *indx = nullptr; + indx = stLoginAcmResponse.date; + dataOut.httpTime.Year = atoi(indx); + indx = strchr(indx, '-'); + indx++; + dataOut.httpTime.Mon = atoi(indx); + indx++; + indx = strchr(indx, '-'); + indx++; + dataOut.httpTime.Day = atoi(indx); + indx = strchr(indx, ' '); + indx++; + dataOut.httpTime.Hour = atoi(indx); + indx = strchr(indx, ':'); + indx++; + dataOut.httpTime.Min = atoi(indx); + indx++; + indx = strchr(indx, ':'); + indx++; + dataOut.httpTime.Sec = atoi(indx); + + LogInfo("http time is %d-%d-%d-%d-%d-%d\r\n", + dataOut.httpTime.Year, dataOut.httpTime.Mon, dataOut.httpTime.Day, dataOut.httpTime.Hour, dataOut.httpTime.Min, dataOut.httpTime.Sec); + SINT32 sec = 0; + sec = sf_get_seconds(dataOut.httpTime); // 28800000 + sec += stLoginAcmResponse.offset / 1000; + sf_get_date(sec, &dataOut.httpTime); + LogInfo("dataOut.httpTime is %d-%d-%d-%d-%d-%d\r\n", + dataOut.httpTime.Year, dataOut.httpTime.Mon, dataOut.httpTime.Day, dataOut.httpTime.Hour, dataOut.httpTime.Min, dataOut.httpTime.Sec); + cJSON_Delete(json); + return ret; +} +SINT32 ACMServersHandle::SendFilesAnlysis(char *recvData) +{ + char *p = nullptr; + char *out = nullptr; + cJSON *json = nullptr; + cJSON *first = nullptr; + cJSON *second = nullptr; + cJSON *third = nullptr; + SINT32 ret = 0; + SINT8 index = 0; + SF_REPORT_FILE_ATTR_S *pSubReportFileAttr = &SubReportFileAttr; + + // ret = http_response_status_code((char *)param->databuf); + ret = ResponseStatusCode(recvData); + if (ret == SF_FAILURE) + { + LogError("Recv error.\n"); + // return SF_DATA_ERROR_REQUEST; // TODO: + return SF_FAILURE; + } + + p = strchr(recvData, '{'); + json = cJSON_Parse(p); + if (!json) + { + LogInfo("Error before: [%s]\n", cJSON_GetErrorPtr()); + cJSON_Delete(json); + // return SF_DATA_ERROR_DATA_FORMAT; //TODO: + return SF_FAILURE; + } + + first = cJSON_GetObjectItem(json, "code"); + LogInfo("...code = %d\n", first->valueint); + + first = cJSON_GetObjectItem(json, "errCode"); + ret = first->valueint; + LogInfo("...errCode = %d\n", first->valueint); + + first = cJSON_GetObjectItem(json, "data"); + second = cJSON_GetObjectItem(first, "otaCommand"); + if (second != nullptr) + { + stLoginAcmResponse.otaCommand = second->valueint; + LogInfo("...otaCommand = %d\n", stLoginAcmResponse.otaCommand); + } + + second = cJSON_GetObjectItem(first, "downloadUrl"); + if (second->valuestring != nullptr) + { + memset(stLoginAcmResponse.downloadUrl, '\0', sizeof(stLoginAcmResponse.downloadUrl)); + sf_http_decrypt(second->valuestring, stLoginAcmResponse.downloadUrl, strlen(second->valuestring)); + LogInfo("...downloadUrl = %s\n", stLoginAcmResponse.downloadUrl); + } + + second = cJSON_GetObjectItem(first, "hdCommand"); + if (second != nullptr) + { + stLoginAcmResponse.hdCommand = second->valueint; + LogInfo("...hdCommand = %d\n", stLoginAcmResponse.hdCommand); + } + + if ((stLoginAcmResponse.hdCommand > 0) && (stLoginAcmResponse.hdCommand < 100)) + { + second = cJSON_GetObjectItem(first, "hdPhototVOList"); + SINT8 i = pSubReportFileAttr->filecnt; + for (index = 0; index < stLoginAcmResponse.hdCommand; index++) + { + third = cJSON_GetArrayItem(second, index); + pSubReportFileAttr->stSendFileAttr[i].enFileTye = (SF_FILE_TYPE_E)cJSON_GetObjectItem(third, "fileType")->valueSINT32; + sprintf(pSubReportFileAttr->stSendFileAttr[i].SubFileName, "%s", cJSON_GetObjectItem(third, "fileName")->valuestring); + + LogInfo("enFileTye:%d, SubFileName:%s\n", + pSubReportFileAttr->stSendFileAttr[i].enFileTye, + pSubReportFileAttr->stSendFileAttr[i].SubFileName); + i++; + pSubReportFileAttr->filecnt = i; + } + LogInfo("filecnt:%d\n", pSubReportFileAttr->filecnt); + } + + cJSON_Delete(json); + free(out); + + return ret; +} +SINT32 ACMServersHandle::SyncFileAnlysis(char *recvData, SyncResult &result) +{ + int ret = 0; + char *p = nullptr; + char *out = nullptr; + cJSON *json = nullptr; + cJSON *first = nullptr; + ret = ResponseStatusCode(recvData); + if (ret == SF_FAILURE) + { + LogError("Recv error.\n"); + // dataOut.mIsLogin = false; + // return SF_DATA_ERROR_REQUEST; // TODO: + return SF_FAILURE; + } + p = strchr(recvData, '{'); + json = cJSON_Parse(p); + if (!json) + { + LogInfo("Error before: [%s]\n", cJSON_GetErrorPtr()); + cJSON_Delete(json); + // return SF_DATA_ERROR_DATA_FORMAT;// TODO: + return SF_FAILURE; + } + first = cJSON_GetObjectItem(json, "code"); + LogInfo("...code = %d\n", first->valueint); + + first = cJSON_GetObjectItem(json, "errCode"); + LogInfo("...errCode = %d\n", first->valueint); + if (first->valueint != 0) + { + HttpServers::data_error_collection(first->valueint); + cJSON_Delete(json); + return SF_FAILURE; + } + + first = cJSON_GetObjectItem(json, "msg"); + if (first) + { + LogInfo("...msg = %s\n", first->valuestring); + } + first = cJSON_GetObjectItem(json, "data"); + if (first) + { + out = cJSON_Print(first); + LogInfo("...out = %s\n", out); + if (!(strstr(out, "{") && strstr(out, "}"))) + { + result.ParaSync = SYNC_DOWNLOAD_FROM_SERVERS; + LogInfo("...ParaSync = %d\n", result.ParaSync); + return SF_FAILURE; + } + free(out); + } + + SyncFileAnlysisJson(first, result); + result.ParaSync = SYNC_UPLOAD_TO_SERVERS; + cJSON_Delete(json); + + LogInfo("...ParaSync = %d\n", result.ParaSync); + return SF_SUCCESS; +} +void ACMServersHandle::SyncFileAnlysisJson(cJSON *json, SyncResult &result) +{ + LogInfo("============================SyncFileAnlysisJson\n"); + char *out = nullptr; + cJSON *first = json; + cJSON *second = nullptr; + int ret = 0; + UINT8 temp = 0; + char *indx = nullptr; + Param did = GetParam(PARAM_DID); + Param batteryTpye = GetParam(PARAM_BATTERY_TYPE); + Param cameraMode = GetParam(PARAM_CAMERA_MODE); + Param flashLed = GetParam(PARAM_FLASH_LED); + Param sdLoop = GetParam(PARAM_SD_LOOP); + Param pirSwitch = GetParam(PARAM_PIR_SWITCH); + Param stampSwitch = GetParam(PARAM_STAMP_SWITCH); + Param imageSize = GetParam(PARAM_IMAGE_SIZE); + Param multiShot = GetParam(PARAM_NAME_MULTI_SHOT); + Param digitPirSensitivity = GetParam(PARAM_PIR_SENSITIVITY); + Param videoSize = GetParam(PARAM_VIDEO_SIZE); + Param videoLength = GetParam(PARAM_VIDEO_LENGTH); + Param DigitPirSensitivity = GetParam(PARAM_DIGIT_PIR_SENSITIVITY); + Param PirSensitivity = GetParam(PARAM_PIR_SENSITIVITY); + Param PirDelaySwitch = GetParam(PARAM_PIR_DELAY_SWITCH); + Param PirDelayTime = GetParam(PARAM_PIR_DELAY_TIME); + Param TimelapseSwitch = GetParam(PARAM_TIMELAPSE_SWITCH); + Param TimelapseTime = GetParam(PARAM_TIMELAPSE_TIME); + Param WorkTime1Switch = GetParam(PARAM_WORK_TIME_1_SWITCH); + Param WorkTime = GetParam(PARAM_WORK_TIME); + Param WorkTime2Switch = GetParam(PARAM_WORK_TIME_2_SWITCH); + Param dailyReportSwitch = GetParam(PARAM_DAILY_REPORT_SWITCH); + Param DailyReportTime = GetParam(PARAM_DAILY_REPORT_TIME); + + second = cJSON_GetObjectItem(first, "video"); + if (second) + { + result.CamMode = second->valueint - 1; + cameraMode.numberUInt = second->valueint - 1; + SetParam(cameraMode, PARAM_CAMERA_MODE); + LogInfo("...camera_mode = %d\n", result.CamMode); + } + + second = cJSON_GetObjectItem(first, "image"); + if (second) + { + result.ImgSize = second->valueint; + imageSize.numberUInt = second->valueint; + SetParam(imageSize, PARAM_IMAGE_SIZE); + LogInfo("...img_size = %d\n", result.ImgSize); + } + + second = cJSON_GetObjectItem(first, "multishot"); + if (second) + { + result.Multishot = second->valueint; + if (result.Multishot > 3) + { + result.Multishot = 3; + LogWarning("Multishot [%d] is more than [1,3],so default value [3]\n", second->valueint); + } + LogInfo("...multishot = %d\n", result.Multishot); + multiShot.numberUInt = result.Multishot; + SetParam(multiShot, PARAM_NAME_MULTI_SHOT); + } + + second = cJSON_GetObjectItem(first, "videoSize"); + if (second) + { + result.VideoSize = (second->valueint) - 1; + LogInfo("...video_size = %d\n", result.VideoSize); + videoSize.numberUInt = (second->valueint) - 1; + SetParam(videoSize, PARAM_VIDEO_SIZE); + } + + second = cJSON_GetObjectItem(first, "videoLength"); + if (second) + { + result.VideoLenth = second->valueint; + LogInfo("...video_lenth = %d\n", result.VideoLenth); + videoLength.numberUInt = second->valueint; + SetParam(videoLength, PARAM_VIDEO_LENGTH); + } + + second = cJSON_GetObjectItem(first, "pirswitch"); + if (second) + { + result.PirSwitch = second->valueint; + LogInfo("...pir_work_switch = %d\n", result.PirSwitch); + pirSwitch.numberUInt = second->valueint; + SetParam(pirSwitch, PARAM_PIR_SWITCH); + } + + second = cJSON_GetObjectItem(first, "pirsentivity"); + if (second) + { + result.DigitPirSensitivity = second->valueint; + result.PirSensitivity = HttpServers::sf_pir_to_digit_analog(result.DigitPirSensitivity); + LogInfo("...DigitPirSensitivity = %d\n", result.DigitPirSensitivity); + LogInfo("...pirsentivity = %d\n", result.PirSensitivity); + DigitPirSensitivity.numberUInt = second->valueint; + SetParam(DigitPirSensitivity, PARAM_DIGIT_PIR_SENSITIVITY); + PirSensitivity.numberUInt = result.PirSensitivity; + SetParam(PirSensitivity, PARAM_PIR_SENSITIVITY); + } + + second = cJSON_GetObjectItem(first, "delayFlag"); + if (second) + { + result.PirDelaySwitch = second->valueint; + LogInfo("...pir_delay_switch = %d\n", result.PirDelaySwitch); + PirDelaySwitch.numberUInt = second->valueint; + SetParam(PirDelaySwitch, PARAM_PIR_DELAY_SWITCH); + } + + second = cJSON_GetObjectItem(first, "delayValue"); + if (second) + { + indx = second->valuestring; + PirDelayTime.time.Hour = ((*indx++) - '0') * 10; + PirDelayTime.time.Hour += ((*indx++) - '0'); + PirDelayTime.time.Min = ((*indx++) - '0') * 10; + PirDelayTime.time.Min += ((*indx++) - '0'); + PirDelayTime.time.Sec = ((*indx++) - '0') * 10; + PirDelayTime.time.Sec += ((*indx++) - '0'); + LogInfo("...pir_delay_value = %s\n", second->valuestring); + SetParam(PirDelayTime, PARAM_PIR_DELAY_TIME); + } + + second = cJSON_GetObjectItem(first, "timelapseFlag"); + if (second) + { + result.TimelapseSwitch = second->valueint; + LogInfo("...timelapse_switch = %d\n", result.TimelapseSwitch); + TimelapseSwitch.numberUInt = second->valueint; + SetParam(TimelapseSwitch, PARAM_TIMELAPSE_SWITCH); + } + + second = cJSON_GetObjectItem(first, "timelapseValue"); // + if (second) + { + indx = second->valuestring; + TimelapseTime.time.Hour = ((*indx++) - '0') * 10; + TimelapseTime.time.Hour += ((*indx++) - '0'); + TimelapseTime.time.Min = ((*indx++) - '0') * 10; + TimelapseTime.time.Min += ((*indx++) - '0'); + TimelapseTime.time.Sec = ((*indx++) - '0') * 10; + TimelapseTime.time.Sec += ((*indx++) - '0'); + LogInfo("...timelapse_value = %s\n", second->valuestring); + SetParam(TimelapseTime, PARAM_TIMELAPSE_TIME); + } + + second = cJSON_GetObjectItem(first, "timerFlag"); + if (second) + { + result.WorkTime1Switch = second->valueint; + LogInfo("...work_timer1_swtich = %d\n", result.WorkTime1Switch); + WorkTime1Switch.numberUInt = second->valueint; + SetParam(WorkTime1Switch, PARAM_WORK_TIME_1_SWITCH); + } + + second = cJSON_GetObjectItem(first, "timerValue"); + if (second) + { + indx = second->valuestring; + WorkTime.workTime[0].StartTime.Hour = ((*indx++) - '0') * 10; + WorkTime.workTime[0].StartTime.Hour += ((*indx++) - '0'); + WorkTime.workTime[0].StartTime.Min = ((*indx++) - '0') * 10; + WorkTime.workTime[0].StartTime.Min += ((*indx++) - '0'); + indx++; + WorkTime.workTime[0].StopTime.Hour = ((*indx++) - '0') * 10; + WorkTime.workTime[0].StopTime.Hour += ((*indx++) - '0'); + WorkTime.workTime[0].StopTime.Min = ((*indx++) - '0') * 10; + WorkTime.workTime[0].StopTime.Min += ((*indx++) - '0'); + LogInfo("...work time1 start, h:%d, m:%d\r\n", WorkTime.workTime[0].StartTime.Hour, WorkTime.workTime[0].StartTime.Min); + LogInfo("...work time1 stop, h:%d, m:%d\r\n", WorkTime.workTime[0].StopTime.Hour, WorkTime.workTime[0].StopTime.Min); + LogInfo("...work_timer1_value = %s\n", second->valuestring); + } + + second = cJSON_GetObjectItem(first, "timerFlag2"); + if (second) + { + result.WorkTime2Switch = second->valueint; + LogInfo("...work_timer2_swtich = %d\n", result.WorkTime2Switch); + WorkTime2Switch.numberUInt = second->valueint; + SetParam(WorkTime2Switch, PARAM_WORK_TIME_2_SWITCH); + } + + second = cJSON_GetObjectItem(first, "timerValue2"); + if (second) + { + indx = second->valuestring; + WorkTime.workTime[1].StartTime.Hour = ((*indx++) - '0') * 10; + WorkTime.workTime[1].StartTime.Hour += ((*indx++) - '0'); + WorkTime.workTime[1].StartTime.Min = ((*indx++) - '0') * 10; + WorkTime.workTime[1].StartTime.Min += ((*indx++) - '0'); + indx++; + WorkTime.workTime[1].StopTime.Hour = ((*indx++) - '0') * 10; + WorkTime.workTime[1].StopTime.Hour += ((*indx++) - '0'); + WorkTime.workTime[1].StopTime.Min = ((*indx++) - '0') * 10; + WorkTime.workTime[1].StopTime.Min += ((*indx++) - '0'); + LogInfo("...work_timer2_value = %s\n", second->valuestring); + LogInfo("...work time2 start, h:%d, m:%d\r\n", WorkTime.workTime[1].StartTime.Hour, WorkTime.workTime[1].StartTime.Min); + LogInfo("...work time2 stop, h:%d, m:%d\r\n", WorkTime.workTime[1].StopTime.Hour, WorkTime.workTime[1].StopTime.Min); + } + + SetParam(WorkTime, PARAM_WORK_TIME); + second = cJSON_GetObjectItem(first, "batteryType"); + if (second) + { + result.BatteryType = second->valueint; + LogInfo("...battery_type = %d\n", result.BatteryType); + batteryTpye.numberUInt = second->valueint; + SetParam(batteryTpye, PARAM_BATTERY_TYPE); + } + + second = cJSON_GetObjectItem(first, "ledNumber"); + if (second) + { + result.FlashLed = second->valueint; + LogInfo("...flash_power = %d\n", result.FlashLed); + flashLed.numberUInt = second->valueint; + SetParam(flashLed, PARAM_FLASH_LED); + } + + second = cJSON_GetObjectItem(first, "stamp"); + if (second) + { + result.StampSwitch = second->valueint; + LogInfo("...water_stamp = %d\n", result.StampSwitch); + stampSwitch.numberUInt = second->valueint; + SetParam(stampSwitch, PARAM_STAMP_SWITCH); + } + + second = cJSON_GetObjectItem(first, "sdcycleFlag"); + if (second) + { + result.SdLoop = second->valueint; + LogInfo("...cycle_recording = %d\n", result.SdLoop); + sdLoop.numberUInt = second->valueint; + SetParam(sdLoop, PARAM_SD_LOOP); + } + + second = cJSON_GetObjectItem(first, "dailyreportFlag"); + if (second) + { + result.DailyReportswitch = second->valueint; + LogInfo("...dailyreportFlag = %d\n", result.DailyReportswitch); + dailyReportSwitch.numberUInt = second->valueint; + SetParam(dailyReportSwitch, PARAM_DAILY_REPORT_SWITCH); + } + + second = cJSON_GetObjectItem(first, "dailyreportValue"); // + if (second) + { + indx = second->valuestring; + DailyReportTime.time.Hour = ((*indx++) - '0') * 10; + DailyReportTime.time.Hour += ((*indx++) - '0'); + DailyReportTime.time.Min = ((*indx++) - '0') * 10; + DailyReportTime.time.Min += ((*indx++) - '0'); + LogInfo("...dailyreportValue = %s\n", second->valuestring); + LogInfo("...Hour = %d\n", DailyReportTime.time.Hour); + LogInfo("...Min = %d\n", DailyReportTime.time.Min); + SetParam(DailyReportTime, PARAM_DAILY_REPORT_TIME); + } + if (result.DailyReportswitch == 0) + { + if (DailyReportTime.time.Hour == 0 && + DailyReportTime.time.Min == 0) + { + result.GprsMode = 1; /*realtime*/ + } + else + { + result.GprsMode = 0; /*off*/ + } + } + else + { + + if ((DailyReportTime.time.Hour == 0) && (DailyReportTime.time.Min == 30)) + { + result.GprsMode = 2; + } + else if ((DailyReportTime.time.Hour == 1) && (DailyReportTime.time.Min == 0)) + { + result.GprsMode = 3; + } + else if ((DailyReportTime.time.Hour == 2) && (DailyReportTime.time.Min == 0)) + { + result.GprsMode = 4; + } + else if ((DailyReportTime.time.Hour == 3) && (DailyReportTime.time.Min == 0)) + { + result.GprsMode = 5; + } + else if ((DailyReportTime.time.Hour == 4) && (DailyReportTime.time.Min == 0)) + { + result.GprsMode = 6; + } + else if ((DailyReportTime.time.Hour == 6) && (DailyReportTime.time.Min == 0)) + { + result.GprsMode = 7; + } + else if ((DailyReportTime.time.Hour == 12) && (DailyReportTime.time.Min == 0)) + { + result.GprsMode = 8; + } + else if ((DailyReportTime.time.Hour == 24) && (DailyReportTime.time.Min == 0)) + { + result.GprsMode = 9; + } + } + LogInfo("...GprsMode = %d\n", result.GprsMode); +} +SINT32 ACMServersHandle::LoginPacketGrouping(const AcmServersData &data, std::string &packet) +{ + UINT8 signalStrength = 0; + SF_CHAR mcuVer[16] = {0}; + cJSON *usr; + std::stringstream packetOut; + + SF_STORE_ATTR_S storeattrs; + std::shared_ptr sdCard = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCard); + sdCard->GetInfo(storeattrs); + if (storeattrs.SDStatus != 0) + { + storeattrs.SDTotalSize = 0; + storeattrs.SDFree = 0; + } + // memset(pstdata->databuf, '\0', sizeof(pstdata->databuf)); + sprintf(mcuVer, "%d.%d.%d", (data.mMcuVersion & 0xff00) >> 8, data.mMcuVersion & 0x00ff, data.mMcuSubVersion); + if (data.mSignalLevel == NetworkSignal::LEVEL_3) // 4 + signalStrength = 31; + else if (data.mSignalLevel == NetworkSignal::LEVEL_2) // 3 + signalStrength = 13; + else if (data.mSignalLevel == NetworkSignal::LEVEL_1) // 2 + signalStrength = 7; + + usr = cJSON_CreateObject(); + + cJSON_AddStringToObject(usr, "imei", data.mIMEI.c_str()); + cJSON_AddStringToObject(usr, "iccid", data.mIccid.c_str()); + cJSON_AddNumberToObject(usr, "loginType", data.mStartupMode); + cJSON_AddStringToObject(usr, "sfVersion", data.mAppVersion.c_str()); + cJSON_AddStringToObject(usr, "fwVersion", data.mModuleSubVersion.c_str()); + cJSON_AddStringToObject(usr, "mcuVersion", mcuVer); + cJSON_AddStringToObject(usr, "carriers", data.mServiceProvider.c_str()); + + cJSON_AddNumberToObject(usr, "sdcapacity", storeattrs.SDTotalSize); + cJSON_AddNumberToObject(usr, "sdfree", storeattrs.SDFree); + cJSON_AddNumberToObject(usr, "sdPic", data.SdTotalFile); + + cJSON_AddNumberToObject(usr, "signalStrength", signalStrength); + cJSON_AddNumberToObject(usr, "fahrenheit", data.FcTemper - 22); + cJSON_AddNumberToObject(usr, "battery", data.BatRemainCap); + char *out = cJSON_Print(usr); + packetOut << "POST /AcmService/acmhttp/" << mServersVersion << "/devLogin" + " HTTP/1.1\r\n" + << "Host:" << data.mAcmIP << "\r\n" + << "Connection: keep-alive\r\n" + << "Content-Length: " << strlen(out) << "\r\n" + << "Content-Type: application/json\r\n\r\n" + << out; + free(out); + cJSON_Delete(usr); + packet = packetOut.str(); + return SF_SUCCESS; +} +SINT32 ACMServersHandle::FilesUploadedGrouping(const AcmLoginResult &login, const std::vector &results, std::string &packet) +{ + std::stringstream packetOut; + SF_CHAR ver[24] = {0}; + char *msg = nullptr; + // cJSON *jsonArray = cJSON_CreateArray(); + + // std::vector allData = results; + // std::vector::iterator iter; + // for (iter = allData.begin(); iter != allData.end();) + // { + // cJSON *ArrayItem0 = cJSON_CreateObject(); + // cJSON_AddStringToObject(ArrayItem0, "imei", mData.mIMEI.c_str()); + // cJSON_AddNumberToObject(ArrayItem0, "uploadType", 2); + // cJSON_AddNumberToObject(ArrayItem0, "type", (*iter).mFile.enFileTye); + // cJSON_AddNumberToObject(ArrayItem0, "fileSize", (*iter).mFile.thumbfileSize); + // cJSON_AddStringToObject(ArrayItem0, "data", (*iter).mFile.mSendFileWithTime.c_str()); + // cJSON_AddStringToObject(ArrayItem0, "bindFile", (*iter).mFile.mBindFile.c_str()); + // cJSON_AddNumberToObject(ArrayItem0, "code", static_cast((*iter).mResult)); + // cJSON_AddNumberToObject(ArrayItem0, "did", login.Did); + // cJSON_AddItemToArray(jsonArray, ArrayItem0); + // ++iter; + // } + cJSON *jsonArray = MallocPacketOfSendFileResult(login, results); + + msg = cJSON_Print(jsonArray); + cJSON_Delete(jsonArray); + + SF_STORE_ATTR_S storeattrs; + std::shared_ptr sdCard = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCard); + sdCard->GetInfo(storeattrs); + if (storeattrs.SDStatus != 0) + { + storeattrs.SDTotalSize = 0; + storeattrs.SDFree = 0; + } + packetOut << "POST /AcmService/acmhttp/" << mServersVersion << "/fileResultReport?" + << "sdcapacity=" << storeattrs.SDTotalSize + << "&sdfree=" << storeattrs.SDFree + << "&sdPic=" << mData.SdTotalFile + << "&fahrenheit=" << mData.FcTemper - 22 + << "&sfVersion=" << mData.mAppVersion + << "&signalStrength=" << static_cast(mData.mSignalLevel) + << "&battery=" << static_cast(mData.BatRemainCap) + << " HTTP/1.1\r\n" + << "Host:" << mData.mAcmIP << "\r\n" + << "token:" << login.Token << "\r\n" + << "Connection: keep-alive\r\n" + << "Content-Length: " << strlen(msg) << "\r\n" + << "Content-Type: application/json\r\n\r\n" + << msg; + free(msg); + packet = packetOut.str(); + return 0; +} +cJSON *ACMServersHandle::MallocPacketOfSendFileResult(const AcmLoginResult &login, const std::vector &results) +{ + SF_CHAR ver[24] = {0}; + char *msg = nullptr; + cJSON *jsonArray = cJSON_CreateArray(); + + std::vector allData = results; + std::vector::iterator iter; + for (iter = allData.begin(); iter != allData.end();) + { + cJSON *ArrayItem0 = cJSON_CreateObject(); + cJSON_AddStringToObject(ArrayItem0, "imei", mData.mIMEI.c_str()); + cJSON_AddNumberToObject(ArrayItem0, "uploadType", 2); + cJSON_AddNumberToObject(ArrayItem0, "type", (*iter).mFile.enFileTye); + cJSON_AddNumberToObject(ArrayItem0, "fileSize", (*iter).mFile.thumbfileSize); + cJSON_AddStringToObject(ArrayItem0, "data", (*iter).mFile.mSendFileWithTime.c_str()); + cJSON_AddStringToObject(ArrayItem0, "bindFile", (*iter).mFile.mBindFile.c_str()); + cJSON_AddNumberToObject(ArrayItem0, "code", static_cast((*iter).mResult)); + cJSON_AddNumberToObject(ArrayItem0, "did", login.Did); + cJSON_AddItemToArray(jsonArray, ArrayItem0); + ++iter; + } + return jsonArray; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandle.h b/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandle.h new file mode 100644 index 000000000..9e8932535 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandle.h @@ -0,0 +1,158 @@ +#ifndef ACM_SERVERS_HANDLE_H +#define ACM_SERVERS_HANDLE_H +#include "INetworkManager.h" +#include "HttpServers.h" +#include "SfTypeDefine.h" +#include "ISystemTime.h" +#include "cJSON.h" +#include +constexpr int USER_BIND = 1; +constexpr int USER_NOT_BIND = 0; +constexpr int SYNC_DOWNLOAD_FROM_SERVERS = 0; +constexpr int SYNC_UPLOAD_TO_SERVERS = 1; +// constexpr int NEED_TO_UPLOAD_TO_SERVERS = 0; +typedef struct +{ + int devResetCommand; // + int hdCommand; // + int offset; // + int otaCommand; // + int resetUrlCommand; // + int sdFormatCommand; // + int synConfigCommand; // + int logCommand; // + int leftOverPic; + int getPic; + int RegionalChange; + char date[32]; // + char downloadUrl[160]; // + char ip[24]; // + char name[32]; // + char passwd[48]; // + char port[32]; // + char serverIp[24]; // + char url[64]; // + char userEmail[16]; // + char uuid[13]; // + char p2pId[32]; + char p2pName[64]; + char p2pSecret[64]; +} LOGIN_ACM_RESPONSE_S; +#define SF_MAX_PIC_LEN 64 +typedef struct sf_SEND_FILE_ATTR_S +{ + SF_FILE_TYPE_E enFileTye; // upload sub hd or video file type; upload batch send thumb file type; + SF_CHAR SubFileName[SF_MAX_PIC_LEN]; // sub hd or video file name, use as bind file; when batch send thumb file, this is null. + SF_CHAR SendFileName[SF_MAX_PIC_LEN]; // upload sub hd or video file name; upload batch send thumb file name; + UINT32 SendFileSize; // upload sub hd or video file size; upload batch send thumb file size; + UINT32 SendRet; // 0:send success; other:error code + UINT8 SameFlag; + +} SF_SEND_FILE_ATTR_S; +typedef struct sf_REPORT_FILE_ATTR_S +{ + UINT8 filecnt; + SF_SEND_FILE_ATTR_S stSendFileAttr[100]; +} SF_REPORT_FILE_ATTR_S; +typedef struct SF_WORKTIME_S +{ + HttpTime StartTime; + HttpTime StopTime; +} SF_WORKTIME_S; +class SyncResult +{ +public: + SyncResult() + { + ParaSync = 0; + CamMode = 0; + ImgSize = 0; + Multishot = 0; + VideoSize = 0; + VideoLenth = 0; + PirSwitch = 0; + DigitPirSensitivity = 0; + PirSensitivity = 0; + PirDelaySwitch = 0; + WorkTime1Switch = 0; + BatteryType = 0; + FlashLed = 0; + StampSwitch = 0; + SdLoop = 0; + DailyReportswitch = 0; + GprsMode = 0; + WorkTime2Switch = 0; + } + ~SyncResult() + { + } + unsigned char ParaSync; + unsigned char CamMode; + unsigned char ImgSize; + unsigned char Multishot; + unsigned char VideoSize; + unsigned char VideoLenth; + unsigned char PirSwitch; + unsigned char DigitPirSensitivity; + unsigned char PirSensitivity; + unsigned char PirDelaySwitch; + HttpTime PirDelayTime; + unsigned char TimelapseSwitch; + HttpTime TimelapseTime; + unsigned char WorkTime1Switch; + SF_WORKTIME_S WorkTime[2]; + unsigned char BatteryType; + unsigned char FlashLed; + unsigned char StampSwitch; + unsigned char SdLoop; + unsigned char DailyReportswitch; + HttpTime DailyReportTime; + unsigned char GprsMode; + unsigned char WorkTime2Switch; +}; +typedef enum sf_VIDEO_SIZE_E +{ + SF_VIDEO_SIZE_1080 = 0, + SF_VIDEO_SIZE_720, + SF_VIDEO_SIZE_WVGA, + SF_VIDEO_SIZE_BUTT +} SF_VIDEO_SIZE_E; +class ACMServersHandle : public VAcmServersHandle, public HttpServers +{ +public: + ACMServersHandle(const AcmServersData &data); + virtual ~ACMServersHandle() = default; + static SINT32 GetDomainName(const char *url, char *host); + RETURN_CODE Login(AcmLoginResult &dataOut) override; + RETURN_CODE SyncConfig(void) override; + RETURN_CODE GetLoginDate(AcmLoginResult &data) override; + RETURN_CODE SendFileResult(const std::vector &results) override; + +protected: + virtual cJSON *MallocPacketOfSync(const AcmLoginResult &loginData, const unsigned int &modiyFlay); + virtual cJSON *MallocPacketOfSendFileResult(const AcmLoginResult &login, const std::vector &results); + virtual void SyncFileAnlysisJson(cJSON *json, SyncResult &result); + +private: + SINT32 Transfer(const std::string &sendData, char *recvBuf, const unsigned int &recvBufLength); + SINT32 LoginRecvAnalysis(char *recvData, AcmLoginResult &dataOut); + SINT32 SendFilesAnlysis(char *recvData); + SINT32 SyncFileAnlysis(char *recvData, SyncResult &result); + SINT32 LoginPacketGrouping(const AcmServersData &data, std::string &packet); + SINT32 FilesUploadedGrouping(const AcmLoginResult &login, const std::vector &results, std::string &packet); + SINT32 sf_net_packetgrouping_sync(const AcmLoginResult &loginData, std::string &packet, const unsigned int &modiyFlay); + SINT32 debug_remotecontrol_packet(void); + SINT32 packet_gps_parse(char *pstring); + +protected: + std::string mServersVersion; + +protected: + const AcmServersData mData; + +private: + AcmLoginResult mLoginResponse; + LOGIN_ACM_RESPONSE_S stLoginAcmResponse; // TODO: 待优化,和AcmLoginResult重复 + SF_REPORT_FILE_ATTR_S SubReportFileAttr; +}; +#endif // !ACM_SERVERS_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandleV2.cpp b/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandleV2.cpp new file mode 100644 index 000000000..d97f22be2 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandleV2.cpp @@ -0,0 +1,70 @@ +#include "ACMServersHandleV2.h" +#include "IDualCoreManager.h" +#include "IPeripheralManager.h" +#include "FileManager.h" +#include "Log.h" +ACMServersHandleV2::ACMServersHandleV2(const AcmServersData &data) + : ACMServersHandle(data) +{ + mServersVersion = "v2"; +} +cJSON *ACMServersHandleV2::MallocPacketOfSync(const AcmLoginResult &loginData, const unsigned int &modiyFlay) +{ + cJSON *root = nullptr; + cJSON *preroot = nullptr; + preroot = cJSON_CreateObject(); + root = ACMServersHandle::MallocPacketOfSync(loginData, modiyFlay); + if (!preroot || !root) + { + return nullptr; + } + cJSON_AddItemToObject(preroot, "deviceSettingDTO", root); + cJSON_AddStringToObject(preroot, "token", loginData.Token.c_str()); + return preroot; +} +cJSON *ACMServersHandleV2::MallocPacketOfSendFileResult(const AcmLoginResult &login, const std::vector &results) +{ + cJSON *root = nullptr; + cJSON *preroot = nullptr; + preroot = cJSON_CreateObject(); + root = ACMServersHandle::MallocPacketOfSendFileResult(login, results); + if (!preroot || !root) + { + return nullptr; + } + SF_STORE_ATTR_S storeattrs; + std::shared_ptr sdCard = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCard); + sdCard->GetInfo(storeattrs); + if (storeattrs.SDStatus != 0) + { + storeattrs.SDTotalSize = 0; + storeattrs.SDFree = 0; + } + const int totalFileNum = sf_get_video_pic_num("/mnt/mmc/DCIM"); + // cJSON_AddItemToObject(preroot, "deviceSettingDTO", root); + // cJSON_AddStringToObject(preroot, "token", loginData.Token.c_str()); + cJSON_AddNumberToObject(preroot, "battery", IDualCoreManager::GetInstance()->GetBatRemainCap()); + cJSON_AddNumberToObject(preroot, "did", login.Did); + cJSON_AddNumberToObject(preroot, "fahrenheit", IDualCoreManager::GetInstance()->GetFcTemper() - 22); + cJSON_AddItemToObject(preroot, "fileDTOList", root); + + cJSON_AddNumberToObject(preroot, "sdcapacity", storeattrs.SDTotalSize); + cJSON_AddNumberToObject(preroot, "sdfree", storeattrs.SDFree); + cJSON_AddNumberToObject(preroot, "sdPic", totalFileNum); + cJSON_AddStringToObject(preroot, "sfVersion", mData.mAppVersion.c_str()); + cJSON_AddNumberToObject(preroot, "signalStrength", static_cast(mData.mSignalLevel)); + return preroot; +} +void ACMServersHandleV2::SyncFileAnlysisJson(cJSON *json, SyncResult &result) +{ + LogError("ACMServersHandleV2::SyncFileAnlysisJson.\n"); + cJSON *first = nullptr; + first = cJSON_GetObjectItem(json, "deviceSettingVO"); + if (!first) + { + LogError("ACMServersHandleV2::SyncFileAnlysisJson failed.\n"); + return; + } + ACMServersHandle::SyncFileAnlysisJson(first, result); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandleV2.h b/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandleV2.h new file mode 100644 index 000000000..f55076a98 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/ACMServersHandleV2.h @@ -0,0 +1,15 @@ +#ifndef ACM_SERVERS_HANDLE_V2_H +#define ACM_SERVERS_HANDLE_V2_H +#include "ACMServersHandle.h" +class ACMServersHandleV2 : public ACMServersHandle +{ +public: + ACMServersHandleV2(const AcmServersData &data); + virtual ~ACMServersHandleV2() = default; + +protected: + cJSON *MallocPacketOfSync(const AcmLoginResult &loginData, const unsigned int &modiyFlay) override; + cJSON *MallocPacketOfSendFileResult(const AcmLoginResult &login, const std::vector &results) override; + void SyncFileAnlysisJson(cJSON *json, SyncResult &result) override; +}; +#endif // !ACM_SERVERS_HANDLE_V2_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/AuthServersHandle.cpp b/code/application/sifarsdk/application/NetworkManager/src/AuthServersHandle.cpp new file mode 100644 index 000000000..1dd6ce190 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/AuthServersHandle.cpp @@ -0,0 +1,127 @@ +#include "AuthServersHandle.h" +#include "SfTypeDefine.h" +#include "Log.h" +#include "cJSON.h" +#include "sf_base64.h" +#include +AuthServersHandle::AuthServersHandle(const AuthRequestDataIn &dataIn) : HttpServers(dataIn.mWebIP), mDataIn(dataIn) +{ +} +RETURN_CODE AuthServersHandle::GetACMServersMessage(AuthRequestDataOut &data) +{ + LogInfo("AuthServersHandle::GetACMServersMessage.\n"); + constexpr unsigned int BUFFER_SIZE = 2048; + // mDataOut = data; + SF_CHAR data_buff[BUFFER_SIZE] = {0}; + SINT32 s32ret = SF_FAIL; + Create(); + s32ret = AuthPacket(); + if (s32ret != SF_SUCCESS) + { + Close(); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + + s32ret = Send(mAuthPacket.c_str(), mAuthPacket.length()); + if (s32ret < SF_SUCCESS) + { + Close(); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + Rece(data_buff, BUFFER_SIZE); + AuthResponseParse(data_buff); + data = mDataOut; + if (s32ret != SF_SUCCESS) + { + Close(); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + Close(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +SINT32 AuthServersHandle::AuthPacket(void) +{ + constexpr unsigned int BUFFER_SIZE = 2048; + SF_CHAR data_buff[BUFFER_SIZE] = {0}; + sprintf(data_buff, "POST /CameraManager/center/device/imeiAndMSisdn" + "?imei=%s&iccid=%s" + " HTTP/1.1\r\n" + "Host:%s\r\n" + "Connection: keep-alive\n" + "Content-Type: application/json\r\n\r\n", + mDataIn.mIMEI.c_str(), mDataIn.mIccid.c_str(), mDataIn.mWebIP.c_str()); + mAuthPacket = data_buff; + return SF_SUCCESS; +} +#define SF_DEV_NOT_EXIST 20002 +#define SF_DEV_NOT_BIND 20006 +SINT32 AuthServersHandle::AuthResponseParse(char *data) +{ + char *p = nullptr; + char *out = nullptr; + cJSON *json = nullptr; + cJSON *first = nullptr; + cJSON *second = nullptr; + cJSON *subListItem = nullptr; + SINT32 s32ret = SF_SUCCESS; + UINT16 index = 0; + SF_CHAR tempStr[128] = {0}; + SF_CHAR decode_tempStr[128] = {0}; + + s32ret = ResponseStatusCode(data); + + p = strchr(data, '{'); + json = cJSON_Parse(p); + if (!json) + { + LogError("Error before: [%s]\n", cJSON_GetErrorPtr()); + cJSON_Delete(json); + return SF_FAIL; + } + + first = cJSON_GetObjectItem(json, "statu"); + LogInfo("...code = %d\n", first->valueint); + first = cJSON_GetObjectItem(json, "errCode"); + LogInfo("...errCode = %d\n", first->valueint); + + if (first->valueint == 0) + { + first = cJSON_GetObjectItem(json, "msg"); + LogInfo("...msg = %s\n", first->valuestring); + first = cJSON_GetObjectItem(json, "content"); + out = cJSON_Print(first); + if (!strstr(out, "null")) + { + for (index = 0; index < 3; index++) + { + subListItem = cJSON_GetArrayItem(first, index); + if (cJSON_GetObjectItem(subListItem, "serverType")->valueSINT32 == 4) + { + second = cJSON_GetObjectItem(subListItem, "ip"); + memcpy(tempStr, second->valuestring, strlen(second->valuestring)); + + sf_base64_decode(tempStr, decode_tempStr); + + mDataOut.mAcmIP = decode_tempStr; + LogInfo("AcmIP = %s\n", mDataOut.mAcmIP.c_str()); + } + } + } + free(out); + } + else + { + s32ret = first->valueint; + if (first->valueint == SF_DEV_NOT_EXIST) + { + LogError("device does not exist\n"); + } + else if (first->valueint == SF_DEV_NOT_BIND) + { + LogError("Device not bound\n"); + } + } + + cJSON_Delete(json); + return s32ret; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/AuthServersHandle.h b/code/application/sifarsdk/application/NetworkManager/src/AuthServersHandle.h new file mode 100644 index 000000000..1b75dd811 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/AuthServersHandle.h @@ -0,0 +1,24 @@ +#ifndef AUTH_SERVERS_HANDLE_H +#define AUTH_SERVERS_HANDLE_H +#include "HttpServers.h" +#include "VReturnCode.h" +#include "INetworkManager.h" +#include "VAuthServers.h" +class AuthServersHandle : public HttpServers, public VAuthServers +{ +public: + AuthServersHandle(const AuthRequestDataIn &dataIn); + ~AuthServersHandle() = default; + RETURN_CODE GetACMServersMessage(AuthRequestDataOut &data) override; + +private: + SINT32 AuthPacket(void); + SINT32 AuthResponseParse(char *data); + +private: + // const std::string mWebIP; + const AuthRequestDataIn mDataIn; + std::string mAuthPacket; + AuthRequestDataOut mDataOut; +}; +#endif // !AUTH_SERVERS_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/FilesServersHandle.cpp b/code/application/sifarsdk/application/NetworkManager/src/FilesServersHandle.cpp new file mode 100644 index 000000000..c0179c432 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/FilesServersHandle.cpp @@ -0,0 +1,276 @@ +#include "FilesServersHandle.h" +#include "SfTypeDefine.h" +#include "RtcTimeCpp.h" +#include "Log.h" +#include "FileManager.h" +#include +#include +#include +#include +FilesServersHandle::FilesServersHandle(const FileServersData &data) + : HttpServers(data.mIP), mData(data) +{ + mUploadingRuning = false; +} +RETURN_CODE FilesServersHandle::UploadFile(UploadFileData &data) +{ + SINT16 s32ret = SF_FAILURE; + HttpFileAttr pstFileAttr; + memset(&pstFileAttr, 0, sizeof(HttpFileAttr)); + memcpy(pstFileAttr.thumbfileName, data.thumbfileName.c_str(), data.thumbfileName.length()); // TODO: Not safe here. + memcpy(pstFileAttr.thumbfilePath, data.thumbfilePath.c_str(), data.thumbfilePath.length()); // TODO: Not safe here. + pstFileAttr.thumbfileSize = data.thumbfileSize; + LogInfo("=================== thumbfileSize = %d\n", data.thumbfileSize); + pstFileAttr.enFileTye = data.enFileTye; + s32ret = AddHeader(&pstFileAttr, mData); + if (s32ret != SF_SUCCESS) + { + LogError("AddHeader failed.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + data.mSendFileWithTime = pstFileAttr.thumbfileName; + s32ret = FillTxt(&pstFileAttr); + if (s32ret != SF_SUCCESS) + { + LogError("FillTxt failed.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + s32ret = PushFileV2(&pstFileAttr); + if (s32ret != SF_SUCCESS) + { + LogError("push file failed!!!\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +// RETURN_CODE FilesServersHandle::UploadFiles(const std::vector &data) +// { +// std::lock_guard locker(mMutex); +// SINT32 s32ret = SF_SUCCESS; +// if (data.empty()) +// { +// LogWarning("Files is empty.\n"); +// } +// else +// { +// s32ret = HttpServers::Create(); +// if (s32ret != SF_SUCCESS) +// { +// LogError("Login failed\n"); +// return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); +// } +// std::vector allData = data; +// std::vector::iterator iter; +// for (iter = allData.begin(); iter != allData.end();) +// { +// UploadFile(*iter); +// sf_file_remove((*iter).thumbfilePath.c_str()); +// ++iter; +// } +// HttpServers::Close(); +// } +// return VReturnCode::NewCode(VReturnCodeDefine::OK); +// } +void FilesServersHandle::UploadingFiles(void) +{ + SINT32 s32ret = SF_SUCCESS; + s32ret = HttpServers::Create(); + if (s32ret != SF_SUCCESS) + { + LogError("HttpServers::Create() failed\n"); + return; + } + while (mUploadingRuning) + { + std::shared_ptr task = GetOneTaskToUpload(); + if (task) + { + UploadingFilesFromOneTask(task); + } + else + { + std::lock_guard locker(mMutex); + if (mTasks.size() == 0) + { + mUploadingRuning = false; + break; + } + } + } + HttpServers::Close(); +} +RETURN_CODE FilesServersHandle::UploadFiles(const std::shared_ptr &task) +{ + AddUploadTask(task); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +SINT32 FilesServersHandle::FillTxt(HttpFileAttr *pstFileAttr) +{ + SINT32 len = 0; + SF_CHAR *pBuf = NULL; + SF_CHAR *bufBak = NULL; + int readSize = 0; + UINT32 tolFileSize = 0; + SINT32 fdScrFile = 0; + SINT32 fdDstFile = 0; + fdScrFile = open(pstFileAttr->thumbfilePath, O_RDWR); /*open jpg file*/ + fdDstFile = open(pstFileAttr->txtfilePath, O_RDWR); /*open txt file*/ + tolFileSize = pstFileAttr->thumbfileSize; + LogInfo("tolFileSize = %d\n", tolFileSize); + LogInfo("thumbfilePath = %s\n", pstFileAttr->thumbfilePath); + LogInfo("txtfilePathName = %s\n", pstFileAttr->txtfilePath); + bufBak = (tolFileSize > MMZBLOCKSIZE) ? (SF_CHAR *)malloc(MMZBLOCKSIZE) : (SF_CHAR *)malloc(tolFileSize); + if (bufBak < 0) + { + LogError("malloc buf fail!\n"); + close(fdScrFile); + close(fdDstFile); + return SF_FAILURE; + } + lseek(fdDstFile, 0, SEEK_END); + while (tolFileSize > 0) + { + pBuf = bufBak; + readSize = (tolFileSize >= MMZBLOCKSIZE) ? read(fdScrFile, pBuf, MMZBLOCKSIZE) : read(fdScrFile, pBuf, tolFileSize); + if (readSize <= 0) + { + + LogError("read fail!\n"); + free(bufBak); + close(fdScrFile); + close(fdDstFile); + return SF_FAILURE; + } + tolFileSize -= readSize; + len = write(fdDstFile, pBuf, readSize); + if (len != readSize) + { + LogError("write fail!\n"); + free(bufBak); + close(fdScrFile); + close(fdDstFile); + return SF_FAILURE; + } + } + free(bufBak); + close(fdScrFile); + close(fdDstFile); + return SF_SUCCESS; +} +SINT32 FilesServersHandle::PushFileV2(HttpFileAttr *pstFileAttr) +{ + SINT32 s32ret = SF_SUCCESS; + SF_CHAR buf[HTTPCLIENT_REV_SIZE] = {0}; + s32ret = HttpPushFile(pstFileAttr); + if (s32ret != SF_SUCCESS) + { + // HttpServers::Close(); + LogError("push file failed!!!\n"); + return SF_FAILURE; + } + s32ret = HttpServers::Rece(buf, HTTPCLIENT_REV_SIZE); + if (s32ret <= 0) + { + LogError("recv innormal!!!"); + // HttpServers::Close(); + return SF_FAILURE; + } + LogInfo("recv buf:%s\n", buf); + return SF_SUCCESS; +} +SINT32 FilesServersHandle::HttpPushFile(HttpFileAttr *stFileAttr) +{ + SINT32 ret = SF_SUCCESS; + SINT32 fileFd = 0; + SINT32 tolFileSize = 0; + SINT32 readSize = 0; + struct stat statBuf; + SF_CHAR *pBuf = NULL; + SF_CHAR *bufBak = NULL; + fileFd = open(stFileAttr->txtfilePath, O_RDONLY); + if (fileFd < 0) + { + LogError("open file[%s] error!\n", stFileAttr->txtfilePath); + return SF_FAILURE; + } + fstat(fileFd, &statBuf); + tolFileSize = statBuf.st_size; + LogInfo("tolFileSize:%d\n", tolFileSize); + bufBak = (tolFileSize > 1024 * 1024 * 5) ? (SF_CHAR *)malloc(1024 * 1024 * 5) : (SF_CHAR *)malloc(tolFileSize); + if (bufBak == NULL) + { + LogError("malloc buf fail!\n"); + close(fileFd); + return SF_FAILURE; + } + while (tolFileSize > 0) + { + pBuf = bufBak; + readSize = (tolFileSize >= 1024 * 1024 * 5) ? read(fileFd, pBuf, 1024 * 1024 * 5) : read(fileFd, pBuf, tolFileSize); + LogInfo("send file data, tolFileSize:%d, read size:%d\n", tolFileSize, readSize); + tolFileSize -= readSize; + if (readSize < 0) + { + free(bufBak); + close(fileFd); + return SF_FAILURE; + } + ret = HttpServers::Send(pBuf, readSize); + if (ret < 0) + { + LogError("Connection error (send returned %d)\n", ret); + free(bufBak); + close(fileFd); + return ret; + } + } + free(bufBak); + close(fileFd); + LogInfo("SF_SUCCESS!\n"); + return SF_SUCCESS; +} +void FilesServersHandle::AddUploadTask(const std::shared_ptr &task) +{ + std::lock_guard locker(mMutex); + if (!mUploadingRuning) + { + LogInfo("Create uploading files thread.\n"); + mUploadingRuning = true; + auto uploadFilesThread = [](std::shared_ptr servers) + { + servers->UploadingFiles(); + }; + std::thread uploadThread(uploadFilesThread, shared_from_this()); + uploadThread.detach(); + } + mTasks.push_back(task); +} +std::shared_ptr FilesServersHandle::GetOneTaskToUpload(void) +{ + std::lock_guard locker(mMutex); + std::vector>::iterator iter; + if (mTasks.empty()) + { + LogInfo("mTasks is empty.\n"); + std::shared_ptr nullTask; + return nullTask; + } + LogInfo("There is one task need to be uploaded.\n"); + iter = mTasks.begin(); + std::shared_ptr tmp = *iter; + iter = mTasks.erase(iter); + return tmp; +} +bool FilesServersHandle::UploadingFilesFromOneTask(const std::shared_ptr &task) +{ + std::vector allData = task->GetFiles(); + std::vector::iterator iter; + for (iter = allData.begin(); iter != allData.end();) + { + // UploadFileData tmp = *iter; + UploadFile(*iter); + task->UploadResultResponse(*iter, UploadResult::SUCCEED); + ++iter; + } + return true; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/FilesServersHandle.h b/code/application/sifarsdk/application/NetworkManager/src/FilesServersHandle.h new file mode 100644 index 000000000..afede0d9b --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/FilesServersHandle.h @@ -0,0 +1,35 @@ +#ifndef FILES_SERVERS_HANDLE_H +#define FILES_SERVERS_HANDLE_H +#include "INetworkManager.h" +#include "HttpCommon.h" +#include "HttpServers.h" +#include +#include +#include +constexpr int MMZBLOCKSIZE = 1024; +constexpr int HTTPCLIENT_REV_SIZE = 512; +class FilesServersHandle : public VFileServersHandle, public HttpServers, public std::enable_shared_from_this +{ +public: + FilesServersHandle(const FileServersData &data); + ~FilesServersHandle() = default; + RETURN_CODE UploadFiles(const std::shared_ptr &task) override; + +private: + void UploadingFiles(void); + // RETURN_CODE UploadFiles(const std::vector &data); + RETURN_CODE UploadFile(UploadFileData &data); + SINT32 FillTxt(HttpFileAttr *pstFileAttr); + SINT32 PushFileV2(HttpFileAttr *pstFileAttr); + SINT32 HttpPushFile(HttpFileAttr *stFileAttr); + void AddUploadTask(const std::shared_ptr &task); + std::shared_ptr GetOneTaskToUpload(void); + bool UploadingFilesFromOneTask(const std::shared_ptr &task); + +private: + std::mutex mMutex; + const FileServersData mData; + std::vector> mTasks; + bool mUploadingRuning; +}; +#endif // !FILES_SERVERS_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/HttpServers.cpp b/code/application/sifarsdk/application/NetworkManager/src/HttpServers.cpp new file mode 100644 index 000000000..26bfe599f --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/HttpServers.cpp @@ -0,0 +1,235 @@ +#include "HttpServers.h" +#include "Log.h" +#include "HMACSHA.h" +#include "sf_aes.h" +#include "sf_base64.h" +#include +#include +#include +#include +#include +#include +#include +#include + +HttpServers::HttpServers(const std::string &hostName) : HttpBase(hostName) +{ +} +SINT32 HttpServers::ResponseStatusCode(char *data) +{ + char *p = nullptr; + constexpr int ACK_CODE_BUF_LENGTH = 4; + char ack[ACK_CODE_BUF_LENGTH] = {0}; + + p = strstr(data, "HTTP/1.1"); + if (!p) + { + LogError("Nullptr reponse.\n"); + return SF_FAILURE; + } + memcpy(ack, p + 9, ACK_CODE_BUF_LENGTH - 1); + switch (atoi(ack) / 100) + { + case 1: + LogInfo(">>>information corresponding\n"); + return SF_SUCCESS; + case 2: + LogInfo(">>>successful response\n"); + return SF_SUCCESS; + case 3: + LogInfo(">>>redirect message\n"); + return SF_SUCCESS; + case 4: + LogError(">>>Client error response\n"); + return SF_FAILURE; + case 5: + LogError(">>>server error response\n"); + return SF_FAILURE; + default: + LogError(">>>undefined error response\n"); + return SF_FAILURE; + } + + return SF_SUCCESS; +} +SINT32 HttpServers::data_error_collection(UINT32 valueint) +{ + switch (valueint) + { + case SF_SYS_ERR: + LogError("SF_SYS_ERR\n"); + break; + case SF_PARA_ERR: + LogError("SF_PARA_ERR\n"); + break; + case SF_DEV_NOT_EXIST: + LogError("SF_DEV_NOT_EXIST\n"); + break; + case SF_USER_NOT_EXIST: + LogError("SF_USER_NOT_EXIST\n"); + break; + case SF_SIM_NOT_EXIST: + LogError("SF_SIM_NOT_EXIST\n"); + break; + case SF_SIM_NET_NOT_TURN_ON: + LogError("SF_SIM_NET_NOT_TURN_ON\n"); + break; + case SF_SIM_DEV_NOT_BIND: + LogError("SF_SIM_DEV_NOT_BIND\n"); + break; + default: + LogError("undefined error\n!!!"); + break; + } + return SF_SUCCESS; +} +UINT16 HttpServers::sf_pir_to_digit_analog(UINT8 pirs) +{ + UINT16 pirlevel = 0; + + if (pirs > 7) + pirlevel = 0; + else if (pirs > 6) + pirlevel = 1; + else + pirlevel = 2; + + return pirlevel; +} +SINT32 HttpServers::AddHeader(HttpFileAttr *pstFileAttr, const FileServersData &serversData) +{ + if (!pstFileAttr) + { + LogError("Nullptr pointer.\n"); + return SF_FAILURE; + } + SINT32 s32Ret = SF_SUCCESS; + SINT16 i = 0; + SINT16 fd = 0; + SF_CHAR typestr[16] = {0}; + SF_CHAR httpstr[512] = {0}; + SF_CHAR objectName[128] = {0}; + SF_CHAR txtfilename[64] = {0}; + SF_CHAR txtfilePathName[128] = {0}; + SF_CHAR picfilename[36] = {0}; // src jpg file + SF_CHAR amzPw[128] = {0}; + SF_CHAR signatureStr[128] = {0}; + SF_CHAR timestr[64] = {0}; + int len = 0; + + LogInfo("pstFileAttr->enFileTye:%d\n", pstFileAttr->enFileTye); + LogInfo("pstFileAttr->thumbfileName:%s,%d\n", pstFileAttr->thumbfileName, strlen(pstFileAttr->thumbfileName)); + + const HttpTime time = GetTimezoneTime(serversData.mData.TimeZone); + LogInfo("System time is %d-%d-%d-%d-%d-%d\r\n", time.Year, time.Mon, time.Day, time.Hour, time.Min, time.Sec); + sprintf(timestr, "%d%02d%02d%02d%02d%02d", time.Year, time.Mon, time.Day, time.Hour, time.Min, time.Sec); + + if (pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_THUM_3M) + { + sprintf(objectName, "thumb_%s%s", timestr, pstFileAttr->thumbfileName); + sprintf(pstFileAttr->thumbfileName, "%s", objectName); // TODO: -Wformat-overflow= + sprintf(objectName, "%s/%s", serversData.mIMEI.c_str(), pstFileAttr->thumbfileName); + } + else + { + sprintf(objectName, "%s%s", timestr, pstFileAttr->thumbfileName); + sprintf(pstFileAttr->thumbfileName, "%s", objectName); + sprintf(objectName, "%s/%s", serversData.mIMEI.c_str(), pstFileAttr->thumbfileName); + } + + memcpy(picfilename, pstFileAttr->thumbfileName, strlen(pstFileAttr->thumbfileName) - 4); + sprintf(txtfilename, "%s.txt", picfilename); /*creat txt file name*/ + + sprintf(txtfilePathName, "%s%s", SF_SD_ROOT, txtfilename); /*creat txt file path*/ + + LogInfo("txtfilePathName =[%s]\n", txtfilePathName); + LogInfo("thumbfilePath =[%s]\n", pstFileAttr->thumbfilePath); + // s32Ret = sf_file_size_get(pstFileAttr->thumbfilePath, &pstFileAttr->thumbfileSize); + // if (pstFileAttr->thumbfileSize < 0 || s32Ret == SF_FAILURE) + // { + // LogError("thumbfilePath%s]: filesize error\n", pstFileAttr->thumbfilePath); + // return SF_FAILURE; + // } + + fd = open(txtfilePathName, O_CREAT | O_RDWR, 0); + if (fd <= 0) + { + LogError("create file [%s] failed\n", txtfilePathName); + return SF_FAILURE; + } + + if ((pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_THUM_3M) || (pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_THUM_5M) || + (pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_3M) || (pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_5M)) + sprintf(typestr, "image/JPG"); + else if ((pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_1080P) || (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_720P) || + (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_WVGA) || (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_THUM_1080P) || + (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_THUM_720P) || (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_THUM_WVGA)) + sprintf(typestr, "video/MOV"); + else if (pstFileAttr->enFileTye == SF_FILE_TYPE_GPS || pstFileAttr->enFileTye == SF_FILE_TYPE_TRIGGER || pstFileAttr->enFileTye == SF_FILE_TYPE_LOG_ERROR) + sprintf(typestr, "text/plain"); + + for (i = 0; i < 7; i++) + { + memset(httpstr, '\0', sizeof(httpstr)); + switch (i) + { + case 0: + sprintf(httpstr, "PUT /%s HTTP/1.1\r\n", objectName); + break; + case 1: + sprintf(httpstr, "Host: %s.%s\r\n", serversData.mData.szBucket.c_str(), AMZ_HOST); // s3 + break; + case 2: + sprintf(amzPw, "%s%s", AMZ_PW_TITLE, serversData.mData.szPassword.c_str()); + SignatureTime signatureTime; + signatureTime.Year = time.Year; + signatureTime.Mon = time.Mon; + signatureTime.Day = time.Day; + signatureTime.Hour = time.Hour; + signatureTime.Min = time.Min; + signatureTime.Sec = time.Sec; + amz_signature((UINT8 *)signatureStr, pstFileAttr->thumbfileSize, (UINT8 *)objectName, (UINT8 *)typestr, (UINT8 *)amzPw, + (UINT8 *)serversData.mData.szBucket.c_str(), (UINT8 *)serversData.mData.szIP.c_str(), signatureTime); + sprintf(httpstr, "Authorization: %s Credential=%s/%d%02d%02d/%s/%s/%s,SignedHeaders=content-length;content-type;host;x-amz-date,Signature=%s\r\n", + SECRET_TYPE, serversData.mData.szUsername.c_str(), time.Year, time.Mon, time.Day, + serversData.mData.szIP.c_str(), AMZ, SECRET_VER, signatureStr); + + break; + case 3: + sprintf(httpstr, "Content-Length: %d\r\n", pstFileAttr->thumbfileSize); + break; + case 4: + sprintf(httpstr, "Content-Type: %s\r\n", typestr); + break; + case 5: + sprintf(httpstr, "x-amz-date: %d%02d%02dT%02d%02d%02dZ\r\n", time.Year, time.Mon, time.Day, time.Hour, time.Min, time.Sec); + + break; + case 6: + sprintf(httpstr, "x-amz-content-sha256: UNSIGNED-PAYLOAD\r\n\r\n"); + break; + } + + len = write(fd, httpstr, strlen(httpstr)); + LogInfo("write result len = %d\n", len); + } + close(fd); + sync(); + + memset(pstFileAttr->txtfileName, '\0', sizeof(pstFileAttr->txtfileName)); + memset(pstFileAttr->txtfilePath, '\0', sizeof(pstFileAttr->txtfilePath)); + memcpy(pstFileAttr->txtfileName, txtfilename, strlen(txtfilename)); + memcpy(pstFileAttr->txtfilePath, txtfilePathName, strlen(txtfilePathName)); + + return s32Ret; +} +int HttpServers::sf_http_decrypt(char *src, char *dst, int len) +{ + constexpr int MBEDTLS_CIPHER_AES_128_CBC = 5; + constexpr int MBEDTLS_DECRYPT = 0; + char buf[256] = {0}; + UINT8 datalen = 0; + datalen = sf_base64_decode(src, buf); + datalen = sf_cipher(MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_DECRYPT, (UINT8 *)buf, (UINT8 *)dst, datalen); + return datalen; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/HttpServers.h b/code/application/sifarsdk/application/NetworkManager/src/HttpServers.h new file mode 100644 index 000000000..b21c0a8d0 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/HttpServers.h @@ -0,0 +1,55 @@ +#ifndef HTTP_SERVERS_H +#define HTTP_SERVERS_H +#include "SfTypeDefine.h" +#include "HttpCommon.h" +#include "IHalCommon.h" +#include "INetworkManager.h" +#include "ISystemTime.h" +#include "TimeHandle.h" +#include "HttpBase.h" +#include +constexpr int OBJECT_NAME_BUF_LEN = 128; +constexpr int NAME_LENGTH = 64; +constexpr int FILE_PATH_LENGTH = 128; + +#define SF_DEV_NOT_EXIST 20002 +#define SF_DEV_NOT_BIND 20006 +#define SF_SYS_ERR 1 +#define SF_PARA_ERR 3 +#define SF_USER_NOT_EXIST 10006 +#define SF_SIM_NOT_EXIST 30002 +#define SF_SIM_NET_NOT_TURN_ON 30004 +#define SF_SIM_DEV_NOT_BIND 20011 +// #define SF_DEV_DETAILS_NOT_VILLAGE 20009 +// #define SF_DEV_AUTH_INVALID 401 + +typedef struct sf_OSS_s +{ + UINT8 szIP[64]; + UINT8 szBucket[32]; + UINT8 szUsername[32]; + UINT8 szPassword[48]; +} SF_OSS_S; +typedef struct sf_FILE_ATTR_S +{ + SF_FILE_TYPE_E enFileTye; + SF_CHAR thumbfileName[NAME_LENGTH]; + SF_CHAR thumbfilePath[FILE_PATH_LENGTH]; + SF_CHAR txtfilePath[FILE_PATH_LENGTH]; + SF_CHAR txtfileName[NAME_LENGTH]; + UINT32 thumbfileSize; +} HttpFileAttr; +class HttpServers : public HttpBase, public TimeHandle +{ +public: + HttpServers(const std::string &hostName); + virtual ~HttpServers() = default; + +protected: + SINT32 ResponseStatusCode(char *data); + SINT32 AddHeader(HttpFileAttr *pstFileAttr, const FileServersData &serversData); + int sf_http_decrypt(char *src, char *dst, int len); + SINT32 data_error_collection(UINT32 valueint); + UINT16 sf_pir_to_digit_analog(UINT8 pirs); +}; +#endif // !HTTP_SERVERS_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/INetworkManager.cpp b/code/application/sifarsdk/application/NetworkManager/src/INetworkManager.cpp new file mode 100644 index 000000000..f2217ddd6 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/INetworkManager.cpp @@ -0,0 +1,29 @@ +#include "INetworkManager.h" +#include "Log.h" +#include +std::shared_ptr &INetworkManager::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/MobileModule.cpp b/code/application/sifarsdk/application/NetworkManager/src/MobileModule.cpp new file mode 100644 index 000000000..dadd905f1 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/MobileModule.cpp @@ -0,0 +1,69 @@ +#include "MobileModule.h" +#include "VReturnCode.h" +#include "IStateManager.h" +#include "INetworkManager.h" +#include "Log.h" +MobileModule::MobileModule() +{ + mNetworkHardware = std::make_shared(); +} +MobileModule::~MobileModule() +{ + mNetworkHardware = std::make_shared(); +} +RETURN_CODE MobileModule::Init() +{ + LogInfo("MobileModule::Init\n"); + IPeripheralManager::GetInstance()->GetNetworkModuleHandle(mNetworkHardware); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE MobileModule::UnInit() +{ + mNetworkHardware->UnInit(); + mNetworkHardware.reset(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +bool MobileModule::IsModuleWorking(void) +{ + return mNetworkHardware->IsModuleWorking(); +} +void MobileModule::LinkNetworkInit(SimInitCallback func) +{ + LogInfo("LinkNetworkInit, start to init the sim card.\n"); + mNetworkHardware->SimInit(func); +} +void MobileModule::RegisterNetwork(const RegisterNetworkType &type, RegisterNetworkCallback func) +{ + if (RegisterNetworkType::MANUAL == type) + { + mNetworkHardware->RegisterNetworkManual(func); + } + if (RegisterNetworkType::AUTO == type) + { + mNetworkHardware->RegisterNetworkAuto(func); + } +} +void MobileModule::NetApnConfig(void) +{ + auto netApnConfigCallback = [](const NetApnConfigDataOut &result) + { + LogInfo("MobileModule::NetApnConfig callback.\n"); + // TODO: What to do if failed?? + NetApnConfigResult apnResult = result.result; + if (NetApnConfigResult::SUCCEED == apnResult) + { + std::shared_ptr message = std::make_shared(StateEvent::APN_CONFIG_SUCCEED); + IStateManager::GetInstance()->SendStateMessage(message); + } + else + { + std::shared_ptr message = std::make_shared(StateEvent::APN_CONFIG_FAILED); + IStateManager::GetInstance()->SendStateMessage(message); + } + }; + mNetworkHardware->NetApnConfig(netApnConfigCallback); +} +void MobileModule::KeepAliveWithLiveServers(void) +{ + mNetworkHardware->KeepAliveForLive(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/MobileModule.h b/code/application/sifarsdk/application/NetworkManager/src/MobileModule.h new file mode 100644 index 000000000..139f6dbbc --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/MobileModule.h @@ -0,0 +1,22 @@ +#ifndef MOBILE_MODULE_H +#define MOBILE_MODULE_H +#include "VNetworkModule.h" +#include "IPeripheralManager.h" +#include "VAuthServers.h" +class MobileModule : public VNetworkModule +{ +public: + MobileModule(); + virtual ~MobileModule(); + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + bool IsModuleWorking(void) override; + void LinkNetworkInit(SimInitCallback func) override; + void RegisterNetwork(const RegisterNetworkType &type, RegisterNetworkCallback func) override; + void NetApnConfig(void) override; + void KeepAliveWithLiveServers(void) override; + +private: + std::shared_ptr mNetworkHardware; +}; +#endif // !MOBILE_MODULE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/NetworkManager.cpp b/code/application/sifarsdk/application/NetworkManager/src/NetworkManager.cpp new file mode 100644 index 000000000..327111746 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/NetworkManager.cpp @@ -0,0 +1,157 @@ +#include "NetworkManager.h" +#include "VReturnCode.h" +#include "NetworkManagerMakePtr.h" +#include "AuthServersHandle.h" +#include "IStateManager.h" +#include "Log.h" +#include "ACMServersHandle.h" +#include +NetworkManager::NetworkManager() +{ + mNetworkModule = std::make_shared(); +} +NetworkManager::~NetworkManager() +{ + mNetworkModule = std::make_shared(); +} +RETURN_CODE NetworkManager::Init() +{ + // TODO: What if create network module failed? + NetworkManagerMakePtr::GetInstance()->CreateNetworkModule(mNetworkModule); + mNetworkModule->Init(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManager::UnInit() +{ + mNetworkModule->UnInit(); + mNetworkModule.reset(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManager::NetworkHardwareIsWorking(void) +{ + if (mNetworkModule->IsModuleWorking()) + { + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + else + { + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } +} +RETURN_CODE NetworkManager::AuthRequest(const AuthRequestDataIn &dataIn, AuthRequestDataOut &dataOut) +{ + std::shared_ptr auth; + NetworkManagerMakePtr::GetInstance()->CreateAuthServers(auth, dataIn); + if (auth) + { + auth->GetACMServersMessage(dataOut); + // mParameter.mAcmIP = dataOut.mAcmIP; + mAuthRequestData = dataOut; + LogInfo("Auth servers ok, acm ip = %s\n", mAuthRequestData.mAcmIP.c_str()); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + else + { + LogError("NetworkManager::AuthRequest:Nullptr.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } +} +RETURN_CODE NetworkManager::GetParameter(NetworkParameter ¶m) +{ + param = mParameter; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManager::GetFileServersHandle(std::shared_ptr &servers, const FileServersData &data) +{ + auto code = NetworkManagerMakePtr::GetInstance()->CreateFileServers(servers, data); + return code; +} +RETURN_CODE NetworkManager::GetAcmServersHandle(std::shared_ptr &servers, const AcmServersData &data) +{ + AcmServersData acmData = data; + constexpr int IP_BUF_LENGTH = 32; + char acmip[IP_BUF_LENGTH] = {0}; + ACMServersHandle::GetDomainName(acmData.mAcmIP.c_str(), acmip); + acmData.mAcmIP = acmip; + auto code = NetworkManagerMakePtr::GetInstance()->CreateAcmServers(servers, acmData); + mAcmServers = servers; + return code; +} +RETURN_CODE NetworkManager::GetAcmServersHandle(std::shared_ptr &servers) +{ + servers = mAcmServers; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManager::KeepAliveWithLiveServers(void) +{ + mNetworkModule->KeepAliveWithLiveServers(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManager::LinkNetworkInit(void) +{ + auto simInitCallback = [](const SimInitDataOut &result) + { + LogInfo("module mIMEI = %s\n", result.mIMEI.c_str()); + LogInfo("module mModuleSubVersion = %s\n", result.mModuleSubVersion.c_str()); + LogInfo("module mIccid = %s\n", result.mIccid.c_str()); + LogInfo("module mType = %d\n", static_cast(result.mType)); + if (SimInitResult::SIM_INIT_OK == result.mResult) + { + std::shared_ptr message = std::make_shared(StateEvent::LINK_NETWORK_INIT_SUCCEED); + IStateManager::GetInstance()->SendStateMessage(message); + } + else + { + std::shared_ptr message = std::make_shared(StateEvent::LINK_NETWORK_INIT_FAILED); + IStateManager::GetInstance()->SendStateMessage(message); + // std::shared_ptr message = + // std::make_shared>(StateEvent::LINK_NETWORK_INIT_FAILED, result); + // IStateManager::GetInstance()->SendStateMessage(message); + } + std::dynamic_pointer_cast(INetworkManager::GetInstance())->LinkNetworkInitGetData(result); + }; + mNetworkModule->LinkNetworkInit(simInitCallback); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManager::RegisterNetwork(const RegisterNetworkType &type) +{ + auto registerNetworkCallback = [](const RegisterNetworkDataOut &result) + { + LogInfo("NetworkManager::RegisterNetwork callback.\n"); + if (RegisterNetworkResult::SUCCEED == result.result) + { + std::shared_ptr message = std::make_shared(StateEvent::REGISTER_NETWORK_SUCCEED); + IStateManager::GetInstance()->SendStateMessage(message); + } + else + { + std::shared_ptr message = std::make_shared(StateEvent::REGISTER_NETWORK_FAILED); + IStateManager::GetInstance()->SendStateMessage(message); + } + std::dynamic_pointer_cast(INetworkManager::GetInstance())->RegisterNetworkGetData(result); + std::dynamic_pointer_cast(INetworkManager::GetInstance())->NetApnConfig(); + }; + mNetworkModule->RegisterNetwork(type, registerNetworkCallback); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void NetworkManager::NetApnConfig(void) +{ + mNetworkModule->NetApnConfig(); +} +void NetworkManager::LinkNetworkInitGetData(const SimInitDataOut &data) +{ + mSimInitData = data; + mParameter.mIccid = data.mIccid; + mParameter.mIMEI = data.mIMEI; + mParameter.mModuleSubVersion = data.mModuleSubVersion; +} +void NetworkManager::RegisterNetworkGetData(const RegisterNetworkDataOut &data) +{ + std::map signalConvert; + signalConvert[SignalLevel::LEVEL_0] = NetworkSignal::LEVEL_0; + signalConvert[SignalLevel::LEVEL_1] = NetworkSignal::LEVEL_1; + signalConvert[SignalLevel::LEVEL_2] = NetworkSignal::LEVEL_2; + signalConvert[SignalLevel::LEVEL_3] = NetworkSignal::LEVEL_3; + mParameter.mSignalLevel = signalConvert[data.mSignalLevel]; + mParameter.mServiceProvider = data.mServiceProvider; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/NetworkManager.h b/code/application/sifarsdk/application/NetworkManager/src/NetworkManager.h new file mode 100644 index 000000000..14d3fa277 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/NetworkManager.h @@ -0,0 +1,33 @@ +#ifndef NETWORK_MANAGER_H +#define NETWORK_MANAGER_H +#include "INetworkManager.h" +#include "VNetworkModule.h" +#include +class NetworkManager : public INetworkManager +{ +public: + NetworkManager(); + virtual ~NetworkManager(); + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + RETURN_CODE NetworkHardwareIsWorking(void) override; + RETURN_CODE AuthRequest(const AuthRequestDataIn &dataIn, AuthRequestDataOut &dataOut) override; + RETURN_CODE LinkNetworkInit(void) override; + RETURN_CODE RegisterNetwork(const RegisterNetworkType &type) override; + RETURN_CODE GetParameter(NetworkParameter ¶m) override; + RETURN_CODE GetFileServersHandle(std::shared_ptr &servers, const FileServersData &data) override; + RETURN_CODE GetAcmServersHandle(std::shared_ptr &servers, const AcmServersData &data) override; + RETURN_CODE GetAcmServersHandle(std::shared_ptr &servers) override; + RETURN_CODE KeepAliveWithLiveServers(void) override; + void NetApnConfig(void); + void LinkNetworkInitGetData(const SimInitDataOut &data); + void RegisterNetworkGetData(const RegisterNetworkDataOut &data); + +private: + std::shared_ptr mNetworkModule; + NetworkParameter mParameter; + SimInitDataOut mSimInitData; + AuthRequestDataOut mAuthRequestData; + std::shared_ptr mAcmServers; +}; +#endif // !NETWORK_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/NetworkManagerMakePtr.cpp b/code/application/sifarsdk/application/NetworkManager/src/NetworkManagerMakePtr.cpp new file mode 100644 index 000000000..887ca38fd --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/NetworkManagerMakePtr.cpp @@ -0,0 +1,75 @@ +#include "NetworkManagerMakePtr.h" +#include "NetworkManager.h" +#include "Log.h" +#include "MobileModule.h" +#include "AuthServersHandle.h" +#include "FilesServersHandle.h" +#include "ACMServersHandleV2.h" +#include "HttpCommon.h" +#include +// #include +// #include +bool CreateNetworkManagerModule(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = NetworkManagerMakePtr::GetInstance()->CreateNetworkMachineInstance(instance); + if (code->IsCodeOK()) + { + LogInfo("Network manager instance is ok.\n"); + INetworkManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &NetworkManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + /** + * @brief + * The non-thread-safe changing is only for gtest. + */ + instance = *impl; + } + return instance; +} +RETURN_CODE NetworkManagerMakePtr::CreateNetworkMachineInstance(std::shared_ptr &instance) +{ + auto tmp = std::make_shared(); + if (tmp) + { + instance = std::move(tmp); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + LogError("Create network manager module failed.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::MAKE_SHARED_PTR_FAILED); +} +RETURN_CODE NetworkManagerMakePtr::CreateNetworkModule(std::shared_ptr &impl) +{ + auto tmp = std::make_shared(); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManagerMakePtr::CreateAuthServers(std::shared_ptr &impl, const AuthRequestDataIn &dataIn) +{ + auto tmp = std::make_shared(dataIn); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManagerMakePtr::CreateFileServers(std::shared_ptr &impl, const FileServersData &data) +{ + FileServersData serversData = data; + serversData.mIP = serversData.mData.szBucket; + serversData.mIP.append("."); + serversData.mIP.append(AMZ_HOST); + auto tmp = std::make_shared(serversData); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE NetworkManagerMakePtr::CreateAcmServers(std::shared_ptr &impl, const AcmServersData &data) +{ + auto tmp = std::make_shared(data); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/NetworkManagerMakePtr.h b/code/application/sifarsdk/application/NetworkManager/src/NetworkManagerMakePtr.h new file mode 100644 index 000000000..b2e95d2e2 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/NetworkManagerMakePtr.h @@ -0,0 +1,22 @@ +#ifndef NETWORK_MANAGER_MAKE_PTR_H +#define NETWORK_MANAGER_MAKE_PTR_H +#include "INetworkManager.h" +#include "VReturnCode.h" +#include "VNetworkModule.h" +#include "VAuthServers.h" +#include +class NetworkManagerMakePtr +{ +public: + NetworkManagerMakePtr() = default; + virtual ~NetworkManagerMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE CreateNetworkMachineInstance(std::shared_ptr &instance); + virtual RETURN_CODE CreateNetworkModule(std::shared_ptr &impl); + virtual RETURN_CODE CreateAuthServers(std::shared_ptr &impl, const AuthRequestDataIn &dataIn); + virtual RETURN_CODE CreateFileServers(std::shared_ptr &impl, const FileServersData &data); + virtual RETURN_CODE CreateAcmServers(std::shared_ptr &impl, const AcmServersData &data); +}; +#endif // !NETWORK_MANAGER_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/TimeHandle.cpp b/code/application/sifarsdk/application/NetworkManager/src/TimeHandle.cpp new file mode 100644 index 000000000..8ccfd901e --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/TimeHandle.cpp @@ -0,0 +1,126 @@ +#include "TimeHandle.h" +#include "Log.h" +UINT32 TimeHandle::sf_get_seconds(HttpTime rtc) +{ + UINT32 res = 0; + + UINT32 tempYear = rtc.Year; + UINT32 tempMon = rtc.Mon; + UINT32 tempDay = rtc.Day; + UINT32 tempHour = rtc.Hour; + UINT32 tempMin = rtc.Min; + UINT32 tempSec = rtc.Sec; + + if (tempMon <= 2) + { + tempMon += 10; + tempYear -= 1; + } + else + { + tempMon -= 2; + } + + /*LogInfo("----32 gprs_getSeconds---------%d/%d/%d %d:%d%d---------------------------------------\n", rtc.tmx_Year, rtc.tmx_mon, rtc.tmx_mday, rtc.tmx_hour, rtc.tmx_min, rtc.tmx_sec);*/ + + res = (UINT32)(tempYear / 4 - tempYear / 100 + tempYear / 400) + 367 * tempMon / 12 + tempDay + tempYear * 365 - 719499; + + /*LogInfo("----32 gprs_getSeconds---------res:%x----------%ld-----------------------------\n", res, res);*/ + + res = ((res * 24 + tempHour) * 60 + tempMin) * 60 + tempSec; + + /*LogInfo("-64 ---gprs_getSeconds---------res:%x----------%ld-----------------------------\n", res, res);*/ + return res; +} +void TimeHandle::sf_get_date(UINT32 second, HttpTime *ptmx) +{ + HttpTime tmx; + + split_year_day_std((int)(second / 86400), (int *)&tmx.Year, (int *)&tmx.Day); // TODO: 类型不匹配 + get_monthday(tmx.Day, isleap(tmx.Year), &tmx); + get_subtime(second % 86400, &tmx); + + LogInfo("-----After------%04d/%02d/%02d %02d:%02d:%02d-------------------------------------\n", + tmx.Year, tmx.Mon, tmx.Day, tmx.Hour, tmx.Min, tmx.Sec); + ptmx->Year = tmx.Year; + ptmx->Mon = tmx.Mon; + ptmx->Day = tmx.Day; + ptmx->Hour = tmx.Hour; + ptmx->Min = tmx.Min; + ptmx->Sec = tmx.Sec; +} +void TimeHandle::split_year_day_std(int days, int *year, int *day) +{ + int curr_day = get_yeardays(*year = 1970); + while (days >= curr_day) + { + days -= curr_day; + *year += 1; + curr_day = get_yeardays(*year); + } + *day = days; +} +int TimeHandle::get_yeardays(int year) +{ + if (isleap(year)) + return 366; + return 365; +} +int TimeHandle::isleap(int year) +{ + return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); +} +void TimeHandle::get_monthday(int day, int is_leap, HttpTime *tmx) +{ + int i, mons[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + if (is_leap) + mons[1] += 1; + for (i = 0; i < 12; ++i) + { + if (day < mons[i]) + { + tmx->Mon = i + 1; + tmx->Day = day + 1; + return; + } + day -= mons[i]; + } +} +void TimeHandle::get_subtime(int sec_in_day, HttpTime *tmx) +{ + tmx->Hour = sec_in_day / (60 * 60); + tmx->Min = sec_in_day % (60 * 60) / 60; + tmx->Sec = sec_in_day % 60; +} +void TimeHandle::TypeConversionOfTime(const HttpTime &timeIn, SystemTime &timeOut) +{ + // Don't use memcpy for uncoupled. + timeOut.Year = timeIn.Year; + timeOut.Mon = timeIn.Mon; + timeOut.Day = timeIn.Day; + timeOut.Hour = timeIn.Hour; + timeOut.Min = timeIn.Min; + timeOut.Sec = timeIn.Sec; +} +void TimeHandle::TypeConversionOfTime(const SystemTime &timeIn, HttpTime &timeOut) +{ + // Don't use memcpy for uncoupled. + timeOut.Year = timeIn.Year; + timeOut.Mon = timeIn.Mon; + timeOut.Day = timeIn.Day; + timeOut.Hour = timeIn.Hour; + timeOut.Min = timeIn.Min; + timeOut.Sec = timeIn.Sec; +} +const HttpTime TimeHandle::GetTimezoneTime(const char &timeZone) +{ + LogInfo("timeZone = %d\n", timeZone); + HttpTime result; + UINT32 second = 0; + SystemTime time = GetSystemTime(); + TypeConversionOfTime(time, result); + second = sf_get_seconds(result); + second -= timeZone * 3600; + sf_get_date(second, &result); + return result; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/TimeHandle.h b/code/application/sifarsdk/application/NetworkManager/src/TimeHandle.h new file mode 100644 index 000000000..18460aaea --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/TimeHandle.h @@ -0,0 +1,22 @@ +#ifndef TIME_HANDLE_H +#define TIME_HANDLE_H +#include "ISystemTime.h" +#include "SfTypeDefine.h" +#include "INetworkManager.h" +class TimeHandle +{ +public: + TimeHandle() = default; + virtual ~TimeHandle() = default; + UINT32 sf_get_seconds(HttpTime rtc); + void sf_get_date(UINT32 second, HttpTime *ptmx); + void split_year_day_std(int days, int *year, int *day); + int get_yeardays(int year); + int isleap(int year); + void get_monthday(int day, int is_leap, HttpTime *tmx); + void get_subtime(int sec_in_day, HttpTime *tmx); + void TypeConversionOfTime(const HttpTime &timeIn, SystemTime &timeOut); + void TypeConversionOfTime(const SystemTime &timeIn, HttpTime &timeOut); + const HttpTime GetTimezoneTime(const char &timeZone); +}; +#endif // !TIME_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/VAuthServers.h b/code/application/sifarsdk/application/NetworkManager/src/VAuthServers.h new file mode 100644 index 000000000..c2a5c3b9d --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/VAuthServers.h @@ -0,0 +1,11 @@ +#ifndef V_AUTH_SERVERS_H +#define V_AUTH_SERVERS_H +#include "VReturnCode.h" +class VAuthServers +{ +public: + VAuthServers() = default; + virtual ~VAuthServers() = default; + virtual RETURN_CODE GetACMServersMessage(AuthRequestDataOut &data) = 0; +}; +#endif // !V_AUTH_SERVERS_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/NetworkManager/src/VNetworkModule.h b/code/application/sifarsdk/application/NetworkManager/src/VNetworkModule.h new file mode 100644 index 000000000..996d22e20 --- /dev/null +++ b/code/application/sifarsdk/application/NetworkManager/src/VNetworkModule.h @@ -0,0 +1,20 @@ +#ifndef V_NETWORK_MODULE_H +#define V_NETWORK_MODULE_H +#include "VReturnCode.h" +#include "INetworkManager.h" +#include "IPeripheralManager.h" +#include +class VNetworkModule +{ +public: + VNetworkModule() = default; + virtual ~VNetworkModule() = default; + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual bool IsModuleWorking(void) { return false; } + virtual void LinkNetworkInit(SimInitCallback func) {} + virtual void RegisterNetwork(const RegisterNetworkType &type, RegisterNetworkCallback func) {} + virtual void NetApnConfig(void) {} + virtual void KeepAliveWithLiveServers(void) {} +}; +#endif // !V_NETWORK_MODULE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/README.md b/code/application/sifarsdk/application/README.md new file mode 100644 index 000000000..b0f18afe0 --- /dev/null +++ b/code/application/sifarsdk/application/README.md @@ -0,0 +1,4 @@ +# 应用层相关代码 +## 目录介绍 +main:主线程 \ +StateManger:状态管理模块 \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/CMakeLists.txt b/code/application/sifarsdk/application/StateManager/CMakeLists.txt new file mode 100644 index 000000000..79020c694 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/CMakeLists.txt @@ -0,0 +1,39 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${APPLICATION_SOURCE_PATH}/NetworkManager/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/StateMachineManager/include + ${COMPONENT_SOURCE_PATH}/CameraManager/include + ${COMPONENT_SOURCE_PATH}/DualCoreManager/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/SystemTime/include + ${COMPONENT_SOURCE_PATH}/FileManager/include + ${COMPONENT_SOURCE_PATH}/Config/include + ${COMPONENT_SOURCE_PATH}/McuManager/include + ${COMPONENT_SOURCE_PATH}/UpgradeManager/include + ${COMPONENT_SOURCE_PATH}/Qrcode/include + ${COMPONENT_SOURCE_PATH}/LiveManager/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME StateManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} StateMachineManager CameraManager NetworkManager DualCoreManager PeripheralManager McuManager LiveManager Qrcode ReturnCode Log) + diff --git a/code/application/sifarsdk/application/StateManager/include/IStateManager.h b/code/application/sifarsdk/application/StateManager/include/IStateManager.h new file mode 100644 index 000000000..5486dced7 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/include/IStateManager.h @@ -0,0 +1,123 @@ +#ifndef I_STATE_MANAGER_H +#define I_STATE_MANAGER_H +#include "VReturnCode.h" +#include +#include +/** + * @brief + * The return code of state machine module. + * Attention: StateMachineCodeDefineStr must be added one item when define one new code. + */ +enum class StateMachineCodeDefine +{ + INIT_FAIL = static_cast(VReturnCodeDefine::END), + AN_INITIALIZED_CODE, + STATE_MACHINE_INIT_FAILED, + END +}; +/** + * @brief + * The event need to be manager by state manager. + */ +enum class StateEvent +{ + STARTUP = 0, + LINK_NETWORK_SIM_INIT_SUCCEED, + LINK_NETWORK_SIM_INIT_FAILED, + LINK_NETWORK_INIT_SUCCEED, + LINK_NETWORK_INIT_FAILED, + REGISTER_NETWORK_SUCCEED, + REGISTER_NETWORK_FAILED, + APN_CONFIG_SUCCEED, + APN_CONFIG_FAILED, + LIVE_START_MEDIA, + LIVE_STOP_MEDIA, + STATE_EVENT_END +}; +enum class StartupMode +{ + STARTUP_MODE_OFF = 0, + STARTUP_MODE_ONKEY, + STARTUP_MODE_TIMELAPSE, + STARTUP_MODE_NORMAL, + STARTUP_MODE_RING, + STARTUP_MODE_PIR, + STARTUP_MODE_WARNING, + STARTUP_MODE_SERVER, + STARTUP_MODE_DP, + STARTUP_MODE_USB, + STARTUP_MODE_RESET, + STARTUP_MODE_SYN_PARAM, + STARTUP_MODE_BATCH_SEND, + STARTUP_MODE_BUTT, + STARTUP_MODE_END +}; +constexpr int RETRY_UNTIL_MANAGED = -1; // For VStateMessage::mRetryNumber +/** + * @brief + * Virtual class used to send message to state. + */ +class VStateMessage +{ +public: + VStateMessage(const StateEvent &event) : mEvent(event) + { + mRetryNumber = 0; + mDelay = 0; + } + virtual ~VStateMessage() = default; + const StateEvent mEvent; + /** + * @brief + * Retry for some important event, in case that the device is in the momentary state. + * Attention : Default to be 0, never abuse it, because it use more time to handl the message. + */ + int mRetryNumber; + /** + * @brief + * Handl the message after the delay time. + */ + unsigned int mDelay; + /** + * @brief + * The handl call back tell the sender the result of the event, use it if needed. + * bool - handled or not. + * std::shared_ptr - what is handled. + */ + std::function)> mFinalResult; +}; +/** + * @brief + * Never add any function in this class, just used for making any data and send to state. + * @tparam T + */ +template +class VStateMessageV2 : public VStateMessage +{ + +public: + VStateMessageV2(const StateEvent &event, T value) : VStateMessage(event), mData(value) + { + } + virtual ~VStateMessageV2() = default; + +public: + /** + * @brief + * 数据 + */ + T mData; +}; +class IStateManager +{ +public: + IStateManager() = default; + virtual ~IStateManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SendStateMessage(const std::shared_ptr &message) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE StartCameraStateMachine(const StartupMode &mode) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreateStateManager(void); +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/BatchSendState.cpp b/code/application/sifarsdk/application/StateManager/src/BatchSendState.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/application/StateManager/src/BatchSendState.h b/code/application/sifarsdk/application/StateManager/src/BatchSendState.h new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/application/StateManager/src/CameraFilesHandle.cpp b/code/application/sifarsdk/application/StateManager/src/CameraFilesHandle.cpp new file mode 100644 index 000000000..49506bd68 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraFilesHandle.cpp @@ -0,0 +1,17 @@ +#include "CameraFilesHandle.h" +CameraFilesHandle::CameraFilesHandle() +{ + mFileServers = std::make_shared(); +} +CameraFilesHandle::~CameraFilesHandle() +{ + mFileServers = std::make_shared(); +} +void CameraFilesHandle::InitFileServers(const std::string &IP) +{ + // INetworkManager::GetInstance()->GetFileServersHandle(mFileServers, IP); +} +void CameraFilesHandle::UploadFile(const CameraTaskResponse &file) +{ + // mFileServers->UploadFile(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraFilesHandle.h b/code/application/sifarsdk/application/StateManager/src/CameraFilesHandle.h new file mode 100644 index 000000000..ba2f66ba4 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraFilesHandle.h @@ -0,0 +1,19 @@ +#ifndef CAMERA_FILES_HANDLE_H +#define CAMERA_FILES_HANDLE_H +#include "ICameraManager.h" +#include "INetworkManager.h" +#include +class CameraFilesHandle +{ +public: + CameraFilesHandle(); + virtual ~CameraFilesHandle(); + +protected: + void InitFileServers(const std::string &IP); + void UploadFile(const CameraTaskResponse &file); + +private: + std::shared_ptr mFileServers; +}; +#endif // !CAMERA_FILES_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraMessage.cpp b/code/application/sifarsdk/application/StateManager/src/CameraMessage.cpp new file mode 100644 index 000000000..150671233 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraMessage.cpp @@ -0,0 +1,113 @@ +#include "CameraMessage.h" +#include "Log.h" +const bool NOT_EXECUTED = false; +const bool EXECUTED = true; +MessageHandle::MessageHandle() +{ + mEventHandle[InnerStateEvent::KEY_ACTION_HAPPENED] = + std::bind(&MessageHandle::KeyActionHandle, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::GPIO_INPUT_TRANSFORM] = + std::bind(&MessageHandle::GpioInputHandle, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::MCU_MESSAGE] = + std::bind(&MessageHandle::McuMessageHandle, this, std::placeholders::_1); +} +bool MessageHandle::EventHandle(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::map::iterator iter; + std::shared_ptr message = std::dynamic_pointer_cast(msg->GetMessageObj()); + InnerStateEvent event = static_cast(message->mMessage->mEvent); + iter = mEventHandle.find(event); + if (iter != mEventHandle.end()) + { + return mEventHandle[event](msg); + } + return NOT_EXECUTED; +} +bool MessageHandle::KeyActionHandle(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::map::iterator iter; + std::map::iterator iterKey; + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr> message = std::dynamic_pointer_cast>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + iterKey = mKeyClickHandle.find(message->mData.mKey); + if (iterKey != mKeyClickHandle.end() && SfKeyAction::SF_KEY_ACTION_SHORT_CLICK == message->mData.mKeyAction) + { + return mKeyClickHandle[message->mData.mKey](message->mData); + } + iterKey = mKeyHoldDownHandle.find(message->mData.mKey); + if (iterKey != mKeyHoldDownHandle.end() && (SfKeyAction::SF_KEY_ACTION_HOLD_DOWN == message->mData.mKeyAction)) + { + return mKeyHoldDownHandle[message->mData.mKey](message->mData); + } + iterKey = mKeyHoldUpHandle.find(message->mData.mKey); + if (iterKey != mKeyHoldUpHandle.end() && (SfKeyAction::SF_KEY_ACTION_HOLD_UP == message->mData.mKeyAction)) + { + return mKeyHoldUpHandle[message->mData.mKey](message->mData); + } + iter = mKeyActionHandle.find(message->mData.mKey); + if (iter != mKeyActionHandle.end()) + { + return mKeyActionHandle[message->mData.mKey](msg); + } + return NOT_EXECUTED; +} +bool MessageHandle::GpioInputHandle(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::map::iterator iter; + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr> message = std::dynamic_pointer_cast>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + iter = mGpioInputHandle.find(message->mData.mDevice); + if (iter != mGpioInputHandle.end()) + { + return mGpioInputHandle[message->mData.mDevice](msg); + } + return NOT_EXECUTED; +} +bool MessageHandle::McuMessageHandle(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::map::iterator iter; + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr>> message = + std::dynamic_pointer_cast>>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + iter = mMcuMessageHandle.find(message->mData->mEvent); + if (iter != mMcuMessageHandle.end()) + { + return mMcuMessageHandle[message->mData->mEvent](msg); + } + return NOT_EXECUTED; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraMessage.h b/code/application/sifarsdk/application/StateManager/src/CameraMessage.h new file mode 100644 index 000000000..0f4b0924e --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraMessage.h @@ -0,0 +1,130 @@ +#ifndef CAMERA_MESSAGE_H +#define CAMERA_MESSAGE_H +#include "IStateManager.h" +#include "IStateMachineManager.h" +#include "IPeripheralManager.h" +#include "ICameraManager.h" +#include "SfTypeDefine.h" +#include "IMcuManager.h" +#include "Log.h" +#include +#include +#include +using EventHandleFunc = std::function; +enum class InnerStateEvent +{ + STARTUP = static_cast(StateEvent::STATE_EVENT_END), + SIM_INIT, + SIM_INIT_TIME_OUT, + SIM_INIT_RETRY, + KEY_ACTION_HAPPENED, + GPIO_INPUT_TRANSFORM, + MCU_MESSAGE, + // CHECK_SD_CARD_BEFORE_POWER_OFF, + POWER_OFF_STATE_HOLD_TIME_OUT, + CAMERA_TASK_TIME_OUT, + CAMERA_TASK_FINISHED, + UPLOAD_FILES_VOLUNTARY, + UPLOAD_FILES_PASSIVE, + UPLOAD_FILE_ALL_FINISHED, + UPLOADING_FILE_TIME_OUT, + SUBSCRIBLE_UPLOAD_FILES, + ONKEY_IDLE_TIME_OUT, + SD_CARD_EVENT, + BATTERY_CHANGED_EVENT, + POWER_OFF_EVENT, + AUTO_SHUT_DOWN_START, + // KEY_RESET_LONG_PRESSING, // TODO: delete + NETWORK_MODULE_UPGRADE, + SD_CARD_FORMAT, + MSDC_MODE, + LIVE_SERVICE_INIT, + AUTH_AND_LOGIN, + INNER_STATE_EVENT_END +}; +enum class UpgradeType +{ + NETWORK_MODULE = 0, + MCU, + CPU, + END +}; +class KeyActionData +{ +public: + KeyActionData(const SfKeyDefine key, const unsigned int &holdTimeMs, const SfKeyAction &keyAction) + : mKey(key), mHoldTimeMs(holdTimeMs), mKeyAction(keyAction) + { + } + ~KeyActionData() = default; + const SfKeyDefine mKey; + const unsigned int mHoldTimeMs; + const SfKeyAction mKeyAction; +}; +using KeyHanldeFunc = std::function; +class GpioInputData +{ +public: + GpioInputData(const GpioDevice &device, const DeviceInput &input) + : mDevice(device), mInput(input) + { + } + ~GpioInputData() = default; + const GpioDevice mDevice; + const DeviceInput mInput; +}; +/** + * @brief + * Message class, used to send message to state machine module. + */ +class CameraMessage : public VMessageObject +{ +public: + CameraMessage(const std::shared_ptr &message) : mMessage(message) + { + } + virtual ~CameraMessage() = default; + const std::shared_ptr mMessage; // The message from users of state manager module. +}; +class MessageHandle +{ +public: + MessageHandle(); + virtual ~MessageHandle() = default; + bool EventHandle(VStateMachineMessage *msg); + virtual bool KeyActionHandle(VStateMachineMessage *msg); + bool GpioInputHandle(VStateMachineMessage *msg); + bool McuMessageHandle(VStateMachineMessage *msg); + + // protected: + // template + // bool GetMessageData(VStateMachineMessage *msg, T &data) + // { + // if (nullptr == msg) + // { + // LogError("nullptr pointer.\n"); + // return false; + // } + // std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + // std::shared_ptr> message = + // std::dynamic_pointer_cast>(cameraMessage->mMessage); + // if (!message) + // { + // LogError("nullptr pointer.\n"); + // return false; + // } + // data = message->mData; + // return true; + // } +protected: + std::map mEventHandle; + std::map mKeyActionHandle; + std::map mKeyClickHandle; + std::map mKeyHoldDownHandle; + std::map mKeyHoldUpHandle; + std::map mGpioInputHandle; + std::map mMcuMessageHandle; + +public: +}; +#endif // !CAMERA_MESSAGE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraStateMachine.cpp b/code/application/sifarsdk/application/StateManager/src/CameraStateMachine.cpp new file mode 100644 index 000000000..6642833e9 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraStateMachine.cpp @@ -0,0 +1,111 @@ +#include "CameraStateMachine.h" +#include "StateManagerCode.h" +#include "Log.h" +#include "IDualCoreManager.h" +#include "StateManagerMakePtr.h" +#include "IStateManager.h" +#include "IMcuManager.h" +#include +CameraStateMachine::CameraStateMachine() +{ + mStartupMode = StartupMode::STARTUP_MODE_END; +} +std::shared_ptr &CameraStateMachine::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + /** + * @brief + * The non-thread-safe changing is only for gtest. + */ + instance = *impl; + } + return instance; +} +RETURN_CODE CameraStateMachine::Init() +{ + LogInfo("State machine init.\n"); + auto code = IStateMachineManager::GetInstance()->CreateStateMachine(mStateMachine); + if (!code->IsCodeOK()) + { + return code; + } + if (!mStateMachine->InitialStateMachine()) + { + code = StateMachineCode::NewCode(StateMachineCodeDefine::STATE_MACHINE_INIT_FAILED); + LogError("State machine init failed.\n"); + return code; + } + std::shared_ptr mcuDevice = std::make_shared(); + IMcuManager::GetInstance()->GetMcuDevice(mcuDevice); + mStartupMode = static_cast(mcuDevice->GetStartupMode()); + LogInfo("CameraStateMachine::Init, mStartupMode mode = %d\n", static_cast(mStartupMode)); + IStateManager::GetInstance()->StartCameraStateMachine(mStartupMode); + return code; +} +RETURN_CODE CameraStateMachine::UnInit() +{ + mStateMachine->SwitchState(mAllStates[CameraStates::DEFAULT_STATE].get()); + mStateMachine->StopHandlerThread(); + mStateMachine = std::make_shared(); + mAllStates.clear(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraStateMachine::SendStateMessage(const std::shared_ptr &message) +{ + std::shared_ptr msg = std::make_shared(message); + mStateMachine->SendMessage(static_cast(message->mEvent), msg); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraStateMachine::MessageExecutedLater(const std::shared_ptr &message, int64_t delayTimeMs) +{ + std::shared_ptr msg = std::make_shared(message); + mStateMachine->MessageExecutedLater(static_cast(message->mEvent), msg, delayTimeMs); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void CameraStateMachine::StartCameraStateMachine(const StartupMode &mode) +{ + InitAllStates(mode); +} +void CameraStateMachine::SwitchState(const CameraStates &state) +{ + mStateMachine->SwitchState(mAllStates[state].get()); +} +void CameraStateMachine::StopTimer(int timerName) +{ + mStateMachine->StopTimer(timerName); +} +void CameraStateMachine::DelayMessage(VStateMachineMessage *msg) +{ + mStateMachine->DelayMessage(msg); +} +RETURN_CODE CameraStateMachine::InitAllStates(const StartupMode &mode) +{ + LogInfo("CameraStateMachine::InitAllStates.\n"); + mAllStates[CameraStates::DEFAULT_STATE] = StateManagerMakePtr::GetInstance()->CreateDefaultState(); + mAllStates[CameraStates::STARTUP_STATE] = StateManagerMakePtr::GetInstance()->CreateStartupState(mode); + mAllStates[CameraStates::PERIPHERAL_ABNORMAL_STATE] = StateManagerMakePtr::GetInstance()->CreatePeripheralAbnormalState(); + mAllStates[CameraStates::SIM_INIT_STATE] = StateManagerMakePtr::GetInstance()->CreateSimInitState(); + mAllStates[CameraStates::REGISTER_NETWORK_STATE] = StateManagerMakePtr::GetInstance()->CreateRegisterNetworkState(); + mAllStates[CameraStates::NETWORK_IDLE_STATE] = StateManagerMakePtr::GetInstance()->CreateNetworkIdleState(); + mAllStates[CameraStates::NETWORK_ANOMALY_STATE] = StateManagerMakePtr::GetInstance()->CreateNetworkAnomalyState(); + mAllStates[CameraStates::UPLOADING_STATE] = StateManagerMakePtr::GetInstance()->CreateUploadingState(); + mAllStates[CameraStates::UPGRADE_STATE] = StateManagerMakePtr::GetInstance()->CreateUpgradeState(); + mAllStates[CameraStates::POWER_OFF_STATE] = StateManagerMakePtr::GetInstance()->CreatePowerOffState(); + mAllStates[CameraStates::MSDC_STATE] = StateManagerMakePtr::GetInstance()->CreateMSDCState(); + mStateMachine->StatePlus(mAllStates[CameraStates::DEFAULT_STATE].get(), nullptr); + mStateMachine->StatePlus(mAllStates[CameraStates::PERIPHERAL_ABNORMAL_STATE].get(), mAllStates[CameraStates::DEFAULT_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::STARTUP_STATE].get(), mAllStates[CameraStates::DEFAULT_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::POWER_OFF_STATE].get(), mAllStates[CameraStates::DEFAULT_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::MSDC_STATE].get(), mAllStates[CameraStates::DEFAULT_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::SIM_INIT_STATE].get(), mAllStates[CameraStates::STARTUP_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::REGISTER_NETWORK_STATE].get(), mAllStates[CameraStates::STARTUP_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::NETWORK_IDLE_STATE].get(), mAllStates[CameraStates::STARTUP_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::NETWORK_ANOMALY_STATE].get(), mAllStates[CameraStates::STARTUP_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::UPLOADING_STATE].get(), mAllStates[CameraStates::STARTUP_STATE].get()); + mStateMachine->StatePlus(mAllStates[CameraStates::UPGRADE_STATE].get(), mAllStates[CameraStates::STARTUP_STATE].get()); + mStateMachine->SetFirstState(mAllStates[CameraStates::DEFAULT_STATE].get()); + mStateMachine->StartStateMachine(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraStateMachine.h b/code/application/sifarsdk/application/StateManager/src/CameraStateMachine.h new file mode 100644 index 000000000..356892bd3 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraStateMachine.h @@ -0,0 +1,56 @@ +#ifndef CAMERA_STATE_MACHINE_H +#define CAMERA_STATE_MACHINE_H +#include "VReturnCode.h" +#include "IStateMachineManager.h" +#include "IStateManager.h" +#include "CameraMessage.h" +#include +#include +/* Message Processed */ +// static const bool EXECUTED = true; +// #define EXECUTED true +/* The message is not processed. */ +// static const bool NOT_EXECUTED = false; +// #define NOT_EXECUTED false +const bool NOT_EXECUTED = false; +const bool EXECUTED = true; +enum class CameraStates +{ + DEFAULT_STATE = 0, + STARTUP_STATE, + SIM_INIT_STATE, + PERIPHERAL_ABNORMAL_STATE, + REGISTER_NETWORK_STATE, + NETWORK_IDLE_STATE, + NETWORK_ANOMALY_STATE, + UPLOADING_STATE, + UPGRADE_STATE, + POWER_OFF_STATE, + MSDC_STATE, + STATE_END +}; +class CameraStateMachine +{ +public: + CameraStateMachine(); + virtual ~CameraStateMachine() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + RETURN_CODE Init(); + RETURN_CODE UnInit(); + RETURN_CODE SendStateMessage(const std::shared_ptr &message); + RETURN_CODE MessageExecutedLater(const std::shared_ptr &message, int64_t delayTimeMs); + void StartCameraStateMachine(const StartupMode &mode); + void SwitchState(const CameraStates &state); + void StopTimer(int timerName); + void DelayMessage(VStateMachineMessage *msg); + const StartupMode GetStartupMode(void) { return mStartupMode; } + +private: + RETURN_CODE InitAllStates(const StartupMode &mode); + +private: + std::shared_ptr mStateMachine; + std::map> mAllStates; + StartupMode mStartupMode; +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraTaskHandle.cpp b/code/application/sifarsdk/application/StateManager/src/CameraTaskHandle.cpp new file mode 100644 index 000000000..d78fd97cb --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraTaskHandle.cpp @@ -0,0 +1,99 @@ +#include "CameraTaskHandle.h" +#include "CameraStateMachine.h" +#include "Log.h" +#include "IDualCoreManager.h" +#include "IConfig.h" +CameraTaskHandle::CameraTaskHandle(const CameraTaskType &type, const InnerStateEvent &bindStateEvent, const std::weak_ptr &owner) + : mType(type), mBindStateEvent(bindStateEvent), mOwner(owner) +{ + mFinished = true; +} +unsigned int CameraTaskHandle::TaskTimeOut(void) +{ + switch (mType) + { + case CameraTaskType::PICTURE: + { + return CAMERA_TASK_TIMEOUT_MS; + break; + } + case CameraTaskType::VIDEO: + { + return CAMERA_TASK_TIMEOUT_MS; + break; + } + case CameraTaskType::PICTURE_AND_VIDEO: + { + return CAMERA_TASK_TIMEOUT_MS; + break; + } + + default: + return 0; + break; + } +} +const signed int CameraTaskHandle::GetIsNight(void) +{ + return IDualCoreManager::GetInstance()->IsNight(); +} +const unsigned int CameraTaskHandle::GetIsMultShot(void) +{ + return GetParam(PARAM_NAME_MULTI_SHOT).numberUInt; +} +void CameraTaskHandle::Response(const std::vector &response) +{ + mAllResponse = response; + std::shared_ptr message = + std::make_shared>>(static_cast(InnerStateEvent::CAMERA_TASK_FINISHED), shared_from_this()); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} +std::shared_ptr CameraTaskHandle::GetOwner(void) +{ + std::shared_ptr owner = mOwner.lock(); + if (mOwner.expired()) + { + std::shared_ptr nullOwner; + return nullOwner; + } + return owner; +} +void CameraTaskHandle::OwnerFinishedTask(void) +{ + std::shared_ptr owner = mOwner.lock(); + if (mOwner.expired()) + { + return; + } + owner->TaskResponse(mAllResponse); +} +std::shared_ptr CameraTaskHandle::GetTaskHandleFromStateMachineMessage(VStateMachineMessage *msg) +{ + std::shared_ptr task; + if (nullptr == msg) + { + LogError("Nullptr pointer.\n"); + return task; + } + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr>> message = + std::dynamic_pointer_cast>>(cameraMessage->mMessage); + if (!message) + { + return task; + } + task = message->mData; + return task; +} +bool CameraTaskHandle::OwnerFinshTask(std::shared_ptr &owner, std::shared_ptr &task) +{ + if (owner) + { + task->OwnerFinishedTask(); + return true; + } + else + { + return false; + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraTaskHandle.h b/code/application/sifarsdk/application/StateManager/src/CameraTaskHandle.h new file mode 100644 index 000000000..81843d436 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraTaskHandle.h @@ -0,0 +1,52 @@ +#ifndef CAMERA_TASK_HANDLE_H +#define CAMERA_TASK_HANDLE_H +#include "ICameraManager.h" +#include "CameraMessage.h" +#include "IHalCommon.h" +#include "IStateMachineManager.h" +#include +constexpr int CAMERA_TASK_TIMEOUT_MS = 1000 * 60; +class VCameraTaskOwner +{ +public: + VCameraTaskOwner() = default; + virtual ~VCameraTaskOwner() = default; + virtual void TaskResponse(const std::vector &response) = 0; +}; +class CameraTaskHandle : public VCameraTask, public std::enable_shared_from_this +{ +public: + CameraTaskHandle(const CameraTaskType &type, const InnerStateEvent &bindStateEvent, const std::weak_ptr &owner); + ~CameraTaskHandle() = default; + virtual unsigned int TaskTimeOut(void); + const CameraTaskType GetTaskType(void) override { return mType; } + const signed int GetIsNight(void) override; + const unsigned int GetIsMultShot(void) override; + bool IsTaskFinished(void) override { return mFinished; } + void Response(const std::vector &response) override; + void SetTaskFinished(void) { mFinished = true; } + std::shared_ptr GetOwner(void); + void OwnerFinishedTask(void); + static std::shared_ptr GetTaskHandleFromStateMachineMessage(VStateMachineMessage *msg); + static bool OwnerFinshTask(std::shared_ptr &owner, std::shared_ptr &task); + +private: + const CameraTaskType mType; + const InnerStateEvent mBindStateEvent; + const std::weak_ptr mOwner; + bool mFinished; + CameraTaskResponse mResponseData; + std::vector mAllResponse; +}; +template +bool CameraTaskFinished(VStateMachineMessage *msg) +{ + std::shared_ptr task = CameraTaskHandle::GetTaskHandleFromStateMachineMessage(msg); + if (task) + { + std::shared_ptr owner = std::dynamic_pointer_cast(task->GetOwner()); + return CameraTaskHandle::OwnerFinshTask(owner, task); + } + return false; +} +#endif // !CAMERA_TASK_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraTaskMonitor.cpp b/code/application/sifarsdk/application/StateManager/src/CameraTaskMonitor.cpp new file mode 100644 index 000000000..dce4f1c3b --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraTaskMonitor.cpp @@ -0,0 +1,9 @@ +#include "CameraTaskMonitor.h" +#include "CameraStateMachine.h" +#include "StateCameraTask.h" +#include "Log.h" +void CameraTaskMonitor::Response(const std::vector &response) +{ + LogInfo("CameraTaskMonitor::Response.\n"); + StateCameraTask::UploadFilesToServers(response, InnerStateEvent::UPLOAD_FILES_PASSIVE); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/CameraTaskMonitor.h b/code/application/sifarsdk/application/StateManager/src/CameraTaskMonitor.h new file mode 100644 index 000000000..682ceb62d --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/CameraTaskMonitor.h @@ -0,0 +1,11 @@ +#ifndef CAMERA_TASK_MONITOR_H +#define CAMERA_TASK_MONITOR_H +#include "ICameraManager.h" +class CameraTaskMonitor : public VCameraTask, public std::enable_shared_from_this +{ +public: + CameraTaskMonitor() = default; + ~CameraTaskMonitor() = default; + void Response(const std::vector &response) override; +}; +#endif // !CAMERA_TASK_MONITOR_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/DefaultState.cpp b/code/application/sifarsdk/application/StateManager/src/DefaultState.cpp new file mode 100644 index 000000000..3c04dc526 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/DefaultState.cpp @@ -0,0 +1,327 @@ +#include "DefaultState.h" +#include "CameraStateMachine.h" +#include "INetworkManager.h" +#include "IPeripheralManager.h" +#include "Log.h" +#include "CameraTaskMonitor.h" +#include "IConfig.h" +DefaultState::DefaultState() : State("DefaultState") +{ + mNetworkModuleHandle = std::make_shared(); + mEventHandle[InnerStateEvent::STARTUP] = + std::bind(&DefaultState::StartupEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::SD_CARD_EVENT] = + std::bind(&DefaultState::SDCardEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::BATTERY_CHANGED_EVENT] = + std::bind(&DefaultState::BatteryEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::POWER_OFF_EVENT] = + std::bind(&DefaultState::PowerOffEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::UPLOAD_FILES_PASSIVE] = + std::bind(&DefaultState::UploadFilesPassiveEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::UPLOAD_FILES_VOLUNTARY] = + std::bind(&DefaultState::UploadFilesVoluntaryEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::SD_CARD_FORMAT] = + std::bind(&DefaultState::SDCardFormat, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::MSDC_MODE] = + std::bind(&DefaultState::MSDCModeHandle, this, std::placeholders::_1); + mMcuMessageHandle[McuEvent::STARTUP_MODE_CHANGED] = + std::bind(&DefaultState::McuStartupModeChanged, this, std::placeholders::_1); + mKeyActionHandle[SfKeyDefine::KEY_PIN_FORMAT] = + std::bind(&DefaultState::KeySDFormatHandle, this, std::placeholders::_1); + mGpioInputHandle[GpioDevice::USB] = + std::bind(&DefaultState::GpioUSBInput, this, std::placeholders::_1); +} +DefaultState::~DefaultState() +{ + mNetworkModuleHandle = std::make_shared(); +} +void DefaultState::GoInState() +{ + LogInfo("DefaultState::GoInState==================== in\n"); + IPeripheralManager::GetInstance()->SetKeyMonitor(shared_from_this()); + IPeripheralManager::GetInstance()->SetGpioMonitor(shared_from_this()); + IDualCoreManager::GetInstance()->SetBatteryMonitor(shared_from_this()); + std::shared_ptr mcuDevice = std::make_shared(); + IMcuManager::GetInstance()->GetMcuDevice(mcuDevice); + mcuDevice->SetMonitor(shared_from_this()); + SDCardInit(); + auto code = INetworkManager::GetInstance()->NetworkHardwareIsWorking(); + if (!code->IsCodeOK()) + { + LogError("Network module is not ok.\n"); + // CameraStateMachine::GetInstance()->SwitchState(CameraStates::PERIPHERAL_ABNORMAL_STATE); + } + std::shared_ptr camera = std::make_shared(); + std::shared_ptr cameraMonitor = std::make_shared(); + ICameraManager::GetInstance()->GetCameraHandle(CameraType::MAIN_CAMERA, camera); + camera->SetSpontaneousTaskMonitor(cameraMonitor); + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::STARTUP)); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} +void DefaultState::GoOutState() +{ + LogInfo("DefaultState::GoOutState==================== out\n"); + mNetworkModuleHandle->UnInit(); + if (mSDCardState) + { + mSDCardState->DeleteState(); + mSDCardState.reset(); + } + if (mPowerState) + { + mPowerState->DeleteState(); + mPowerState.reset(); + } +} +bool DefaultState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +RETURN_CODE DefaultState::KeyActionHappened(const SfKeyDefine &key, const SfKeyAction &event, const unsigned int holdTimeMs) +{ + LogInfo("DefaultState::KeyActionHappened key = %d, action = %d, holdTims = %d\n", static_cast(key), static_cast(event), holdTimeMs); + KeyActionData data(key, holdTimeMs, event); + std::shared_ptr message = + std::make_shared>(static_cast(InnerStateEvent::KEY_ACTION_HAPPENED), data); + CameraStateMachine::GetInstance()->SendStateMessage(message); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE DefaultState::InputTransform(const GpioDevice &gpio, const DeviceInput &input) +{ + LogInfo("DefaultState::InputTransform GPIO = %d, input = %d\n", static_cast(gpio), static_cast(input)); + GpioInputData data(gpio, input); + std::shared_ptr message = + std::make_shared>(static_cast(InnerStateEvent::GPIO_INPUT_TRANSFORM), data); + CameraStateMachine::GetInstance()->SendStateMessage(message); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE DefaultState::McuEventHapped(const std::shared_ptr &message) +{ + LogInfo("DefaultState::McuEventHapped.\n"); + std::shared_ptr mcuMessage = + std::make_shared>>(static_cast(InnerStateEvent::MCU_MESSAGE), message); + CameraStateMachine::GetInstance()->SendStateMessage(mcuMessage); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void DefaultState::ReportSDCardStatus(const SF_SD_STATUS_E &status) +{ + LogInfo("DefaultState::ReportSDCardStatus = %d.\n", static_cast(status)); + std::shared_ptr message = + std::make_shared>(static_cast(InnerStateEvent::SD_CARD_EVENT), status); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} +void DefaultState::BatteryChanged(const BatteryLevel &level) +{ + LogInfo("DefaultState::BatteryChanged.\n"); + std::shared_ptr message = + std::make_shared>(static_cast(InnerStateEvent::BATTERY_CHANGED_EVENT), level); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} +bool DefaultState::StartupEvent(VStateMachineMessage *msg) +{ + CameraStateMachine::GetInstance()->SwitchState(CameraStates::STARTUP_STATE); + return EXECUTED; +} +bool DefaultState::McuStartupModeChanged(VStateMachineMessage *msg) +{ + std::shared_ptr message = + std::make_shared(static_cast(InnerStateEvent::POWER_OFF_EVENT)); + CameraStateMachine::GetInstance()->SendStateMessage(message); + return EXECUTED; +} +bool DefaultState::SDCardEvent(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr> message = + std::dynamic_pointer_cast>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + const SF_SD_STATUS_E status = message->mData; + if (mSDCardState) + { + mSDCardState->DeleteState(); + } + switch (status) + { + case SD_MOUNT_SUCCESS: + { + mSDCardState = LedState::SetLedState(SfLedIndex::SF_LED_SD, SfLedState::SF_LED_STATE_GREEN, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + case SD_MOUNT_FAILURE: + { + mSDCardState = LedState::SetLedState(SfLedIndex::SF_LED_SD, SfLedState::SF_LED_STATE_RED, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + case SF_SD_FULL: + case SF_SD_ERROR: + { + mSDCardState = LedState::SetLedState(SfLedIndex::SF_LED_SD, SfLedState::SF_LED_STATE_YELLOW, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + + default: + break; + } + return EXECUTED; +} +bool DefaultState::BatteryEvent(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr> message = + std::dynamic_pointer_cast>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + if (mPowerState) + { + mPowerState->DeleteState(); + } + const BatteryLevel level = message->mData; + switch (level) + { + case BatteryLevel::LEVEL_0: + case BatteryLevel::LEVEL_1: + { + mPowerState = LedState::SetLedState(SfLedIndex::SF_LED_BAT, SfLedState::SF_LED_STATE_RED, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + case BatteryLevel::LEVEL_2: + case BatteryLevel::LEVEL_3: + { + mPowerState = LedState::SetLedState(SfLedIndex::SF_LED_BAT, SfLedState::SF_LED_STATE_YELLOW, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + case BatteryLevel::LEVEL_4: + { + mPowerState = LedState::SetLedState(SfLedIndex::SF_LED_BAT, SfLedState::SF_LED_STATE_GREEN, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + case BatteryLevel::NO_POWER: + { + mPowerState = LedState::SetLedState(SfLedIndex::SF_LED_BAT, SfLedState::SF_LED_STATE_RED, KEEP_ALIVE_FOREVER, BLINKING_FAST_MS); + break; + } + + default: + break; + } + return EXECUTED; +} +bool DefaultState::PowerOffEvent(VStateMachineMessage *msg) +{ + LogInfo("Device will power off.\n"); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::POWER_OFF_STATE); + return EXECUTED; +} +bool DefaultState::KeySDFormatHandle(VStateMachineMessage *msg) +{ + LogInfo("DefaultState::KeySDFormatHandle.\n"); + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::map::iterator iter; + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr> message = std::dynamic_pointer_cast>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + constexpr int PRESSING_TIME_MS_TO_FORAMT = 1000 * 5; + if (PRESSING_TIME_MS_TO_FORAMT <= message->mData.mHoldTimeMs) + { + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::SD_CARD_FORMAT)); + CameraStateMachine::GetInstance()->SendStateMessage(message); + } + return EXECUTED; +} +bool DefaultState::SDCardFormat(VStateMachineMessage *msg) +{ + std::shared_ptr sdCard = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCard); + sdCard->Format(); + return EXECUTED; +} +bool DefaultState::GpioUSBInput(VStateMachineMessage *msg) +{ + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::MSDC_MODE)); + CameraStateMachine::GetInstance()->SendStateMessage(message); + return EXECUTED; +} +bool DefaultState::MSDCModeHandle(VStateMachineMessage *msg) +{ + CameraStateMachine::GetInstance()->DelayMessage(msg); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::MSDC_STATE); + return EXECUTED; +} +bool DefaultState::UploadFilesPassiveEvent(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr>> message = + std::dynamic_pointer_cast>>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + constexpr int DELAY_UPLOAD_FILES_MS = 500; + std::shared_ptr messageConvert = + std::make_shared>>(static_cast(InnerStateEvent::UPLOAD_FILES_PASSIVE), message->mData); + CameraStateMachine::GetInstance()->MessageExecutedLater(messageConvert, DELAY_UPLOAD_FILES_MS); + return EXECUTED; +} +bool DefaultState::UploadFilesVoluntaryEvent(VStateMachineMessage *msg) // TODO: 优化重复代码 +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr>> message = + std::dynamic_pointer_cast>>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + constexpr int DELAY_UPLOAD_FILES_MS = 500; + std::shared_ptr messageConvert = + std::make_shared>>(static_cast(InnerStateEvent::UPLOAD_FILES_VOLUNTARY), message->mData); + CameraStateMachine::GetInstance()->MessageExecutedLater(messageConvert, DELAY_UPLOAD_FILES_MS); + return EXECUTED; +} +void DefaultState::SDCardInit(void) +{ + std::shared_ptr sdCardHandle = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCardHandle); + sdCardHandle->SetMonitor(shared_from_this()); + SF_SD_STATUS_E status = sdCardHandle->GetStatus(); + LogInfo("DefaultState::SDCardInit sd status = %d\n", static_cast(status)); + std::shared_ptr message = + std::make_shared>(static_cast(InnerStateEvent::SD_CARD_EVENT), status); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/DefaultState.h b/code/application/sifarsdk/application/StateManager/src/DefaultState.h new file mode 100644 index 000000000..85c85ba2e --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/DefaultState.h @@ -0,0 +1,53 @@ + +#ifndef DEFAULT_STATE_H +#define DEFAULT_STATE_H +#include "IStateMachineManager.h" +#include "IPeripheralManager.h" +#include "CameraMessage.h" +#include "IMcuManager.h" +#include "LedState.h" +#include "IDualCoreManager.h" +class DefaultState + : public State, + public MessageHandle, + public VKeyMonitor, + public VGpioMonitor, + public VSDCardMonitor, + public VMcuMonitor, + public VBatteryMonitor, + public std::enable_shared_from_this +{ +public: + DefaultState(); + virtual ~DefaultState(); + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + RETURN_CODE KeyActionHappened(const SfKeyDefine &key, const SfKeyAction &event, const unsigned int holdTimeMs) override; + RETURN_CODE InputTransform(const GpioDevice &gpio, const DeviceInput &input) override; + RETURN_CODE McuEventHapped(const std::shared_ptr &message) override; + void ReportSDCardStatus(const SF_SD_STATUS_E &status) override; + void BatteryChanged(const BatteryLevel &level) override; + +private: + bool StartupEvent(VStateMachineMessage *msg); + bool McuStartupModeChanged(VStateMachineMessage *msg); + bool SDCardEvent(VStateMachineMessage *msg); + bool BatteryEvent(VStateMachineMessage *msg); + bool PowerOffEvent(VStateMachineMessage *msg); + // bool KeyResetHandle(VStateMachineMessage *msg); + bool KeySDFormatHandle(VStateMachineMessage *msg); + // bool KeyResetLongPressing(VStateMachineMessage *msg); + bool SDCardFormat(VStateMachineMessage *msg); + bool GpioUSBInput(VStateMachineMessage *msg); + bool MSDCModeHandle(VStateMachineMessage *msg); + bool UploadFilesPassiveEvent(VStateMachineMessage *msg); + bool UploadFilesVoluntaryEvent(VStateMachineMessage *msg); + void SDCardInit(void); + +private: + std::shared_ptr mNetworkModuleHandle; + std::shared_ptr mSDCardState; + std::shared_ptr mPowerState; +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/IStateManger.cpp b/code/application/sifarsdk/application/StateManager/src/IStateManger.cpp new file mode 100644 index 000000000..f34493ebf --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/IStateManger.cpp @@ -0,0 +1,29 @@ +#include "IStateManager.h" +#include "Log.h" +#include +std::shared_ptr &IStateManager::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/LedState.cpp b/code/application/sifarsdk/application/StateManager/src/LedState.cpp new file mode 100644 index 000000000..f02e1f5c4 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/LedState.cpp @@ -0,0 +1,29 @@ +#include "LedState.h" +LedState::LedState(const SfLedState &state, const unsigned int &keepAliveTime, const unsigned int &blinkPeriod) + : mState(state), mKeepAliveTime(keepAliveTime), mBlinkPeriod(blinkPeriod) +{ +} +RETURN_CODE LedState::GetLedState(SfLedState &state) +{ + state = mState; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +unsigned int LedState::GetKeepAliveTimeMs(void) +{ + return mKeepAliveTime; +} +unsigned int LedState::GetBlinkTimeMs(void) +{ + return mBlinkPeriod; +} +void LedState::DeleteState(void) +{ + mKeepAliveTime = DELETED_LED_STATE; +} +std::shared_ptr LedState::SetLedState(const SfLedIndex &led, const SfLedState &state, const long int &keepAliveTime, const unsigned int &blinkPeriod) +{ + std::shared_ptr ledState = std::make_shared(state, keepAliveTime, blinkPeriod); + std::shared_ptr ledState2 = ledState; + IPeripheralManager::GetInstance()->SetLedState(led, ledState2); + return ledState; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/LedState.h b/code/application/sifarsdk/application/StateManager/src/LedState.h new file mode 100644 index 000000000..e90a0478a --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/LedState.h @@ -0,0 +1,24 @@ +#ifndef LED_STATE_H +#define LED_STATE_H +#include "IPeripheralManager.h" +constexpr int LED_BLINKING_FAST_PERIOD = 500; +constexpr int LED_BLINKING_SLOW_PERIOD = 1000; +class LedState : public VLedState +{ +public: + LedState(const SfLedState &state, const unsigned int &keepAliveTime = KEEP_ALIVE_FOREVER, const unsigned int &blinkPeriod = LED_NOT_BLINK); + ~LedState() = default; + RETURN_CODE GetLedState(SfLedState &state) override; + unsigned int GetKeepAliveTimeMs(void) override; + unsigned int GetBlinkTimeMs(void) override; + void DeleteState(void); + +public: + static std::shared_ptr SetLedState(const SfLedIndex &led, const SfLedState &state, const long int &keepAliveTime = KEEP_ALIVE_FOREVER, const unsigned int &blinkPeriod = LED_NOT_BLINK); + +private: + const SfLedState mState; + unsigned int mKeepAliveTime; + const unsigned int mBlinkPeriod; +}; +#endif // !LED_STATE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/MSDCState.cpp b/code/application/sifarsdk/application/StateManager/src/MSDCState.cpp new file mode 100644 index 000000000..9719aa6e1 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/MSDCState.cpp @@ -0,0 +1,55 @@ +#include "MSDCState.h" +#include "CameraStateMachine.h" +#include "Log.h" +#include "IMcuManager.h" +#include "IPeripheralManager.h" +#include "IDualCoreManager.h" +#include "IConfig.h" +#include "IHal.h" +MSDCState::MSDCState() : State("MSDCState") +{ + mEventHandle[InnerStateEvent::MSDC_MODE] = + std::bind(&MSDCState::MSDCModeHandle, this, std::placeholders::_1); +} +MSDCState::~MSDCState() +{ +} +void MSDCState::GoInState() +{ + LogInfo("MSDCState::GoInState==================== in\n"); +} +void MSDCState::GoOutState() +{ + LogInfo("MSDCState::GoOutState==================== out\n"); +} +bool MSDCState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +bool MSDCState::MSDCModeHandle(VStateMachineMessage *msg) +{ + LogInfo("MSDCState::MSDCModeHandle.\n"); + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr> message = std::dynamic_pointer_cast>(cameraMessage->mMessage); + if (message->mData.mInput == DeviceInput::VALID) + { + SetMSDCMode(); + } + if (message->mData.mInput == DeviceInput::INVALID) + { + UnSetMSDCMode(); + } + return EXECUTED; +} +void MSDCState::SetMSDCMode(void) +{ + std::shared_ptr sdCard = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCard); + sdCard->USBInsert(); +} +void MSDCState::UnSetMSDCMode(void) +{ + std::shared_ptr message = + std::make_shared(static_cast(InnerStateEvent::POWER_OFF_EVENT)); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/MSDCState.h b/code/application/sifarsdk/application/StateManager/src/MSDCState.h new file mode 100644 index 000000000..38a71546f --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/MSDCState.h @@ -0,0 +1,24 @@ + +#ifndef MSDC_STATE_H +#define MSDC_STATE_H +#include "IStateMachineManager.h" +#include "CameraMessage.h" +#include "LedState.h" +#include +class MSDCState : public State, public MessageHandle, public std::enable_shared_from_this +{ +public: + MSDCState(); + virtual ~MSDCState(); + +private: + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + bool MSDCModeHandle(VStateMachineMessage *msg); + void SetMSDCMode(void); + void UnSetMSDCMode(void); + +private: +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/NetworkAnomalyState.cpp b/code/application/sifarsdk/application/StateManager/src/NetworkAnomalyState.cpp new file mode 100644 index 000000000..1c85385e2 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/NetworkAnomalyState.cpp @@ -0,0 +1,29 @@ +#include "NetworkAnomalyState.h" +#include "Log.h" +NetworkAnomalyState::NetworkAnomalyState() : State("NetworkAnomalyState") +{ + // mEventHandle[InnerStateEvent::UPLOAD_FILES_VOLUNTARY] = + // std::bind(&NetworkAnomalyState::UploadFileToServersEvent, this, std::placeholders::_1); +} +NetworkAnomalyState::~NetworkAnomalyState() +{ +} +void NetworkAnomalyState::GoInState() +{ + LogInfo("NetworkAnomalyState::GoInState==================== in\n"); +} +void NetworkAnomalyState::GoOutState() +{ + LogInfo("NetworkAnomalyState::GoOutState==================== out\n"); +} +bool NetworkAnomalyState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +// bool NetworkAnomalyState::UploadFileToServersEvent(VStateMachineMessage *msg) +// { +// LogInfo("NetworkAnomalyState::UploadFileToServersEvent.\n"); +// CameraStateMachine::GetInstance()->DelayMessage(msg); +// CameraStateMachine::GetInstance()->SwitchState(CameraStates::UPLOADING_STATE); +// return EXECUTED; +// } \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/NetworkAnomalyState.h b/code/application/sifarsdk/application/StateManager/src/NetworkAnomalyState.h new file mode 100644 index 000000000..9d93ae58b --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/NetworkAnomalyState.h @@ -0,0 +1,19 @@ +#ifndef NETWORK_ANOMALY_STATE_H +#define NETWORK_ANOMALY_STATE_H +#include "IStateMachineManager.h" +#include "CameraStateMachine.h" +#include "CameraMessage.h" +class NetworkAnomalyState : public State, public MessageHandle +{ +public: + NetworkAnomalyState(); + virtual ~NetworkAnomalyState(); + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + // bool UploadFileToServersEvent(VStateMachineMessage *msg); + +private: + // std::shared_ptr mNetworkModuleHandle; +}; +#endif // !NETWORK_ANOMALY_STATE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/NetworkIdleState.cpp b/code/application/sifarsdk/application/StateManager/src/NetworkIdleState.cpp new file mode 100644 index 000000000..28186ce65 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/NetworkIdleState.cpp @@ -0,0 +1,38 @@ +#include "NetworkIdleState.h" +#include "Log.h" +NetworkIdleState::NetworkIdleState() : State("NetworkIdleState") +{ + mEventHandle[InnerStateEvent::UPLOAD_FILES_VOLUNTARY] = + std::bind(&NetworkIdleState::UploadFileToServersEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::NETWORK_MODULE_UPGRADE] = + std::bind(&NetworkIdleState::UpgradeNetworkModuleEvent, this, std::placeholders::_1); +} +NetworkIdleState::~NetworkIdleState() +{ +} +void NetworkIdleState::GoInState() +{ + LogInfo("NetworkIdleState::GoInState==================== in\n"); +} +void NetworkIdleState::GoOutState() +{ + LogInfo("NetworkIdleState::GoOutState==================== out\n"); +} +bool NetworkIdleState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +bool NetworkIdleState::UploadFileToServersEvent(VStateMachineMessage *msg) +{ + LogInfo("NetworkIdleState::UploadFileToServersEvent.\n"); + CameraStateMachine::GetInstance()->DelayMessage(msg); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::UPLOADING_STATE); + return EXECUTED; +} +bool NetworkIdleState::UpgradeNetworkModuleEvent(VStateMachineMessage *msg) +{ + LogInfo("NetworkIdleState::UpgradeNetworkModuleEvent.\n"); + CameraStateMachine::GetInstance()->DelayMessage(msg); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::UPGRADE_STATE); + return EXECUTED; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/NetworkIdleState.h b/code/application/sifarsdk/application/StateManager/src/NetworkIdleState.h new file mode 100644 index 000000000..678032c8f --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/NetworkIdleState.h @@ -0,0 +1,22 @@ +#ifndef NETWORK_IDLE_STATE_H +#define NETWORK_IDLE_STATE_H +#include "IStateMachineManager.h" +#include "CameraStateMachine.h" +#include "CameraMessage.h" +class NetworkIdleState : public State, public MessageHandle +{ +public: + NetworkIdleState(); + virtual ~NetworkIdleState(); + +private: + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + bool UploadFileToServersEvent(VStateMachineMessage *msg); + bool UpgradeNetworkModuleEvent(VStateMachineMessage *msg); + +private: + // std::shared_ptr mNetworkModuleHandle; +}; +#endif // !NETWORK_IDLE_STATE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/NormalStartState.cpp b/code/application/sifarsdk/application/StateManager/src/NormalStartState.cpp new file mode 100644 index 000000000..157d1c271 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/NormalStartState.cpp @@ -0,0 +1,26 @@ +#include "NormalStartState.h" +#include "CameraStateMachine.h" +#include "Log.h" +// #include "IMcuManager.h" +// #include "IPeripheralManager.h" +// #include "IDualCoreManager.h" +// #include "IConfig.h" +// #include "IHal.h" +NormalStartState::NormalStartState() +{ + // mEventHandle[InnerStateEvent::POWER_OFF_STATE_HOLD_TIME_OUT] = + // std::bind(&NormalStartState::PowerOffNow, this, std::placeholders::_1); +} +NormalStartState::~NormalStartState() +{ +} +void NormalStartState::GoInState() +{ + LogInfo("NormalStartState::GoInState==================== in\n"); + StartupState::GoInState(); +} +void NormalStartState::GoOutState() +{ + LogInfo("NormalStartState::GoOutState==================== out\n"); + StartupState::GoOutState(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/NormalStartState.h b/code/application/sifarsdk/application/StateManager/src/NormalStartState.h new file mode 100644 index 000000000..4bd2aa84a --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/NormalStartState.h @@ -0,0 +1,29 @@ +#ifndef NORMAL_START_STATE_H +#define NORMAL_START_STATE_H +#include "IStateMachineManager.h" +#include "CameraMessage.h" +#include "LedState.h" +#include "StartupState.h" +#include +class NormalStartState : public StartupState, public std::enable_shared_from_this +{ +public: + NormalStartState(); + virtual ~NormalStartState(); + +private: + void GoInState() override; + void GoOutState() override; + // bool PowerOffNow(VStateMachineMessage *msg); + // void PowerOffStateLedShow(const StartupMode &startupMode); + // SINT32 CheckSdCard(SF_POWEROFF_TYPE_E enType); + // SINT32 sf_sys_poweroff(SF_POWEROFF_TYPE_E poweroffType); + +private: + // std::shared_ptr mLedStateOff; + // std::shared_ptr mLedStateBlinking; + // std::thread mCheckSdCardThread; + // bool mThreadRuning; + // SF_POWEROFF_TYPE_E mPowerOffType; +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/OnKeyState.cpp b/code/application/sifarsdk/application/StateManager/src/OnKeyState.cpp new file mode 100644 index 000000000..7fa71dc1b --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/OnKeyState.cpp @@ -0,0 +1,338 @@ +#include "OnKeyState.h" +#include "CameraStateMachine.h" +#include "INetworkManager.h" +#include "ICameraManager.h" +#include "CameraTaskHandle.h" +#include "Log.h" +#include "IConfig.h" +#include "IPeripheralManager.h" +#include "IDualCoreManager.h" +#include "sf_qrcode.h" +#include "ILiveManager.h" +OnKeyState::OnKeyState() +{ + mEventHandle[static_cast(StateEvent::LINK_NETWORK_INIT_SUCCEED)] = + std::bind(&OnKeyState::LinkNetworkSucceedEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::AUTO_SHUT_DOWN_START] = + std::bind(&OnKeyState::TimeOutStart, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::KEY_ACTION_HAPPENED] = + std::bind(&OnKeyState::KeyActionHandle, this, std::placeholders::_1); + // mEventHandle[InnerStateEvent::GPIO_INPUT_TRANSFORM] = + // std::bind(&MessageHandle::GpioInputHandle, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::CAMERA_TASK_FINISHED] = + std::bind(&OnKeyState::CameraTaskFinished, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::CAMERA_TASK_TIME_OUT] = + std::bind(&OnKeyState::CameraTaskTimeOut, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::ONKEY_IDLE_TIME_OUT] = + std::bind(&OnKeyState::IdleTimeOut, this, std::placeholders::_1); + mEventHandle[static_cast(StateEvent::APN_CONFIG_SUCCEED)] = + std::bind(&OnKeyState::ApnConfigSucceedEvent, this, std::placeholders::_1); + // mEventHandle[InnerStateEvent::KEY_RESET_LONG_PRESSING] = + // std::bind(&OnKeyState::KeyResetLongPressing, this, std::placeholders::_1); + // mKeyActionHandle[SfKeyDefine::KEY_PIN_SYNC] = + // std::bind(&OnKeyState::KeySyncHandle, this, std::placeholders::_1); + mKeyClickHandle[SfKeyDefine::KEY_PIN_SYNC] = + std::bind(&OnKeyState::ClickKeySync, this, std::placeholders::_1); + mKeyHoldDownHandle[SfKeyDefine::KEY_PIN_SYNC] = + std::bind(&OnKeyState::HoldDownKeySync, this, std::placeholders::_1); + mKeyHoldUpHandle[SfKeyDefine::KEY_PIN_SYNC] = + std::bind(&OnKeyState::HoldUpKeySync, this, std::placeholders::_1); + mKeyClickHandle[SfKeyDefine::KEY_PIN_RESET] = + std::bind(&OnKeyState::ClickKeyReset, this, std::placeholders::_1); + mKeyHoldDownHandle[SfKeyDefine::KEY_PIN_RESET] = + std::bind(&OnKeyState::HoldDownKeyReset, this, std::placeholders::_1); + mKeyHoldUpHandle[SfKeyDefine::KEY_PIN_RESET] = + std::bind(&OnKeyState::HoldUpKeyReset, this, std::placeholders::_1); + mKeyClickHandle[SfKeyDefine::KEY_PIN_FORMAT] = + std::bind(&OnKeyState::ClickKeySDFormat, this, std::placeholders::_1); + mKeyHoldDownHandle[SfKeyDefine::KEY_PIN_FORMAT] = + std::bind(&OnKeyState::HoldDownKeySDFormat, this, std::placeholders::_1); + mKeyHoldUpHandle[SfKeyDefine::KEY_PIN_FORMAT] = + std::bind(&OnKeyState::HoldUpKeySDFormat, this, std::placeholders::_1); + mGpioInputHandle[GpioDevice::PIR] = + std::bind(&OnKeyState::GpioPirInput, this, std::placeholders::_1); +} +void OnKeyState::GoInState() +{ + LogInfo("OnKeyState::GoInState==================== in\n"); + StartupState::GoInState(); + // std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::ONKEY_IDLE_TIME_OUT)); + // CameraStateMachine::GetInstance()->MessageExecutedLater(message, ONKEY_IDLE_TIME_OUT_MS); + SetStartupLedState(SfLedState::SF_LED_STATE_ON); +} +void OnKeyState::GoOutState() +{ + LogInfo("OnKeyState::GoOutState==================== out\n"); + ClearAllTask(); + StartupState::GoOutState(); + DeleteStartupLedState(); +} +void OnKeyState::TaskResponse(const std::vector &response) +{ + LogInfo("OnKeyState::TaskResponse files amount = %d\n", response.size()); + if (response.empty()) + { + LogWarning("Files is empty.\n"); + } + else + { + StateCameraTask::UploadFilesToServers(response, InnerStateEvent::UPLOAD_FILES_VOLUNTARY); + ClearOneTask(); + } +} +bool OnKeyState::ApnConfigSucceedEvent(VStateMachineMessage *msg) +{ + LogInfo("OnKeyState::ApnConfigSucceedEvent.\n"); + std::shared_ptr message2 = std::make_shared(static_cast(InnerStateEvent::AUTH_AND_LOGIN)); + CameraStateMachine::GetInstance()->SendStateMessage(message2); + // if (ILiveManager::GetInstance()->LiveEnable()) + // { + // std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::LIVE_SERVICE_INIT)); + // CameraStateMachine::GetInstance()->SendStateMessage(message); + // } + return EXECUTED; +} +bool OnKeyState::KeyActionHandle(VStateMachineMessage *msg) +{ + // Reset time out evnet. + CameraStateMachine::GetInstance()->StopTimer(static_cast(InnerStateEvent::ONKEY_IDLE_TIME_OUT)); + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::ONKEY_IDLE_TIME_OUT)); + CameraStateMachine::GetInstance()->MessageExecutedLater(message, ONKEY_IDLE_TIME_OUT_MS); + return MessageHandle::KeyActionHandle(msg); +} +bool OnKeyState::LinkNetworkSucceedEvent(VStateMachineMessage *msg) +{ + LogInfo("OnKeyState::LinkNetworkSucceedEvent.\n"); + INetworkManager::GetInstance()->RegisterNetwork(RegisterNetworkType::MANUAL); + return EXECUTED; +} +bool OnKeyState::ClickKeySync(const KeyActionData &key) +{ + MakeOneCameraTask(InnerStateEvent::KEY_ACTION_HAPPENED, shared_from_this()); + return EXECUTED; +} +bool OnKeyState::HoldDownKeySync(const KeyActionData &key) +{ + LogInfo("OnKeyState::HoldDownKeySync.\n"); + constexpr int PRESSING_TIME_MS_TO_UPGRADE = 1000 * 5; + if (PRESSING_TIME_MS_TO_UPGRADE > key.mHoldTimeMs) + { + return EXECUTED; + } + std::map state; + IPeripheralManager::GetInstance()->GetAllKeysState(state); + std::map::iterator iter; + iter = state.find(SfKeyDefine::KEY_PIN_RESET); + if (iter != state.end()) + { + if (PRESSING_TIME_MS_TO_UPGRADE <= iter->second.mHoldTimeMs) + { + LogInfo("Group keys sync + reset:upgrade network module.\n"); + UpgradeDevice(UpgradeType::NETWORK_MODULE); + mKeyHoldDownHandle.erase(SfKeyDefine::KEY_PIN_SYNC); + return EXECUTED; + } + } + return EXECUTED; +} +bool OnKeyState::HoldUpKeySync(const KeyActionData &key) +{ + LogInfo("OnKeyState::HoldUpKeySync.\n"); + mKeyHoldDownHandle[SfKeyDefine::KEY_PIN_SYNC] = + std::bind(&OnKeyState::HoldDownKeySync, this, std::placeholders::_1); + return EXECUTED; +} +bool OnKeyState::ClickKeyReset(const KeyActionData &key) +{ + std::map state; + IPeripheralManager::GetInstance()->GetAllKeysState(state); + std::map::iterator iter; + iter = state.find(SfKeyDefine::KEY_PIN_SYNC); + if (iter != state.end()) + { + constexpr int SYNC_HOLD_MS = 1000 * 5; + if (SYNC_HOLD_MS <= iter->second.mHoldTimeMs) + { + LogInfo("Group keys long ok + click reset.\n"); + std::shared_ptr sdCard = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCard); + const SF_SD_STATUS_E sdState = sdCard->GetStatus(); + if (sdState == SD_MOUNT_SUCCESS || sdState == SF_SD_FULL) + { + Param version = GetParam(PARAM_NAME_APP_VERSION); + NetworkParameter param; + INetworkManager::GetInstance()->GetParameter(param); + LogInfo("imei = %s", param.mIMEI.c_str()); + // #ifdef SF_VERSION_RELEASE + // #define ACCESS_KEY "ACT1CSHKRO01" + // #else + // #define ACCESS_KEY "AC40CSHKRO01" + // #endif + sf_qrcode_create(param.mIMEI.c_str(), param.mIccid.c_str(), version.str, "AC40CSHKRO01"); + } + else + { + LogError("Create qrcode failed, sd card not available.\n"); + } + } + } + return EXECUTED; +} +bool OnKeyState::HoldDownKeyReset(const KeyActionData &key) +{ + LogInfo("OnKeyState::HoldDownKeyReset.\n"); + constexpr int PRESSING_TIME_MS_TO_RESET = 1000 * 5; + if (PRESSING_TIME_MS_TO_RESET > key.mHoldTimeMs) + { + return EXECUTED; + } + std::map state; + IPeripheralManager::GetInstance()->GetAllKeysState(state); + std::map::iterator iter; + iter = state.find(SfKeyDefine::KEY_PIN_SYNC); + if (iter == state.end()) + { + LogInfo("ResetParam()\n"); + mKeyHoldDownHandle.erase(SfKeyDefine::KEY_PIN_RESET); + ResetParam(); + return EXECUTED; + } + return EXECUTED; +} +bool OnKeyState::ClickKeySDFormat(const KeyActionData &key) +{ + std::map state; + IPeripheralManager::GetInstance()->GetAllKeysState(state); + std::map::iterator iter; + iter = state.find(SfKeyDefine::KEY_PIN_SYNC); + if (iter != state.end()) + { + constexpr int SYNC_HOLD_MS = 1000 * 5; + if (SYNC_HOLD_MS <= iter->second.mHoldTimeMs) + { + LogInfo("Group keys long ok + click sd format.\n"); + // TODO: do something, close debug mode. + } + } + return EXECUTED; +} +bool OnKeyState::HoldDownKeySDFormat(const KeyActionData &key) +{ + LogInfo("OnKeyState::HoldDownKeySDFormat.\n"); + constexpr int PRESSING_TIME_MS_TO_RESET = 1000 * 5; + if (PRESSING_TIME_MS_TO_RESET > key.mHoldTimeMs) + { + return EXECUTED; + } + std::map state; + IPeripheralManager::GetInstance()->GetAllKeysState(state); + std::map::iterator iter; + iter = state.find(SfKeyDefine::KEY_PIN_SYNC); + if (iter == state.end()) + { + LogInfo("Group keys sync + sd format:upgrade mcu.\n"); + UpgradeDevice(UpgradeType::MCU); + mKeyHoldDownHandle.erase(SfKeyDefine::KEY_PIN_FORMAT); + return EXECUTED; + } + return EXECUTED; +} +bool OnKeyState::HoldUpKeySDFormat(const KeyActionData &key) +{ + mKeyHoldDownHandle[SfKeyDefine::KEY_PIN_FORMAT] = + std::bind(&OnKeyState::HoldDownKeySDFormat, this, std::placeholders::_1); + return EXECUTED; +} +bool OnKeyState::HoldUpKeyReset(const KeyActionData &key) +{ + LogInfo("OnKeyState::HoldUpKeyReset.\n"); + mKeyHoldDownHandle[SfKeyDefine::KEY_PIN_RESET] = + std::bind(&OnKeyState::HoldDownKeyReset, this, std::placeholders::_1); + return EXECUTED; +} +bool OnKeyState::CameraTaskFinished(VStateMachineMessage *msg) +{ + LogInfo("OnKeyState::CameraTaskFinished.\n"); + return ::CameraTaskFinished(msg); +} +bool OnKeyState::CameraTaskTimeOut(VStateMachineMessage *msg) +{ + LogInfo("OnKeyState::CameraTaskTimeOut.\n"); + ClearOneTask(); + return EXECUTED; +} +bool OnKeyState::IdleTimeOut(VStateMachineMessage *msg) +{ + LogInfo("OnKeyState::IdleTimeOut.\n"); + std::shared_ptr message = + std::make_shared(static_cast(InnerStateEvent::POWER_OFF_EVENT)); + CameraStateMachine::GetInstance()->SendStateMessage(message); + return EXECUTED; +} +bool OnKeyState::GpioPirInput(VStateMachineMessage *msg) +{ + LogInfo("OnKeyState::GpioPirInput.\n"); + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr> message = std::dynamic_pointer_cast>(cameraMessage->mMessage); + if (message->mData.mInput == DeviceInput::VALID) + { + LogInfo("Blinking 1s.\n"); + constexpr int BLINKING_TIME_MS = 1000; + constexpr int BLINK_PERIOD_MS = 500; + LedState::SetLedState(SfLedIndex::SF_LED_STATUS, SfLedState::SF_LED_STATE_ON, BLINKING_TIME_MS, BLINK_PERIOD_MS); + } + return EXECUTED; +} +bool OnKeyState::TimeOutStart(VStateMachineMessage *msg) +{ + LogInfo("onkey start time out = 3min.\n"); + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::ONKEY_IDLE_TIME_OUT)); + CameraStateMachine::GetInstance()->MessageExecutedLater(message, ONKEY_IDLE_TIME_OUT_MS); + return EXECUTED; +} +void OnKeyState::UpgradeDevice(const UpgradeType &type) +{ + constexpr int UPGRADE_LOWEST_BATTERY_PERCENT = 40; + if (UPGRADE_LOWEST_BATTERY_PERCENT >= IDualCoreManager::GetInstance()->GetBatRemainCap()) + { + std::shared_ptr message = + std::make_shared>(static_cast(InnerStateEvent::NETWORK_MODULE_UPGRADE), type); + CameraStateMachine::GetInstance()->SendStateMessage(message); + } + else + { + LogWarning("Not enough battery to upgrade.\n"); + } +} +bool OnKeyState::KeyResetLongPressing(VStateMachineMessage *msg) +{ + std::map state; + IPeripheralManager::GetInstance()->GetAllKeysState(state); + std::map::iterator iter; + iter = state.find(SfKeyDefine::KEY_PIN_SYNC); + if (iter != state.end()) + { + constexpr int SYNC_HOLD_MS = 1000 * 5; + if (SYNC_HOLD_MS <= iter->second.mHoldTimeMs) + { + constexpr int UPGRADE_LOWEST_BATTERY_PERCENT = 40; + if (UPGRADE_LOWEST_BATTERY_PERCENT >= IDualCoreManager::GetInstance()->GetBatRemainCap()) + { + std::shared_ptr message = + std::make_shared(static_cast(InnerStateEvent::NETWORK_MODULE_UPGRADE)); + CameraStateMachine::GetInstance()->SendStateMessage(message); + } + else + { + LogWarning("Not enough battery to upgrade.\n"); + } + return EXECUTED; + } + if (TIME_MEANS_KEY_NOT_HOLD != iter->second.mHoldTimeMs) + { + // Other state can not handle this message. + return EXECUTED; + } + } + return NOT_EXECUTED; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/OnKeyState.h b/code/application/sifarsdk/application/StateManager/src/OnKeyState.h new file mode 100644 index 000000000..10555005c --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/OnKeyState.h @@ -0,0 +1,36 @@ +#ifndef ONKEY_STATE_H +#define ONKEY_STATE_H +#include "StartupState.h" +#include +constexpr int ONKEY_IDLE_TIME_OUT_MS = 1000 * 180; +class OnKeyState : public StartupState, public VCameraTaskOwner, public std::enable_shared_from_this +{ +public: + OnKeyState(); + virtual ~OnKeyState() = default; + void GoInState() override; + void GoOutState() override; + void TaskResponse(const std::vector &response) override; + +private: + bool ApnConfigSucceedEvent(VStateMachineMessage *msg); + bool KeyActionHandle(VStateMachineMessage *msg) override; + bool LinkNetworkSucceedEvent(VStateMachineMessage *msg); + bool ClickKeySync(const KeyActionData &key); + bool HoldDownKeySync(const KeyActionData &key); + bool HoldUpKeySync(const KeyActionData &key); + bool ClickKeyReset(const KeyActionData &key); + bool HoldDownKeyReset(const KeyActionData &key); + bool ClickKeySDFormat(const KeyActionData &key); + bool HoldDownKeySDFormat(const KeyActionData &key); + bool HoldUpKeySDFormat(const KeyActionData &key); + bool HoldUpKeyReset(const KeyActionData &key); + bool CameraTaskFinished(VStateMachineMessage *msg); + bool CameraTaskTimeOut(VStateMachineMessage *msg); + bool IdleTimeOut(VStateMachineMessage *msg); + bool GpioPirInput(VStateMachineMessage *msg); + bool TimeOutStart(VStateMachineMessage *msg); + void UpgradeDevice(const UpgradeType &type); + bool KeyResetLongPressing(VStateMachineMessage *msg); // TODO: delete +}; +#endif // !ONKEY_STATE_H diff --git a/code/application/sifarsdk/application/StateManager/src/PeripheralAbnormalState.cpp b/code/application/sifarsdk/application/StateManager/src/PeripheralAbnormalState.cpp new file mode 100644 index 000000000..c66f8864a --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/PeripheralAbnormalState.cpp @@ -0,0 +1,27 @@ +#include "PeripheralAbnormalState.h" +#include "CameraStateMachine.h" +#include "Log.h" +PeripheralAbnormalState::PeripheralAbnormalState() : State("PeripheralAbnormalState") +{ + mEventHandle[InnerStateEvent::STARTUP] = std::bind(&PeripheralAbnormalState::StartupEvent, this, std::placeholders::_1); +} +PeripheralAbnormalState::~PeripheralAbnormalState() +{ +} +void PeripheralAbnormalState::GoInState() +{ + LogInfo("PeripheralAbnormalState::GoInState==================== in\n"); +} +void PeripheralAbnormalState::GoOutState() +{ + LogInfo("PeripheralAbnormalState::GoOutState==================== out\n"); +} +bool PeripheralAbnormalState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +bool PeripheralAbnormalState::StartupEvent(VStateMachineMessage *msg) +{ + LogError("Device can't startup becase peripheral abnormal.\n"); + return EXECUTED; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/PeripheralAbnormalState.h b/code/application/sifarsdk/application/StateManager/src/PeripheralAbnormalState.h new file mode 100644 index 000000000..b5a353a61 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/PeripheralAbnormalState.h @@ -0,0 +1,17 @@ + +#ifndef PERIPHERAL_ABNORMAL_STATE_H +#define PERIPHERAL_ABNORMAL_STATE_H +#include "IStateMachineManager.h" +#include "CameraMessage.h" +#include +class PeripheralAbnormalState : public State, public MessageHandle +{ +public: + PeripheralAbnormalState(); + virtual ~PeripheralAbnormalState(); + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + bool StartupEvent(VStateMachineMessage *msg); +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/PirStartState.cpp b/code/application/sifarsdk/application/StateManager/src/PirStartState.cpp new file mode 100644 index 000000000..5fff5ce26 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/PirStartState.cpp @@ -0,0 +1,42 @@ +#include "PirStartState.h" +#include "Log.h" +#include "CameraStateMachine.h" +#include "CameraMessage.h" +PirStartState::PirStartState() +{ + mEventHandle[InnerStateEvent::UPLOAD_FILES_PASSIVE] = + std::bind(&PirStartState::UploadFilesPassiveEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::SUBSCRIBLE_UPLOAD_FILES] = + std::bind(&StartupState::UploadSubscribeFilesEvent, this, std::placeholders::_1); +} +void PirStartState::GoInState() +{ + LogInfo("PirStartState::GoInState==================== in\n"); + StartupState::GoInState(); +} +void PirStartState::GoOutState() +{ + LogInfo("PirStartState::GoOutState==================== out\n"); + StartupState::GoOutState(); +} +bool PirStartState::UploadFilesPassiveEvent(VStateMachineMessage *msg) +{ + LogInfo("PirStartState::UploadFilesPassiveEvent.\n"); + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr>> message = + std::dynamic_pointer_cast>>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::shared_ptr messageConvert = + std::make_shared>>(static_cast(InnerStateEvent::UPLOAD_FILES_VOLUNTARY), message->mData); + CameraStateMachine::GetInstance()->SendStateMessage(messageConvert); + return EXECUTED; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/PirStartState.h b/code/application/sifarsdk/application/StateManager/src/PirStartState.h new file mode 100644 index 000000000..9f5145e50 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/PirStartState.h @@ -0,0 +1,15 @@ +#ifndef PIR_START_STATE_H +#define PIR_START_STATE_H +#include "StartupState.h" +class PirStartState : public StartupState, public std::enable_shared_from_this +{ +public: + PirStartState(); + virtual ~PirStartState() = default; + +private: + void GoInState() override; + void GoOutState() override; + bool UploadFilesPassiveEvent(VStateMachineMessage *msg); +}; +#endif // !PIR_START_STATE_H diff --git a/code/application/sifarsdk/application/StateManager/src/PowerOffState.cpp b/code/application/sifarsdk/application/StateManager/src/PowerOffState.cpp new file mode 100644 index 000000000..bb2349aee --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/PowerOffState.cpp @@ -0,0 +1,145 @@ +#include "PowerOffState.h" +#include "CameraStateMachine.h" +#include "Log.h" +#include "IMcuManager.h" +#include "IPeripheralManager.h" +#include "IDualCoreManager.h" +#include "IConfig.h" +#include "IHal.h" +#include "ILiveManager.h" +PowerOffState::PowerOffState() : State("PowerOffState") +{ + mEventHandle[InnerStateEvent::POWER_OFF_STATE_HOLD_TIME_OUT] = + std::bind(&PowerOffState::PowerOffNow, this, std::placeholders::_1); + mThreadRuning = false; +} +PowerOffState::~PowerOffState() +{ +} +void PowerOffState::GoInState() +{ + LogInfo("PowerOffState::GoInState==================== in\n"); + std::shared_ptr mcuDevice = std::make_shared(); + IMcuManager::GetInstance()->GetMcuDevice(mcuDevice); + StartupMode changedStartupMode = static_cast(mcuDevice->GetStartupMode()); + PowerOffStateLedShow(changedStartupMode); + if (StartupMode::STARTUP_MODE_NORMAL == changedStartupMode) + { + LogInfo("STARTUP_MODE_NORMAL.\n"); + std::shared_ptr message = + std::make_shared(static_cast(InnerStateEvent::POWER_OFF_STATE_HOLD_TIME_OUT)); + constexpr int STATE_HOLD_TIME_OUT_MS = 1000 * 5; + CameraStateMachine::GetInstance()->MessageExecutedLater(message, STATE_HOLD_TIME_OUT_MS); + } + if (StartupMode::STARTUP_MODE_OFF == changedStartupMode) + { + LogInfo("STARTUP_MODE_OFF.\n"); + std::shared_ptr message = + std::make_shared(static_cast(InnerStateEvent::POWER_OFF_STATE_HOLD_TIME_OUT)); + CameraStateMachine::GetInstance()->SendStateMessage(message); + } + auto checkSdCardThreadStart = [](std::shared_ptr state) + { + state->CheckSdCard(SF_POWEROFF_KEYOFF); + }; + mThreadRuning = true; + mCheckSdCardThread = std::thread(checkSdCardThreadStart, shared_from_this()); +} +void PowerOffState::GoOutState() +{ + LogInfo("PowerOffState::GoOutState==================== out\n"); + CameraStateMachine::GetInstance()->StopTimer(static_cast(InnerStateEvent::POWER_OFF_STATE_HOLD_TIME_OUT)); + if (mLedStateOff) + { + mLedStateOff->DeleteState(); + mLedStateOff.reset(); + } + if (mLedStateBlinking) + { + mLedStateBlinking->DeleteState(); + mLedStateBlinking.reset(); + } + mThreadRuning = false; + if (mCheckSdCardThread.joinable()) + { + mCheckSdCardThread.join(); + } +} +bool PowerOffState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +bool PowerOffState::PowerOffNow(VStateMachineMessage *msg) +{ + LogInfo("PowerOffState::PowerOffNow.\n"); + mThreadRuning = false; + if (mCheckSdCardThread.joinable()) + { + mCheckSdCardThread.join(); + } + ILiveManager::GetInstance()->KeepAlive(); + SaveConfig(); + sf_sys_poweroff(mPowerOffType); + return EXECUTED; +} +void PowerOffState::PowerOffStateLedShow(const StartupMode &startupMode) +{ + mLedStateOff = LedState::SetLedState(SfLedIndex::SF_LED_STATUS, SfLedState::SF_LED_STATE_OFF, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + if (StartupMode::STARTUP_MODE_NORMAL == startupMode) + { + constexpr int BLINKING_ALIVE_TIME_MS = 1000 * 5; + constexpr int BLINK_PERIOD_MS = 500; + mLedStateBlinking = LedState::SetLedState(SfLedIndex::SF_LED_STATUS, SfLedState::SF_LED_STATE_ON, BLINKING_ALIVE_TIME_MS, BLINK_PERIOD_MS); + } +} +SINT32 PowerOffState::CheckSdCard(SF_POWEROFF_TYPE_E enType) +{ + SF_STORE_ATTR_S storeattrs = {0}; + const StartupMode startup = CameraStateMachine::GetInstance()->GetStartupMode(); + Param sdLoop = GetParam(PARAM_SD_LOOP); + Param reset = GetParam(PARAM_RESET_FLAG); + std::shared_ptr sdCard = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCard); + sdCard->GetInfo(storeattrs); + SF_SD_STATUS_E sdState = sdCard->GetStatus(); + if ((startup != StartupMode::STARTUP_MODE_ONKEY) && (startup != StartupMode::STARTUP_MODE_NORMAL) && (startup != StartupMode::STARTUP_MODE_OFF)) + { + if (SD_LOOP_ENABLE == sdLoop.numberUInt) + { + if ((storeattrs.SDStatus == 0) & (storeattrs.SDFree < SDLOOP_REMAIN_SPACE)) + { + sdCard->LoopRemove(IHal::GetInstance()->GetSDCardCheckPath()); + LogInfo("loop remove finished!!!\n"); + } + } + } + // if (pCustomer->DebugMode) // TODO: + // sync(); + if (RESET_ENABLE == reset.numberUInt) + { + mPowerOffType = SF_POWEROFF_SYNC_PARAM; + reset.numberUInt = RESET_DISABLE; + SetParam(reset, PARAM_RESET_FLAG); + } + else if (SD_LOOP_ENABLE != sdLoop.numberUInt && SF_SD_FULL == sdState) + { + mPowerOffType = SF_POWEROFF_SD_FULL; + } + else + { + mPowerOffType = enType; + } + return SF_SUCCESS; +} +SINT32 PowerOffState::sf_sys_poweroff(SF_POWEROFF_TYPE_E poweroffType) +{ + SINT32 ret = SF_FAILURE; + IHal::GetInstance()->DoSomethingBeforPowerOff(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + IDualCoreManager::GetInstance()->SetMcuTime(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::shared_ptr mcuDevice = std::make_shared(); + IMcuManager::GetInstance()->GetMcuDevice(mcuDevice); + mcuDevice->sf_mcu_reg_set(SF_MCU_POWEROFF, poweroffType); + return ret; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/PowerOffState.h b/code/application/sifarsdk/application/StateManager/src/PowerOffState.h new file mode 100644 index 000000000..dae792d1a --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/PowerOffState.h @@ -0,0 +1,43 @@ +#ifndef POWER_OFF_STATE_H +#define POWER_OFF_STATE_H +#include "IStateMachineManager.h" +#include "CameraMessage.h" +#include "LedState.h" +#include +typedef enum sfPOWEROFF_TYPE_E +{ + SF_POWEROFF_NOT = 0x00, + SF_POWEROFF_AUTO = 0x01, /*auto power when 3min no operation*/ + SF_POWEROFF_REBOOT = 0x02, /*poweroff to reboot*/ + SF_POWEROFF_KEYON = 0x03, + SF_POWEROFF_KEYOFF = 0x04, + SF_POWEROFF_SYNC_PARAM = 0x05, + SF_POWEROFF_GPS_DP = 0x06, + SF_POWEROFF_SD_FULL = 0x07, + SF_POWEROFF_LOW_BAT = 0x08, + SF_POWEROFF_NO_SD = 0x09, + SF_POWEROFF_BUTT, +} SF_POWEROFF_TYPE_E; +class PowerOffState : public State, public MessageHandle, public std::enable_shared_from_this +{ +public: + PowerOffState(); + virtual ~PowerOffState(); + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + +private: + bool PowerOffNow(VStateMachineMessage *msg); + void PowerOffStateLedShow(const StartupMode &startupMode); + SINT32 CheckSdCard(SF_POWEROFF_TYPE_E enType); + SINT32 sf_sys_poweroff(SF_POWEROFF_TYPE_E poweroffType); + +private: + std::shared_ptr mLedStateOff; + std::shared_ptr mLedStateBlinking; + std::thread mCheckSdCardThread; + bool mThreadRuning; + SF_POWEROFF_TYPE_E mPowerOffType; +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/RegisterNetworkState.cpp b/code/application/sifarsdk/application/StateManager/src/RegisterNetworkState.cpp new file mode 100644 index 000000000..ce91709ff --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/RegisterNetworkState.cpp @@ -0,0 +1,35 @@ +#include "RegisterNetworkState.h" +#include "CameraStateMachine.h" +#include "Log.h" +#include "INetworkManager.h" +RegisterNetworkState::RegisterNetworkState() : State("RegisterNetworkState") +{ + mEventHandle[static_cast(StateEvent::REGISTER_NETWORK_FAILED)] = + std::bind(&RegisterNetworkState::RegisterNetworkFailedEvent, this, std::placeholders::_1); +} +void RegisterNetworkState::GoInState() +{ + LogInfo("RegisterNetworkState::GoInState==================== in\n"); + // mSignalState = LedState::SetLedState(SfLedIndex::SF_LED_SIG1, SfLedState::SF_LED_STATE_GREEN, KEEP_ALIVE_FOREVER, BLINKING_SLOW_MS); + // INetworkManager::GetInstance()->LinkNetworkInit(); + // std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::SIM_INIT_TIME_OUT)); + // CameraStateMachine::GetInstance()->MessageExecutedLater(message, SIM_INIT_TIME_OUT_MS); +} +void RegisterNetworkState::GoOutState() +{ + LogInfo("RegisterNetworkState::GoOutState==================== out\n"); + if (mSignalState) + { + mSignalState->DeleteState(); + mSignalState.reset(); + } +} +bool RegisterNetworkState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +bool RegisterNetworkState::RegisterNetworkFailedEvent(VStateMachineMessage *msg) +{ + LogInfo("RegisterNetworkState::RegisterNetworkFailedEvent.\n"); + return EXECUTED; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/RegisterNetworkState.h b/code/application/sifarsdk/application/StateManager/src/RegisterNetworkState.h new file mode 100644 index 000000000..5877cddd4 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/RegisterNetworkState.h @@ -0,0 +1,19 @@ +#ifndef REGISTER_NETWORK_STATE_H +#define REGISTER_NETWORK_STATE_H +#include "IStateMachineManager.h" +#include "CameraMessage.h" +#include "LedState.h" +class RegisterNetworkState : public State, public MessageHandle +{ +public: + RegisterNetworkState(); + virtual ~RegisterNetworkState() = default; + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + bool RegisterNetworkFailedEvent(VStateMachineMessage *msg); + +private: + std::shared_ptr mSignalState; +}; +#endif // !REGISTER_NETWORK_STATE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/RingStartState.cpp b/code/application/sifarsdk/application/StateManager/src/RingStartState.cpp new file mode 100644 index 000000000..34f8340e0 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/RingStartState.cpp @@ -0,0 +1,38 @@ +#include "RingStartState.h" +#include "Log.h" +#include "CameraStateMachine.h" +#include "CameraMessage.h" +RingStartState::RingStartState() +{ +} +void RingStartState::GoInState() +{ + LogInfo("RingStartState::GoInState==================== in\n"); + StartupState::GoInState(); +} +void RingStartState::GoOutState() +{ + LogInfo("RingStartState::GoOutState==================== out\n"); + StartupState::GoOutState(); +} +// bool RingStartState::UploadFilesPassiveEvent(VStateMachineMessage *msg) +// { +// LogInfo("RingStartState::UploadFilesPassiveEvent.\n"); +// if (nullptr == msg) +// { +// LogError("nullptr pointer.\n"); +// return NOT_EXECUTED; +// } +// std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); +// std::shared_ptr>> message = +// std::dynamic_pointer_cast>>(cameraMessage->mMessage); +// if (!message) +// { +// LogError("nullptr pointer.\n"); +// return NOT_EXECUTED; +// } +// std::shared_ptr messageConvert = +// std::make_shared>>(static_cast(InnerStateEvent::UPLOAD_FILES_VOLUNTARY), message->mData); +// CameraStateMachine::GetInstance()->SendStateMessage(messageConvert); +// return EXECUTED; +// } \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/RingStartState.h b/code/application/sifarsdk/application/StateManager/src/RingStartState.h new file mode 100644 index 000000000..937bd428c --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/RingStartState.h @@ -0,0 +1,15 @@ +#ifndef RING_START_STATE_H +#define RING_START_STATE_H +#include "StartupState.h" +class RingStartState : public StartupState, public std::enable_shared_from_this +{ +public: + RingStartState(); + virtual ~RingStartState() = default; + +private: + void GoInState() override; + void GoOutState() override; + // bool UploadFilesPassiveEvent(VStateMachineMessage *msg); +}; +#endif // !RING_START_STATE_H diff --git a/code/application/sifarsdk/application/StateManager/src/ShutDownState.cpp b/code/application/sifarsdk/application/StateManager/src/ShutDownState.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/application/StateManager/src/ShutDownState.h b/code/application/sifarsdk/application/StateManager/src/ShutDownState.h new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/application/StateManager/src/SimInitState.cpp b/code/application/sifarsdk/application/StateManager/src/SimInitState.cpp new file mode 100644 index 000000000..539e608d5 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/SimInitState.cpp @@ -0,0 +1,58 @@ +#include "SimInitState.h" +#include "CameraStateMachine.h" +#include "Log.h" +#include "INetworkManager.h" +constexpr int SIM_INIT_RETRY_LATER_MS = 100; +SimInitState::SimInitState() : State("SimInitState") +{ + mEventHandle[static_cast(StateEvent::LINK_NETWORK_INIT_SUCCEED)] = + std::bind(&SimInitState::LinkNetworkSucceedEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::SIM_INIT_TIME_OUT] = + std::bind(&SimInitState::SimInitTimeOutEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::SIM_INIT] = + std::bind(&SimInitState::SimInit, this, std::placeholders::_1); +} +void SimInitState::GoInState() +{ + LogInfo("SimInitState::GoInState==================== in\n"); + // std::shared_ptr simInit = std::make_shared(static_cast(InnerStateEvent::SIM_INIT)); + // CameraStateMachine::GetInstance()->SendStateMessage(simInit); + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::SIM_INIT_TIME_OUT)); + CameraStateMachine::GetInstance()->MessageExecutedLater(message, SIM_INIT_TIME_OUT_MS); +} +void SimInitState::GoOutState() +{ + LogInfo("SimInitState::GoOutState==================== out\n"); +} +bool SimInitState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +bool SimInitState::SimInitTimeOutEvent(VStateMachineMessage *msg) +{ + // TODO: + LogInfo("SimInitTimeOutEvent.\n"); + return EXECUTED; +} +bool SimInitState::LinkNetworkSucceedEvent(VStateMachineMessage *msg) +{ + LogInfo("SimInitState::LinkNetworkSucceedEvent.\n"); + CameraStateMachine::GetInstance()->StopTimer(static_cast(InnerStateEvent::SIM_INIT_TIME_OUT)); + CameraStateMachine::GetInstance()->DelayMessage(msg); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::REGISTER_NETWORK_STATE); + return EXECUTED; +} +bool SimInitState::SimInit(VStateMachineMessage *msg) +{ + auto code = INetworkManager::GetInstance()->NetworkHardwareIsWorking(); + if (!code->IsCodeOK()) + { + // LogError("Network module is not ok, will retry again after %dms.\n", SIM_INIT_RETRY_LATER_MS); + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::SIM_INIT)); + CameraStateMachine::GetInstance()->MessageExecutedLater(message, SIM_INIT_RETRY_LATER_MS); + return EXECUTED; + } + LogInfo("Sim init.\n"); + INetworkManager::GetInstance()->LinkNetworkInit(); + return EXECUTED; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/SimInitState.h b/code/application/sifarsdk/application/StateManager/src/SimInitState.h new file mode 100644 index 000000000..dfdaf6eda --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/SimInitState.h @@ -0,0 +1,18 @@ +#ifndef SIM_INIT_STATE_H +#define SIM_INIT_STATE_H +#include "IStateMachineManager.h" +#include "CameraMessage.h" +constexpr int SIM_INIT_TIME_OUT_MS = 1000 * 60; +class SimInitState : public State, public MessageHandle +{ +public: + SimInitState(); + virtual ~SimInitState() = default; + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + bool SimInitTimeOutEvent(VStateMachineMessage *msg); + bool LinkNetworkSucceedEvent(VStateMachineMessage *msg); + bool SimInit(VStateMachineMessage *msg); +}; +#endif // !SIM_INIT_STATE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StartupState.cpp b/code/application/sifarsdk/application/StateManager/src/StartupState.cpp new file mode 100644 index 000000000..aaff9b171 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StartupState.cpp @@ -0,0 +1,308 @@ +#include "StartupState.h" +#include "CameraStateMachine.h" +#include "IDualCoreManager.h" +#include "Log.h" +#include "IConfig.h" +#include "INetworkManager.h" +#include "ILiveManager.h" +StartupState::StartupState() : State("StartupState") +{ + mEventHandle[static_cast(StateEvent::LINK_NETWORK_INIT_SUCCEED)] = + std::bind(&StartupState::LinkNetworkSucceedEvent, this, std::placeholders::_1); + mEventHandle[static_cast(StateEvent::LINK_NETWORK_INIT_FAILED)] = + std::bind(&StartupState::LinkNetworkFailedEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::SIM_INIT] = + std::bind(&StartupState::SimInitEvent, this, std::placeholders::_1); + mEventHandle[static_cast(StateEvent::REGISTER_NETWORK_SUCCEED)] = + std::bind(&StartupState::RegisterNetworkSucceedEvent, this, std::placeholders::_1); + mEventHandle[static_cast(StateEvent::REGISTER_NETWORK_FAILED)] = + std::bind(&StartupState::RegisterNetworkFailedEvent, this, std::placeholders::_1); + mEventHandle[static_cast(StateEvent::APN_CONFIG_SUCCEED)] = + std::bind(&StartupState::ApnConfigSucceedEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::LIVE_SERVICE_INIT] = + std::bind(&StartupState::LiveServiceInitEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::AUTH_AND_LOGIN] = + std::bind(&StartupState::AuthAndLoginEvent, this, std::placeholders::_1); + mEventHandle[static_cast(StateEvent::APN_CONFIG_FAILED)] = + std::bind(&StartupState::ApnConfigFailedEvent, this, std::placeholders::_1); + mEventHandle[static_cast(StateEvent::LIVE_START_MEDIA)] = + std::bind(&StartupState::LiveStartMediaEvent, this, std::placeholders::_1); + mEventHandle[static_cast(StateEvent::LIVE_STOP_MEDIA)] = + std::bind(&StartupState::LiveStopMediaEvent, this, std::placeholders::_1); +} +void StartupState::GoInState() +{ + LogInfo("StartupState::GoInState==================== in\n"); + StateCameraTask::Init(); + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::SIM_INIT)); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} +void StartupState::GoOutState() +{ + LogInfo("StartupState::GoOutState==================== out\n"); + StateCameraTask::UnInit(); + if (mSignalState) + { + mSignalState->DeleteState(); + mSignalState.reset(); + } + if (mUserState) + { + mUserState->DeleteState(); + mUserState.reset(); + } +} +bool StartupState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +bool StartupState::SimInitEvent(VStateMachineMessage *msg) +{ + if (mSignalState) + { + mSignalState->DeleteState(); + mSignalState.reset(); + } + if (mUserState) + { + mUserState->DeleteState(); + mUserState.reset(); + } + mSignalState = LedState::SetLedState(SfLedIndex::SF_LED_SIG1, SfLedState::SF_LED_STATE_GREEN, KEEP_ALIVE_FOREVER, BLINKING_SLOW_MS); + mUserState = LedState::SetLedState(SfLedIndex::SF_LED_USERBIND, SfLedState::SF_LED_STATE_GREEN, KEEP_ALIVE_FOREVER, BLINKING_SLOW_MS); + CameraStateMachine::GetInstance()->DelayMessage(msg); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::SIM_INIT_STATE); + return EXECUTED; +} +void StartupState::SetStartupLedState(const SfLedState &state, const long int &keepAliveTime, const unsigned int &blinkPeriod) +{ + mStartupLedState = LedState::SetLedState(SfLedIndex::SF_LED_STATUS, state, keepAliveTime, blinkPeriod); +} +void StartupState::DeleteStartupLedState(void) +{ + if (mStartupLedState) + { + mStartupLedState->DeleteState(); + mStartupLedState.reset(); + } +} +bool StartupState::RegisterNetworkSucceedEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::RegisterNetworkSucceedEvent.\n"); + NetworkParameter param; + INetworkManager::GetInstance()->GetParameter(param); + if (mSignalState) + { + mSignalState->DeleteState(); + mSignalState.reset(); + } + switch (param.mSignalLevel) + { + case NetworkSignal::LEVEL_0: + { + mSignalState = LedState::SetLedState(SfLedIndex::SF_LED_SIG1, SfLedState::SF_LED_STATE_RED, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + case NetworkSignal::LEVEL_1: + case NetworkSignal::LEVEL_2: + { + mSignalState = LedState::SetLedState(SfLedIndex::SF_LED_SIG1, SfLedState::SF_LED_STATE_YELLOW, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + case NetworkSignal::LEVEL_3: + { + mSignalState = LedState::SetLedState(SfLedIndex::SF_LED_SIG1, SfLedState::SF_LED_STATE_GREEN, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + break; + } + + default: + LogError("Get signal level failed.\n"); + break; + } + return EXECUTED; +} +bool StartupState::RegisterNetworkFailedEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::RegisterNetworkFailedEvent.\n"); + if (mSignalState) + { + mSignalState->DeleteState(); + mSignalState.reset(); + } + mSignalState = LedState::SetLedState(SfLedIndex::SF_LED_SIG1, SfLedState::SF_LED_STATE_RED, KEEP_ALIVE_FOREVER, BLINKING_FAST_MS); + SendAutoShutDownEvent(); + return EXECUTED; +} +bool StartupState::ApnConfigSucceedEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::ApnConfigSucceedEvent.\n"); + if (ILiveManager::GetInstance()->LiveEnable()) + { + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::LIVE_SERVICE_INIT)); + CameraStateMachine::GetInstance()->SendStateMessage(message); + } + std::shared_ptr message2 = std::make_shared(static_cast(InnerStateEvent::AUTH_AND_LOGIN)); + CameraStateMachine::GetInstance()->SendStateMessage(message2); + return EXECUTED; +} +bool StartupState::ApnConfigFailedEvent(VStateMachineMessage *msg) +{ + SendAutoShutDownEvent(); + return EXECUTED; +} +bool StartupState::LinkNetworkSucceedEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::LinkNetworkSucceedEvent.\n"); + INetworkManager::GetInstance()->RegisterNetwork(RegisterNetworkType::MANUAL); + return EXECUTED; +} +bool StartupState::LinkNetworkFailedEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::LinkNetworkFailedEvent.\n"); + if (mSignalState) + { + mSignalState->DeleteState(); + mSignalState.reset(); + } + mSignalState = LedState::SetLedState(SfLedIndex::SF_LED_SIG1, SfLedState::SF_LED_STATE_RED, KEEP_ALIVE_FOREVER, BLINKING_SLOW_MS); + SendAutoShutDownEvent(); + return EXECUTED; +} +bool StartupState::LiveServiceInitEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::LiveServiceInitEvent.\n"); + ILiveManager::GetInstance()->StartLiveService(); + return EXECUTED; +} +bool StartupState::LiveStartMediaEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::LiveStartMediaEvent.\n"); + ILiveManager::GetInstance()->StartLiveMedia(); + return EXECUTED; +} +bool StartupState::LiveStopMediaEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::LiveStopMediaEvent.\n"); + ILiveManager::GetInstance()->StopLiveMedia(); + return EXECUTED; +} +bool StartupState::AuthAndLoginEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::AuthAndLogin.\n"); + NetworkParameter param; + INetworkManager::GetInstance()->GetParameter(param); + LogInfo("imei = %s, iccid = %s\n", param.mIMEI.c_str(), param.mIccid.c_str()); + Param webIp = GetParam(PARAM_NAME_WEB_IP); + LogInfo("webIp = %s\n", webIp.str); + AuthRequestDataIn dataIn(webIp.str, param.mIMEI.c_str(), param.mIccid.c_str()); + AuthRequestDataOut dataOut; + INetworkManager::GetInstance()->AuthRequest(dataIn, dataOut); + LogInfo("acm ip = %s\n", dataOut.mAcmIP.c_str()); + constexpr int CAN_NOT_GET_ACM_IP_FROM_SERVERS = 0; + if (dataOut.mAcmIP.length() != CAN_NOT_GET_ACM_IP_FROM_SERVERS) + { + std::shared_ptr acmServers = std::make_shared(); + AcmServersData acm; + acm.mIMEI = param.mIMEI; + acm.mIccid = param.mIccid; + acm.mAcmIP = dataOut.mAcmIP; + LogInfo("mSignalLevel = %d\n", static_cast(param.mSignalLevel)); + acm.mSignalLevel = param.mSignalLevel; + LogInfo("mServiceProvider = %s\n", param.mServiceProvider.c_str()); + acm.mServiceProvider = param.mServiceProvider; + acm.FcTemper = IDualCoreManager::GetInstance()->GetFcTemper(); + LogInfo("FcTemper = %d\n", acm.FcTemper); + acm.BatRemainCap = IDualCoreManager::GetInstance()->GetBatRemainCap(); + acm.mModuleSubVersion = param.mModuleSubVersion; + LogInfo("acm.mModuleSubVersion = %s\n", acm.mModuleSubVersion.c_str()); + Param appVersion = GetParam(PARAM_NAME_APP_VERSION); + acm.mAppVersion = appVersion.str; + acm.mMcuVersion = IDualCoreManager::GetInstance()->GetMcuVersion(); + acm.mMcuSubVersion = IDualCoreManager::GetInstance()->GetSubMcuVersion(); + acm.mStartupMode = static_cast(CameraStateMachine::GetInstance()->GetStartupMode()); + INetworkManager::GetInstance()->GetAcmServersHandle(acmServers, acm); + AcmLoginResult result; + acmServers->Login(result); + AcmLoginHandle(result); + if (result.mSyncConfig) + { + LogInfo("Sync config after login.\n"); + acmServers->SyncConfig(); + } + } + else + { + LogError("CAN_NOT_GET_ACM_IP_FROM_SERVERS.\n"); + if (mUserState) + { + mUserState->DeleteState(); + mUserState.reset(); + } + mUserState = LedState::SetLedState(SfLedIndex::SF_LED_USERBIND, SfLedState::SF_LED_STATE_RED, KEEP_ALIVE_FOREVER, LED_NOT_BLINK); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::NETWORK_ANOMALY_STATE); + } + SendAutoShutDownEvent(); + return EXECUTED; +} +bool StartupState::UploadSubscribeFilesEvent(VStateMachineMessage *msg) +{ + LogInfo("StartupState::UploadSubscribeFilesEvent.\n"); + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr>> message = + std::dynamic_pointer_cast>>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::vector allResponse = message->mData; + std::vector::iterator iter; + std::vector allUploadFiles; + for (iter = allResponse.begin(); iter != allResponse.end();) + { + SubscribeMessage tmp = *iter; + UploadFileData uploadFile(tmp.mFileTye, tmp.mTargetFileName, ""); + allUploadFiles.push_back(uploadFile); + ++iter; + } + std::shared_ptr message2 = + std::make_shared>>(static_cast(InnerStateEvent::UPLOAD_FILES_VOLUNTARY), allUploadFiles); + CameraStateMachine::GetInstance()->SendStateMessage(message2); + return EXECUTED; +} +void StartupState::AcmLoginHandle(const AcmLoginResult &data) +{ + if (data.mIsLogin) + { + if (mUserState) + { + mUserState->DeleteState(); + mUserState.reset(); + } + mUserState = LedState::SetLedState(SfLedIndex::SF_LED_USERBIND, SfLedState::SF_LED_STATE_GREEN, KEEP_ALIVE_FOREVER, BLINKING_SLOW_MS); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::NETWORK_IDLE_STATE); + if (data.mSubscribleFiles.size() != 0) + { + LogInfo("mSubscribleFiles = %d\n", data.mSubscribleFiles.size()); + std::shared_ptr message = + std::make_shared>>(static_cast(InnerStateEvent::SUBSCRIBLE_UPLOAD_FILES), data.mSubscribleFiles); + CameraStateMachine::GetInstance()->SendStateMessage(message); + } + } + if (data.mOtaUrl.length() != 0) + { + // Upgrade. + LogInfo("Acm login get ota url, will upgrade.\n"); + } +} +void StartupState::SendAutoShutDownEvent(void) +{ + std::shared_ptr message = + std::make_shared(static_cast(InnerStateEvent::AUTO_SHUT_DOWN_START)); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StartupState.h b/code/application/sifarsdk/application/StateManager/src/StartupState.h new file mode 100644 index 000000000..3c5935311 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StartupState.h @@ -0,0 +1,43 @@ +#ifndef STARTUP_STATE_H +#define STARTUP_STATE_H +#include "IStateMachineManager.h" +#include "CameraMessage.h" +#include "StateCameraTask.h" +#include "CameraFilesHandle.h" +#include "LedState.h" +#include "IPeripheralManager.h" +class StartupState : public State, public MessageHandle, public StateCameraTask //, public CameraFilesHandle +{ +public: + StartupState(); + virtual ~StartupState() = default; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + bool SimInitEvent(VStateMachineMessage *msg); + bool UploadSubscribeFilesEvent(VStateMachineMessage *msg); + +protected: + void GoInState() override; + void GoOutState() override; + void SetStartupLedState(const SfLedState &state, const long int &keepAliveTime = KEEP_ALIVE_FOREVER, const unsigned int &blinkPeriod = LED_NOT_BLINK); + void DeleteStartupLedState(void); + +private: + bool RegisterNetworkSucceedEvent(VStateMachineMessage *msg); + bool RegisterNetworkFailedEvent(VStateMachineMessage *msg); + bool ApnConfigSucceedEvent(VStateMachineMessage *msg); + bool ApnConfigFailedEvent(VStateMachineMessage *msg); + bool LinkNetworkSucceedEvent(VStateMachineMessage *msg); + bool LinkNetworkFailedEvent(VStateMachineMessage *msg); + bool LiveServiceInitEvent(VStateMachineMessage *msg); + bool LiveStartMediaEvent(VStateMachineMessage *msg); + bool LiveStopMediaEvent(VStateMachineMessage *msg); + bool AuthAndLoginEvent(VStateMachineMessage *msg); + void AcmLoginHandle(const AcmLoginResult &data); + void SendAutoShutDownEvent(void); + +private: + std::shared_ptr mStartupLedState; + std::shared_ptr mSignalState; + std::shared_ptr mUserState; +}; +#endif // !STARTUP_STATE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StateCameraTask.cpp b/code/application/sifarsdk/application/StateManager/src/StateCameraTask.cpp new file mode 100644 index 000000000..545d3a6cf --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StateCameraTask.cpp @@ -0,0 +1,76 @@ +#include "StateCameraTask.h" +#include "CameraStateMachine.h" +#include "INetworkManager.h" +#include "Log.h" +#include "IConfig.h" +StateCameraTask::StateCameraTask() +{ + // mType = CameraTaskType::END; + mCamera = std::make_shared(); + // mRuningTask = std::make_shared(); +} +void StateCameraTask::Init(void) +{ + // Param mode = GetParam(PARAM_CAMERA_MODE); + // CameraTaskType type = static_cast(mode.numberUInt); + // SetCameraTaskType(type); + ICameraManager::GetInstance()->GetCameraHandle(CameraType::MAIN_CAMERA, mCamera); +} +void StateCameraTask::UnInit(void) +{ + mCamera->ClearTask(); + mCamera = std::make_shared(); + mRuningTask.reset(); +} +void StateCameraTask::MakeOneCameraTask(const InnerStateEvent &bindEvent, const std::shared_ptr &owner) +{ + Param mode = GetParam(PARAM_CAMERA_MODE); + LogInfo("PARAM_CAMERA_MODE = %d\n", mode.numberUInt); + std::shared_ptr task = std::make_shared(static_cast(mode.numberUInt), bindEvent, owner); + auto code = mCamera->ExecuteTask(task); + if (code->IsCodeOK()) + { + mRuningTask = task; // TODO: 无法处理并发任务 + unsigned int timeOut = std::dynamic_pointer_cast(task)->TaskTimeOut(); + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::CAMERA_TASK_TIME_OUT)); // TODO: 未能区分owner + CameraStateMachine::GetInstance()->MessageExecutedLater(message, timeOut); + } + else if (static_cast(CameraManagerReturnCodeDefine::CAMERA_TASK_CAN_EXECUTE_MORE) == code->GetIntCode()) + { + LogInfo("Task exist, stop it.\n"); + mCamera->StopTask(); + } +} +void StateCameraTask::ClearOneTask(void) +{ + CameraStateMachine::GetInstance()->StopTimer(static_cast(InnerStateEvent::CAMERA_TASK_TIME_OUT)); + if (mRuningTask) + { + mCamera->StopTask(); + mRuningTask.reset(); + } +} +void StateCameraTask::ClearAllTask(void) +{ + if (mRuningTask) + { + mCamera->StopTask(); + mRuningTask.reset(); + } +} +void StateCameraTask::UploadFilesToServers(const std::vector &response, const InnerStateEvent &event) +{ + std::vector allResponse = response; + std::vector::iterator iter; + std::vector allUploadFiles; + for (iter = allResponse.begin(); iter != allResponse.end();) + { + CameraTaskResponse tmp = *iter; + UploadFileData uploadFile(tmp.enFileTye, tmp.mThumbFileName, tmp.mThumbFilePath); + allUploadFiles.push_back(uploadFile); + ++iter; + } + std::shared_ptr message = + std::make_shared>>(static_cast(event), allUploadFiles); + CameraStateMachine::GetInstance()->SendStateMessage(message); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StateCameraTask.h b/code/application/sifarsdk/application/StateManager/src/StateCameraTask.h new file mode 100644 index 000000000..f04934738 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StateCameraTask.h @@ -0,0 +1,27 @@ +#ifndef STATE_CAMERA_TASK_H +#define STATE_CAMERA_TASK_H +#include "IHalCommon.h" +#include "CameraMessage.h" +#include "ICameraManager.h" +#include "CameraTaskHandle.h" +class StateCameraTask +{ +public: + StateCameraTask(); + virtual ~StateCameraTask() = default; + void Init(void); + void UnInit(void); + // void SetCameraTaskType(const CameraTaskType &type) { mType = type; } // TODO: delete + void MakeOneCameraTask(const InnerStateEvent &bindEvent, const std::shared_ptr &owner); + void ClearOneTask(void); + void ClearAllTask(void); + +public: + static void UploadFilesToServers(const std::vector &response, const InnerStateEvent &event); + +private: + // CameraTaskType mType; + std::shared_ptr mCamera; + std::shared_ptr mRuningTask; +}; +#endif // !STATE_CAMERA_TASK_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StateManager.cpp b/code/application/sifarsdk/application/StateManager/src/StateManager.cpp new file mode 100644 index 000000000..531cd5155 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StateManager.cpp @@ -0,0 +1,23 @@ +#include "StateManager.h" +#include "StateManagerCode.h" +#include "CameraStateMachine.h" +RETURN_CODE StateManager::Init(void) +{ + auto code = CameraStateMachine::GetInstance()->Init(); + return code; +} +RETURN_CODE StateManager::UnInit(void) +{ + auto code = CameraStateMachine::GetInstance()->UnInit(); + return code; +} +RETURN_CODE StateManager::SendStateMessage(const std::shared_ptr &message) +{ + auto code = CameraStateMachine::GetInstance()->SendStateMessage(message); + return code; +} +RETURN_CODE StateManager::StartCameraStateMachine(const StartupMode &mode) +{ + CameraStateMachine::GetInstance()->StartCameraStateMachine(mode); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StateManager.h b/code/application/sifarsdk/application/StateManager/src/StateManager.h new file mode 100644 index 000000000..7fbf6dd6f --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StateManager.h @@ -0,0 +1,16 @@ +#ifndef STATE_MANAGER_IMPL_H +#define STATE_MANAGER_IMPL_H +#include "IStateManager.h" +class StateManager : public IStateManager +{ +public: + StateManager() = default; + ~StateManager() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + RETURN_CODE SendStateMessage(const std::shared_ptr &message) override; + RETURN_CODE StartCameraStateMachine(const StartupMode &mode) override; + +private: +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StateManagerCode.cpp b/code/application/sifarsdk/application/StateManager/src/StateManagerCode.cpp new file mode 100644 index 000000000..2f2146a55 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StateManagerCode.cpp @@ -0,0 +1,35 @@ +#include "StateManagerCode.h" +#include "Log.h" +const std::string StateMachineCodeDefineStr[static_cast(StateMachineCodeDefine::END) - static_cast(VReturnCodeDefine::END) + 1] = { + "INIT_FAIL", + "AN_INITIALIZED_CODE", + "END"}; +const std::string UNDEFINED_STATE_MACHINE_CODE = "Print failed, undefined state machine code."; +std::shared_ptr StateMachineCode::NewCode(const StateMachineCodeDefine &code) +{ + class MakeShared : public StateMachineCode + { + public: + MakeShared(const int &code) : StateMachineCode(code) {} + }; + return std::make_shared(static_cast(code)); +} +std::string StateMachineCode::PrintStringCode() +{ + if (static_cast(VReturnCode::GetIntCode()) < static_cast(VReturnCodeDefine::END)) + { + return VReturnCode::PrintStringCode(); + } + else + { + if (static_cast(StateMachineCodeDefine::END) <= static_cast(VReturnCode::GetIntCode())) + { + LogError("%s\n", UNDEFINED_STATE_MACHINE_CODE.c_str()); + return UNDEFINED_STATE_MACHINE_CODE; + } + LogInfo("Return code:[ %s %s]\n", + StateMachineCodeDefineStr[static_cast(VReturnCode::GetIntCode()) - static_cast(VReturnCodeDefine::END) + 1].c_str(), + GetTips().c_str()); + return StateMachineCodeDefineStr[static_cast(VReturnCode::GetIntCode()) - static_cast(VReturnCodeDefine::END) + 1]; + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StateManagerCode.h b/code/application/sifarsdk/application/StateManager/src/StateManagerCode.h new file mode 100644 index 000000000..63e9c8a04 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StateManagerCode.h @@ -0,0 +1,25 @@ +#ifndef STATE_MAMAGER_CODE_H +#define STATE_MAMAGER_CODE_H +#include "VReturnCode.h" +#include "IStateManager.h" +class StateMachineCode : public VReturnCode +{ +private: + StateMachineCode(const int &code) : VReturnCode(code) + { + } + +public: + ~StateMachineCode() = default; + std::string PrintStringCode() override; + /** + * @brief + * Create a new return code, which is the only way to create a code shared ptr. + * @param code + * @return std::shared_ptr + */ + static std::shared_ptr NewCode(const StateMachineCodeDefine &code); + +private: +}; +#endif diff --git a/code/application/sifarsdk/application/StateManager/src/StateManagerMakePtr.cpp b/code/application/sifarsdk/application/StateManager/src/StateManagerMakePtr.cpp new file mode 100644 index 000000000..03d7bbb9a --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StateManagerMakePtr.cpp @@ -0,0 +1,118 @@ +#include "StateManagerMakePtr.h" +#include "IStateManager.h" +#include "StateManager.h" +#include "OnKeyState.h" +#include "Log.h" +#include "PirStartState.h" +#include "NormalStartState.h" +#include "RingStartState.h" +#include +bool CreateStateManager(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = StateManagerMakePtr::GetInstance()->CreateStateMachineInstance(instance); + if (code->IsCodeOK()) + { + LogInfo("State machine instance is ok.\n"); + IStateManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &StateManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + /** + * @brief + * The non-thread-safe changing is only for gtest. + */ + instance = *impl; + } + return instance; +} +RETURN_CODE StateManagerMakePtr::CreateStateMachineInstance(std::shared_ptr &instance) +{ + auto tmp = std::make_shared(); + if (tmp) + { + instance = std::move(tmp); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + LogError("Create state machine module failed.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::MAKE_SHARED_PTR_FAILED); +} +std::shared_ptr StateManagerMakePtr::CreateDefaultState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreateStartupState(const StartupMode &mode) +{ + LogInfo("StateManagerMakePtr::CreateStartupState: mode = %d\n", static_cast(mode)); + std::shared_ptr startupState = std::make_shared(); + switch (mode) + { + case StartupMode::STARTUP_MODE_ONKEY: + { + startupState = std::make_shared(); + } + break; + case StartupMode::STARTUP_MODE_PIR: + { + startupState = std::make_shared(); + } + break; + case StartupMode::STARTUP_MODE_NORMAL: + { + startupState = std::make_shared(); + } + break; + case StartupMode::STARTUP_MODE_RING: + { + startupState = std::make_shared(); + } + break; + + default: + LogError("Startup mode is wrong.\n"); + break; + } + return startupState; +} +std::shared_ptr StateManagerMakePtr::CreatePeripheralAbnormalState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreateSimInitState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreateRegisterNetworkState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreateNetworkIdleState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreateNetworkAnomalyState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreateUploadingState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreateUpgradeState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreatePowerOffState(void) +{ + return std::make_shared(); +} +std::shared_ptr StateManagerMakePtr::CreateMSDCState(void) +{ + return std::make_shared(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/StateManagerMakePtr.h b/code/application/sifarsdk/application/StateManager/src/StateManagerMakePtr.h new file mode 100644 index 000000000..168f6c0ab --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/StateManagerMakePtr.h @@ -0,0 +1,38 @@ +#ifndef STATE_MANAGER_MAKE_PTR_H +#define STATE_MANAGER_MAKE_PTR_H +#include "VReturnCode.h" +#include "IStateManager.h" +#include "DefaultState.h" +#include "StartupState.h" +#include "SimInitState.h" +#include "RegisterNetworkState.h" +#include "PeripheralAbnormalState.h" +#include "NetworkIdleState.h" +#include "NetworkAnomalyState.h" +#include "UploadingState.h" +#include "UpgradeState.h" +#include "PowerOffState.h" +#include "MSDCState.h" +#include +class StateManagerMakePtr +{ +public: + StateManagerMakePtr() = default; + virtual ~StateManagerMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE CreateStateMachineInstance(std::shared_ptr &instance); + virtual std::shared_ptr CreateDefaultState(void); + virtual std::shared_ptr CreateStartupState(const StartupMode &mode); + virtual std::shared_ptr CreatePeripheralAbnormalState(void); + virtual std::shared_ptr CreateSimInitState(void); + virtual std::shared_ptr CreateRegisterNetworkState(void); + virtual std::shared_ptr CreateNetworkIdleState(void); + virtual std::shared_ptr CreateNetworkAnomalyState(void); + virtual std::shared_ptr CreateUploadingState(void); + virtual std::shared_ptr CreateUpgradeState(void); + virtual std::shared_ptr CreatePowerOffState(void); + virtual std::shared_ptr CreateMSDCState(void); +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/SynDataState.h b/code/application/sifarsdk/application/StateManager/src/SynDataState.h new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/application/StateManager/src/SynDateState.cpp b/code/application/sifarsdk/application/StateManager/src/SynDateState.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/application/StateManager/src/TimeLapseState.cpp b/code/application/sifarsdk/application/StateManager/src/TimeLapseState.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/application/StateManager/src/TimeLapseState.h b/code/application/sifarsdk/application/StateManager/src/TimeLapseState.h new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/application/StateManager/src/UpgradeState.cpp b/code/application/sifarsdk/application/StateManager/src/UpgradeState.cpp new file mode 100644 index 000000000..4235ce4e3 --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/UpgradeState.cpp @@ -0,0 +1,71 @@ +#include "UpgradeState.h" +#include "Log.h" +#include "CameraStateMachine.h" +UpgradeState::UpgradeState() : State("UpgradeState") +{ + mEventHandle[InnerStateEvent::NETWORK_MODULE_UPGRADE] = + std::bind(&UpgradeState::UpgradeNetworkModuleEvent, this, std::placeholders::_1); +} +void UpgradeState::GoInState() +{ + LogInfo("UpgradeState::GoInState==================== in\n"); + // std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::UPLOADING_FILE_TIME_OUT)); + // CameraStateMachine::GetInstance()->MessageExecutedLater(message, UPLOADING_FILE_TIME_OUT_MS); + mSDCardState = LedState::SetLedState(SfLedIndex::SF_LED_SD, SfLedState::SF_LED_STATE_GREEN, KEEP_ALIVE_FOREVER, BLINKING_FAST_MS); +} +void UpgradeState::GoOutState() +{ + LogInfo("UpgradeState::GoOutState==================== out\n"); + if (mSDCardState) + { + mSDCardState->DeleteState(); + } +} +bool UpgradeState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +void UpgradeState::TaskResult(const UpgradeResult &resutl) +{ + if (UpgradeResult::SUCCEED == resutl) + { + LogInfo("Device will power off.\n"); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::POWER_OFF_STATE); + return; + } + LogError("Upgrade failed.\n"); + CameraStateMachine::GetInstance()->SwitchState(CameraStates::NETWORK_IDLE_STATE); +} +bool UpgradeState::UpgradeNetworkModuleEvent(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::map::iterator iter; + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr> message = std::dynamic_pointer_cast>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + switch (message->mData) + { + case UpgradeType::NETWORK_MODULE: + { + std::shared_ptr task = shared_from_this(); + IUpgradeManager::GetInstance()->Upgrade(task); + break; + } + case UpgradeType::MCU: + break; + case UpgradeType::CPU: + break; + + default: + break; + } + return EXECUTED; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/UpgradeState.h b/code/application/sifarsdk/application/StateManager/src/UpgradeState.h new file mode 100644 index 000000000..bb342807c --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/UpgradeState.h @@ -0,0 +1,26 @@ +#ifndef UPGRADE_STATE_H +#define UPGRADE_STATE_H +#include "CameraMessage.h" +#include "LedState.h" +#include "IUpgradeManager.h" +class UpgradeState + : public State, + public MessageHandle, + public VUpgradeNetworkModuleTask, + public std::enable_shared_from_this +{ +public: + UpgradeState(); + ~UpgradeState() = default; + void TaskResult(const UpgradeResult &resutl) override; + +private: + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + bool UpgradeNetworkModuleEvent(VStateMachineMessage *msg); + +private: + std::shared_ptr mSDCardState; +}; +#endif // !UPGRADE_STATE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/UploadTaskHandle.cpp b/code/application/sifarsdk/application/StateManager/src/UploadTaskHandle.cpp new file mode 100644 index 000000000..e20eb56cf --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/UploadTaskHandle.cpp @@ -0,0 +1,50 @@ +#include "UploadTaskHandle.h" +#include "Log.h" +unsigned int UploadTaskHandle::mTaskIndex = 0; +UploadTaskHandle::UploadTaskHandle(const std::vector &files, const std::weak_ptr owner, const unsigned int &index) + : mFiles(files), mOwner(owner), mIndex(index) +{ +} +void UploadTaskHandle::CreateOneTask(const std::vector &files, const std::weak_ptr owner, + std::shared_ptr &task) +{ + class MakeUploadTask : public UploadTaskHandle + { + public: + MakeUploadTask(const std::vector &files, const std::weak_ptr owner, const unsigned int &index) + : UploadTaskHandle(files, owner, index) {} + }; + UploadTaskHandle::mTaskIndex++; // TODO: What happen if out of range. + task = std::make_shared(files, owner, UploadTaskHandle::mTaskIndex); +} +void UploadTaskHandle::UploadResultResponse(const UploadFileData &file, const UploadResult &result) +{ + FileResult fileResult(file, result); + mResults.push_back(fileResult); + LogInfo("Upload file name = %s\n", file.mSendFileWithTime.c_str()); + if (mFiles.size() == mResults.size()) + { + LogInfo("UploadTaskHandle:SendFileResult\n"); + auto owner = mOwner.lock(); + if (!owner) + { + LogWarning("Owner is nullptr.\n"); + return; + } + if (mOwner.expired()) + { + LogWarning("Owner shared ptr expired failed.\n"); + return; + } + std::shared_ptr thisTask = shared_from_this(); + owner->UploadResultResponse(thisTask); + } +} +const std::vector UploadTaskHandle::GetFiles(void) +{ + return mFiles; +} +bool UploadTaskHandle::IsThisTask(const std::shared_ptr &task) +{ + return task->GetIndex() == mIndex ? true : false; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/UploadTaskHandle.h b/code/application/sifarsdk/application/StateManager/src/UploadTaskHandle.h new file mode 100644 index 000000000..60e3f1ece --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/UploadTaskHandle.h @@ -0,0 +1,34 @@ +#ifndef UPLOAD_TASK_HANDLE_H +#define UPLOAD_TASK_HANDLE_H +#include "INetworkManager.h" +#include +class VUploadTaskOwner +{ +public: + VUploadTaskOwner() = default; + virtual ~VUploadTaskOwner() = default; + virtual void UploadResultResponse(std::shared_ptr &task) = 0; +}; +class UploadTaskHandle : public VUploadTask, public std::enable_shared_from_this +{ +protected: + UploadTaskHandle(const std::vector &files, const std::weak_ptr owner, const unsigned int &index); + +public: + ~UploadTaskHandle() = default; + static void CreateOneTask(const std::vector &files, const std::weak_ptr owner, + std::shared_ptr &task); + void UploadResultResponse(const UploadFileData &file, const UploadResult &result) override; + const std::vector GetFiles(void) override; + const std::vector &GetResult(void) { return mResults; } + bool IsThisTask(const std::shared_ptr &task); + const unsigned int &GetIndex(void) { return mIndex; } + +private: + const std::vector mFiles; + std::vector mResults; + const std::weak_ptr mOwner; + const unsigned int mIndex; + static unsigned int mTaskIndex; +}; +#endif // !UPLOAD_TASK_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/UploadingState.cpp b/code/application/sifarsdk/application/StateManager/src/UploadingState.cpp new file mode 100644 index 000000000..f9de5708f --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/UploadingState.cpp @@ -0,0 +1,319 @@ +#include "UploadingState.h" +#include "UploadingState.h" +#include "Log.h" +#include "CameraStateMachine.h" +#include "FileManager.h" +#include "IHalCommon.h" +#include +#include +UploadingState::UploadingState() : State("UploadingState") +{ + mEventHandle[InnerStateEvent::UPLOAD_FILES_VOLUNTARY] = + std::bind(&UploadingState::UploadFileToServersEvent, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::UPLOAD_FILE_ALL_FINISHED] = + std::bind(&UploadingState::StateUploadFileFinished, this, std::placeholders::_1); + mEventHandle[InnerStateEvent::UPLOADING_FILE_TIME_OUT] = + std::bind(&UploadingState::StateUploadFileTimeOut, this, std::placeholders::_1); +} +UploadingState::~UploadingState() +{ +} +void UploadingState::GoInState() +{ + LogInfo("UploadingState::GoInState==================== in\n"); + AcmLoginResult loginData; + if (!mAcmServers) + { + INetworkManager::GetInstance()->GetAcmServersHandle(mAcmServers); + mAcmServers->GetLoginDate(loginData); + } + if (!mFileServers) + { + NetworkParameter parm; + INetworkManager::GetInstance()->GetParameter(parm); + LogInfo("imei = %s", parm.mIMEI.c_str()); + FileServersData data(loginData, parm.mIMEI); + INetworkManager::GetInstance()->GetFileServersHandle(mFileServers, data); + } + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::UPLOADING_FILE_TIME_OUT)); + CameraStateMachine::GetInstance()->MessageExecutedLater(message, UPLOADING_FILE_TIME_OUT_MS); +} +void UploadingState::GoOutState() +{ + LogInfo("UploadingState::GoOutState==================== out\n"); + mFileServers->StopUploading(); +} +bool UploadingState::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return MessageHandle::EventHandle(msg); +} +void UploadingState::UploadResultResponse(std::shared_ptr &task) +{ + std::shared_ptr uploadTask = std::dynamic_pointer_cast(task); + if (uploadTask) + { + LogInfo("Send upload result to acm servers.\n"); + mAcmServers->SendFileResult(uploadTask->GetResult()); + DeleteOneTask(uploadTask); + } + if (mAllTasks.size() == 0) + { + std::shared_ptr message = + std::make_shared(static_cast(InnerStateEvent::UPLOAD_FILE_ALL_FINISHED)); + CameraStateMachine::GetInstance()->SendStateMessage(message); + } +} +bool UploadingState::UploadFileToServersEvent(VStateMachineMessage *msg) +{ + LogInfo("UploadingState::UploadFileToServersEvent.\n"); + return StateUploadFile(msg); +} +void UploadingState::CreateOneTask(const std::vector &files) +{ + // std::vector allFiles = files; + // UploadingState::CreateThumbFiles(allFiles); + std::vector allFiles; + UploadingState::CheckUploadFiles(files, allFiles); + std::shared_ptr task; + UploadTaskHandle::CreateOneTask(allFiles, shared_from_this(), task); + if (task) + { + AddOneTask(task); + mFileServers->UploadFiles(task); + } + else + { + LogError("Create upload task failed.\n"); + } +} +void UploadingState::CheckUploadFiles(const std::vector &files, std::vector &result) +{ + if (files.empty()) + { + LogWarning("Files is empty.\n"); + } + else + { + std::vector tmp = files; + std::vector::iterator iter; + for (iter = tmp.begin(); iter != tmp.end();) + { + constexpr int NULL_STRING_MEANS_SUBSCRIBLE = 0; + if (NULL_STRING_MEANS_SUBSCRIBLE != (*iter).thumbfilePath.length()) + { + LogInfo("upload thumb file = (%s) len = %d\n", (*iter).thumbfilePath.c_str(), (*iter).thumbfilePath.length()); + UploadingState::CreateThumbFile(*iter); + sf_file_size_get((*iter).thumbfilePath.c_str(), &((*iter).thumbfileSize)); + result.push_back(*iter); + } + else + { + LogInfo("upload subscribe file.\n"); + UploadingState::sf_file_subscribe_check(*iter, result); + } + ++iter; + } + } +} +SINT16 UploadingState::sf_file_subscribe_check(const UploadFileData &file, std::vector &result) +{ + UINT16 dirKey = 0; + UINT16 fileKey = 0; + SINT16 ret = 0; + char tempStr[6] = {0}; + char fileName[16] = {0}; + char filePath[128] = {0}; + char thumbfileName[64] = {0}; + char thumbfilePath[128] = {0}; + switch (file.enFileTye) + { + case SF_FILE_TYPE_VIDEO_WVGA: + case SF_FILE_TYPE_VIDEO_720P: + case SF_FILE_TYPE_VIDEO_1080P: + { + LogInfo("SubFileName [%s]\n", file.thumbfileName.c_str()); + strncpy(tempStr, file.thumbfileName.c_str() + (file.thumbfileName.length() - 11), 3); + dirKey = atoi(tempStr); + LogInfo("DIRstr:%s, dirKey:%d\n", tempStr, dirKey); + strncpy(fileName, file.thumbfileName.c_str() + (file.thumbfileName.length() - 12), 12); + fileKey = atoi(fileName + 4); + LogInfo("FileName:%s, fileKey:%d\n", fileName, fileKey); + sprintf(filePath, "%s%s/%03d%s/%s%04d.%s", SF_SD_ROOT, SF_DCF_ROOT_DIR_NAME, dirKey, SF_DCF_DIR_NAME_SUFFIX, SF_DCF_FILE_NAME_PREFIX, fileKey, SF_DCF_EXT_MOV); + LogInfo("srcFile:%s\n", filePath); + ret = sf_file_IsExsit((const char *)filePath); + // pstfileAttr->enFileTye = file.enFileTye; + if (ret != SF_TRUE) + { + LogWarning("[%s] not existed in SD!!!\n", filePath); + break; + } + sprintf(thumbfileName, "%s%04d.%s", SF_DCF_FILE_NAME_PREFIX, fileKey, SF_DCF_EXT_MOV); + sprintf(thumbfilePath, "%s", filePath); + LogInfo("fileName:%s\n", thumbfileName); + LogInfo("thumbfilePath:%s\n", thumbfilePath); + UploadFileData realFile(file.enFileTye, thumbfileName, thumbfilePath); + realFile.mBindFile = file.thumbfileName; + sf_file_size_get(realFile.thumbfilePath.c_str(), &(realFile.thumbfileSize)); + result.push_back(realFile); + break; + } + case SF_FILE_TYPE_PIC_3M: + case SF_FILE_TYPE_PIC_5M: + { + strncpy(tempStr, file.thumbfileName.c_str() + (file.thumbfileName.length() - 11), 3); + dirKey = atoi(tempStr); + LogInfo("DIRstr:%s, dirKey:%d\n", tempStr, dirKey); + strncpy(fileName, file.thumbfileName.c_str() + (file.thumbfileName.length() - 12), 12); + fileKey = atoi(fileName + 4); + LogInfo("FileName:%s, fileKey:%d\n", fileName, fileKey); + sprintf(filePath, "%s%s/%03d%s/%s%s", SF_SD_ROOT, SF_DCF_ROOT_DIR_NAME, dirKey, SF_DCF_DIR_NAME_SUFFIX, SF_DCF_FILE_NAME_PREFIX, fileName + 4); + LogInfo("srcFile:%s\n", filePath); + ret = sf_file_IsExsit((const char *)filePath); + // pstfileAttr->enFileTye = file.enFileTye; + if (ret != SF_TRUE) + { + LogWarning("[%s] not existed in SD!!!\n", filePath); + break; + } + sprintf(thumbfileName, "%s%s", SF_DCF_FILE_NAME_PREFIX, fileName + 4); + sprintf(thumbfilePath, "%s", filePath); + LogInfo("fileName:%s\n", thumbfileName); + LogInfo("thumbfilePath:%s\n", thumbfilePath); + UploadFileData realFile(file.enFileTye, thumbfileName, thumbfilePath); + realFile.mBindFile = file.thumbfileName; + sf_file_size_get(realFile.thumbfilePath.c_str(), &(realFile.thumbfileSize)); + result.push_back(realFile); + break; + } + case SF_FILE_TYPE_LOG_ERROR: + { + sprintf(filePath, "%s%s", SF_SD_ROOT, "SF_GPS.TXT"); + LogInfo("srcFile:%s\n", filePath); + ret = sf_file_IsExsit((const char *)filePath); + // pstfileAttr->enFileTye = SF_FILE_TYPE_LOG_ERROR; + if (ret != SF_TRUE) + { + LogWarning("[%s] not existed in SD!!!\n", filePath); + break; + } + sprintf(thumbfileName, "%s", "SF_CAMERA.TXT"); + sprintf(thumbfilePath, "%s", filePath); + LogInfo("fileName:%s\n", thumbfileName); + LogInfo("thumbfilePath:%s\n", thumbfilePath); + UploadFileData realFile(SF_FILE_TYPE_LOG_ERROR, thumbfileName, thumbfilePath); + realFile.mBindFile = file.thumbfileName; + sf_file_size_get(realFile.thumbfilePath.c_str(), &(realFile.thumbfileSize)); + result.push_back(realFile); + break; + } + default: + ret = -1; + LogInfo("CMD[%d] no process!!!\n", file.enFileTye); + } + + if (ret != SF_TRUE) + return -1; + return SF_SUCCESS; +} +void UploadingState::AddOneTask(const std::shared_ptr &task) +{ + std::lock_guard locker(mMutex); + mAllTasks.push_back(task); +} +void UploadingState::DeleteOneTask(const std::shared_ptr &task) +{ + std::lock_guard locker(mMutex); + std::vector>::iterator iter; + for (iter = mAllTasks.begin(); iter != mAllTasks.end();) + { + if ((*iter)->IsThisTask(task)) + { + iter = mAllTasks.erase(iter); + break; + } + ++iter; + } +} +bool UploadingState::StateUploadFile(VStateMachineMessage *msg) +{ + if (nullptr == msg) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + std::shared_ptr cameraMessage = std::dynamic_pointer_cast(msg->GetMessageObj()); + std::shared_ptr>> message = + std::dynamic_pointer_cast>>(cameraMessage->mMessage); + if (!message) + { + LogError("nullptr pointer.\n"); + return NOT_EXECUTED; + } + auto uploadFilesThread = [](const std::vector &files, std::shared_ptr uploadingState) + { + uploadingState->CreateOneTask(files); + }; + std::thread uploadThread(uploadFilesThread, message->mData, shared_from_this()); + uploadThread.detach(); + return EXECUTED; +} +bool UploadingState::StateUploadFileFinished(VStateMachineMessage *msg) +{ + if (mAllTasks.size() == 0) + { + CameraStateMachine::GetInstance()->SwitchState(CameraStates::NETWORK_IDLE_STATE); + CameraStateMachine::GetInstance()->StopTimer(static_cast(InnerStateEvent::UPLOADING_FILE_TIME_OUT)); + } + return EXECUTED; +} +bool UploadingState::StateUploadFileTimeOut(VStateMachineMessage *msg) +{ + std::shared_ptr message = std::make_shared(static_cast(InnerStateEvent::UPLOADING_FILE_TIME_OUT)); + CameraStateMachine::GetInstance()->MessageExecutedLater(message, UPLOADING_FILE_TIME_OUT_MS); + return EXECUTED; +} +SINT16 UploadingState::CreateThumbFiles(std::vector &files) +{ + if (files.empty()) + { + LogWarning("Files is empty.\n"); + } + else + { + std::vector::iterator iter; + for (iter = files.begin(); iter != files.end();) + { + UploadingState::CreateThumbFile(*iter); + sf_file_size_get((*iter).thumbfilePath.c_str(), &((*iter).thumbfileSize)); + LogInfo("UploadingState::CreateThumbFiles: thumbfileSize = %d\n", (*iter).thumbfileSize); + ++iter; + } + } + return SF_SUCCESS; +} +SINT16 UploadingState::CreateThumbFile(const UploadFileData &file) +{ + SF_CHAR sysCmd[256] = {0}; + SF_CHAR dirKeyStr[4] = {0}; + SF_CHAR fileKeyStr[10] = {0}; + SF_CHAR filePathStr[128] = {0}; + if (strstr(file.thumbfileName.c_str(), SF_DCF_EXT_PHOTO)) + { + strncpy(dirKeyStr, file.thumbfileName.c_str() + 1, 3); + strncpy(fileKeyStr, file.thumbfileName.c_str() + 4, 8); + LogInfo("dirKeyStr:%s, fileKeyStr:%s\n", dirKeyStr, fileKeyStr); + sprintf(filePathStr, "%s%s/%s%s/%s%s", SF_SD_ROOT, SF_DCF_ROOT_DIR_NAME, dirKeyStr, SF_DCF_DIR_NAME_SUFFIX, SF_DCF_FILE_NAME_PREFIX, fileKeyStr); + LogInfo("filePathStr:%s\n", filePathStr); + if (sf_file_IsExsit(filePathStr) == SF_TRUE) + { + sprintf(sysCmd, "/customer/bin/ffmpeg -i %s -v quiet -y -s 640*360 %s", filePathStr, file.thumbfilePath.c_str()); + LogInfo("[%s,%d]cmd: %s\n", __FUNCTION__, __LINE__, sysCmd); + system(sysCmd); + } + else + { + LogError("File doesn't exsit.\n"); + } + } + return SF_SUCCESS; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/StateManager/src/UploadingState.h b/code/application/sifarsdk/application/StateManager/src/UploadingState.h new file mode 100644 index 000000000..0dc87401c --- /dev/null +++ b/code/application/sifarsdk/application/StateManager/src/UploadingState.h @@ -0,0 +1,39 @@ +#ifndef UPLOADING_STATE_H +#define UPLOADING_STATE_H +#include "IStateMachineManager.h" +#include "CameraMessage.h" +#include "INetworkManager.h" +#include "UploadTaskHandle.h" +#include +constexpr int UPLOADING_FILE_TIME_OUT_MS = 1000 * 30; +class UploadingState : public State, public MessageHandle, public VUploadTaskOwner, public std::enable_shared_from_this +{ +public: + UploadingState(); + virtual ~UploadingState(); + void UploadResultResponse(std::shared_ptr &task) override; + + static SINT16 CreateThumbFiles(std::vector &files); + static SINT16 CreateThumbFile(const UploadFileData &file); + static SINT16 sf_file_subscribe_check(const UploadFileData &file, std::vector &result); + +private: + void GoInState() override; + void GoOutState() override; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; + bool UploadFileToServersEvent(VStateMachineMessage *msg); + void CreateOneTask(const std::vector &files); + void CheckUploadFiles(const std::vector &files, std::vector &result); + void AddOneTask(const std::shared_ptr &task); + void DeleteOneTask(const std::shared_ptr &task); + bool StateUploadFile(VStateMachineMessage *msg); + bool StateUploadFileFinished(VStateMachineMessage *msg); + bool StateUploadFileTimeOut(VStateMachineMessage *msg); + +private: + std::mutex mMutex; + std::shared_ptr mAcmServers; + std::shared_ptr mFileServers; + std::vector> mAllTasks; +}; +#endif // !UPLOADING_STATE_H \ No newline at end of file diff --git a/code/application/sifarsdk/application/main/CMakeLists.txt b/code/application/sifarsdk/application/main/CMakeLists.txt new file mode 100644 index 000000000..d0601fc9e --- /dev/null +++ b/code/application/sifarsdk/application/main/CMakeLists.txt @@ -0,0 +1,45 @@ +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + + +set(MAIN_INCLUDE_PATH "${APPLICATION_SOURCE_PATH}/main/src" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${APPLICATION_SOURCE_PATH}/StateManager/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${APPLICATION_SOURCE_PATH}/NetworkManager/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/Log/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/ReturnCode/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/StateMachineManager/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/PeripheralManager/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/CameraManager/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/Config/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/SystemTime/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/DualCoreManager/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/McuManager/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/LiveManager/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${COMPONENT_SOURCE_PATH}/AtCommand/include" CACHE STRING INTERNAL FORCE) +set(MAIN_INCLUDE_PATH "${MAIN_INCLUDE_PATH};${HAL_SOURCE_PATH}/include" CACHE STRING INTERNAL FORCE) +include_directories(${MAIN_INCLUDE_PATH}) + +link_directories( + ${LIBS_OUTPUT_PATH} +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) +# aux_source_directory(./src SRC_FILES) + +# Mark src files for test. +file(GLOB_RECURSE MAIN_SRC_FILE_THIS src/*.cpp src/*.c) +set(MAIN_SRC_FILE "${MAIN_SRC_FILE_THIS}" CACHE STRING INTERNAL FORCE) + +set(TARGET_NAME hunting_x86) +add_executable(${TARGET_NAME} ${SRC_FILES} ${MAIN_SRC_FILE}) + +set(LINK_LIB Hal StateManager StateMachineManager CameraManager Config SystemTime DualCoreManager McuManager UpgradeManager LiveManager AtCommand ReturnCode Log pthread dl) +set(MAIN_LINK_LIB "${LINK_LIB}" CACHE STRING INTERNAL FORCE) +target_link_libraries(${TARGET_NAME} ${MAIN_LINK_LIB}) +if(${COVERAGE_ON} MATCHES "true") + target_link_libraries(${TARGET_NAME} gcov) +endif() diff --git a/code/application/sifarsdk/application/main/main.cpp b/code/application/sifarsdk/application/main/main.cpp new file mode 100644 index 000000000..eb47e5e93 --- /dev/null +++ b/code/application/sifarsdk/application/main/main.cpp @@ -0,0 +1,53 @@ +#include "MainThread.h" +#include "Log.h" +// #include "IStateManager.h" +// #include "IStateMachineManager.h" +#include +#include + +// #include "MainThreadCustomization.h" +// #include "DefaultStateCustomization.h" + +static void *mainCustomizationModule = nullptr; + +static void OpenCustomizationMainThread(void) +{ + #if 0 + // Use dlopen Series function to create a customization main instance. + mainCustomizationModule = dlopen("./MainCustomization.so", RTLD_LAZY); + if (mainCustomizationModule) + { + LogInfo("There is no customization function.\n"); + return; + } + dlerror(); + std::shared_ptr (*createCustomizationModule)(void) = nullptr; + createCustomizationModule = (std::shared_ptr(*)(void))dlsym(mainCustomizationModule, "CreateCustomizationModule"); + if (createCustomizationModule) + { + std::shared_ptr customization1 = createCustomizationModule(); + MainThread::GetInstance(&customization1); + } + + // Or init the customization main instance here. + std::shared_ptr customization2 = std::shared_ptr(); + MainThread::GetInstance(&customization2); + #endif +} +static void ReleaseCustomizationMainThread(void) +{ + if (mainCustomizationModule) + { + dlclose(mainCustomizationModule); + mainCustomizationModule = nullptr; + } +} +int main(int argc, char *argv[]) +{ + OpenCustomizationMainThread(); + MainThread::GetInstance()->Init(); + MainThread::GetInstance()->Runing(); + MainThread::GetInstance()->UnInit(); + ReleaseCustomizationMainThread(); + return 0; +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/main/src/MainThread.cpp b/code/application/sifarsdk/application/main/src/MainThread.cpp new file mode 100644 index 000000000..b0b8a8f0b --- /dev/null +++ b/code/application/sifarsdk/application/main/src/MainThread.cpp @@ -0,0 +1,129 @@ +#include "MainThread.h" +#include "Log.h" +#include "IStateManager.h" +#include "IStateMachineManager.h" +#include "IHal.h" +#include "INetworkManager.h" +#include "IPeripheralManager.h" +#include "ICameraManager.h" +#include "IConfig.h" +#include "ISystemTime.h" +#include "IDualCoreManager.h" +#include "IMcuManager.h" +#include "ILiveManager.h" +#include "IAtCommand.h" +#include +const char *SIFAR_SDK_VERSION = "4SD1HKrCC06"; +MainThread::MainThread() +{ + mMainThreadRuning = false; +} +std::shared_ptr &MainThread::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} +RETURN_CODE MainThread::Init(void) +{ + mMainThreadRuning = true; + InitLog(LOG_EASYLOGGING, nullptr); + LogTrace("main start.\n"); + CreateAllModules(); + IHal::GetInstance()->Init(); + IDualCoreManager::GetInstance()->Init(); + IMcuManager::GetInstance()->Init(); + ConfigInitV2(); + SystemTimeInit(); + IAtCommand::GetInstance()->Init(); + IPeripheralManager::GetInstance()->Init(); + ICameraManager::GetInstance()->Init(); + INetworkManager::GetInstance()->Init(); + IStateManager::GetInstance()->Init(); + ILiveManager::GetInstance()->Init(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE MainThread::UnInit(void) +{ + ILiveManager::GetInstance()->UnInit(); + IStateManager::GetInstance()->UnInit(); + INetworkManager::GetInstance()->UnInit(); + ICameraManager::GetInstance()->UnInit(); + IPeripheralManager::GetInstance()->UnInit(); + IAtCommand::GetInstance()->UnInit(); + SystemTimeUnInit(); + ConfigUnInit(); + IMcuManager::GetInstance()->UnInit(); + IDualCoreManager::GetInstance()->UnInit(); + IHal::GetInstance()->UnInit(); + UnInitLog(); + DestoryAllModules(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE MainThread::CreateAllModules(void) +{ + CustomizationInit(); + CreateHalModuleInstance(); // Make hal module firstly to init the chip. + CreateDualManager(); + CreateMcuManager(); + CreateSystemTimeModule(); + CreateConfig(); + CreateStateManager(); + CreateStateMachineManager(); + CreateNetworkManagerModule(); + CreatePeripheralManager(); + CreateCameraManager(); + // CreateLiveManager(); + CreateAtCommandModule(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void MainThread::DestoryAllModules(void) +{ + auto liveManager = std::make_shared(); + ILiveManager::GetInstance(&liveManager); + auto stateManager = std::make_shared(); + IStateManager::GetInstance(&stateManager); + auto networkManager = std::make_shared(); + INetworkManager::GetInstance(&networkManager); + auto cameraManager = std::make_shared(); + ICameraManager::GetInstance(&cameraManager); + auto peripheralManager = std::make_shared(); + IPeripheralManager::GetInstance(&peripheralManager); + auto mcuManager = std::make_shared(); + IMcuManager::GetInstance(&mcuManager); + auto dualCoreManager = std::make_shared(); + IDualCoreManager::GetInstance(&dualCoreManager); + auto halManager = std::make_shared(); + IHal::GetInstance(&halManager); +} +void MainThread::ResetAllPtrMaker(void) +{ +} +void MainThread::Runing(void) +{ + // mMainThreadRuning = true; + while (mMainThreadRuning) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/application/main/src/MainThread.h b/code/application/sifarsdk/application/main/src/MainThread.h new file mode 100644 index 000000000..d7b8925d3 --- /dev/null +++ b/code/application/sifarsdk/application/main/src/MainThread.h @@ -0,0 +1,24 @@ +#ifndef MAIN_THREAD_H +#define MAIN_THREAD_H +#include "VReturnCode.h" +class MainThread +{ +public: + MainThread(); + virtual ~MainThread() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void); + virtual RETURN_CODE UnInit(void); + void Runing(void); + void Exit(void) { mMainThreadRuning = false; } + virtual void CustomizationInit(void) {} + +private: + RETURN_CODE CreateAllModules(void); + void DestoryAllModules(void); + void ResetAllPtrMaker(void); + +private: + bool mMainThreadRuning; +}; +#endif // !MAIN_THREAD_H \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/README.md b/code/application/sifarsdk/at-command/README.md new file mode 100644 index 000000000..37adb5fa4 --- /dev/null +++ b/code/application/sifarsdk/at-command/README.md @@ -0,0 +1,33 @@ +# 1. AT指令差异化代码适配 + +## 1.1. 概述 +   由于不同厂家的移动网络模块的AT指令有较大差异,暂时使用独立的文件对AT指令和相关逻辑进行维护。架构设计上满足任意芯片芯片可适配任意的AT指令集,所以独立目录管理,仅仅源码独立目录存放,使用时和依赖AT指令集接口的模块源码一起编译成目标文件。 + +## 1.2. 添加新AT指令集方法: +   通过在芯片的工具链配置cmake文件添加路径来选择使用哪个模块(或者版本)的AT指令集源码,实现任意平台可配置任意的AT指令集进行编译链接。 + +以./at-command/eg91为例: + +1. 在此目录新建一个目录,例如“eg91”,存放新模块或者新指令集的代码; +2. 创建AT指令相关接口类文件,参考eg91目录创建一一对应的cpp文件; +3. 创建名为at-command.cmake的配置文件,负责把源码加入到PeripheralManager模块,如存在多版本继承可构建多个源码目录。 + +## 1.3. 项目构建时选择AT指令集方法 +``` +#参考./333DE/build/cmake/toolchain/sigmastart_333DE.toolchain.cmake +set(AT_COMMAND_PATH "${CMAKE_SOURCE_DIR}/at-command/eg91") +``` +   相关模块会使用上述变量(AT_COMMAND_PATH)把该路径下的源码加入到依赖文件集合里面进行项目构建,在编译时链接该目录的所有源码文件。 +例如:./component/PeripheralManager/CMakeLists.txt +``` +# At command src code. +string(COMPARE EQUAL "${AT_COMMAND_PATH}" "" value) +message("The at-command src code path is ${AT_COMMAND_PATH}.") +if (value EQUAL 0) #变量被设置了 +message("build at-command src code.") +include(${AT_COMMAND_PATH}/at-command.cmake) +endif() +``` + +## 1.4. 项目客制化实现 +   at-command目录源码为SifarSDK的公版AT指令集源码,项目在AT指令代码需要修改时,可继承并重载相关函数即可,无需也禁止因为项目需求而修改at-command目录下的源码文件。 diff --git a/code/application/sifarsdk/at-command/eg91/AtDataProcess.cpp b/code/application/sifarsdk/at-command/eg91/AtDataProcess.cpp new file mode 100644 index 000000000..a641b57ed --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtDataProcess.cpp @@ -0,0 +1,34 @@ +#include "AtDataProcess.h" +#include "Log.h" +#include +SINT32 AtDataProcess::eg91_module_Polling_Comparison_CIMI(SF_CHAR *operatorName) +{ + UINT8 i = 0; + static UINT8 CIMIcount = 0; + static SF_CHAR strCIMI[5][8] = {0}; + + LogInfo("CIMIcount = %d,operatorName = [%s]\n", CIMIcount, operatorName); + if (operatorName == SF_NULL) + return SF_FAILURE; + + if (CIMIcount > 5) + return SF_FAILURE; + + for (i = 0; i < 5; i++) + { + LogInfo("strCIMI[%d]: [%s]\n", i, strCIMI[i]); + if (strncmp(strCIMI[i], operatorName, 5) == 0) + return SF_FAILURE; + else + { + if (strlen(strCIMI[i]) == 0) + { + memcpy(strCIMI[i], operatorName, 5); + CIMIcount++; + LogInfo("strCIMI[%d]: [%s]\n", i, strCIMI[i]); + return SF_SUCCESS; + } + } + } + return SF_SUCCESS; +} \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtDataProcess.h b/code/application/sifarsdk/at-command/eg91/AtDataProcess.h new file mode 100644 index 000000000..74febe9b8 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtDataProcess.h @@ -0,0 +1,13 @@ +#ifndef AT_DATA_PROCESS_H +#define AT_DATA_PROCESS_H +#include "SfTypeDefine.h" +class AtDataProcess +{ +public: + AtDataProcess() = default; + virtual ~AtDataProcess() = default; + +protected: + SINT32 eg91_module_Polling_Comparison_CIMI(SF_CHAR *operatorName); +}; +#endif // !AT_DATA_PROCESS_H \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtDefine.h b/code/application/sifarsdk/at-command/eg91/AtDefine.h new file mode 100644 index 000000000..fd2393a59 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtDefine.h @@ -0,0 +1,20 @@ +#ifndef AT_DEFINE_H +#define AT_DEFINE_H + +#define GPRS_MODULE_TYPE_EG91 "EG91" +#define GPRS_MODULE_TYPE_EG95 "EG95" +// #define EG91 "EG91" +// #define EG95 "EG95" +#define APNGPRS_WUYUAN "America.bics" +#define APNGPRS_WUYUAN2 "bicsapn" +#define APNGPRSTEMP "CTNET" +// constexpr int SF_MODULE_VER_MAX_LEN = 50; +constexpr int GSN_BUF_LENGTH = 22; +constexpr int ICCID_BUF_LENGTH = 21; +constexpr int OPERATION_CODE_LENGTH = 6; + +// #define E_PDP_INDEX 7 +// #define V_PDP_INDEX 3 +// #define A_PDP_INDEX 1 + +#endif // !AT_DEFINE_H \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtRegisterNetwork.cpp b/code/application/sifarsdk/at-command/eg91/AtRegisterNetwork.cpp new file mode 100644 index 000000000..d975d6592 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtRegisterNetwork.cpp @@ -0,0 +1,65 @@ +#include "AtRegisterNetwork.h" +#include "Log.h" +#include +void AtRegisterNetwork::RegisterNetworkManual(void) +{ + // TODO: 4G module has already connected ??? + SetManualFlag(true); + auto registerNetworkThreadStart = [](std::shared_ptr atRegisterNetwork) + { + std::dynamic_pointer_cast(atRegisterNetwork)->AtRegisterNetworkManual::RegisterNetworkStart(); + }; + std::thread simInit(registerNetworkThreadStart, SharedFromThis()); + simInit.detach(); +} +void AtRegisterNetwork::AtRegisterNetworkAuto(void) +{ + // TODO: 4G module has already connected ??? + auto registerNetworkThreadStart = [](std::shared_ptr atRegisterNetwork) + { + std::dynamic_pointer_cast(atRegisterNetwork)->AtRegisterNetworkAuto::RegisterNetworkStart(); + }; + std::thread registerNetwork(registerNetworkThreadStart, SharedFromThis()); + registerNetwork.detach(); +} +void AtRegisterNetwork::UsbNetApnConfigStart(void) +{ + constexpr int AT_COMMAND_BUF_LENGTH = 1024; + char atCommand[AT_COMMAND_BUF_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SIM_INFO_S simInfo; + memset(&simInfo, 0, sizeof(SIM_INFO_S)); + GetSimInfo(&simInfo); + std::shared_ptr task_0 = std::make_shared("AT\r", response, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task_0); + SetAtCallTimes(0); + sprintf(atCommand, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", GetPdpIndex(), + simInfo.ApnGPRS, simInfo.ApnUsername, simInfo.ApnPassword); + std::shared_ptr task = std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); + LogInfo("QICSGP command : %s\n", atCommand); +QICSGP_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + if (strstr(response, "OK")) + { + LogInfo("Net apn config succeed.\n"); + AtNetApnConfigResult(NetApnConfigResult::SUCCEED); + return; + } + if (UsbNetApnConfigRetry()) + { + goto QICSGP_RETRY; + } +} +bool AtRegisterNetwork::UsbNetApnConfigRetry(unsigned int defaultRetry) +{ + AtCallOnce(); + if (GetAtCallTimes() <= defaultRetry) + { + LogInfo("Retry to call, call times = %d.\n", GetAtCallTimes()); + return true; + } + LogInfo("Net apn config succeed.\n"); + AtNetApnConfigResult(NetApnConfigResult::FAILED); + return false; +} \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtRegisterNetwork.h b/code/application/sifarsdk/at-command/eg91/AtRegisterNetwork.h new file mode 100644 index 000000000..5afec4e06 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtRegisterNetwork.h @@ -0,0 +1,16 @@ +#ifndef AT_REGISTER_NETWORK_H +#define AT_REGISTER_NETWORK_H +#include "AtRegisterNetworkManual.h" +class AtRegisterNetwork : public AtRegisterNetworkManual +{ +public: + AtRegisterNetwork() = default; + virtual ~AtRegisterNetwork() = default; + void RegisterNetworkManual(void) override; + void AtRegisterNetworkAuto(void) override; + void UsbNetApnConfigStart(void); + +private: + bool UsbNetApnConfigRetry(unsigned int defaultRetry = 200); +}; +#endif // !AT_REGISTER_NETWORK_H \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkAuto.cpp b/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkAuto.cpp new file mode 100644 index 000000000..3cf903ea4 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkAuto.cpp @@ -0,0 +1,17 @@ +#include "AtRegisterNetworkAuto.h" +#include "Log.h" +AtRegisterNetworkAuto::AtRegisterNetworkAuto() +{ + mGeneration = NetGeneration::END; +} +void AtRegisterNetworkAuto::RegisterNetworkStart(void) +{ + LogInfo("AT-Command:AT+QSIMSTAT?\n"); + // std::shared_ptr> task = + // std::make_shared>("AT+QSIMSTAT?\r", &AtRegisterNetworkAuto::QSIMSTAT_Callback, SharedFromThis()); + // SendAtCommandTask(task); +} +ResponseCode AtRegisterNetworkAuto::QSIMSTAT_Callback(const char *buf, const unsigned int &length) +{ + return ResponseCode::RESPONSE_OK; +} \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkAuto.h b/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkAuto.h new file mode 100644 index 000000000..e29400884 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkAuto.h @@ -0,0 +1,21 @@ +#ifndef AT_REGISTER_NETWORK_AUTO_H +#define AT_REGISTER_NETWORK_AUTO_H +#include "VAtRegisterNetwork.h" +#include "AtDefine.h" +#include "AtDataProcess.h" +class AtRegisterNetworkAuto : public VAtRegisterNetwork, public AtDataProcess +{ +public: + AtRegisterNetworkAuto(); + virtual ~AtRegisterNetworkAuto() = default; + +protected: + virtual void RegisterNetworkStart(void); + ResponseCode QSIMSTAT_Callback(const char *buf, const unsigned int &length); + +protected: + NetGeneration mGeneration; + +private: +}; +#endif // !AT_REGISTER_NETWORK_AUTO_H \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkManual.cpp b/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkManual.cpp new file mode 100644 index 000000000..af9f409f9 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkManual.cpp @@ -0,0 +1,427 @@ +#include "AtRegisterNetworkManual.h" +#include "Log.h" +#include "sf_opera_adapt_v2.h" +#include +AtRegisterNetworkManual::AtRegisterNetworkManual() +{ + mManual = false; + mQCFG_Times = 0; +} +bool AtRegisterNetworkManual::RegisterNetworkManualRetry(unsigned int defaultRetry) +{ + AtCallOnce(); + if (GetAtCallTimes() <= defaultRetry) + { + LogInfo("Retry to call, call times = %d.\n", GetAtCallTimes()); + return true; + } + // SetAtCallTimes(); + LogError("Register network manual failed.\n"); + AtRegisterNetworkResult(RegisterNetworkResult::FAILED); + return false; +} +void AtRegisterNetworkManual::RegisterNetworkStart(void) +{ + LogInfo("AT-Command:AT+CGREG?\n"); + CGREG_Handle(); +} +const char *AT_CGREG = "AT+CGREG?\r"; +void AtRegisterNetworkManual::CGREG_Handle(void) +{ + constexpr int CGREG_RETRY_TIMES = 400; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_CGREG, response, RESPONSE_BUF_LENGTH); +CGREG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CGREG_Handle, response = %s\n", response); + if (strstr(response, "+CGREG: 0,")) + { + if (strstr(response, "+CGREG: 0,1") || strstr(response, "+CGREG: 0,5")) + { + LogInfo("reg net sucess:%s\n", response); + QCFG_Handle(); + return; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(400)); + if (GetAtCallTimes() > 320) + { + CIMI_Handle(); + return; + } + else if (GetAtCallTimes() > 180) + { + if ((!strstr(GetApnGprs(), APNGPRS_WUYUAN2)) && (!strstr(GetApnGprs(), APNGPRS_WUYUAN))) + { + LogError("Other sim reg net timeout!\n"); + AtRegisterNetworkResult(RegisterNetworkResult::ERROR_REG_NET); + return; + } + } + } + } + if (RegisterNetworkManualRetry(CGREG_RETRY_TIMES)) + { + goto CGREG_RETRY; + } +} +const char *AT_QCFG_PDP = "AT+QCFG=\"pdp/duplicatechk\",0\r"; +void AtRegisterNetworkManual::QCFG_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG_PDP, response, RESPONSE_BUF_LENGTH); +QCFG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + QCFG_TCP_1_Handle(); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QCFG_RETRY; + } +} +void AtRegisterNetworkManual::CIMI_Handle(void) +{ + constexpr int OPERATION_CODE_LENGTH = 6; + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SF_CHAR *pTemp = nullptr; + SINT16 ret = SF_FAIL; + SF_CHAR operationCode[OPERATION_CODE_LENGTH] = {0}; + SIM_INFO_S pStaticParam; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared("AT+CIMI\r", response, RESPONSE_BUF_LENGTH); +CIMI_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + // memset(atCommand, 0, AT_COMMAND_LENGTH); + SendAtCommandTask(task); + + pTemp = nullptr; + pTemp = strstr(response, "AT+CIMI"); + if (pTemp) + { + memcpy(operationCode, pTemp + 10, 5); + LogInfo("operationCode:%s\n", operationCode); + + ret = eg91_module_Polling_Comparison_CIMI(operationCode); + if (ret != SF_SUCCESS) + // return SF_4G_ERROR_NO_SUPPOET; + { + AtRegisterNetworkResult(RegisterNetworkResult::FAILED_NOT_SUPPORT); + return; + } + + LogInfo("operationCode:%s\n", operationCode); + sprintf(pStaticParam.OperatorCode, "%s", operationCode); + + sf_auto_operation_adaptation(pStaticParam.OperatorCode, &pStaticParam); + if ((strstr(pStaticParam.ApnGPRS, APNGPRS_WUYUAN2)) || (strstr(pStaticParam.ApnGPRS, APNGPRS_WUYUAN))) // mega sim,use in abord + { + + // enMmcLocation = SIM_REG_NET_FIRST_2; + sprintf(atCommand, "AT+CGDCONT=1,\"IPV4V6\",\"%s\"\r", pStaticParam.ApnGPRS); + // sf_hal_ttyusb2_write(response, strlen(response)); + CGDCONT_Handle(atCommand); + return; + } + else + { + // return SF_4G_ERROR_NO_SUPPOET; + AtRegisterNetworkResult(RegisterNetworkResult::FAILED_NOT_SUPPORT); + return; + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (RegisterNetworkManualRetry()) + { + goto CIMI_RETRY; + } +} +const char *AT_QCFG_TCP_1 = "AT+QCFG=\"tcp/windowsize\",0,100\r"; +void AtRegisterNetworkManual::QCFG_TCP_1_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG_TCP_1, response, RESPONSE_BUF_LENGTH); +QCFG_TCP_1_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_TCP_1_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + QCFG_TCP_2_Handle(); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QCFG_TCP_1_RETRY; + } +} +const char *AT_QCFG_TCP_2 = "AT+QCFG=\"tcp/windowsize\",1,100\r"; +void AtRegisterNetworkManual::QCFG_TCP_2_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG_TCP_2, response, RESPONSE_BUF_LENGTH); +QCFG_TCP_2_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_TCP_2_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + QNWINFO_Handle(); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QCFG_TCP_2_RETRY; + } +} +const char *AT_QNWINFO = "AT+QNWINFO\r"; +void AtRegisterNetworkManual::QNWINFO_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QNWINFO, response, RESPONSE_BUF_LENGTH); +QNWINFO_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QNWINFO_Handle, response = %s\n", response); + if (strstr(response, "+QNWINFO:") != nullptr) + { + if (strstr(response, "No Service")) + { + mGeneration = NetGeneration::NET_2G; + } + else if (nullptr != strtok(response, "\"")) + { + SF_CHAR netStr[20] = {0}; + strcpy(netStr, strtok(nullptr, "\"")); + LogInfo("netStr:%s\n", netStr); + if ((strstr(netStr, "DD") != nullptr)) + { + mGeneration = NetGeneration::NET_4G; + } + else if (strstr(netStr, "CDMA") != nullptr || strstr(netStr, "HDR") != nullptr || strstr(netStr, "HSUPA") != nullptr || strstr(netStr, "HSDPA") != nullptr || strstr(netStr, "HSPA+") != nullptr) + { + mGeneration = NetGeneration::NET_3G; + } + else + { + mGeneration = NetGeneration::NET_2G; + } + } + AtGetGeneration(mGeneration); + COPS_Handle(); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QNWINFO_RETRY; + } +} +const char *AT_COPS = "AT+COPS?\r"; +void AtRegisterNetworkManual::COPS_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_COPS, response, RESPONSE_BUF_LENGTH); +COPS_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("COPS_Handle, response = %s\n", response); + SF_CHAR *pStr = nullptr; + if (strstr(response, "+COPS:") != nullptr) + { + strtok(response, "\""); + pStr = strtok(nullptr, "\""); + if (pStr != nullptr) + { + LogInfo("cops1 is %s\r\n", pStr); + AtGetServiceProvider(pStr); + } + + if (NetGeneration::NET_4G == mGeneration) // NetGeneration == 4 + { + QCSQ_Handle(); + return; + } + else + { + CSQ_Handle(); + return; + } + } + if (RegisterNetworkManualRetry()) + { + goto COPS_RETRY; + } +} +const char *AT_QCSQ = "AT+QCSQ\r"; +void AtRegisterNetworkManual::QCSQ_Handle(void) +{ + constexpr int QCSQ_RETRY_TIMES = 10; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCSQ, response, RESPONSE_BUF_LENGTH); +QCSQ_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCSQ_Handle, response = %s\n", response); + SF_CHAR *pStr = nullptr; + SINT32 csq = 0; + UINT8 simSignal = 0; + if (strstr(response, "+QCSQ:")) + { + pStr = nullptr; + pStr = strtok(response, ","); + LogInfo("pStr:%s\n", pStr); + pStr = strtok(nullptr, ","); + LogInfo("pStr:%s\n", pStr); + if (pStr != nullptr) + { + pStr = strtok(nullptr, ","); + // LogInfo("pStr:%s\n", pStr); + csq = 0 - atoi(pStr); + // LogInfo("SINT32:%d\n", csq); + // pStaticParam->SimSignal = (UINT8)csq; // TODO: Get data?? + simSignal = (UINT8)csq; + if (simSignal == 0) + { + if (GetAtCallTimes() >= 10) + { + simSignal = 105; + } + } + else + { + AT_AND_W_Handle(); + AtGetSimSignal(simSignal); + AtRegisterNetworkResult(RegisterNetworkResult::SUCCEED); + return; + } + } + else + { + simSignal = 0; + AtRegisterNetworkResult(RegisterNetworkResult::FAILED_NO_SIGNAL); + AtGetSimSignal(simSignal); + AT_AND_W_Handle(); + return; + } + if (RegisterNetworkManualRetry(QCSQ_RETRY_TIMES)) + { + goto QCSQ_RETRY; + } + AtGetSimSignal(simSignal); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QCSQ_RETRY; + } +} +void AtRegisterNetworkManual::CSQ_Handle(void) +{ + constexpr int CSQ_RETRY_TIMES = 10; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared("AT+CSQ\r", response, RESPONSE_BUF_LENGTH); +CSQ_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CSQ_Handle, response = %s\n", response); + SF_CHAR *pStr = nullptr; + SINT32 csq = 0; + UINT8 simSignal = 0; + if (strstr(response, "+CSQ:")) + { + LogInfo("%s", response); + SF_CHAR *pTemp = nullptr; + pStr = strstr(response, "+CSQ:") + 6; + LogInfo("pStr:%s\n", pStr); + pTemp = strtok(pStr, ","); + LogInfo("pTemp:%s\n", pTemp); + if (pTemp != nullptr) + { + csq = atoi(pTemp); + if ((csq > 31) || (csq == 0)) + { + if (GetAtCallTimes() >= CSQ_RETRY_TIMES) + { + simSignal = 0; + AtRegisterNetworkResult(RegisterNetworkResult::FAILED_NO_SIGNAL); + } + } + else + { + simSignal = csq; + AtGetSimSignal(simSignal); + AtRegisterNetworkResult(RegisterNetworkResult::SUCCEED); + AT_AND_W_Handle(); + return; + } + } + if (RegisterNetworkManualRetry(CSQ_RETRY_TIMES)) + { + goto CSQ_RETRY; + } + AtGetSimSignal(simSignal); + return; + } + if (RegisterNetworkManualRetry()) + { + goto CSQ_RETRY; + } +} +const char *AT_W = "AT&W\r"; +void AtRegisterNetworkManual::AT_AND_W_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_W, response, RESPONSE_BUF_LENGTH); +AT_AND_W_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("AT_AND_W_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + LogInfo("AT_AND_W_Handle ok.\n"); + // AtRegisterNetworkResult(RegisterNetworkResult::SUCCEED); + return; + } + if (RegisterNetworkManualRetry()) + { + goto AT_AND_W_RETRY; + } +} +void AtRegisterNetworkManual::CGDCONT_Handle(const char *atCommand) +{ + constexpr int AT_LENGTH = 1024; + char at[AT_LENGTH] = {0}; + memcpy(at, atCommand, strlen(atCommand)); + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +CGDCONT_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CGDCONT_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + CGREG_Handle(); + } + if (RegisterNetworkManualRetry()) + { + goto CGDCONT_RETRY; + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkManual.h b/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkManual.h new file mode 100644 index 000000000..d00d86fb3 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtRegisterNetworkManual.h @@ -0,0 +1,32 @@ +#ifndef AT_REGISTER_NETWORK_MANUAL_H +#define AT_REGISTER_NETWORK_MANUAL_H +#include "AtRegisterNetworkAuto.h" +class AtRegisterNetworkManual : public AtRegisterNetworkAuto +{ +public: + AtRegisterNetworkManual(); + virtual ~AtRegisterNetworkManual() = default; + void SetManualFlag(const bool &flag) { mManual = flag; } + +protected: + void RegisterNetworkStart(void) override; + virtual void CGREG_Handle(void); + virtual void QCFG_Handle(void); + virtual void CIMI_Handle(void); + virtual void QCFG_TCP_1_Handle(void); + virtual void QCFG_TCP_2_Handle(void); + virtual void QNWINFO_Handle(void); + virtual void COPS_Handle(void); + virtual void QCSQ_Handle(void); + virtual void CSQ_Handle(void); + virtual void AT_AND_W_Handle(void); + virtual void CGDCONT_Handle(const char *atCommand); + +private: + bool RegisterNetworkManualRetry(unsigned int defaultRetry = 200); + +private: + bool mManual; + unsigned int mQCFG_Times; +}; +#endif // !AT_REGISTER_NETWORK_MANUAL_H \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtSimInit.cpp b/code/application/sifarsdk/at-command/eg91/AtSimInit.cpp new file mode 100644 index 000000000..95aedd398 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtSimInit.cpp @@ -0,0 +1,786 @@ +#include "AtSimInit.h" +#include "IPeripheralManager.h" +#include "Log.h" +#include "sf_opera_adapt_v2.h" +#include +const char *AT_COMMAND_ATE = "ATE1\r"; +// class NetworkATTaskV2 : public VNetworkTask +// { +// public: +// NetworkATTaskV2(const char *command, ResponseCode (AtSimInit::*response)(const char *, const unsigned int &), +// std::shared_ptr network) +// : mATCommand(command), mResponse(response), mNetwork(network) +// { +// } +// ~NetworkATTaskV2() +// { +// } +// const char *GetWriteBuf(void) override +// { +// return mATCommand; +// } +// unsigned int GetWriteBufLength(void) override +// { +// return strlen(mATCommand); +// } +// bool IsTaskBlock(void) override +// { +// return true; +// } +// unsigned int RetryTimes(void) override +// { +// return 200; +// } +// ResponseCode Response(const char *buf, const unsigned int &length) override +// { +// if (mResponse) +// { +// ResponseCode code = ((dynamic_cast(mNetwork.get()))->*mResponse)(buf, length); +// return code; +// } +// return ResponseCode::RESPONSE_OK; +// } + +// const char *mATCommand; +// ResponseCode (AtSimInit::*mResponse)(const char *, const unsigned int &); +// std::shared_ptr mNetwork; +// }; +AtSimInit::AtSimInit() +{ + mModuelV05 = 0; + memset(GsnSaved, 0, GSN_BUF_LENGTH); + memset(ModuleVersion, 0, SF_MODULE_VER_MAX_LEN); + memset(lastICCID, 0, ICCID_BUF_LENGTH); + mInitRuning = false; +} +void AtSimInit::UnInit(void) +{ + LogInfo("AtSimInit::UnInit.\n"); + mInitRuning = false; + if (mInitThread.joinable()) + { + mInitThread.join(); + } +} +RETURN_CODE AtSimInit::AtSimCardInit(void) +{ + // TODO: 4G module has already connected ??? + auto SimInitThreadStart = [](std::shared_ptr atCommand) + { + std::dynamic_pointer_cast(atCommand)->AtSimInitStart(); + }; + // std::thread simInit(SimInitThreadStart, SharedFromThis()); + // simInit.detach(); + if (mInitRuning) + { + LogWarning("AtSimCardInit runing.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + mInitRuning = true; + mInitThread = std::thread(SimInitThreadStart, SharedFromThis()); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void AtSimInit::AtSimInitStart(void) +{ + ATE_Handle(); +} +bool AtSimInit::SimInitRetry(void) +{ + if (!mInitRuning) + { + LogWarning("Stop Init.\n"); + return false; + } + constexpr int SIM_INIT_CALL_RETRY = 200; + AtCallOnce(); + if (GetAtCallTimes() <= SIM_INIT_CALL_RETRY) + { + LogInfo("Retry to call, call times = %d.\n", GetAtCallTimes()); + return true; + } + // SetAtCallTimes(); + LogError("Sim card init failed.\n"); // TODO: + return false; +} +void AtSimInit::ATE_Handle(void) +{ + LogInfo("AT-Command:ATE1\n"); + SetAtCallTimes(0); + char response[RESPONSE_BUF_LENGTH] = {0}; + std::shared_ptr task = std::make_shared(AT_COMMAND_ATE, response, RESPONSE_BUF_LENGTH); +ATE_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("AtSimInitStart. response = %s\n", response); + if (strstr(response, "OK")) + { + LogInfo("ATE_Handle response ok.\n"); + AT_GSN_Handle(); + return; + } + if (SimInitRetry()) + { + goto ATE_RETRY; + } +} +const char *AT_GSN = "AT+GSN\r"; +void AtSimInit::AT_GSN_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_GSN, response, RESPONSE_BUF_LENGTH); +AT_GSN_RETRY: + if (!mInitRuning) + { + LogWarning("Stop Init.\n"); + return; + } + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + unsigned int length = std::dynamic_pointer_cast(task)->ActualResponseLength(); + LogInfo("AT_GSN_Handle. response = %s\n", response); + UINT16 index = 0; + SF_CHAR GsnNow[GSN_BUF_LENGTH] = {0}; + if (response[0] != '\0') + { + for (index = 0; index < length; index++) + { + if ((response[index] == '8') && (response[index + 1] == '6')) + { + SF_CHAR tempImei[16] = {0}; + UINT8 p = 0; + for (p = 0; p < IMEI_LEN; p++) + { + if ((response[p + index] >= '0') && (response[p + index] <= '9')) + tempImei[p] = response[p + index]; + else + tempImei[p] = '\0'; + } + tempImei[15] = '\0'; + strcpy(GsnNow, tempImei); + break; + } + } + } + LogInfo("GsnNow = %s\n", GsnNow); + LogInfo("GsnSaved = %s\n", GsnSaved); + if ((GsnNow[0] != '\0') && (strncmp(GsnNow, GsnSaved, IMEI_LEN) == 0)) + { + AtGetIMEI(GsnNow); + ATI_Handle(); + return; + } + else + { + LogWarning("RESPONSE_FAILED_RETRY.\n"); + strcpy(GsnSaved, GsnNow); + goto AT_GSN_RETRY; + } + if (SimInitRetry()) + { + goto AT_GSN_RETRY; + } +} +const char *AT_ATI = "ATI\r"; +void AtSimInit::ATI_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_ATI, response, RESPONSE_BUF_LENGTH); +ATI_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("ATI_Handle.buf = %s\n", response); + SF_CHAR *pTemp = nullptr; + SF_CHAR *p = nullptr; + if ((strstr(response, "OK") != nullptr) || (strstr(response, "ERROR") != nullptr)) + { + pTemp = strstr(response, "Revision:"); + if (pTemp != nullptr) + { + SF_CHAR modulVerStr[256] = {0}; + strcpy(modulVerStr, pTemp + 10); + pTemp = strtok(modulVerStr, "OK"); + p = strtok(pTemp, "\r\n"); + if (strcasecmp(p, ModuleVersion) != 0) + { + strcpy(ModuleVersion, p); + } + } + if ((strstr(response, "AFAR05"))) + { + SetModuleV05(1); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + QFLST_1_Handle("at+qflst=\"../../usr/fota_ip_a/update_report.ur\"\r"); + } + else if (strstr(response, "AFAR07")) + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + QFLST_1_Handle("at+qflst=\"../../data/fota_ip_a/update_report.ur\"\r"); + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + QGMR_Handle(); + } + return; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (SimInitRetry()) + { + goto ATI_RETRY; + } +} +const char *AT_QGMR = "AT+QGMR\r"; +void AtSimInit::QGMR_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QGMR, response, RESPONSE_BUF_LENGTH); +QGMR_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QGMR_Handle.response = %s\n", response); + if (strstr(response, GPRS_MODULE_TYPE_EG91) != nullptr) + { + char subTemp[SF_MODULE_VER_MAX_LEN] = {0}; + eg91_parse_module_version((SF_CHAR *)strstr(response, GPRS_MODULE_TYPE_EG91), subTemp); + AtGetModuleSubVersion(subTemp); + if (strstr(ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) + { + QNVFR_Handle(); + } + else + { + QSIMSTAT_Handle(); + } + return; + } + else if (strstr(response, GPRS_MODULE_TYPE_EG95) != nullptr) + { + char subTemp[SF_MODULE_VER_MAX_LEN] = {0}; + eg91_parse_module_version((SF_CHAR *)strstr(response, GPRS_MODULE_TYPE_EG95), subTemp); + AtGetModuleSubVersion(subTemp); + if (strstr(ModuleVersion, GPRS_MODULE_TYPE_EG95_V)) + { + QNVFR_Handle(); + } + else + { + QSIMSTAT_Handle(); + } + return; + } + else + { + if (GetAtCallTimes() > 5) + { + if (strstr(ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) + { + QNVFR_Handle(); + } + else if (strstr(ModuleVersion, GPRS_MODULE_TYPE_EG95_V)) + { + QNVFR_Handle(); + } + else + { + QSIMSTAT_Handle(); + } + return; + } + if (SimInitRetry()) + { + goto QGMR_RETRY; + } + } +} +const char *AT_QSIMSTAT = "AT+QSIMSTAT?\r"; +void AtSimInit::QSIMSTAT_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = + std::make_shared(AT_QSIMSTAT, response, RESPONSE_BUF_LENGTH); +QSIMSTAT_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QSIMSTAT_Handle. response=%s\n", response); + if (strstr(response, "+QSIMSTAT: 0,0")) + { + if (GetAtCallTimes() > 50) + { + LogError("SimCard not inserted.\n"); + AtSimInitResult(SimInitResult::SIM_INIT_NOT_INSERTED); + return; + } + if (SimInitRetry()) + { + LogWarning("QSIMSTAT_RETRY.\n"); + goto QSIMSTAT_RETRY; + } + } + else if (strstr(response, "+QSIMSTAT: 0,1")) + { + LogInfo("SIM_INIT_QURCCFG.\n"); + QURCCFG_Handle(); + return; + } + else if (strstr(response, "+CPIN: NOT INSERTED")) + { + LogError("SimCard not inserted.\n"); + AtSimInitResult(SimInitResult::SIM_INIT_NOT_INSERTED); + return; + } + if (SimInitRetry()) + { + goto QSIMSTAT_RETRY; + } +} +void AtSimInit::AT_END_Handle(char *atCommand) +{ + constexpr int AT_LENGTH = 1024; + SetAtCallTimes(0); + char response[RESPONSE_BUF_LENGTH] = {0}; + char at[AT_LENGTH] = {0}; + memcpy(at, atCommand, strlen(atCommand)); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); + // AT_END_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("AT_END_Handle. response = %s\n", response); + if (strstr(response, "OK")) + { + LogInfo("Sim card init ok.\n"); + AtSimInitResult(SimInitResult::SIM_INIT_OK); + return; + } + else if (strstr(response, "NOT")) + { + LogError("Sim card init failed, no sim card.\n"); + AtSimInitResult(SimInitResult::SIM_INIT_NOT_INSERTED); + return; + } + else + { + LogWarning("What happened?\n"); + if ((GetAtCallTimes() % 10) == 0) + { // TODO: What happend? No need to handle response? + memset(response, 0, RESPONSE_BUF_LENGTH); + std::shared_ptr task2 = + std::make_shared("AT+CPIN?\r", response, RESPONSE_BUF_LENGTH); // TODO: + SendAtCommandTask(task2); + } + } +} +void AtSimInit::QNVFR_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = + std::make_shared("at+qnvfr=\"/nv/item_files/modem/uim/gstk/feature_bmsk\"\r", response, RESPONSE_BUF_LENGTH); +QNVFR_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QNVFR_Handle.\n"); + if (strstr(response, "+QNVFR: 11000000")) + { + QNVFW_Handle(); + return; + } + else + { + AT_END_Handle((char *)"AT\r"); + return; + } + if (SimInitRetry()) + { + goto QNVFR_RETRY; + } +} +void AtSimInit::QNVFW_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = + std::make_shared("at+qnvfw=\"/nv/item_files/modem/uim/gstk/feature_bmsk\",01000000\r", response, RESPONSE_BUF_LENGTH); +QNVFW_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QNVFW_Handle.\n"); + if (strstr(response, "OK")) + { + AT_END_Handle((char *)"AT\r"); + return; + } + if (SimInitRetry()) + { + goto QNVFW_RETRY; + } +} +void AtSimInit::QFLST_1_Handle(const char *atCommand) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QFLST_1_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QFLST_1_Handle.\n"); + if (strstr(response, "OK")) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + QGMR_Handle(); + return; + } + else if (strstr(response, "ERROR: 417")) + { + UINT8 modulev05 = GetModuleV05(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + if (modulev05 == 1) + { + QFLST_2_Handle("at+qfopen=\"../../usr/fota_ip_a/update_report.ur\",1\r"); + } + else + { + QFLST_2_Handle("at+qfopen=\"../../data/fota_ip_a/update_report.ur\",1\r"); + } + return; + } + else + { + if (GetAtCallTimes() > 10) + { + SetAtCallTimes(0); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + QFLST_2_Handle("ATI\r"); + return; + } + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (SimInitRetry()) + { + goto QFLST_1_RETRY; + } + } +} +void AtSimInit::QFLST_2_Handle(const char *atCommand) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QFLST_2_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QFLST_2_Handle.\n"); + if (strstr(response, "OK")) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + QGMR_Handle(); + return; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ATI_Handle(); + return; + } + if (SimInitRetry()) + { + goto QFLST_2_RETRY; + } +} +const char *AT_QURCCFG = "AT+QURCCFG=\"urcport\",\"usbat\"\r"; +void AtSimInit::QURCCFG_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + std::shared_ptr task = std::make_shared(AT_QURCCFG, response, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QSIMSTAT_Handle. response=%s\n", response); // TODO: ?? + QCFG_1_Handle(); +} +const char *AT_QCFG = "AT+QCFG=\"risignaltype\",\"physical\"\r"; +void AtSimInit::QCFG_1_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG, response, RESPONSE_BUF_LENGTH); +QCFG_1_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_1_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + QCFG_2_Handle(); + return; + } + if (SimInitRetry()) + { + goto QCFG_1_RETRY; + } +} +const char *AT_QCFG_2 = "AT+QCFG=\"urc/ri/other\",\"off\"\r"; +void AtSimInit::QCFG_2_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG_2, response, RESPONSE_BUF_LENGTH); +QCFG_2_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_2_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + QLWCFG_1_Handle(); + return; + } + if (SimInitRetry()) + { + goto QCFG_2_RETRY; + } +} +const char *AT_QLWCFG = "AT+QLWCFG=\"urc\",0\r"; +void AtSimInit::QLWCFG_1_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QLWCFG, response, RESPONSE_BUF_LENGTH); +QLWCFG_1_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QLWCFG_1_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + QLWCFG_2_Handle(); + return; + } + if (SimInitRetry()) + { + goto QLWCFG_1_RETRY; + } +} +const char *AT_QLWCFG_2 = "AT+QLWCFG=\"startup\",0\r"; +void AtSimInit::QLWCFG_2_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QLWCFG_2, response, RESPONSE_BUF_LENGTH); +QLWCFG_2_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QLWCFG_2_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + CPIN_Handle(); + return; + } + if (SimInitRetry()) + { + goto QLWCFG_2_RETRY; + } +} +const char *AT_CPIN = "AT+CPIN?\r"; +void AtSimInit::CPIN_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_CPIN, response, RESPONSE_BUF_LENGTH); +CPIN_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CPIN_Handle. response=%s\n", response); + if (strstr(response, "READY")) + { + QCCID_Handle(); + return; + } + if (SimInitRetry()) + { + goto CPIN_RETRY; + } +} +const char *AT_QCCID = "AT+QCCID\r"; +void AtSimInit::QCCID_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCCID, response, RESPONSE_BUF_LENGTH); +QCCID_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCCID_Handle. response=%s\n", response); + SF_CHAR *pStr = nullptr; + SF_CHAR tempICCID[ICCID_BUF_LENGTH] = {0}; + if ((strstr(response, "+QCCID: ") != nullptr)) + { + pStr = strstr(response, "+QCCID: "); + memcpy(tempICCID, pStr + 8, 20); + if ((tempICCID[19] <= '9') && (tempICCID[19] >= '0')) + tempICCID[20] = '\0'; + else + tempICCID[19] = '\0'; + if (strncmp(lastICCID, tempICCID, 21) == 0) + { + LogInfo("ICCID=%s\n", tempICCID); + AtGetICCID(tempICCID); + CIMI_Handle(); + return; + } + else + { + strcpy(lastICCID, tempICCID); + memset(tempICCID, '\0', sizeof(tempICCID)); + goto QCCID_RETRY; + } + } + if (SimInitRetry()) + { + goto QCCID_RETRY; + } +} +const char *AT_CIMI = "AT+CIMI\r"; +void AtSimInit::CIMI_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_CIMI, response, RESPONSE_BUF_LENGTH); +CIMI_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CIMI_Handle. response=%s\n", response); + SF_CHAR operationCode[OPERATION_CODE_LENGTH] = {0}; + SF_CHAR *pTemp = nullptr; + SIM_INFO_S simInfo = {0}; + pTemp = strstr(response, "AT+CIMI"); + constexpr int SF_TTYUSB_RECV_MAX = 580; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = {0}; + if (pTemp) + { + memcpy(operationCode, pTemp + 10, 5); + LogInfo("operationCode:%s\n", operationCode); + sprintf(simInfo.OperatorCode, "%s", operationCode); + sf_auto_operation_adaptation(simInfo.OperatorCode, &simInfo); + LogInfo("ApnGPRS:%s\n", simInfo.ApnGPRS); + if ((strstr(simInfo.ApnGPRS, APNGPRS_WUYUAN2)) || (strstr(simInfo.ApnGPRS, APNGPRS_WUYUAN))) // 20408 sifar kpn sim + { + AtGetSimType(SF_SIM_MEGA); + // 1. mega sim,set pdp 1 apn + eg91_module_Polling_Comparison_CIMI(operationCode); // mega sim,recorde sim operation code + sprintf(ttyData, "AT+CGDCONT=1,\"IPV4V6\",\"%s\"\r", simInfo.ApnGPRS); + AT_END_Handle(ttyData); + return; + } + else if (strstr(simInfo.ApnGPRS, APNGPRSTEMP)) + { + AtGetSimType(SF_SIM_MEGA_IOT); + AT_END_Handle((char *)"AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + return; + } + else + { + // AtSimInitResult(SimInitResult::SIM_INIT_NOT_SUPPORT_MOBILE_NETWORK); + AtSimInitResult(SimInitResult::SIM_INIT_OK); + return; + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (SimInitRetry()) + { + goto CIMI_RETRY; + } +} +void AtSimInit::CGDCONT_Handle(void) +{ + // LogInfo("CGDCONT_Handle. buf=%s\n", buf); +} +SINT32 AtSimInit::eg91_parse_module_version(SF_CHAR *pTemp, SF_CHAR *version) +{ + SF_CHAR *pT1 = nullptr; + SF_CHAR *pT2 = nullptr; + SF_CHAR *pT3 = nullptr; + SF_CHAR *pT4 = nullptr; + + pT1 = strstr(pTemp, "FAR"); + pT2 = strstr(pTemp, "_"); + pT3 = strstr(pTemp, "GAR"); + pT4 = strstr(pTemp, "OCPU"); + + LogInfo("pTemp = %s\n", pTemp); + LogInfo("pT1 = %s\n", pT1); + LogInfo("pT2 = %s\n", pT2); + LogInfo("pT3 = %s\n", pT3); + + if (pT1 != nullptr) + eg91_parse_module_version_detail(pTemp, pT1, pT2, pT4, version); + else if (pT3 != nullptr) + eg91_parse_module_version_detail(pTemp, pT3, pT2, pT4, version); + + LogInfo("version:%s\n", version); + return SF_SUCCESS; +} +void AtSimInit::eg91_parse_module_version_detail(SF_CHAR *pTemp, SF_CHAR *pT1, SF_CHAR *pT2, SF_CHAR *pT4, SF_CHAR *version) +{ + // FILE_HEADER *sim_info_t = sf_statistics_param_get(); + const char *moduleVersion = GetModuleVersionParam(); + SF_CHAR str0[5] = {0}; + SF_CHAR str1[5] = {0}; + SF_CHAR str2[5] = {0}; + SF_CHAR str3[5] = {0}; + SF_CHAR str4[256] = {0}; + SF_CHAR str5[256] = {0}; + SF_CHAR *pT5 = nullptr; + memcpy(str1, pTemp + 4, pT1 - pTemp - 4); + // printf("str1 = %s\n", str1); + memcpy(str2, pT1 + 3, 2); + // printf("str2 = %s\n", str2); + memcpy(str3, pT1 + 6, 2); + // printf("str3 = %s\n", str3); + + if (strstr(moduleVersion, GPRS_MODULE_TYPE_EG91)) + { + sprintf(str0, "%s", "91"); + } + else if (strstr(moduleVersion, GPRS_MODULE_TYPE_EG95)) + { + sprintf(str0, "%s", "95"); + } + else + { + sprintf(str0, "%s", "UN"); + } + + if (pT2 != nullptr) + { + strcpy(str4, pT2 + 1); + // printf("str4 = %s\n", str4); + pT5 = strtok(str4, "\r\n"); + + if (pT5 != nullptr) + { + strcpy(str5, pT5); + // printf("str5 = %s\n",str5); + + if (pT4 != nullptr) + sprintf(version, "S%sY%sY%sY%sY%sOS", str0, str1, str2, str3, str5); + else + sprintf(version, "S%sY%sY%sY%sY%sS", str0, str1, str2, str3, str5); + } + else + { + if (pT4 != nullptr) + sprintf(version, "S%sY%sY%sY%sOS", str0, str1, str2, str3); + else + sprintf(version, "S%sY%sY%sY%sS", str0, str1, str2, str3); + } + } + else + { + if (pT4 != nullptr) + sprintf(version, "S%sY%sY%sY%sOS", str0, str1, str2, str3); + else + sprintf(version, "S%sY%sY%sY%sS", str0, str1, str2, str3); + } + + LogInfo("module_QGver = %s\n", version); + return; +} \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/AtSimInit.h b/code/application/sifarsdk/at-command/eg91/AtSimInit.h new file mode 100644 index 000000000..77d30df3f --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/AtSimInit.h @@ -0,0 +1,52 @@ +#ifndef AT_SIM_INIT_H +#define AT_SIM_INIT_H +#include "VAtSimInit.h" +#include "SfTypeDefine.h" +#include "sf_opera_adapt_v2.h" +#include "AtDefine.h" +#include "AtDataProcess.h" +#include +class AtSimInit : public VAtSimInit, public AtDataProcess +{ +public: + AtSimInit(); + virtual ~AtSimInit() = default; + void UnInit(void); + RETURN_CODE AtSimCardInit(void) override; + +protected: + virtual bool SimInitRetry(void); + virtual void SetModuleV05(const UINT8 &moduleV05) { mModuelV05 = moduleV05; } + UINT8 GetModuleV05(void) { return mModuelV05; } + virtual void AtSimInitStart(void); + virtual void ATE_Handle(void); + virtual void AT_GSN_Handle(void); + virtual void ATI_Handle(void); + virtual void QGMR_Handle(void); + virtual void QSIMSTAT_Handle(void); + virtual void AT_END_Handle(char *atCommand); + virtual void QNVFR_Handle(void); + virtual void QNVFW_Handle(void); + virtual void QFLST_1_Handle(const char *atCommand); + virtual void QFLST_2_Handle(const char *atCommand); + virtual void QURCCFG_Handle(void); + virtual void QCFG_1_Handle(void); + virtual void QCFG_2_Handle(void); + virtual void QLWCFG_1_Handle(void); + virtual void QLWCFG_2_Handle(void); + virtual void CPIN_Handle(void); + virtual void QCCID_Handle(void); + virtual void CIMI_Handle(void); + virtual void CGDCONT_Handle(void); + SINT32 eg91_parse_module_version(SF_CHAR *pTemp, SF_CHAR *version); + void eg91_parse_module_version_detail(SF_CHAR *pTemp, SF_CHAR *pT1, SF_CHAR *pT2, SF_CHAR *pT4, SF_CHAR *version); + +private: + UINT8 mModuelV05; + char ModuleVersion[SF_MODULE_VER_MAX_LEN]; // TODO: Input param. + SF_CHAR GsnSaved[GSN_BUF_LENGTH]; + SF_CHAR lastICCID[ICCID_BUF_LENGTH]; + std::thread mInitThread; + bool mInitRuning; +}; +#endif // !AT_SIM_INIT_H \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/at-command.cmake b/code/application/sifarsdk/at-command/eg91/at-command.cmake new file mode 100644 index 000000000..823462481 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/at-command.cmake @@ -0,0 +1,4 @@ + +INCLUDE(CMakeForceCompiler) + +aux_source_directory(${AT_COMMAND_PATH} SRC_FILES) \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/test/AtCommandMock.cpp b/code/application/sifarsdk/at-command/eg91/test/AtCommandMock.cpp new file mode 100644 index 000000000..13a926375 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/test/AtCommandMock.cpp @@ -0,0 +1,439 @@ +#include "AtCommandMock.h" +#include "Log.h" +extern const char *AT_COMMAND_ATE; +extern const char *AT_GSN; +extern const char *AT_ATI; +extern const char *AT_QGMR; +extern const char *AT_QSIMSTAT; +extern const char *AT_QURCCFG; +extern const char *AT_QCFG; +extern const char *AT_QCFG_2; +extern const char *AT_QLWCFG; +extern const char *AT_QLWCFG_2; +extern const char *AT_CPIN; +extern const char *AT_QCCID; +extern const char *AT_CIMI; +extern const char *AT_CGREG; +extern const char *AT_QCFG_PDP; +extern const char *AT_QCFG_TCP_1; +extern const char *AT_QCFG_TCP_2; +extern const char *AT_QNWINFO; +extern const char *AT_COPS; +extern const char *AT_QCSQ; +extern const char *AT_W; +const char *AT_COMMAND_ATE_RESPONSE_OK = "ATE1\r\nOK\r"; +const char *AT_COMMAND_GSN_RESPONSE_OK = "AT+GSN\r\n864004046816259\r\nOK\r"; +const char *AT_COMMAND_ATI_RESPONSE_OK = "ATI\r\nQuectel\r\nEG95\r\nRevision: EG95EXGAR08A04M1G\r\nOK\r"; +const char *AT_COMMAND_QGMR_RESPONSE_OK = "AT+QGMR\r\nEG95EXGAR08A04M1G_20.002.20.002\r\nOK\r"; +const char *AT_COMMAND_QSIMSTAT_RESPONSE_OK = "AT+QSIMSTAT?\r\n+QSIMSTAT: 0,1\r\nOK\r"; +const char *AT_COMMAND_QURCCFG_RESPONSE_OK = "AT+QURCCFG=\"urcport\",\"usbat\"\r\nOK\r"; +const char *AT_COMMAND_QCFG_RESPONSE_OK = "AT+QCFG=\"risignaltype\",\"physical\"\r\nOK\r"; +const char *AT_COMMAND_QCFG_2_RESPONSE_OK = "AT+QCFG=\"urc/ri/other\",\"off\"\r\nOK\r"; +const char *AT_COMMAND_QLWCFG_RESPONSE_OK = "AT+QLWCFG=\"urc\",0\r\nOK\r"; +const char *AT_COMMAND_QLWCFG_2_RESPONSE_OK = "AT+QLWCFG=\"startup\",0\r\nOK\r"; +const char *AT_COMMAND_CPIN_RESPONSE_OK = "AT+CPIN?\r\n+CPIN: READY\r\nOK\r"; +const char *AT_COMMAND_QCCID_RESPONSE_OK = "AT+QCCID\r\n+QCCID: 898607B0101980001318\r\nOK\r"; +const char *AT_COMMAND_CIMI_RESPONSE_OK = "AT+CIMI\r\n460041057611818\r\nOK\r"; + +const char *AT_CGREG_RESPONSE_OK = "AT+CGREG?\r\n+CGREG: 0,1\r\nOK\r"; +const char *AT_QCFG_PDP_RESPONSE_OK = "AT+QCFG=\"pdp/duplicatechk\",0\r\nOK\r"; +const char *AT_QCFG_TCP_1_RESPONSE_OK = "AT+QCFG=\"tcp/windowsize\",0,100\r\nOK\r"; +const char *AT_QCFG_TCP_2_RESPONSE_OK = "AT+QCFG=\"tcp/windowsize\",1,100\r\nOK\r"; +const char *AT_QNWINFO_RESPONSE_OK = "AT+QNWINFO\r\n+QNWINFO: \"FDD LTE\",\"46000\",\"LTE BAND 3\",1300\r\nOK\r"; +const char *AT_COPS_RESPONSE_OK = "AT+COPS?\r\n+COPS: 0,0,\"CHINA MOBILE\",7\r\nOK\r"; +const char *AT_QCSQ_RESPONSE_OK = "AT+QCSQ\r\n+QCSQ: \"LTE\",50,-82,109,-13\r\nOK\r"; +const char *AT_W_RESPONSE_OK = "AT&W\r\nOK\r"; +const char *AT_QICSGP_RESPONSE_OK = "XXXXXXXXXX\r\nOK\r"; + +void AtCommandMock::AtCommandInit(const int &usbFd, std::shared_ptr &mock) +{ + auto selectOk = [=, &mock](int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) + { + FD_ZERO(readfds); + FD_SET(usbFd, readfds); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + + auto APN_CONFIG_RESPONSE_MONITOR = [=, &mock](const void *writeBuf, const unsigned int &length) + { + if (strstr((const char *)writeBuf, "AT+QICSGP=")) + { + auto ATE_QICSGP = [=, &mock](const int &usbFd) + { + LogInfo("ATE_QICSGP mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_QICSGP_RESPONSE_OK, strlen(AT_QICSGP_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_QICSGP_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, writeBuf, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(ATE_QICSGP)), ::testing::Return(length))); + } + }; + EXPECT_CALL(*mock.get(), write(::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<1, 2>(::testing::Invoke(APN_CONFIG_RESPONSE_MONITOR)), ::testing::Return(MOCK_WRITE_FAILED))); + + auto ATE_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("ATE_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_ATE_RESPONSE_OK, strlen(AT_COMMAND_ATE_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_ATE_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_COMMAND_ATE, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(ATE_RESPONSE)), ::testing::Return(strlen(AT_COMMAND_ATE)))); + + auto AT_GSN_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_GSN_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_GSN_RESPONSE_OK, strlen(AT_COMMAND_GSN_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_GSN_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_GSN, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_GSN_RESPONSE)), ::testing::Return(strlen(AT_GSN)))); + + auto AT_ATI_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_ATI_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_ATI_RESPONSE_OK, strlen(AT_COMMAND_ATI_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_ATI_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_ATI, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_ATI_RESPONSE)), ::testing::Return(strlen(AT_ATI)))); + + auto AT_QGMR_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QGMR_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_QGMR_RESPONSE_OK, strlen(AT_COMMAND_QGMR_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_QGMR_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QGMR, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QGMR_RESPONSE)), ::testing::Return(strlen(AT_QGMR)))); + + auto AT_QSIMSTAT_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QSIMSTAT_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_QSIMSTAT_RESPONSE_OK, strlen(AT_COMMAND_QSIMSTAT_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_QSIMSTAT_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QSIMSTAT, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QSIMSTAT_RESPONSE)), ::testing::Return(strlen(AT_QSIMSTAT)))); + + auto AT_QURCCFG_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QURCCFG_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_QURCCFG_RESPONSE_OK, strlen(AT_COMMAND_QURCCFG_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_QURCCFG_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QURCCFG, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QURCCFG_RESPONSE)), ::testing::Return(strlen(AT_QURCCFG)))); + + auto AT_QCFG_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QCFG_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_QCFG_RESPONSE_OK, strlen(AT_COMMAND_QCFG_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_QCFG_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QCFG, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QCFG_RESPONSE)), ::testing::Return(strlen(AT_QCFG)))); + + auto AT_QCFG_2_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QCFG_2_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_QCFG_2_RESPONSE_OK, strlen(AT_COMMAND_QCFG_2_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_QCFG_2_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QCFG_2, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QCFG_2_RESPONSE)), ::testing::Return(strlen(AT_QCFG_2)))); + + auto AT_QLWCFG_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QLWCFG_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_QLWCFG_RESPONSE_OK, strlen(AT_COMMAND_QLWCFG_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_QLWCFG_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QLWCFG, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QLWCFG_RESPONSE)), ::testing::Return(strlen(AT_QLWCFG)))); + + auto AT_QLWCFG_2_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QLWCFG_2_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_QLWCFG_2_RESPONSE_OK, strlen(AT_COMMAND_QLWCFG_2_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_QLWCFG_2_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QLWCFG_2, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QLWCFG_2_RESPONSE)), ::testing::Return(strlen(AT_QLWCFG_2)))); + + auto AT_CPIN_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_CPIN_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_CPIN_RESPONSE_OK, strlen(AT_COMMAND_CPIN_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_CPIN_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_CPIN, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_CPIN_RESPONSE)), ::testing::Return(strlen(AT_CPIN)))); + + auto AT_QCCID_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QCCID_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_QCCID_RESPONSE_OK, strlen(AT_COMMAND_QCCID_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_QCCID_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QCCID, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QCCID_RESPONSE)), ::testing::Return(strlen(AT_QCCID)))); + + auto AT_CIMI_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_CIMI_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COMMAND_CIMI_RESPONSE_OK, strlen(AT_COMMAND_CIMI_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COMMAND_CIMI_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_CIMI, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_CIMI_RESPONSE)), ::testing::Return(strlen(AT_CIMI)))); + + auto AT_CGREG_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_CGREG_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_CGREG_RESPONSE_OK, strlen(AT_CGREG_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_CGREG_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_CGREG, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_CGREG_RESPONSE)), ::testing::Return(strlen(AT_CGREG)))); + + auto AT_QCFG_PDP_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QCFG_PDP_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_QCFG_PDP_RESPONSE_OK, strlen(AT_QCFG_PDP_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_QCFG_PDP_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QCFG_PDP, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QCFG_PDP_RESPONSE)), ::testing::Return(strlen(AT_QCFG_PDP)))); + + auto AT_QCFG_TCP_1_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QCFG_TCP_1_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_QCFG_TCP_1_RESPONSE_OK, strlen(AT_QCFG_TCP_1_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_QCFG_TCP_1_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QCFG_TCP_1, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QCFG_TCP_1_RESPONSE)), ::testing::Return(strlen(AT_QCFG_TCP_1)))); + + auto AT_QCFG_TCP_2_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QCFG_TCP_2_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_QCFG_TCP_2_RESPONSE_OK, strlen(AT_QCFG_TCP_2_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_QCFG_TCP_2_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QCFG_TCP_2, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QCFG_TCP_2_RESPONSE)), ::testing::Return(strlen(AT_QCFG_TCP_2)))); + + auto AT_QNWINFO_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QNWINFO_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_QNWINFO_RESPONSE_OK, strlen(AT_QNWINFO_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_QNWINFO_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QNWINFO, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QNWINFO_RESPONSE)), ::testing::Return(strlen(AT_QNWINFO)))); + + auto AT_COPS_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_COPS_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_COPS_RESPONSE_OK, strlen(AT_COPS_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_COPS_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_COPS, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_COPS_RESPONSE)), ::testing::Return(strlen(AT_COPS)))); + + auto AT_QCSQ_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_QCSQ_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_QCSQ_RESPONSE_OK, strlen(AT_QCSQ_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_QCSQ_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_QCSQ, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_QCSQ_RESPONSE)), ::testing::Return(strlen(AT_QCSQ)))); + + auto AT_W_RESPONSE = [=, &mock](const int &usbFd) + { + LogInfo("AT_W_RESPONSE mock\n"); + auto readBuf = [=, &mock](int fd, void *buf, size_t count) + { + memcpy(buf, AT_W_RESPONSE_OK, strlen(AT_W_RESPONSE_OK)); + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::Return(MOCK_SELECT_FAILED))); + }; + EXPECT_CALL(*mock.get(), read(usbFd, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2>(::testing::Invoke(readBuf)), ::testing::Return(strlen(AT_W_RESPONSE_OK)))); + EXPECT_CALL(*mock.get(), select(usbFd + 1, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0, 1, 2, 3, 4>(::testing::Invoke(selectOk)), ::testing::Return(MOCK_SELECT_READABLE))); + }; + EXPECT_CALL(*mock.get(), write(usbFd, AT_W, ::testing::_)) + .WillRepeatedly(::testing::DoAll(::testing::WithArgs<0>(::testing::Invoke(AT_W_RESPONSE)), ::testing::Return(strlen(AT_W)))); +} \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/test/AtCommandMock.h b/code/application/sifarsdk/at-command/eg91/test/AtCommandMock.h new file mode 100644 index 000000000..2baafbd36 --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/test/AtCommandMock.h @@ -0,0 +1,13 @@ +#ifndef AT_COMMAND_MOCK_H +#define AT_COMMAND_MOCK_H +#include "LinuxApiTest.h" +class AtCommandMock +{ +public: + AtCommandMock() = default; + ~AtCommandMock() = default; + +public: + static void AtCommandInit(const int &usbFd, std::shared_ptr &mock); +}; +#endif // !AT_COMMAND_MOCK_H \ No newline at end of file diff --git a/code/application/sifarsdk/at-command/eg91/test/at-command-mock.cmake b/code/application/sifarsdk/at-command/eg91/test/at-command-mock.cmake new file mode 100644 index 000000000..4a95e90aa --- /dev/null +++ b/code/application/sifarsdk/at-command/eg91/test/at-command-mock.cmake @@ -0,0 +1,4 @@ + +INCLUDE(CMakeForceCompiler) + +aux_source_directory(${AT_COMMAND_PATH}/test SRC_FILES) \ No newline at end of file diff --git a/code/application/sifarsdk/build/README.md b/code/application/sifarsdk/build/README.md new file mode 100644 index 000000000..96979dea0 --- /dev/null +++ b/code/application/sifarsdk/build/README.md @@ -0,0 +1,3 @@ +# cmake编译配置 +## 目录 +./toolchain:配置编译工具链 \ No newline at end of file diff --git a/code/application/sifarsdk/build/cmake/Makefile b/code/application/sifarsdk/build/cmake/Makefile new file mode 100644 index 000000000..e78d1db89 --- /dev/null +++ b/code/application/sifarsdk/build/cmake/Makefile @@ -0,0 +1,8 @@ +all: + @mkdir -p ../../cmake-shell-linux;\ + cd ../../cmake-shell-linux;\ + pwd;\ + cmake -DCMAKE_TOOLCHAIN_FILE="./build/cmake/toolchain/linux.toolchain.cmake" ..;\ + cd .. +clean: + rm -rf ../../cmake-shell-linux \ No newline at end of file diff --git a/code/application/sifarsdk/build/cmake/README.md b/code/application/sifarsdk/build/cmake/README.md new file mode 100644 index 000000000..97dfa0045 --- /dev/null +++ b/code/application/sifarsdk/build/cmake/README.md @@ -0,0 +1,2 @@ +# cmake + diff --git a/code/application/sifarsdk/build/cmake/toolchain/linux.toolchain.cmake b/code/application/sifarsdk/build/cmake/toolchain/linux.toolchain.cmake new file mode 100644 index 000000000..6d0f40bda --- /dev/null +++ b/code/application/sifarsdk/build/cmake/toolchain/linux.toolchain.cmake @@ -0,0 +1,49 @@ + +INCLUDE(CMakeForceCompiler) + +set(CMAKE_C_COMPILER gcc) +set(CMAKE_CXX_COMPILER g++) + +# path to compiler and utilities +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + + + + +# Name of the target platform +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm) + +# Version of the system +set(CMAKE_SYSTEM_VERSION 1) + + +add_definitions(-Wall -O2 -Os) +add_definitions(-Wno-unused-local-typedefs) +add_definitions(-Wstrict-aliasing -Wwrite-strings) + + +set(TOOLCHAIN_NAME arm-linux-gnueabihf) + + +set(TARGET_PLATFORM "linux") +set(AT_COMMAND_PATH "${CMAKE_SOURCE_DIR}/at-command/eg91") +set(COVERAGE_ON "true") +set(AT_COMMAND_SRC_PATH "eg91") +set(LIVE_PLATFORM_SRC_PATH "linux_mock") +set(CONFIG_FILE_PATH "./sfSysParm.bin") +set(CONFIG_FILE_STATIC_PATH "./sfStatisticsParm.bin") +set(SF_DCF_EXT_PHOTO "jpg") +set(SF_DCF_EXT_MOV "mp4") +set(SF_SD_ROOT "/mnt/mmc/") +set(SF_DCF_DIR_NAME_SUFFIX "SYCAM") +set(SF_DCF_ROOT_DIR_NAME "DCIM") +set(SF_DCF_THM_DIR_NAME "THUMB") +set(SF_DCF_FILE_NAME_PREFIX "HRTP") + +# ------------ build curl + openssl ------------ start +set(CROSS_COMPILE_PREFIX "") +set(CURL_OPENSSL_LIB_SHARED_ENABLE "false") +# ------------ build curl + openssl ------------ end \ No newline at end of file diff --git a/code/application/sifarsdk/build/global_config.cmake b/code/application/sifarsdk/build/global_config.cmake new file mode 100644 index 000000000..7d2a60a56 --- /dev/null +++ b/code/application/sifarsdk/build/global_config.cmake @@ -0,0 +1,17 @@ +# 根据实际平台修改 TARGET_PLATFORM 的定义 + +# set(TARGET_PLATFORM "linux") +set(DEFINE_LINUX "linux") +set(DEFINE_SIGMASTART_333DE "sigmastart_333DE") + +set(EXEC_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/out/bin") +set(LIBS_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/out/libs") +set(TEST_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/out/test") + +set(PROJECT_ROOT_PATH "${CMAKE_SOURCE_DIR}") +set(APPLICATION_SOURCE_PATH "${CMAKE_SOURCE_DIR}/application") +set(COMPONENT_SOURCE_PATH "${CMAKE_SOURCE_DIR}/component") +set(HAL_SOURCE_PATH "${CMAKE_SOURCE_DIR}/hal") +set(TEST_SOURCE_PATH "${CMAKE_SOURCE_DIR}/test") +set(EXTERNAL_SOURCE_PATH "${CMAKE_SOURCE_DIR}/external") +set(DEPENDENCY_LIBS_PATH "${CMAKE_SOURCE_DIR}/lib") diff --git a/code/application/sifarsdk/build/independent_source.cmake b/code/application/sifarsdk/build/independent_source.cmake new file mode 100644 index 000000000..53f1e8865 --- /dev/null +++ b/code/application/sifarsdk/build/independent_source.cmake @@ -0,0 +1,14 @@ + +# This config file is only for independent source files. + +# Never leave over any warning in independt project. +# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wextra") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") + +# For build coverage report in linux-x86 +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) + # SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") + # SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +endif() \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/CMakeLists.txt b/code/application/sifarsdk/component/AtCommand/CMakeLists.txt new file mode 100644 index 000000000..928dcf0c8 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/CMakeLists.txt @@ -0,0 +1,41 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Config/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/cJSON/include + ${HAL_SOURCE_PATH}/include + ${AT_COMMAND_PATH} +) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) +# Config to choose live service platform. +# string(COMPARE EQUAL "${AT_COMMAND_PATH}" "" value) +# message("The at-command src code path is ${AT_COMMAND_PATH}.") +# if (value EQUAL 0) #变量被设置了 +# message("build at-command src code.") +# include(${AT_COMMAND_PATH}/at-command.cmake) +# endif() + +include(${COMPONENT_SOURCE_PATH}/AtCommand/src/${AT_COMMAND_SRC_PATH}/at_command.cmake) + +set(TARGET_NAME AtCommand) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} Config Hal ReturnCode Log) + + +# SF_LIBS += -llink_visual_device +# SF_LIBS += -liot_sdk +# SF_LIBS += -liot_hal +# SF_LIBS += -liot_tls \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/include/IAtCommand.h b/code/application/sifarsdk/component/AtCommand/include/IAtCommand.h new file mode 100644 index 000000000..7c507111e --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/include/IAtCommand.h @@ -0,0 +1,143 @@ +#ifndef I_AT_COMMAND_H +#define I_AT_COMMAND_H +#include "VReturnCode.h" +#include +enum class AtInitSimResult +{ + SIM_INIT_OK = 0, + SIM_INIT_INSERTED, + SIM_INIT_NOT_INSERTED, + SIM_INIT_NOT_SUPPORT_MOBILE_NETWORK, + SIM_INIT_END +}; +enum class AtNetGeneration +{ + NET_2G = 0, + NET_3G, + NET_4G, + END +}; +enum class AtRegisterNetworkResult +{ + SUCCEED = 0, + FAILED, + ERROR_REG_NET, + FAILED_NOT_SUPPORT, + FAILED_NO_SIGNAL, + END +}; +enum class AtConfigNetApnResult +{ + SUCCEED = 0, + FAILED, + END +}; +enum class AtSimTpye +{ + SF_SIM_MEGA = 0, // normal mega sim, use in abroad + SF_SIM_MEGA_IOT, // special mega sim, only use in T110 + SF_SIM_OTHER, // other sim + SF_SIM_BUTT, + END +}; +enum class AtSignalLevel +{ + LEVEL_0 = 0, + LEVEL_1 = 2, + LEVEL_2 = 3, + LEVEL_3 = 4, + END +}; +class AtSimInitData +{ +public: + AtSimInitData() + { + mResult = AtInitSimResult::SIM_INIT_END; + mType = AtSimTpye::END; + } + ~AtSimInitData() + { + } + AtInitSimResult mResult; + std::string mIMEI; + std::string mModuleSubVersion; + std::string mIccid; + AtSimTpye mType; +}; +class NetworkRegisterResult +{ +public: + NetworkRegisterResult() + { + result = AtRegisterNetworkResult::END; + mGeneration = AtNetGeneration::END; + mSimSignal = 0; + mSignalLevel = AtSignalLevel::END; + } + ~NetworkRegisterResult() + { + } + AtRegisterNetworkResult result; + AtNetGeneration mGeneration; + std::string mServiceProvider; + unsigned char mSimSignal; + AtSignalLevel mSignalLevel; +}; +class AtNetApnConfigData +{ +public: + AtNetApnConfigData(const AtConfigNetApnResult &result) + : mResult(result) + { + } + ~AtNetApnConfigData() + { + } + const AtConfigNetApnResult mResult; +}; +class VAtTask +{ +public: + VAtTask() = default; + virtual ~VAtTask() = default; +}; +class AtDeviceMessage +{ +public: + AtDeviceMessage() + { + mPdp = 0; + } + ~AtDeviceMessage() + { + } + unsigned int mPdp; +}; +class VAtOwner +{ +public: + VAtOwner() = default; + virtual ~VAtOwner() = default; + virtual void GetDeviceMessage(AtDeviceMessage &message) {} + virtual void AtFinishInitSimCard(const AtSimInitData &data) {} + virtual void AtFinishRegisterNetwork(const NetworkRegisterResult &data) {} + virtual void AtFinishNetApnConfig(const AtNetApnConfigData &data) {} + virtual void WriteAtCommand(const std::shared_ptr &task) {} +}; +class IAtCommand +{ +public: + IAtCommand() = default; + virtual ~IAtCommand() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SimInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE AtRegisterNetworkManual(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE AtNetApnConfig(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetOwner(std::shared_ptr &Owner) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE MqttKeepAlive(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreateAtCommandModule(void); +#endif // !I_AT_COMMAND_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/AtCommandMakePtr.cpp b/code/application/sifarsdk/component/AtCommand/src/AtCommandMakePtr.cpp new file mode 100644 index 000000000..b5af1d0e9 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/AtCommandMakePtr.cpp @@ -0,0 +1,30 @@ +#include "AtCommandMakePtr.h" +#include "Log.h" +#include "VReturnCode.h" +#include +bool CreateAtCommandModule(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = AtCommandMakePtr::GetInstance()->CreateAtCommand(instance); + if (code->IsCodeOK()) + { + LogInfo("Peripheral manager instance is ok.\n"); + IAtCommand::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &AtCommandMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + instance = *impl; + } + return instance; +} +RETURN_CODE AtCommandMakePtr::CreateAtCommand(std::shared_ptr &impl) +{ + CreateAtCommandImpl(impl); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/AtCommandMakePtr.h b/code/application/sifarsdk/component/AtCommand/src/AtCommandMakePtr.h new file mode 100644 index 000000000..a14c92400 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/AtCommandMakePtr.h @@ -0,0 +1,17 @@ +#ifndef AT_COMMAND_MAKE_PTR_H +#define AT_COMMAND_MAKE_PTR_H +#include "IAtCommand.h" +#include "VReturnCode.h" +#include +class AtCommandMakePtr +{ +public: + AtCommandMakePtr() = default; + virtual ~AtCommandMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE CreateAtCommand(std::shared_ptr &impl); +}; +bool CreateAtCommandImpl(std::shared_ptr &impl); +#endif // !AT_COMMAND_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/AtDataProcess.cpp b/code/application/sifarsdk/component/AtCommand/src/AtDataProcess.cpp new file mode 100644 index 000000000..a641b57ed --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/AtDataProcess.cpp @@ -0,0 +1,34 @@ +#include "AtDataProcess.h" +#include "Log.h" +#include +SINT32 AtDataProcess::eg91_module_Polling_Comparison_CIMI(SF_CHAR *operatorName) +{ + UINT8 i = 0; + static UINT8 CIMIcount = 0; + static SF_CHAR strCIMI[5][8] = {0}; + + LogInfo("CIMIcount = %d,operatorName = [%s]\n", CIMIcount, operatorName); + if (operatorName == SF_NULL) + return SF_FAILURE; + + if (CIMIcount > 5) + return SF_FAILURE; + + for (i = 0; i < 5; i++) + { + LogInfo("strCIMI[%d]: [%s]\n", i, strCIMI[i]); + if (strncmp(strCIMI[i], operatorName, 5) == 0) + return SF_FAILURE; + else + { + if (strlen(strCIMI[i]) == 0) + { + memcpy(strCIMI[i], operatorName, 5); + CIMIcount++; + LogInfo("strCIMI[%d]: [%s]\n", i, strCIMI[i]); + return SF_SUCCESS; + } + } + } + return SF_SUCCESS; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/AtDataProcess.h b/code/application/sifarsdk/component/AtCommand/src/AtDataProcess.h new file mode 100644 index 000000000..74febe9b8 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/AtDataProcess.h @@ -0,0 +1,13 @@ +#ifndef AT_DATA_PROCESS_H +#define AT_DATA_PROCESS_H +#include "SfTypeDefine.h" +class AtDataProcess +{ +public: + AtDataProcess() = default; + virtual ~AtDataProcess() = default; + +protected: + SINT32 eg91_module_Polling_Comparison_CIMI(SF_CHAR *operatorName); +}; +#endif // !AT_DATA_PROCESS_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/AtDefine.h b/code/application/sifarsdk/component/AtCommand/src/AtDefine.h new file mode 100644 index 000000000..fd2393a59 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/AtDefine.h @@ -0,0 +1,20 @@ +#ifndef AT_DEFINE_H +#define AT_DEFINE_H + +#define GPRS_MODULE_TYPE_EG91 "EG91" +#define GPRS_MODULE_TYPE_EG95 "EG95" +// #define EG91 "EG91" +// #define EG95 "EG95" +#define APNGPRS_WUYUAN "America.bics" +#define APNGPRS_WUYUAN2 "bicsapn" +#define APNGPRSTEMP "CTNET" +// constexpr int SF_MODULE_VER_MAX_LEN = 50; +constexpr int GSN_BUF_LENGTH = 22; +constexpr int ICCID_BUF_LENGTH = 21; +constexpr int OPERATION_CODE_LENGTH = 6; + +// #define E_PDP_INDEX 7 +// #define V_PDP_INDEX 3 +// #define A_PDP_INDEX 1 + +#endif // !AT_DEFINE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/IAtCommand.cpp b/code/application/sifarsdk/component/AtCommand/src/IAtCommand.cpp new file mode 100644 index 000000000..1700c6c5b --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/IAtCommand.cpp @@ -0,0 +1,29 @@ +#include "IAtCommand.h" +#include "Log.h" +#include +std::shared_ptr &IAtCommand::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/VAtBasics.cpp b/code/application/sifarsdk/component/AtCommand/src/VAtBasics.cpp new file mode 100644 index 000000000..f1fe5fe2e --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/VAtBasics.cpp @@ -0,0 +1,27 @@ +#include "VAtBasics.h" +#include "Log.h" +AtTaskBasics_V2::AtTaskBasics_V2(const char *command, char *responseBuf, const unsigned int &responseBufLength) + : mATCommand(command), mResponseBuf(responseBuf), mResponseLength(responseBufLength) +{ + mActualResponseLength = 0; + mRetryTimes = DEFAULT_RETRY_TIMES; +} +ResponseCode AtTaskBasics_V2::Response(const char *buf, const unsigned int &length) +{ + if (nullptr == mResponseBuf) + { + LogWarning("Can't save response data.\n"); + return ResponseCode::RESPONSE_OK; + } + if (mResponseLength >= length) + { + memcpy(mResponseBuf, buf, length); + } + else + { + memcpy(mResponseBuf, buf, mResponseLength); + LogError("Response data loss.\n"); + } + mActualResponseLength = length; + return ResponseCode::RESPONSE_OK; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/VAtBasics.h b/code/application/sifarsdk/component/AtCommand/src/VAtBasics.h new file mode 100644 index 000000000..06b4f57c7 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/VAtBasics.h @@ -0,0 +1,69 @@ +#ifndef V_AT_BASICS_H +#define V_AT_BASICS_H +#include "VReturnCode.h" +#include "IHal.h" +#include "IAtCommand.h" +#include "SfTypeDefine.h" +#include "sf_opera_adapt_v2.h" +#include +constexpr int RESPONSE_BUF_LENGTH = 1024; +class AtTaskBasics : public VNetworkTask, public VAtTask +{ +public: + AtTaskBasics(const char *command) : mATCommand(command) + { + } + ~AtTaskBasics() + { + } + const char *GetWriteBuf(void) override { return mATCommand; } + unsigned int GetWriteBufLength(void) override { return strlen(mATCommand); } + bool IsTaskBlock(void) override { return true; } + unsigned int RetryTimes(void) override { return 200; } + +private: + const char *mATCommand; +}; +constexpr int DO_NOT_RETRY_READ_AFTER_FAILED = 0; +class AtTaskBasics_V2 : public VNetworkTask, public VAtTask +{ +public: + AtTaskBasics_V2(const char *command, char *responseBuf, const unsigned int &responseBufLength); + ~AtTaskBasics_V2() + { + } + const char *GetWriteBuf(void) override { return mATCommand; } + unsigned int GetWriteBufLength(void) override { return strlen(mATCommand); } + bool IsTaskBlock(void) override { return true; } + unsigned int RetryTimes(void) override { return mRetryTimes; } + void SetRetryTimes(const unsigned int &retry) { mRetryTimes = retry; } + ResponseCode Response(const char *buf, const unsigned int &length) override; + unsigned int ActualResponseLength(void) { return mActualResponseLength; } + +private: + const char *mATCommand; + char *mResponseBuf; + const unsigned int mResponseLength; + unsigned int mActualResponseLength; + unsigned int mRetryTimes; +}; +constexpr int DEFAULT_RETRY_TIMES = 200; +class VAtBasics +{ +public: + VAtBasics() + { + mSingleCommandRetryTimes = 0; + } + virtual ~VAtBasics() = default; + virtual void SendAtCommandTask(std::shared_ptr task) = 0; + virtual void GetSimInfo(SIM_INFO_S *info) = 0; + virtual std::shared_ptr SharedFromThis(void) = 0; + void AtCallOnce(void) { mSingleCommandRetryTimes++; } + void SetAtCallTimes(const UINT16 ×) { mSingleCommandRetryTimes = times; } + UINT16 GetAtCallTimes(void) { return mSingleCommandRetryTimes; } + +private: + UINT16 mSingleCommandRetryTimes; +}; +#endif // !V_AT_BASICS_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/VAtMqtt.h b/code/application/sifarsdk/component/AtCommand/src/VAtMqtt.h new file mode 100644 index 000000000..28499f57a --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/VAtMqtt.h @@ -0,0 +1,18 @@ +#ifndef V_AT_MQTT_H +#define V_AT_MQTT_H +#include "VReturnCode.h" +#include "VAtBasics.h" +#include "IAtCommand.h" +#include "SfTypeDefine.h" +class VAtMqtt : public virtual VAtBasics +{ +public: + VAtMqtt() = default; + virtual ~VAtMqtt() = default; + virtual void sf_mqtt_client_start(void) = 0; + virtual void sf_mqtt_client_thread_stop(void) = 0; + virtual SINT16 sf_mqtt_client_try_recv(void) = 0; + virtual SINT16 sf_mqtt_client_open(void) = 0; + virtual SINT16 sf_mqtt_client_close(void) = 0; +}; +#endif // !V_AT_MQTT_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/VAtRegisterNetwork.h b/code/application/sifarsdk/component/AtCommand/src/VAtRegisterNetwork.h new file mode 100644 index 000000000..a965f0fb5 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/VAtRegisterNetwork.h @@ -0,0 +1,23 @@ +#ifndef V_AT_REGISTER_NETWORK_H +#define V_AT_REGISTER_NETWORK_H +#include "VReturnCode.h" +#include "IHal.h" +// #include "IPeripheralManager.h" +#include "IAtCommand.h" +#include "VAtBasics.h" +class VAtRegisterNetwork : public virtual VAtBasics +{ +public: + VAtRegisterNetwork() = default; + virtual ~VAtRegisterNetwork() = default; + virtual void RegisterNetworkManual(void) = 0; + virtual void AtRegisterNetworkAuto(void) = 0; + virtual void AtGetGeneration(const AtNetGeneration &generation) = 0; + virtual void AtGetSimSignal(const UINT8 &signal) = 0; + virtual void AtRegisterNetworkFinished(const AtRegisterNetworkResult &result) = 0; + virtual void AtNetApnConfigFinished(const AtConfigNetApnResult &result) = 0; + virtual void AtGetServiceProvider(const std::string &serviceProvider) = 0; + virtual unsigned int GetPdpIndex(void) = 0; + virtual const char *GetApnGprs(void) { return "nullptr"; } +}; +#endif // !V_AT_REGISTER_NETWORK_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/VAtSimInit.h b/code/application/sifarsdk/component/AtCommand/src/VAtSimInit.h new file mode 100644 index 000000000..5e9b5765d --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/VAtSimInit.h @@ -0,0 +1,20 @@ +#ifndef V_AT_SIM_INIT_H +#define V_AT_SIM_INIT_H +#include "VReturnCode.h" +#include "VAtBasics.h" +#include "IAtCommand.h" +class VAtSimInit : public virtual VAtBasics +{ +public: + VAtSimInit() = default; + virtual ~VAtSimInit() = default; + virtual RETURN_CODE AtSimCardInit(void) = 0; + virtual void AtGetIMEI(const char *imei) = 0; + virtual void AtGetModuleSubVersion(const char *version) = 0; + virtual const char *GetModuleVersionParam(void) { return "nullptr"; } + virtual void AtSimInitFinished(const AtInitSimResult &result) = 0; + virtual void AtGetICCID(const char *iccid) = 0; + virtual void AtGetSimType(const AtSimTpye &type) = 0; + virtual void AtGetSimInfo(const SIM_INFO_S *info) = 0; +}; +#endif // !V_AT_SIM_INIT_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtMqtt.cpp b/code/application/sifarsdk/component/AtCommand/src/eg91/AtMqtt.cpp new file mode 100644 index 000000000..7f47798a1 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtMqtt.cpp @@ -0,0 +1,589 @@ +#include "AtMqtt.h" +#include "Log.h" +#include "SfTypeDefine.h" +#include "IConfig.h" +AtMqtt::AtMqtt() +{ + mInitRuning = false; +} +void AtMqtt::UnInit(void) +{ + LogInfo("AtMqtt::UnInit.\n"); + mInitRuning = false; + if (mInitThread.joinable()) + { + mInitThread.join(); + } +} +void AtMqtt::sf_mqtt_client_start(void) +{ + auto mqttClientStart = [](std::shared_ptr atCommand) + { + std::dynamic_pointer_cast(atCommand)->sf_mqtt_client_recv(); + }; + if (mInitRuning) + { + LogWarning("AtSimCardInit runing.\n"); + return; + } + mInitRuning = true; + mInitThread = std::thread(mqttClientStart, SharedFromThis()); +} +void AtMqtt::sf_mqtt_client_thread_stop(void) +{ + AtMqtt::UnInit(); +} +SINT16 AtMqtt::sf_mqtt_client_try_recv(void) +{ + QMTRECV_Handle(); + return SF_SUCCESS; +} +bool AtMqtt::MqttRetry(const unsigned int &defaultRetry) +{ + if (!mInitRuning) + { + LogWarning("Stop Init.\n"); + return false; + } + // constexpr int SIM_INIT_CALL_RETRY = 200; + AtCallOnce(); + if (GetAtCallTimes() <= defaultRetry) + { + LogInfo("AtMqtt Retry to call, call times = %d.\n", GetAtCallTimes()); + return true; + } + LogError("AtMqtt failed.\n"); // TODO: + return false; +} +SINT16 AtMqtt::sf_mqtt_client_recv(void) +{ + SINT16 ret = SF_SUCCESS; + + while (mInitRuning) + { + ClientStart(); + } + return ret; +} +void AtMqtt::ClientStart(void) +{ + LogInfo("AT-Command:ATE1\n"); + SetAtCallTimes(0); + char response[RESPONSE_BUF_LENGTH] = {0}; + std::shared_ptr task = std::make_shared(ONLY_READ_FROM_NETWORK, response, RESPONSE_BUF_LENGTH); + std::dynamic_pointer_cast(task)->SetRetryTimes(DO_NOT_RETRY_READ_AFTER_FAILED); +CLIENT_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + if (strstr(response, "+QMTRECV:") != 0) + { + LogInfo("ClientStart. response = %s\n", response); + // sf_p2p_cmd_set(1); + mInitRuning = false; + } + else + { + // std::this_thread::sleep_for(std::chrono::milliseconds(20)); + goto CLIENT_RETRY; + } +} +void AtMqtt::QMTRECV_Handle(void) +{ + // TODO: never use this function. + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTRECV=%d\r", MQTT_CLIENT_ID); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QMTRECV_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTRECV_Handle.\n"); + + if (strstr(response, "ERROR") != 0) + { + // sf_mqtt_client_close(pfnParam); + // sf_mqtt_client_open(pfnParam); + + // timeout_count = 0; + // memset(ttyData, '\0', SF_TTYUSB_RECV_MAX); + // snprintf(ttyData, "AT+QMTRECV=%d\r", MQTT_CLIENT_ID); + // ttyRet = sf_hal_write(ttyData, strlen(ttyData)); + } + else if (strstr(response, "+QMTRECV:") != 0) + { + // timeout_count = 0; + // memset(ttyData, '\0', SF_TTYUSB_RECV_MAX); + // snprintf(ttyData, "AT+QMTRECV=%d\r", MQTT_CLIENT_ID); + // ttyRet = sf_hal_write(ttyData, strlen(ttyData)); + } + else + { + // timeout_count = 0; + // memset(ttyData, '\0', SF_TTYUSB_RECV_MAX); + // snprintf(ttyData, "AT+QMTRECV=%d\r", MQTT_CLIENT_ID); + // ttyRet = sf_hal_write(ttyData, strlen(ttyData)); + } + + if (MqttRetry()) + { + goto QMTRECV_RETRY; + } +} +SINT16 AtMqtt::sf_mqtt_client_open(void) +{ + QISTATE_Handle(); + return SF_SUCCESS; +} +SINT16 AtMqtt::sf_mqtt_client_close(void) +{ + QMTDISC_Handle(); + return SF_SUCCESS; +} +void AtMqtt::QISTATE_Handle(void) +{ + LogInfo("QISTATE_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QISTATE=0,%d\r", TCP_PDP); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QISTATE_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QISTATE_Handle. response=%s\n", response); + if (strstr(response, "+QISTATE:")) + { + char *p = NULL; + p = strstr(response, "+QISTATE:"); + p = strchr(p, ','); + p = strchr(p + 1, ','); + p = strchr(p + 1, ','); + p = strchr(p + 1, ','); + p = strchr(p + 1, ','); + if (atoi(p + 1) == 2) + { + LogInfo("Keep alive login MQTT.\n"); + MQTT_OPEN_END_Handle(); + } + else + { + QICSGP_Handle(); + } + } + else if ((strstr(response, "OK"))) + { + QICSGP_Handle(); + } + + if (MqttRetry()) + { + goto QISTATE_RETRY; + } + QICSGP_Handle(); +} +void AtMqtt::QMTRECV_2_Handle(void) +{ + LogInfo("QMTRECV_2_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTRECV=%d\r", MQTT_CLIENT_ID); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QMTRECV_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTRECV_2_Handle. response=%s\n", response); + + if (strstr(response, "OK")) + { + return; + } + else if (!strstr(response, "+QMTRECV: 0")) + { + // memset(&pfnParam->arrttyData, '\0', SF_TTYUSB_RECV_MAX); + // memcpy(&pfnParam->arrttyData, response, SF_TTYUSB_RECV_MAX); // TODO: + return; + } + else + return; + + if (MqttRetry()) + { + goto QMTRECV_RETRY; + } +} +void AtMqtt::QIDEACT_Handle(void) +{ + LogInfo("QIDEACT_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QIDEACT=%d\r", TCP_PDP); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QIDEACT_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QIDEACT_Handle. response=%s\n", response); + QICSGP_Handle(); + + if (MqttRetry()) + { + goto QIDEACT_RETRY; + } +} +void AtMqtt::QICSGP_Handle(void) +{ + LogInfo("QICSGP_Handle.\n"); + SIM_INFO_S simInfo; + memset(&simInfo, 0, sizeof(SIM_INFO_S)); + GetSimInfo(&simInfo); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", + TCP_PDP, simInfo.ApnGPRS, simInfo.ApnUsername, simInfo.ApnPassword); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QICSGP_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QICSGP_Handle. response=%s\n", response); + + if (strstr(response, "OK")) + { + QIACT_Handle(); + } + else if (strstr(response, "ERROR")) + { + // sts = 0; + // ret = SF_TCP_ERROR_AT; // TODO: + return; + } + + if (MqttRetry()) + { + goto QICSGP_RETRY; + } +} +void AtMqtt::QIACT_Handle(void) +{ + LogInfo("QIACT_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QIACT=%d\r", TCP_PDP); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QIACT_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QIACT_Handle. response=%s\n", response); + + if (strstr(response, "OK")) + { + QMTCFG_PDPCID_Handle(); + } + else if (strstr(response, "ERROR")) + { + LogError("QIACT_Handle. response error.\n"); + } + + if (MqttRetry(TCP_PDP_TRY_TIME)) + { + goto QIACT_RETRY; + } +} +void AtMqtt::QMTCFG_PDPCID_Handle(void) +{ + LogInfo("QMTCFG_PDPCID_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTCFG=\"pdpcid\",%d,%d\r", MQTT_CLIENT_ID, TCP_PDP); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QMTCFG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTCFG_PDPCID_Handle. response=%s\n", response); + + if (strstr(response, "OK")) + { + QMTCFG_KEEP_ALIVE_Handle(); + } + else if (strstr(response, "ERROR")) + { + LogError("QMTCFG_PDPCID_Handle. response error.\n"); + } + + if (MqttRetry(TCP_PDP_TRY_TIME)) + { + goto QMTCFG_RETRY; + } +} +void AtMqtt::QMTCFG_KEEP_ALIVE_Handle(void) +{ + LogInfo("QMTCFG_KEEP_ALIVE_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTCFG=\"keepalive\",%d,120\r", MQTT_CLIENT_ID); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QMTCFG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTCFG_KEEP_ALIVE_Handle. response=%s\n", response); + + if (strstr(response, "OK")) + { + QMTCFG_QMTPING_Handle(); + } + + if (MqttRetry()) + { + goto QMTCFG_RETRY; + } +} +void AtMqtt::QMTCFG_QMTPING_Handle(void) +{ + LogInfo("QMTCFG_QMTPING_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTCFG=\"qmtping\",5\r"); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QMTCFG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTCFG_QMTPING_Handle. response=%s\n", response); + + if (strstr(response, "OK")) + { + QMTCFG_RECV_Handle(); + } + + if (MqttRetry()) + { + goto QMTCFG_RETRY; + } +} +void AtMqtt::QMTCFG_RECV_Handle(void) +{ + LogInfo("QMTCFG_RECV_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTCFG=\"recv/mode\",%d,0,0\r", MQTT_CLIENT_ID); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QMTCFG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTCFG_RECV_Handle. response=%s\n", response); + + if (strstr(response, "OK")) + { + QMTCFG_ALIAUTH_Handle(); + } + + if (MqttRetry()) + { + goto QMTCFG_RETRY; + } +} +void AtMqtt::QMTCFG_ALIAUTH_Handle(void) +{ + LogInfo("QMTCFG_ALIAUTH_Handle.\n"); + Param p2pId = GetParam(PARAM_P2P_ID); + memset(&p2pId, 0, sizeof(Param)); + Param p2pName = GetParam(PARAM_P2P_NAME); + memset(&p2pName, 0, sizeof(Param)); + Param p2pSecret = GetParam(PARAM_P2P_SECRET); + memset(&p2pSecret, 0, sizeof(Param)); + constexpr int AT_COMMAND_LENGTH = 520; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTCFG=\"aliauth\",0,\"%s\",\"%s\",\"%s\"\r", p2pId.str, p2pName.str, p2pSecret.str); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QMTCFG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTCFG_ALIAUTH_Handle. response=%s\n", response); + constexpr int RETRY_TIMES = 100; + if (strstr(response, "OK")) + { + QMTOPEN_Handle(); + } + else if ((strstr(response, "ERROR"))) + { + LogError("QMTCFG_ALIAUTH_Handle response error.\n"); + } + + if (MqttRetry(RETRY_TIMES)) + { + goto QMTCFG_RETRY; + } + QMTOPEN_Handle(); +} +void AtMqtt::QMTOPEN_Handle(void) +{ + LogInfo("QMTOPEN_Handle.\n"); + Param mqttIP = GetParam(PARAM_MQTT_IP); + memset(&mqttIP, 0, sizeof(Param)); + Param mqttPort = GetParam(PARAM_MQTT_PORT); + memset(&mqttPort, 0, sizeof(Param)); + SF_CHAR tempStr[32] = {0}; + UINT16 reOpenTimes = 2; + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTOPEN=%d,\"%s\",%d\r", MQTT_CLIENT_ID, mqttIP.str, mqttPort.numberInt); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +AT_WRITE_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTOPEN_Handle. response=%s\n", response); + constexpr int RETRY_TIMES = 600; + SF_CHAR *pbuf = NULL; + pbuf = strstr(response, "+QMTOPEN:"); + if (pbuf != NULL) + { + memcpy(tempStr, pbuf, 13); + } + if ((strncmp(tempStr, "+QMTOPEN:", 9) == 0) && (tempStr[12] == '0')) + { + QMTCONN_Handle(); + } + else if (((strncmp(tempStr, "+QMTOPEN:", 9) == 0) && (tempStr[12] != '0')) || (strncmp(tempStr, "+CME ERROR", 10) == 0)) + { + if (reOpenTimes) + { + reOpenTimes--; + LogError("QMTOPEN Fail, re connect mqtt.\n"); + } + else + { + LogError("Re connect mqtt fail.\n"); + MQTT_OPEN_END_Handle(); + } + } + + if (MqttRetry(RETRY_TIMES)) + { + goto AT_WRITE_RETRY; + } + LogError("Connect acm timeout.\n"); + MQTT_OPEN_END_Handle(); +} +void AtMqtt::QMTCONN_Handle(void) +{ + LogInfo("QMTCONN_Handle.\n"); + Param p2pName = GetParam(PARAM_P2P_NAME); + memset(&p2pName, 0, sizeof(Param)); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTCONN=%d,\"%s\"\r", MQTT_CLIENT_ID, p2pName.str); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +AT_WRITE_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTCONN_Handle. response=%s\n", response); + constexpr int RETRY_TIMES = 600; + if (strstr(response, "+QMTCONN: 0,0,0")) + { + return; + } + + if (MqttRetry(RETRY_TIMES)) + { + goto AT_WRITE_RETRY; + } + LogError("Connect acm timeout.\n"); + MQTT_OPEN_END_Handle(); +} +void AtMqtt::MQTT_OPEN_END_Handle(void) +{ + LogInfo("MQTT_OPEN_END_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QIDEACT=%d\r", TCP_PDP); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QIDEACT_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("MQTT_OPEN_END_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + return; + } + else if (!strstr(response, "+QMTRECV: 0")) + { + // memset(&pfnParam->arrttyData, '\0', SF_TTYUSB_RECV_MAX); + // memcpy(&pfnParam->arrttyData, ttyData, SF_TTYUSB_RECV_MAX); // TODO: + return; + } + else + return; + + if (MqttRetry()) + { + goto QIDEACT_RETRY; + } +} +void AtMqtt::QMTDISC_Handle(void) +{ + LogInfo("QMTDISC_Handle.\n"); + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QISTATE=0,%d\r", TCP_PDP); + std::shared_ptr task0 = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task0); + memset(atCommand, 0, AT_COMMAND_LENGTH); + snprintf(atCommand, AT_COMMAND_LENGTH, "AT+QMTDISC=%d\r", MQTT_CLIENT_ID); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +AT_WRITE_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QMTDISC_Handle. response=%s\n", response); + if ((strstr(response, "+QMTDISC: 0,0")) || (strstr(response, "ERROR")) || (strstr(response, "OK"))) + { + MQTT_OPEN_END_Handle(); + } + + if (MqttRetry()) + { + goto AT_WRITE_RETRY; + } + MQTT_OPEN_END_Handle(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtMqtt.h b/code/application/sifarsdk/component/AtCommand/src/eg91/AtMqtt.h new file mode 100644 index 000000000..daf60b394 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtMqtt.h @@ -0,0 +1,48 @@ +#ifndef AT_MQTT_H +#define AT_MQTT_H +#include "VAtMqtt.h" +#include "SfTypeDefine.h" +#include "sf_opera_adapt_v2.h" +#include "AtDefine.h" +#include "AtDataProcess.h" +#include +constexpr int TCP_PDP = 9; +constexpr int TCP_PDP_TRY_TIME = 7; +constexpr int MQTT_CLIENT_ID = 0; +class AtMqtt : public VAtMqtt, public AtDataProcess +{ +public: + AtMqtt(); + virtual ~AtMqtt() = default; + void UnInit(void); + void sf_mqtt_client_start(void) override; + void sf_mqtt_client_thread_stop(void) override; + SINT16 sf_mqtt_client_try_recv(void) override; + SINT16 sf_mqtt_client_open(void) override; + SINT16 sf_mqtt_client_close(void) override; + +protected: + virtual bool MqttRetry(const unsigned int &defaultRetry = DEFAULT_RETRY_TIMES); + SINT16 sf_mqtt_client_recv(void); + virtual void ClientStart(void); + virtual void QMTRECV_Handle(void); + virtual void QISTATE_Handle(void); + virtual void QMTRECV_2_Handle(void); + virtual void QIDEACT_Handle(void); + virtual void QICSGP_Handle(void); + virtual void QIACT_Handle(void); + virtual void QMTCFG_PDPCID_Handle(void); + virtual void QMTCFG_KEEP_ALIVE_Handle(void); + virtual void QMTCFG_QMTPING_Handle(void); + virtual void QMTCFG_RECV_Handle(void); + virtual void QMTCFG_ALIAUTH_Handle(void); + virtual void QMTOPEN_Handle(void); + virtual void QMTCONN_Handle(void); + virtual void MQTT_OPEN_END_Handle(void); + virtual void QMTDISC_Handle(void); + +private: + std::thread mInitThread; + bool mInitRuning; +}; +#endif // !AT_MQTT_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetwork.cpp b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetwork.cpp new file mode 100644 index 000000000..69cb5d4ea --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetwork.cpp @@ -0,0 +1,65 @@ +#include "AtRegisterNetwork.h" +#include "Log.h" +#include +void AtRegisterNetwork::RegisterNetworkManual(void) +{ + // TODO: 4G module has already connected ??? + SetManualFlag(true); + auto registerNetworkThreadStart = [](std::shared_ptr atRegisterNetwork) + { + std::dynamic_pointer_cast(atRegisterNetwork)->AtRegisterNetworkManual::RegisterNetworkStart(); + }; + std::thread simInit(registerNetworkThreadStart, SharedFromThis()); + simInit.detach(); +} +void AtRegisterNetwork::AtRegisterNetworkAuto(void) +{ + // TODO: 4G module has already connected ??? + auto registerNetworkThreadStart = [](std::shared_ptr atRegisterNetwork) + { + std::dynamic_pointer_cast(atRegisterNetwork)->AtRegisterNetworkAuto::RegisterNetworkStart(); + }; + std::thread registerNetwork(registerNetworkThreadStart, SharedFromThis()); + registerNetwork.detach(); +} +void AtRegisterNetwork::UsbNetApnConfigStart(void) +{ + constexpr int AT_COMMAND_BUF_LENGTH = 1024; + char atCommand[AT_COMMAND_BUF_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SIM_INFO_S simInfo; + memset(&simInfo, 0, sizeof(SIM_INFO_S)); + GetSimInfo(&simInfo); + std::shared_ptr task_0 = std::make_shared("AT\r", response, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task_0); + SetAtCallTimes(0); + sprintf(atCommand, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", GetPdpIndex(), + simInfo.ApnGPRS, simInfo.ApnUsername, simInfo.ApnPassword); + std::shared_ptr task = std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); + LogInfo("QICSGP command : %s\n", atCommand); +QICSGP_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + if (strstr(response, "OK")) + { + LogInfo("Net apn config succeed.\n"); + AtNetApnConfigFinished(AtConfigNetApnResult::SUCCEED); + return; + } + if (UsbNetApnConfigRetry()) + { + goto QICSGP_RETRY; + } +} +bool AtRegisterNetwork::UsbNetApnConfigRetry(unsigned int defaultRetry) +{ + AtCallOnce(); + if (GetAtCallTimes() <= defaultRetry) + { + LogInfo("Retry to call, call times = %d.\n", GetAtCallTimes()); + return true; + } + LogInfo("Net apn config succeed.\n"); + AtNetApnConfigFinished(AtConfigNetApnResult::FAILED); + return false; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetwork.h b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetwork.h new file mode 100644 index 000000000..26a7eda70 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetwork.h @@ -0,0 +1,16 @@ +#ifndef AT_REGISTER_NETWORK_H +#define AT_REGISTER_NETWORK_H +#include "AtRegisterNetworkManual.h" +class AtRegisterNetwork : public AtRegisterNetworkManual +{ +public: + AtRegisterNetwork() = default; + virtual ~AtRegisterNetwork() = default; + void RegisterNetworkManual(void) override; + void AtRegisterNetworkAuto(void) override; + void UsbNetApnConfigStart(void); + +private: + bool UsbNetApnConfigRetry(unsigned int defaultRetry = DEFAULT_RETRY_TIMES); +}; +#endif // !AT_REGISTER_NETWORK_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkAuto.cpp b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkAuto.cpp new file mode 100644 index 000000000..ff8cdd012 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkAuto.cpp @@ -0,0 +1,17 @@ +#include "AtRegisterNetworkAuto.h" +#include "Log.h" +AtRegisterNetworkAuto::AtRegisterNetworkAuto() +{ + mGeneration = AtNetGeneration::END; +} +void AtRegisterNetworkAuto::RegisterNetworkStart(void) +{ + LogInfo("AT-Command:AT+QSIMSTAT?\n"); + // std::shared_ptr> task = + // std::make_shared>("AT+QSIMSTAT?\r", &AtRegisterNetworkAuto::QSIMSTAT_Callback, SharedFromThis()); + // SendAtCommandTask(task); +} +ResponseCode AtRegisterNetworkAuto::QSIMSTAT_Callback(const char *buf, const unsigned int &length) +{ + return ResponseCode::RESPONSE_OK; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkAuto.h b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkAuto.h new file mode 100644 index 000000000..16c937dae --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkAuto.h @@ -0,0 +1,21 @@ +#ifndef AT_REGISTER_NETWORK_AUTO_H +#define AT_REGISTER_NETWORK_AUTO_H +#include "VAtRegisterNetwork.h" +#include "AtDefine.h" +#include "AtDataProcess.h" +class AtRegisterNetworkAuto : public VAtRegisterNetwork, public AtDataProcess +{ +public: + AtRegisterNetworkAuto(); + virtual ~AtRegisterNetworkAuto() = default; + +protected: + virtual void RegisterNetworkStart(void); + ResponseCode QSIMSTAT_Callback(const char *buf, const unsigned int &length); + +protected: + AtNetGeneration mGeneration; + +private: +}; +#endif // !AT_REGISTER_NETWORK_AUTO_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkManual.cpp b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkManual.cpp new file mode 100644 index 000000000..3940f5949 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkManual.cpp @@ -0,0 +1,427 @@ +#include "AtRegisterNetworkManual.h" +#include "Log.h" +#include "sf_opera_adapt_v2.h" +#include +AtRegisterNetworkManual::AtRegisterNetworkManual() +{ + mManual = false; + mQCFG_Times = 0; +} +bool AtRegisterNetworkManual::RegisterNetworkManualRetry(unsigned int defaultRetry) +{ + AtCallOnce(); + if (GetAtCallTimes() <= defaultRetry) + { + LogInfo("Retry to call, call times = %d.\n", GetAtCallTimes()); + return true; + } + // SetAtCallTimes(); + LogError("Register network manual failed.\n"); + AtRegisterNetworkFinished(AtRegisterNetworkResult::FAILED); + return false; +} +void AtRegisterNetworkManual::RegisterNetworkStart(void) +{ + LogInfo("AT-Command:AT+CGREG?\n"); + CGREG_Handle(); +} +const char *AT_CGREG = "AT+CGREG?\r"; +void AtRegisterNetworkManual::CGREG_Handle(void) +{ + constexpr int CGREG_RETRY_TIMES = 400; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_CGREG, response, RESPONSE_BUF_LENGTH); +CGREG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CGREG_Handle, response = %s\n", response); + if (strstr(response, "+CGREG: 0,")) + { + if (strstr(response, "+CGREG: 0,1") || strstr(response, "+CGREG: 0,5")) + { + LogInfo("reg net sucess:%s\n", response); + QCFG_Handle(); + return; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(400)); + if (GetAtCallTimes() > 320) + { + CIMI_Handle(); + return; + } + else if (GetAtCallTimes() > 180) + { + if ((!strstr(GetApnGprs(), APNGPRS_WUYUAN2)) && (!strstr(GetApnGprs(), APNGPRS_WUYUAN))) + { + LogError("Other sim reg net timeout!\n"); + AtRegisterNetworkFinished(AtRegisterNetworkResult::ERROR_REG_NET); + return; + } + } + } + } + if (RegisterNetworkManualRetry(CGREG_RETRY_TIMES)) + { + goto CGREG_RETRY; + } +} +const char *AT_QCFG_PDP = "AT+QCFG=\"pdp/duplicatechk\",0\r"; +void AtRegisterNetworkManual::QCFG_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG_PDP, response, RESPONSE_BUF_LENGTH); +QCFG_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + QCFG_TCP_1_Handle(); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QCFG_RETRY; + } +} +void AtRegisterNetworkManual::CIMI_Handle(void) +{ + constexpr int OPERATION_CODE_LENGTH = 6; + constexpr int AT_COMMAND_LENGTH = 256; + char atCommand[AT_COMMAND_LENGTH] = {0}; + char response[RESPONSE_BUF_LENGTH] = {0}; + SF_CHAR *pTemp = nullptr; + SINT16 ret = SF_FAIL; + SF_CHAR operationCode[OPERATION_CODE_LENGTH] = {0}; + SIM_INFO_S pStaticParam; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared("AT+CIMI\r", response, RESPONSE_BUF_LENGTH); +CIMI_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + // memset(atCommand, 0, AT_COMMAND_LENGTH); + SendAtCommandTask(task); + + pTemp = nullptr; + pTemp = strstr(response, "AT+CIMI"); + if (pTemp) + { + memcpy(operationCode, pTemp + 10, 5); + LogInfo("operationCode:%s\n", operationCode); + + ret = eg91_module_Polling_Comparison_CIMI(operationCode); + if (ret != SF_SUCCESS) + // return SF_4G_ERROR_NO_SUPPOET; + { + AtRegisterNetworkFinished(AtRegisterNetworkResult::FAILED_NOT_SUPPORT); + return; + } + + LogInfo("operationCode:%s\n", operationCode); + sprintf(pStaticParam.OperatorCode, "%s", operationCode); + + sf_auto_operation_adaptation(pStaticParam.OperatorCode, &pStaticParam); + if ((strstr(pStaticParam.ApnGPRS, APNGPRS_WUYUAN2)) || (strstr(pStaticParam.ApnGPRS, APNGPRS_WUYUAN))) // mega sim,use in abord + { + + // enMmcLocation = SIM_REG_NET_FIRST_2; + sprintf(atCommand, "AT+CGDCONT=1,\"IPV4V6\",\"%s\"\r", pStaticParam.ApnGPRS); + // sf_hal_ttyusb2_write(response, strlen(response)); + CGDCONT_Handle(atCommand); + return; + } + else + { + // return SF_4G_ERROR_NO_SUPPOET; + AtRegisterNetworkFinished(AtRegisterNetworkResult::FAILED_NOT_SUPPORT); + return; + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (RegisterNetworkManualRetry()) + { + goto CIMI_RETRY; + } +} +const char *AT_QCFG_TCP_1 = "AT+QCFG=\"tcp/windowsize\",0,100\r"; +void AtRegisterNetworkManual::QCFG_TCP_1_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG_TCP_1, response, RESPONSE_BUF_LENGTH); +QCFG_TCP_1_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_TCP_1_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + QCFG_TCP_2_Handle(); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QCFG_TCP_1_RETRY; + } +} +const char *AT_QCFG_TCP_2 = "AT+QCFG=\"tcp/windowsize\",1,100\r"; +void AtRegisterNetworkManual::QCFG_TCP_2_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG_TCP_2, response, RESPONSE_BUF_LENGTH); +QCFG_TCP_2_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_TCP_2_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + QNWINFO_Handle(); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QCFG_TCP_2_RETRY; + } +} +const char *AT_QNWINFO = "AT+QNWINFO\r"; +void AtRegisterNetworkManual::QNWINFO_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QNWINFO, response, RESPONSE_BUF_LENGTH); +QNWINFO_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QNWINFO_Handle, response = %s\n", response); + if (strstr(response, "+QNWINFO:") != nullptr) + { + if (strstr(response, "No Service")) + { + mGeneration = AtNetGeneration::NET_2G; + } + else if (nullptr != strtok(response, "\"")) + { + SF_CHAR netStr[20] = {0}; + strcpy(netStr, strtok(nullptr, "\"")); + LogInfo("netStr:%s\n", netStr); + if ((strstr(netStr, "DD") != nullptr)) + { + mGeneration = AtNetGeneration::NET_4G; + } + else if (strstr(netStr, "CDMA") != nullptr || strstr(netStr, "HDR") != nullptr || strstr(netStr, "HSUPA") != nullptr || strstr(netStr, "HSDPA") != nullptr || strstr(netStr, "HSPA+") != nullptr) + { + mGeneration = AtNetGeneration::NET_3G; + } + else + { + mGeneration = AtNetGeneration::NET_2G; + } + } + AtGetGeneration(mGeneration); + COPS_Handle(); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QNWINFO_RETRY; + } +} +const char *AT_COPS = "AT+COPS?\r"; +void AtRegisterNetworkManual::COPS_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_COPS, response, RESPONSE_BUF_LENGTH); +COPS_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("COPS_Handle, response = %s\n", response); + SF_CHAR *pStr = nullptr; + if (strstr(response, "+COPS:") != nullptr) + { + strtok(response, "\""); + pStr = strtok(nullptr, "\""); + if (pStr != nullptr) + { + LogInfo("cops1 is %s\r\n", pStr); + AtGetServiceProvider(pStr); + } + + if (AtNetGeneration::NET_4G == mGeneration) // AtNetGeneration == 4 + { + QCSQ_Handle(); + return; + } + else + { + CSQ_Handle(); + return; + } + } + if (RegisterNetworkManualRetry()) + { + goto COPS_RETRY; + } +} +const char *AT_QCSQ = "AT+QCSQ\r"; +void AtRegisterNetworkManual::QCSQ_Handle(void) +{ + constexpr int QCSQ_RETRY_TIMES = 10; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCSQ, response, RESPONSE_BUF_LENGTH); +QCSQ_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCSQ_Handle, response = %s\n", response); + SF_CHAR *pStr = nullptr; + SINT32 csq = 0; + UINT8 simSignal = 0; + if (strstr(response, "+QCSQ:")) + { + pStr = nullptr; + pStr = strtok(response, ","); + LogInfo("pStr:%s\n", pStr); + pStr = strtok(nullptr, ","); + LogInfo("pStr:%s\n", pStr); + if (pStr != nullptr) + { + pStr = strtok(nullptr, ","); + // LogInfo("pStr:%s\n", pStr); + csq = 0 - atoi(pStr); + // LogInfo("SINT32:%d\n", csq); + // pStaticParam->SimSignal = (UINT8)csq; // TODO: Get data?? + simSignal = (UINT8)csq; + if (simSignal == 0) + { + if (GetAtCallTimes() >= 10) + { + simSignal = 105; + } + } + else + { + AT_AND_W_Handle(); + AtGetSimSignal(simSignal); + AtRegisterNetworkFinished(AtRegisterNetworkResult::SUCCEED); + return; + } + } + else + { + simSignal = 0; + AtRegisterNetworkFinished(AtRegisterNetworkResult::FAILED_NO_SIGNAL); + AtGetSimSignal(simSignal); + AT_AND_W_Handle(); + return; + } + if (RegisterNetworkManualRetry(QCSQ_RETRY_TIMES)) + { + goto QCSQ_RETRY; + } + AtGetSimSignal(simSignal); + return; + } + if (RegisterNetworkManualRetry()) + { + goto QCSQ_RETRY; + } +} +void AtRegisterNetworkManual::CSQ_Handle(void) +{ + constexpr int CSQ_RETRY_TIMES = 10; + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared("AT+CSQ\r", response, RESPONSE_BUF_LENGTH); +CSQ_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CSQ_Handle, response = %s\n", response); + SF_CHAR *pStr = nullptr; + SINT32 csq = 0; + UINT8 simSignal = 0; + if (strstr(response, "+CSQ:")) + { + LogInfo("%s", response); + SF_CHAR *pTemp = nullptr; + pStr = strstr(response, "+CSQ:") + 6; + LogInfo("pStr:%s\n", pStr); + pTemp = strtok(pStr, ","); + LogInfo("pTemp:%s\n", pTemp); + if (pTemp != nullptr) + { + csq = atoi(pTemp); + if ((csq > 31) || (csq == 0)) + { + if (GetAtCallTimes() >= CSQ_RETRY_TIMES) + { + simSignal = 0; + AtRegisterNetworkFinished(AtRegisterNetworkResult::FAILED_NO_SIGNAL); + } + } + else + { + simSignal = csq; + AtGetSimSignal(simSignal); + AtRegisterNetworkFinished(AtRegisterNetworkResult::SUCCEED); + AT_AND_W_Handle(); + return; + } + } + if (RegisterNetworkManualRetry(CSQ_RETRY_TIMES)) + { + goto CSQ_RETRY; + } + AtGetSimSignal(simSignal); + return; + } + if (RegisterNetworkManualRetry()) + { + goto CSQ_RETRY; + } +} +const char *AT_W = "AT&W\r"; +void AtRegisterNetworkManual::AT_AND_W_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_W, response, RESPONSE_BUF_LENGTH); +AT_AND_W_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("AT_AND_W_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + LogInfo("AT_AND_W_Handle ok.\n"); + // AtRegisterNetworkFinished(AtRegisterNetworkResult::SUCCEED); + return; + } + if (RegisterNetworkManualRetry()) + { + goto AT_AND_W_RETRY; + } +} +void AtRegisterNetworkManual::CGDCONT_Handle(const char *atCommand) +{ + constexpr int AT_LENGTH = 1024; + char at[AT_LENGTH] = {0}; + memcpy(at, atCommand, strlen(atCommand)); + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +CGDCONT_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CGDCONT_Handle, response = %s\n", response); + if (strstr(response, "OK")) + { + CGREG_Handle(); + } + if (RegisterNetworkManualRetry()) + { + goto CGDCONT_RETRY; + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkManual.h b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkManual.h new file mode 100644 index 000000000..d00d86fb3 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtRegisterNetworkManual.h @@ -0,0 +1,32 @@ +#ifndef AT_REGISTER_NETWORK_MANUAL_H +#define AT_REGISTER_NETWORK_MANUAL_H +#include "AtRegisterNetworkAuto.h" +class AtRegisterNetworkManual : public AtRegisterNetworkAuto +{ +public: + AtRegisterNetworkManual(); + virtual ~AtRegisterNetworkManual() = default; + void SetManualFlag(const bool &flag) { mManual = flag; } + +protected: + void RegisterNetworkStart(void) override; + virtual void CGREG_Handle(void); + virtual void QCFG_Handle(void); + virtual void CIMI_Handle(void); + virtual void QCFG_TCP_1_Handle(void); + virtual void QCFG_TCP_2_Handle(void); + virtual void QNWINFO_Handle(void); + virtual void COPS_Handle(void); + virtual void QCSQ_Handle(void); + virtual void CSQ_Handle(void); + virtual void AT_AND_W_Handle(void); + virtual void CGDCONT_Handle(const char *atCommand); + +private: + bool RegisterNetworkManualRetry(unsigned int defaultRetry = 200); + +private: + bool mManual; + unsigned int mQCFG_Times; +}; +#endif // !AT_REGISTER_NETWORK_MANUAL_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtSimInit.cpp b/code/application/sifarsdk/component/AtCommand/src/eg91/AtSimInit.cpp new file mode 100644 index 000000000..4ce48d476 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtSimInit.cpp @@ -0,0 +1,743 @@ +#include "AtSimInit.h" +// #include "IPeripheralManager.h" +#include "Log.h" +#include "sf_opera_adapt_v2.h" +#include +const char *AT_COMMAND_ATE = "ATE1\r"; +AtSimInit::AtSimInit() +{ + mModuelV05 = 0; + memset(GsnSaved, 0, GSN_BUF_LENGTH); + memset(ModuleVersion, 0, SF_MODULE_VER_MAX_LEN); + memset(lastICCID, 0, ICCID_BUF_LENGTH); + mInitRuning = false; +} +void AtSimInit::UnInit(void) +{ + LogInfo("AtSimInit::UnInit.\n"); + mInitRuning = false; + if (mInitThread.joinable()) + { + mInitThread.join(); + } +} +RETURN_CODE AtSimInit::AtSimCardInit(void) +{ + // TODO: 4G module has already connected ??? + auto SimInitThreadStart = [](std::shared_ptr atCommand) + { + std::dynamic_pointer_cast(atCommand)->AtSimInitStart(); + }; + if (mInitRuning) + { + LogWarning("AtSimCardInit runing.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + mInitRuning = true; + mInitThread = std::thread(SimInitThreadStart, SharedFromThis()); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void AtSimInit::AtSimInitStart(void) +{ + ATE_Handle(); +} +bool AtSimInit::SimInitRetry(void) +{ + if (!mInitRuning) + { + LogWarning("Stop Init.\n"); + return false; + } + constexpr int SIM_INIT_CALL_RETRY = 200; + AtCallOnce(); + if (GetAtCallTimes() <= SIM_INIT_CALL_RETRY) + { + LogInfo("Retry to call, call times = %d.\n", GetAtCallTimes()); + return true; + } + // SetAtCallTimes(); + LogError("Sim card init failed.\n"); // TODO: + return false; +} +void AtSimInit::ATE_Handle(void) +{ + LogInfo("AT-Command:ATE1\n"); + SetAtCallTimes(0); + char response[RESPONSE_BUF_LENGTH] = {0}; + std::shared_ptr task = std::make_shared(AT_COMMAND_ATE, response, RESPONSE_BUF_LENGTH); +ATE_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("AtSimInitStart. response = %s\n", response); + if (strstr(response, "OK")) + { + LogInfo("ATE_Handle response ok.\n"); + AT_GSN_Handle(); + return; + } + if (SimInitRetry()) + { + goto ATE_RETRY; + } +} +const char *AT_GSN = "AT+GSN\r"; +void AtSimInit::AT_GSN_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_GSN, response, RESPONSE_BUF_LENGTH); +AT_GSN_RETRY: + if (!mInitRuning) + { + LogWarning("Stop Init.\n"); + return; + } + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + unsigned int length = std::dynamic_pointer_cast(task)->ActualResponseLength(); + LogInfo("AT_GSN_Handle. response = %s\n", response); + UINT16 index = 0; + SF_CHAR GsnNow[GSN_BUF_LENGTH] = {0}; + if (response[0] != '\0') + { + for (index = 0; index < length; index++) + { + if ((response[index] == '8') && (response[index + 1] == '6')) + { + SF_CHAR tempImei[16] = {0}; + UINT8 p = 0; + for (p = 0; p < IMEI_LEN; p++) + { + if ((response[p + index] >= '0') && (response[p + index] <= '9')) + tempImei[p] = response[p + index]; + else + tempImei[p] = '\0'; + } + tempImei[15] = '\0'; + strcpy(GsnNow, tempImei); + break; + } + } + } + LogInfo("GsnNow = %s\n", GsnNow); + LogInfo("GsnSaved = %s\n", GsnSaved); + if ((GsnNow[0] != '\0') && (strncmp(GsnNow, GsnSaved, IMEI_LEN) == 0)) + { + AtGetIMEI(GsnNow); + ATI_Handle(); + return; + } + else + { + LogWarning("RESPONSE_FAILED_RETRY.\n"); + strcpy(GsnSaved, GsnNow); + goto AT_GSN_RETRY; + } + if (SimInitRetry()) + { + goto AT_GSN_RETRY; + } +} +const char *AT_ATI = "ATI\r"; +void AtSimInit::ATI_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_ATI, response, RESPONSE_BUF_LENGTH); +ATI_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("ATI_Handle.buf = %s\n", response); + SF_CHAR *pTemp = nullptr; + SF_CHAR *p = nullptr; + if ((strstr(response, "OK") != nullptr) || (strstr(response, "ERROR") != nullptr)) + { + pTemp = strstr(response, "Revision:"); + if (pTemp != nullptr) + { + SF_CHAR modulVerStr[256] = {0}; + strcpy(modulVerStr, pTemp + 10); + pTemp = strtok(modulVerStr, "OK"); + p = strtok(pTemp, "\r\n"); + if (strcasecmp(p, ModuleVersion) != 0) + { + strcpy(ModuleVersion, p); + } + } + if ((strstr(response, "AFAR05"))) + { + SetModuleV05(1); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + QFLST_1_Handle("at+qflst=\"../../usr/fota_ip_a/update_report.ur\"\r"); + } + else if (strstr(response, "AFAR07")) + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + QFLST_1_Handle("at+qflst=\"../../data/fota_ip_a/update_report.ur\"\r"); + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + QGMR_Handle(); + } + return; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (SimInitRetry()) + { + goto ATI_RETRY; + } +} +const char *AT_QGMR = "AT+QGMR\r"; +void AtSimInit::QGMR_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QGMR, response, RESPONSE_BUF_LENGTH); +QGMR_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QGMR_Handle.response = %s\n", response); + if (strstr(response, GPRS_MODULE_TYPE_EG91) != nullptr) + { + char subTemp[SF_MODULE_VER_MAX_LEN] = {0}; + eg91_parse_module_version((SF_CHAR *)strstr(response, GPRS_MODULE_TYPE_EG91), subTemp); + AtGetModuleSubVersion(subTemp); + if (strstr(ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) + { + QNVFR_Handle(); + } + else + { + QSIMSTAT_Handle(); + } + return; + } + else if (strstr(response, GPRS_MODULE_TYPE_EG95) != nullptr) + { + char subTemp[SF_MODULE_VER_MAX_LEN] = {0}; + eg91_parse_module_version((SF_CHAR *)strstr(response, GPRS_MODULE_TYPE_EG95), subTemp); + AtGetModuleSubVersion(subTemp); + if (strstr(ModuleVersion, GPRS_MODULE_TYPE_EG95_V)) + { + QNVFR_Handle(); + } + else + { + QSIMSTAT_Handle(); + } + return; + } + else + { + if (GetAtCallTimes() > 5) + { + if (strstr(ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) + { + QNVFR_Handle(); + } + else if (strstr(ModuleVersion, GPRS_MODULE_TYPE_EG95_V)) + { + QNVFR_Handle(); + } + else + { + QSIMSTAT_Handle(); + } + return; + } + if (SimInitRetry()) + { + goto QGMR_RETRY; + } + } +} +const char *AT_QSIMSTAT = "AT+QSIMSTAT?\r"; +void AtSimInit::QSIMSTAT_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = + std::make_shared(AT_QSIMSTAT, response, RESPONSE_BUF_LENGTH); +QSIMSTAT_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QSIMSTAT_Handle. response=%s\n", response); + if (strstr(response, "+QSIMSTAT: 0,0")) + { + if (GetAtCallTimes() > 50) + { + LogError("SimCard not inserted.\n"); + AtSimInitFinished(AtInitSimResult::SIM_INIT_NOT_INSERTED); + return; + } + if (SimInitRetry()) + { + LogWarning("QSIMSTAT_RETRY.\n"); + goto QSIMSTAT_RETRY; + } + } + else if (strstr(response, "+QSIMSTAT: 0,1")) + { + LogInfo("SIM_INIT_QURCCFG.\n"); + QURCCFG_Handle(); + return; + } + else if (strstr(response, "+CPIN: NOT INSERTED")) + { + LogError("SimCard not inserted.\n"); + AtSimInitFinished(AtInitSimResult::SIM_INIT_NOT_INSERTED); + return; + } + if (SimInitRetry()) + { + goto QSIMSTAT_RETRY; + } +} +void AtSimInit::AT_END_Handle(char *atCommand) +{ + constexpr int AT_LENGTH = 1024; + SetAtCallTimes(0); + char response[RESPONSE_BUF_LENGTH] = {0}; + char at[AT_LENGTH] = {0}; + memcpy(at, atCommand, strlen(atCommand)); + std::shared_ptr task = + std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); + // AT_END_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("AT_END_Handle. response = %s\n", response); + if (strstr(response, "OK")) + { + LogInfo("Sim card init ok.\n"); + AtSimInitFinished(AtInitSimResult::SIM_INIT_OK); + return; + } + else if (strstr(response, "NOT")) + { + LogError("Sim card init failed, no sim card.\n"); + AtSimInitFinished(AtInitSimResult::SIM_INIT_NOT_INSERTED); + return; + } + else + { + LogWarning("What happened?\n"); + if ((GetAtCallTimes() % 10) == 0) + { // TODO: What happend? No need to handle response? + memset(response, 0, RESPONSE_BUF_LENGTH); + std::shared_ptr task2 = + std::make_shared("AT+CPIN?\r", response, RESPONSE_BUF_LENGTH); // TODO: + SendAtCommandTask(task2); + } + } +} +void AtSimInit::QNVFR_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = + std::make_shared("at+qnvfr=\"/nv/item_files/modem/uim/gstk/feature_bmsk\"\r", response, RESPONSE_BUF_LENGTH); +QNVFR_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QNVFR_Handle.\n"); + if (strstr(response, "+QNVFR: 11000000")) + { + QNVFW_Handle(); + return; + } + else + { + AT_END_Handle((char *)"AT\r"); + return; + } + if (SimInitRetry()) + { + goto QNVFR_RETRY; + } +} +void AtSimInit::QNVFW_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = + std::make_shared("at+qnvfw=\"/nv/item_files/modem/uim/gstk/feature_bmsk\",01000000\r", response, RESPONSE_BUF_LENGTH); +QNVFW_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QNVFW_Handle.\n"); + if (strstr(response, "OK")) + { + AT_END_Handle((char *)"AT\r"); + return; + } + if (SimInitRetry()) + { + goto QNVFW_RETRY; + } +} +void AtSimInit::QFLST_1_Handle(const char *atCommand) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QFLST_1_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QFLST_1_Handle.\n"); + if (strstr(response, "OK")) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + QGMR_Handle(); + return; + } + else if (strstr(response, "ERROR: 417")) + { + UINT8 modulev05 = GetModuleV05(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + if (modulev05 == 1) + { + QFLST_2_Handle("at+qfopen=\"../../usr/fota_ip_a/update_report.ur\",1\r"); + } + else + { + QFLST_2_Handle("at+qfopen=\"../../data/fota_ip_a/update_report.ur\",1\r"); + } + return; + } + else + { + if (GetAtCallTimes() > 10) + { + SetAtCallTimes(0); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + QFLST_2_Handle("ATI\r"); + return; + } + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (SimInitRetry()) + { + goto QFLST_1_RETRY; + } + } +} +void AtSimInit::QFLST_2_Handle(const char *atCommand) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(atCommand, response, RESPONSE_BUF_LENGTH); +QFLST_2_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QFLST_2_Handle.\n"); + if (strstr(response, "OK")) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + QGMR_Handle(); + return; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ATI_Handle(); + return; + } + if (SimInitRetry()) + { + goto QFLST_2_RETRY; + } +} +const char *AT_QURCCFG = "AT+QURCCFG=\"urcport\",\"usbat\"\r"; +void AtSimInit::QURCCFG_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + std::shared_ptr task = std::make_shared(AT_QURCCFG, response, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QSIMSTAT_Handle. response=%s\n", response); // TODO: ?? + QCFG_1_Handle(); +} +const char *AT_QCFG = "AT+QCFG=\"risignaltype\",\"physical\"\r"; +void AtSimInit::QCFG_1_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG, response, RESPONSE_BUF_LENGTH); +QCFG_1_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_1_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + QCFG_2_Handle(); + return; + } + if (SimInitRetry()) + { + goto QCFG_1_RETRY; + } +} +const char *AT_QCFG_2 = "AT+QCFG=\"urc/ri/other\",\"off\"\r"; +void AtSimInit::QCFG_2_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCFG_2, response, RESPONSE_BUF_LENGTH); +QCFG_2_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCFG_2_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + QLWCFG_1_Handle(); + return; + } + if (SimInitRetry()) + { + goto QCFG_2_RETRY; + } +} +const char *AT_QLWCFG = "AT+QLWCFG=\"urc\",0\r"; +void AtSimInit::QLWCFG_1_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QLWCFG, response, RESPONSE_BUF_LENGTH); +QLWCFG_1_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QLWCFG_1_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + QLWCFG_2_Handle(); + return; + } + if (SimInitRetry()) + { + goto QLWCFG_1_RETRY; + } +} +const char *AT_QLWCFG_2 = "AT+QLWCFG=\"startup\",0\r"; +void AtSimInit::QLWCFG_2_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QLWCFG_2, response, RESPONSE_BUF_LENGTH); +QLWCFG_2_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QLWCFG_2_Handle. response=%s\n", response); + if (strstr(response, "OK")) + { + CPIN_Handle(); + return; + } + if (SimInitRetry()) + { + goto QLWCFG_2_RETRY; + } +} +const char *AT_CPIN = "AT+CPIN?\r"; +void AtSimInit::CPIN_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_CPIN, response, RESPONSE_BUF_LENGTH); +CPIN_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CPIN_Handle. response=%s\n", response); + if (strstr(response, "READY")) + { + QCCID_Handle(); + return; + } + if (SimInitRetry()) + { + goto CPIN_RETRY; + } +} +const char *AT_QCCID = "AT+QCCID\r"; +void AtSimInit::QCCID_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_QCCID, response, RESPONSE_BUF_LENGTH); +QCCID_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("QCCID_Handle. response=%s\n", response); + SF_CHAR *pStr = nullptr; + SF_CHAR tempICCID[ICCID_BUF_LENGTH] = {0}; + if ((strstr(response, "+QCCID: ") != nullptr)) + { + pStr = strstr(response, "+QCCID: "); + memcpy(tempICCID, pStr + 8, 20); + if ((tempICCID[19] <= '9') && (tempICCID[19] >= '0')) + tempICCID[20] = '\0'; + else + tempICCID[19] = '\0'; + if (strncmp(lastICCID, tempICCID, 21) == 0) + { + LogInfo("ICCID=%s\n", tempICCID); + AtGetICCID(tempICCID); + CIMI_Handle(); + return; + } + else + { + strcpy(lastICCID, tempICCID); + memset(tempICCID, '\0', sizeof(tempICCID)); + goto QCCID_RETRY; + } + } + if (SimInitRetry()) + { + goto QCCID_RETRY; + } +} +const char *AT_CIMI = "AT+CIMI\r"; +void AtSimInit::CIMI_Handle(void) +{ + char response[RESPONSE_BUF_LENGTH] = {0}; + SetAtCallTimes(0); + std::shared_ptr task = std::make_shared(AT_CIMI, response, RESPONSE_BUF_LENGTH); +CIMI_RETRY: + memset(response, 0, RESPONSE_BUF_LENGTH); + SendAtCommandTask(task); + LogInfo("CIMI_Handle. response=%s\n", response); + SF_CHAR operationCode[OPERATION_CODE_LENGTH] = {0}; + SF_CHAR *pTemp = nullptr; + SIM_INFO_S simInfo = {0}; + pTemp = strstr(response, "AT+CIMI"); + constexpr int SF_TTYUSB_RECV_MAX = 580; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = {0}; + if (pTemp) + { + memcpy(operationCode, pTemp + 10, 5); + LogInfo("operationCode:%s\n", operationCode); + sprintf(simInfo.OperatorCode, "%s", operationCode); + sf_auto_operation_adaptation(simInfo.OperatorCode, &simInfo); + LogInfo("ApnGPRS:%s\n", simInfo.ApnGPRS); + if ((strstr(simInfo.ApnGPRS, APNGPRS_WUYUAN2)) || (strstr(simInfo.ApnGPRS, APNGPRS_WUYUAN))) // 20408 sifar kpn sim + { + AtGetSimType(AtSimTpye::SF_SIM_MEGA); + // 1. mega sim,set pdp 1 apn + eg91_module_Polling_Comparison_CIMI(operationCode); // mega sim,recorde sim operation code + sprintf(ttyData, "AT+CGDCONT=1,\"IPV4V6\",\"%s\"\r", simInfo.ApnGPRS); + AT_END_Handle(ttyData); + return; + } + else if (strstr(simInfo.ApnGPRS, APNGPRSTEMP)) + { + AtGetSimType(AtSimTpye::SF_SIM_MEGA_IOT); + AT_END_Handle((char *)"AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + return; + } + else + { + // AtSimInitFinished(AtInitSimResult::SIM_INIT_NOT_SUPPORT_MOBILE_NETWORK); + AtSimInitFinished(AtInitSimResult::SIM_INIT_OK); + return; + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (SimInitRetry()) + { + goto CIMI_RETRY; + } +} +void AtSimInit::CGDCONT_Handle(void) +{ + // LogInfo("CGDCONT_Handle. buf=%s\n", buf); +} +SINT32 AtSimInit::eg91_parse_module_version(SF_CHAR *pTemp, SF_CHAR *version) +{ + SF_CHAR *pT1 = nullptr; + SF_CHAR *pT2 = nullptr; + SF_CHAR *pT3 = nullptr; + SF_CHAR *pT4 = nullptr; + + pT1 = strstr(pTemp, "FAR"); + pT2 = strstr(pTemp, "_"); + pT3 = strstr(pTemp, "GAR"); + pT4 = strstr(pTemp, "OCPU"); + + LogInfo("pTemp = %s\n", pTemp); + LogInfo("pT1 = %s\n", pT1); + LogInfo("pT2 = %s\n", pT2); + LogInfo("pT3 = %s\n", pT3); + + if (pT1 != nullptr) + eg91_parse_module_version_detail(pTemp, pT1, pT2, pT4, version); + else if (pT3 != nullptr) + eg91_parse_module_version_detail(pTemp, pT3, pT2, pT4, version); + + LogInfo("version:%s\n", version); + return SF_SUCCESS; +} +void AtSimInit::eg91_parse_module_version_detail(SF_CHAR *pTemp, SF_CHAR *pT1, SF_CHAR *pT2, SF_CHAR *pT4, SF_CHAR *version) +{ + // FILE_HEADER *sim_info_t = sf_statistics_param_get(); + const char *moduleVersion = GetModuleVersionParam(); + SF_CHAR str0[5] = {0}; + SF_CHAR str1[5] = {0}; + SF_CHAR str2[5] = {0}; + SF_CHAR str3[5] = {0}; + SF_CHAR str4[256] = {0}; + SF_CHAR str5[256] = {0}; + SF_CHAR *pT5 = nullptr; + memcpy(str1, pTemp + 4, pT1 - pTemp - 4); + // printf("str1 = %s\n", str1); + memcpy(str2, pT1 + 3, 2); + // printf("str2 = %s\n", str2); + memcpy(str3, pT1 + 6, 2); + // printf("str3 = %s\n", str3); + + if (strstr(moduleVersion, GPRS_MODULE_TYPE_EG91)) + { + sprintf(str0, "%s", "91"); + } + else if (strstr(moduleVersion, GPRS_MODULE_TYPE_EG95)) + { + sprintf(str0, "%s", "95"); + } + else + { + sprintf(str0, "%s", "UN"); + } + + if (pT2 != nullptr) + { + strcpy(str4, pT2 + 1); + // printf("str4 = %s\n", str4); + pT5 = strtok(str4, "\r\n"); + + if (pT5 != nullptr) + { + strcpy(str5, pT5); + // printf("str5 = %s\n",str5); + + if (pT4 != nullptr) + sprintf(version, "S%sY%sY%sY%sY%sOS", str0, str1, str2, str3, str5); + else + sprintf(version, "S%sY%sY%sY%sY%sS", str0, str1, str2, str3, str5); + } + else + { + if (pT4 != nullptr) + sprintf(version, "S%sY%sY%sY%sOS", str0, str1, str2, str3); + else + sprintf(version, "S%sY%sY%sY%sS", str0, str1, str2, str3); + } + } + else + { + if (pT4 != nullptr) + sprintf(version, "S%sY%sY%sY%sOS", str0, str1, str2, str3); + else + sprintf(version, "S%sY%sY%sY%sS", str0, str1, str2, str3); + } + + LogInfo("module_QGver = %s\n", version); + return; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/AtSimInit.h b/code/application/sifarsdk/component/AtCommand/src/eg91/AtSimInit.h new file mode 100644 index 000000000..77d30df3f --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/AtSimInit.h @@ -0,0 +1,52 @@ +#ifndef AT_SIM_INIT_H +#define AT_SIM_INIT_H +#include "VAtSimInit.h" +#include "SfTypeDefine.h" +#include "sf_opera_adapt_v2.h" +#include "AtDefine.h" +#include "AtDataProcess.h" +#include +class AtSimInit : public VAtSimInit, public AtDataProcess +{ +public: + AtSimInit(); + virtual ~AtSimInit() = default; + void UnInit(void); + RETURN_CODE AtSimCardInit(void) override; + +protected: + virtual bool SimInitRetry(void); + virtual void SetModuleV05(const UINT8 &moduleV05) { mModuelV05 = moduleV05; } + UINT8 GetModuleV05(void) { return mModuelV05; } + virtual void AtSimInitStart(void); + virtual void ATE_Handle(void); + virtual void AT_GSN_Handle(void); + virtual void ATI_Handle(void); + virtual void QGMR_Handle(void); + virtual void QSIMSTAT_Handle(void); + virtual void AT_END_Handle(char *atCommand); + virtual void QNVFR_Handle(void); + virtual void QNVFW_Handle(void); + virtual void QFLST_1_Handle(const char *atCommand); + virtual void QFLST_2_Handle(const char *atCommand); + virtual void QURCCFG_Handle(void); + virtual void QCFG_1_Handle(void); + virtual void QCFG_2_Handle(void); + virtual void QLWCFG_1_Handle(void); + virtual void QLWCFG_2_Handle(void); + virtual void CPIN_Handle(void); + virtual void QCCID_Handle(void); + virtual void CIMI_Handle(void); + virtual void CGDCONT_Handle(void); + SINT32 eg91_parse_module_version(SF_CHAR *pTemp, SF_CHAR *version); + void eg91_parse_module_version_detail(SF_CHAR *pTemp, SF_CHAR *pT1, SF_CHAR *pT2, SF_CHAR *pT4, SF_CHAR *version); + +private: + UINT8 mModuelV05; + char ModuleVersion[SF_MODULE_VER_MAX_LEN]; // TODO: Input param. + SF_CHAR GsnSaved[GSN_BUF_LENGTH]; + SF_CHAR lastICCID[ICCID_BUF_LENGTH]; + std::thread mInitThread; + bool mInitRuning; +}; +#endif // !AT_SIM_INIT_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/Eg91AtCommand.cpp b/code/application/sifarsdk/component/AtCommand/src/eg91/Eg91AtCommand.cpp new file mode 100644 index 000000000..ac1b6c659 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/Eg91AtCommand.cpp @@ -0,0 +1,187 @@ +#include "Eg91AtCommand.h" +#include "Log.h" +bool CreateAtCommandImpl(std::shared_ptr &impl) +{ + impl = std::make_shared(); + return true; +} +Eg91AtCommand::Eg91AtCommand() +{ + mOwner = std::make_shared(); +} +RETURN_CODE Eg91AtCommand::Init(void) +{ + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Eg91AtCommand::UnInit(void) +{ + AtSimInit::UnInit(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Eg91AtCommand::SetOwner(std::shared_ptr &Owner) +{ + mOwner = Owner; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Eg91AtCommand::SimInit(void) +{ + AtSimInit::AtSimCardInit(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Eg91AtCommand::AtRegisterNetworkManual(void) +{ + AtRegisterNetwork::RegisterNetworkManual(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Eg91AtCommand::AtNetApnConfig(void) +{ + AtRegisterNetwork::UsbNetApnConfigStart(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE Eg91AtCommand::MqttKeepAlive(void) +{ + AtMqtt::sf_mqtt_client_thread_stop(); + AtMqtt::sf_mqtt_client_close(); + AtMqtt::sf_mqtt_client_open(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void Eg91AtCommand::SendAtCommandTask(std::shared_ptr task) +{ + mOwner->WriteAtCommand(task); +} +void Eg91AtCommand::AtGetIMEI(const char *imei) +{ + mSimInitData.mIMEI = imei; +} +void Eg91AtCommand::AtGetModuleSubVersion(const char *version) +{ + mSimInitData.mModuleSubVersion = version; +} +void Eg91AtCommand::AtGetICCID(const char *iccid) +{ + mSimInitData.mIccid = iccid; +} +void Eg91AtCommand::AtGetSimType(const AtSimTpye &type) +{ + mSimInitData.mType = type; +} +void Eg91AtCommand::AtSimInitFinished(const AtInitSimResult &result) +{ + mSimInitData.mResult = result; + LogInfo("Sim init result %d\n", static_cast(result)); + mOwner->AtFinishInitSimCard(mSimInitData); +} +std::shared_ptr Eg91AtCommand::SharedFromThis(void) +{ + return std::dynamic_pointer_cast(shared_from_this()); +} +void Eg91AtCommand::AtGetGeneration(const AtNetGeneration &generation) +{ + LogInfo("AtGetGeneration = %d\n", static_cast(generation)); + mRegisterNetworkData.mGeneration = generation; +} +void Eg91AtCommand::AtGetSimSignal(const UINT8 &signal) +{ + LogInfo("AtGetSimSignal = %d\n", signal); + mRegisterNetworkData.mSimSignal = signal; +} +void Eg91AtCommand::AtGetSimInfo(const SIM_INFO_S *info) +{ + if (info) + { + memcpy(&mSimInfo, info, sizeof(SIM_INFO_S)); + } +} +void Eg91AtCommand::GetSimInfo(SIM_INFO_S *info) +{ + if (info) + { + memcpy(info, &mSimInfo, sizeof(SIM_INFO_S)); + } +} +void Eg91AtCommand::AtRegisterNetworkFinished(const AtRegisterNetworkResult &result) +{ + mRegisterNetworkData.result = result; + LogInfo("Eg91AtCommand::AtRegisterNetworkResult %d\n", static_cast(result)); + FigureOutSignalLevel(mRegisterNetworkData); + mOwner->AtFinishRegisterNetwork(mRegisterNetworkData); +} +void Eg91AtCommand::AtGetServiceProvider(const std::string &serviceProvider) +{ + mRegisterNetworkData.mServiceProvider = serviceProvider; +} +void Eg91AtCommand::AtNetApnConfigFinished(const AtConfigNetApnResult &result) +{ + AtNetApnConfigData data(result); + mOwner->AtFinishNetApnConfig(data); +} +unsigned int Eg91AtCommand::GetPdpIndex(void) +{ + AtDeviceMessage message; + mOwner->GetDeviceMessage(message); + return message.mPdp; +} +void Eg91AtCommand::FigureOutSignalLevel(NetworkRegisterResult &data) +{ + if (AtNetGeneration::NET_4G == data.mGeneration) + { + data.mSignalLevel = FigureOutSignalLevel_4G(data.mSimSignal); + } + else if (AtNetGeneration::NET_3G == data.mGeneration) + { + data.mSignalLevel = FigureOutSignalLevel_3G(data.mSimSignal); + } + else + { + LogError("FigureOutSignalLevel failed.\n"); + data.mSignalLevel = AtSignalLevel::LEVEL_0; // TODO: What should do? + } + LogInfo("FigureOutSignalLevel data.mSignalLevel = %d\n", static_cast(data.mSignalLevel)); +} +AtSignalLevel Eg91AtCommand::FigureOutSignalLevel_4G(unsigned char &simSignal) +{ + if (simSignal == 0) + { + return AtSignalLevel::LEVEL_0; // 0 + } + else if ((simSignal <= 95) && (simSignal > 0)) + { + return AtSignalLevel::LEVEL_3; // 4 + } + else if ((simSignal <= 105) && (simSignal > 95)) + { + return AtSignalLevel::LEVEL_2; // 3 + } + else if ((simSignal <= 115) && (simSignal > 105)) + { + return AtSignalLevel::LEVEL_2; // 3 + } + else if ((simSignal > 115)) + return AtSignalLevel::LEVEL_1; // 2 + + return AtSignalLevel::LEVEL_0; +} +AtSignalLevel Eg91AtCommand::FigureOutSignalLevel_3G(unsigned char &simSignal) +{ + if (simSignal == 0) + { + return AtSignalLevel::LEVEL_0; // 0 + } + else if (simSignal < 10) + { + return AtSignalLevel::LEVEL_1; // 2 + } + else if (simSignal < 14) + { + return AtSignalLevel::LEVEL_2; // t100, custumer signal level,20210914 // 3 + } + else if (simSignal < 18) + { + return AtSignalLevel::LEVEL_2; // t100, custumer signal level,20210914 // 3 + } + else if (simSignal <= 31) + { + return AtSignalLevel::LEVEL_3; // t100, custumer signal level,20210914 // 4 + } + return AtSignalLevel::LEVEL_0; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/Eg91AtCommand.h b/code/application/sifarsdk/component/AtCommand/src/eg91/Eg91AtCommand.h new file mode 100644 index 000000000..c97b7ed53 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/Eg91AtCommand.h @@ -0,0 +1,48 @@ +#ifndef EG91_AT_COMMAND_H +#define EG91_AT_COMMAND_H +#include "IAtCommand.h" +#include "AtSimInit.h" +#include "AtRegisterNetwork.h" +#include "AtMqtt.h" +class Eg91AtCommand : public IAtCommand, public AtSimInit, public AtRegisterNetwork, public AtMqtt, public std::enable_shared_from_this +{ +public: + Eg91AtCommand(); + virtual ~Eg91AtCommand() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + RETURN_CODE SetOwner(std::shared_ptr &Owner) override; + RETURN_CODE SimInit(void) override; + RETURN_CODE AtRegisterNetworkManual(void) override; + RETURN_CODE AtNetApnConfig(void) override; + RETURN_CODE MqttKeepAlive(void) override; + +private: + void SendAtCommandTask(std::shared_ptr task) override; + void AtGetIMEI(const char *imei) override; + void AtGetModuleSubVersion(const char *version) override; + void AtGetICCID(const char *iccid) override; + void AtGetSimType(const AtSimTpye &type) override; + void AtSimInitFinished(const AtInitSimResult &result) override; + std::shared_ptr SharedFromThis(void) override; + void AtGetGeneration(const AtNetGeneration &generation) override; + void AtGetSimSignal(const UINT8 &signal) override; + void AtGetSimInfo(const SIM_INFO_S *info) override; + void GetSimInfo(SIM_INFO_S *info) override; + void AtRegisterNetworkFinished(const AtRegisterNetworkResult &result) override; + void AtGetServiceProvider(const std::string &serviceProvider) override; + void AtNetApnConfigFinished(const AtConfigNetApnResult &result) override; + unsigned int GetPdpIndex(void) override; + +private: + void FigureOutSignalLevel(NetworkRegisterResult &data); + AtSignalLevel FigureOutSignalLevel_4G(unsigned char &simSignal); + AtSignalLevel FigureOutSignalLevel_3G(unsigned char &simSignal); + +private: + std::shared_ptr mOwner; + AtSimInitData mSimInitData; + NetworkRegisterResult mRegisterNetworkData; + SIM_INFO_S mSimInfo; // TODO: delete no use. +}; +#endif // !EG91_AT_COMMAND_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/eg91/at_command.cmake b/code/application/sifarsdk/component/AtCommand/src/eg91/at_command.cmake new file mode 100644 index 000000000..76f6f2d83 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/eg91/at_command.cmake @@ -0,0 +1,7 @@ + +INCLUDE(CMakeForceCompiler) + +include_directories( + ${COMPONENT_SOURCE_PATH}/AtCommand/src/${AT_COMMAND_SRC_PATH} +) +aux_source_directory(${COMPONENT_SOURCE_PATH}/AtCommand/src/${AT_COMMAND_SRC_PATH} SRC_FILES) \ No newline at end of file diff --git a/code/application/sifarsdk/component/AtCommand/src/sf_opera_adapt_v2.c b/code/application/sifarsdk/component/AtCommand/src/sf_opera_adapt_v2.c new file mode 100644 index 000000000..419912cc4 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/sf_opera_adapt_v2.c @@ -0,0 +1,1690 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: Oliver + * + * Ver: 1.0.0 2018/5/7 + * Ver: 1.0.1 2018/8/6: Oliver + * Ver: 1.1.0 2018/8/6: Oliver + * Ver: 1.1.1 2018/8/8: Oliver + * Ver: 1.1.2 2018/8/9: Will + * Ver: 1.1.3 2018/11/7: Will-Add Ukraine Italy Spain (AT@T Modify) +**************************************************************************/ +#include +#include "Log.h" +#include "sf_opera_adapt_v2.h" + +#define MMS_SET (0) + +UINT16 sf_auto_operation_adaptation(SF_CHAR *operatorName, SIM_INFO_S *sim_info_t) +{ + LogInfo("Auto_Operation_Adjust NEW, Name:%s\n", operatorName); + if((strncmp(operatorName, "46001", 5) == 0) || (strncmp(operatorName, "46010", 5) == 0)) //china union + { + //SMTP,FTP SET + strcpy(sim_info_t->ApnGPRS, "3gnet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + //LOGI("Auto_Operation_Adjust NEW, ApnGPRS:%s\n", sim_info_t->ApnGPRS); + #if MMS_SET + //MMS SET + strcpy(puiPara->APNMMS, "3gwap"); + strcpy(puiPara->URL, "http://mmsc.myuni.com.cn"); + strcpy(puiPara->IP, "10.0.0.172"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + + } + else if((strncmp(operatorName, "46000", 5) == 0) || (strncmp(operatorName, "46002", 5) == 0) || (strncmp(operatorName, "46004", 5) == 0) || (strncmp(operatorName, "46007", 5) == 0))//china union + { + strcpy(sim_info_t->ApnGPRS, "CMNET"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "CMWAP"); + strcpy(puiPara->URL, "mmsc.monternet.com"); + strcpy(puiPara->IP, "10.0.0.172"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "46003", 5) == 0) || (strncmp(operatorName, "46005", 5) == 0) || (strncmp(operatorName, "46011", 5) == 0))//china telcom + { + strcpy(sim_info_t->ApnGPRS, "CTNET"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "CTWAP"); + strcpy(puiPara->URL, "http://mmsc.vnet.mobi"); + strcpy(puiPara->IP, "10.0.0.200"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "31000", 5) == 0) || (strncmp(operatorName, "31001", 5) == 0) || (strncmp(operatorName, "31059", 5) == 0) + || (strncmp(operatorName, "31089", 5) == 0) || (strncmp(operatorName, "31091", 5) == 0) || (strncmp(operatorName, "31111", 5) == 0) + || (strncmp(operatorName, "31127", 5) == 0) || (strncmp(operatorName, "31128", 5) == 0) || (strncmp(operatorName, "31139", 5) == 0) + || (strncmp(operatorName, "31148", 5) == 0)) //Vierzon + { + strcpy((char *)sim_info_t->ApnGPRS, "vzwinternet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy((char *)puiPara->MmsApn, "\0"); + strcpy((char *)puiPara->MmsMmsc, "\0"); + strcpy((char *)puiPara->MmsProxy, "\0"); + strcpy((char *)puiPara->MmsPort, "\0"); + strcpy((char *)puiPara->MmsUserName, "\0"); + strcpy((char *)puiPara->MmsPassword, "\0"); + #endif + } + else if((strncmp(operatorName, "50501", 5) == 0) || (strncmp(operatorName, "50511", 5) == 0) || (strncmp(operatorName, "50571", 5) == 0) || (strncmp(operatorName, "50572", 5) == 0))//australia telstra + { + strcpy(sim_info_t->ApnGPRS, "telstra.internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "telstra.mms"); + strcpy(puiPara->URL, "http://mmsc.telstra.com:8002"); + strcpy(puiPara->IP, "10.1.1.180"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21910", 5) == 0) //Croatia VIPnet + { + strcpy(sim_info_t->ApnGPRS, "data.vip.hr"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.vipnet.hr"); + strcpy(puiPara->URL, "http://mms.vipnet.hr/servlets/mms"); + strcpy(puiPara->IP, "212.91.99.91"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21901", 5) == 0) //Croatia T-Mobile + { + strcpy(sim_info_t->ApnGPRS, "internet.ht.hr"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.htgprs"); + strcpy(puiPara->URL, "http://mms.t-mobile.hr/servlets/mms"); + strcpy(puiPara->IP, "10.12.0.4"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21902", 5) == 0) // Croatia Tele2 + { + strcpy(sim_info_t->ApnGPRS, "internet.tele2.hr"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "internet.tele2.hr"); + strcpy(puiPara->URL, "http://mmsc.tele2.hr"); + strcpy(puiPara->IP, "193.12.40.66"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "23820", 5) == 0) || (strncmp(operatorName, "23830", 5) == 0))//Danmark Telia + { + strcpy(sim_info_t->ApnGPRS, "www.internet.mtelia.dk"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "www.mms.mtelia.dk"); + strcpy(puiPara->URL, "www.mms.mtelia.dk"); + strcpy(puiPara->IP, "139.209.134.131"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23801", 5) == 0) //TDC + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://192.168.241.114:8002"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "194.182.251.15"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23802", 5) == 0) //Telenor + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.telenor.dk"); + strcpy(puiPara->APNMMS, "internet"); + strcpy(puiPara->IP, "212.88.64.8"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23806", 5) == 0) //Oister + { + strcpy(sim_info_t->ApnGPRS, "Data.dk"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.oister.dk"); + strcpy(puiPara->APNMMS, "mmssp"); + strcpy(puiPara->IP, "172.16.53.12"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + + } + else if(strncmp(operatorName, "24603", 5) == 0)//Lithuania Tele 2 + { + strcpy(sim_info_t->ApnGPRS, "internet.tele2.lt"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.tele2.lt"); + strcpy(puiPara->URL, "http://mmsc.tele2.lt"); + strcpy(puiPara->IP, "193.12.40.29"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24602", 5) == 0)//Lithuania BITE + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "http://mmsc/servlets/mms"); + strcpy(puiPara->IP, "192.168.150.2"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms@mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "24601", 5) == 0)//Lithuania Omnitel + { + strcpy(sim_info_t->ApnGPRS, "omnitel"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "gprs.mms.lt"); + strcpy(puiPara->URL, "http://mms.omnitel.net:8002/"); + strcpy(puiPara->IP, "194.176.32.149"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "53001", 5) == 0)//New Zealand Vodafone + { + strcpy(sim_info_t->ApnGPRS, "vodafone"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "live.vodafone.com"); + strcpy(puiPara->URL, "http://pxt.vodafone.net.nz/pxtsend"); + strcpy(puiPara->IP, "172.30.38.3"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "53024", 5) == 0)//New Zealand Vodafone + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "http://mms.2degreesmobile.net.nz:48090"); + strcpy(puiPara->IP, "118.148.1.118"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22610", 5) == 0)// Romania Orange + { + strcpy(sim_info_t->ApnGPRS, "net"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "http://wap.mms.orange.ro:8002"); + strcpy(puiPara->IP, "62.217.247.252"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "22601", 5) == 0)// Romania Vodafone + { + strcpy(sim_info_t->ApnGPRS, "live.vodafone.com"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22603", 5) == 0)// Romania Romtelecom + { + strcpy(sim_info_t->ApnGPRS, "broadband"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22605", 5) == 0)// Romania DIGI.mobil + { + strcpy(sim_info_t->ApnGPRS, "prepaid"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "25028", 5) == 0) || (strncmp(operatorName, "25099", 5) == 0))// Russian Federation Beeline + { + strcpy(sim_info_t->ApnGPRS, "internet.beeline.ru"); + strcpy(sim_info_t->ApnUsername, "beeline"); + strcpy(sim_info_t->ApnPassword, "beeline"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.beeline.ru"); + strcpy(puiPara->URL, "http://mmsc/"); + strcpy(puiPara->IP, "192.168.94.23"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "beeline"); + strcpy(puiPara->PASSWORD, "beeline"); + #endif + } + else if(strncmp(operatorName, "25001", 5) == 0)// Russian Federation MTS + { + strcpy(sim_info_t->ApnGPRS, "internet.mts.ru"); + strcpy(sim_info_t->ApnUsername, "mts"); + strcpy(sim_info_t->ApnPassword, "mts"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.mts.ru"); + strcpy(puiPara->URL, "http://mmsc"); + strcpy(puiPara->IP, "192.168.192.192"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mts"); + strcpy(puiPara->PASSWORD, "mts"); + #endif + } + else if(strncmp(operatorName, "25002", 5) == 0)// Russian Federation MegaFon + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "gdata"); + strcpy(sim_info_t->ApnPassword, "gdata"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "http://mmsc:8002"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "gdata"); + strcpy(puiPara->PASSWORD, "gdata"); + #endif + } + else if(strncmp(operatorName, "25020", 5) == 0)// Russian Federation Tele2 + { + strcpy(sim_info_t->ApnGPRS, "internet.tele2.ru"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.tele2.ru"); + strcpy(puiPara->URL, "http://mmsc.tele2.ru"); + strcpy(puiPara->IP, "193.12.40.65"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25011", 5) == 0)// Russian Federation Yota + { + strcpy(sim_info_t->ApnGPRS, "internet.yota"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.yota"); + strcpy(puiPara->URL, "http://mmsc:8002"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25035", 5) == 0)// Russian Federation Motiv + { + strcpy(sim_info_t->ApnGPRS, "inet.ycc.ru"); + strcpy(sim_info_t->ApnUsername, "motiv"); + strcpy(sim_info_t->ApnPassword, "motiv"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.ycc.ru"); + strcpy(puiPara->URL, "http://mms.ycc.ru"); + strcpy(puiPara->IP, "172.16.2.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "motiv"); + strcpy(puiPara->PASSWORD, "motiv"); + #endif + } + else if(strncmp(operatorName, "24007", 5) == 0)//Sweden Tele2 COMVIQ + { + strcpy(sim_info_t->ApnGPRS, "4G.tele2.se"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.tele2.se"); + strcpy(puiPara->APNMMS, "4G.tele2.se"); + strcpy(puiPara->IP, "130.244.202.30"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24001", 5) == 0)//Sweden TeliaSonera Mobile + { + strcpy(sim_info_t->ApnGPRS, "online.telia.se"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmss"); + strcpy(puiPara->APNMMS, "mms.telia.se"); + strcpy(puiPara->IP, "193.209.134.132"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "telia"); + #endif + } + else if((strncmp(operatorName, "24006", 5) == 0) || (strncmp(operatorName, "24008", 5) == 0) || (strncmp(operatorName, "24024", 5) == 0))//Sweden Telenor Mobile Sverige + { + strcpy(sim_info_t->ApnGPRS, "services.telenor.se"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "services.telenor.se"); + strcpy(puiPara->IP, "172.30.253.241"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "23433", 5) == 0) || (strncmp(operatorName, "23434", 5) == 0))// United Kingdom Orange + { + strcpy(sim_info_t->ApnGPRS, "orangeinternet"); + strcpy(sim_info_t->ApnUsername, "user"); + strcpy(sim_info_t->ApnPassword, "pass"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "orangemms"); + strcpy(puiPara->URL, "http://mms.orange.co.uk/"); + strcpy(puiPara->IP, "192.168.224.10"); + strcpy(puiPara->PORT, "9201"); + strcpy(puiPara->USERNAME, "Orange"); + strcpy(puiPara->PASSWORD, "Multimedia"); + #endif + } + + else if((strncmp(operatorName, "23402", 5) == 0) || (strncmp(operatorName, "23410", 5) == 0) || (strncmp(operatorName, "23411", 5) == 0))// United Kingdom O2 + { + strcpy(sim_info_t->ApnGPRS, "mobile.o2.co.uk"); + strcpy(sim_info_t->ApnUsername, "web"); + strcpy(sim_info_t->ApnPassword, "password"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "payandgo.o2.co.uk"); + strcpy(puiPara->URL, "http://mmsc.mms.o2.co.uk:8002"); + strcpy(puiPara->IP, "193.113.200.195"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "payandgo"); + strcpy(puiPara->PASSWORD, "password"); + #endif + } + else if(strncmp(operatorName, "23415", 5) == 0)//United Kingdom Vodafone + { + strcpy(sim_info_t->ApnGPRS, "pp.vodafone.co.uk"); + strcpy(sim_info_t->ApnUsername, "web"); + strcpy(sim_info_t->ApnPassword, "web"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "wap.vodafone.co.uk"); + strcpy(puiPara->URL, "http://mms.vodafone.co.uk/servlets/mms/"); + strcpy(puiPara->IP, "212.183.137.12"); + strcpy(puiPara->PORT, "9201"); + strcpy(puiPara->USERNAME, "wap"); + strcpy(puiPara->PASSWORD, "wap"); + #endif + } + else if(strncmp(operatorName, "23430", 5) == 0)//United Kingdom T-Mobile + { + strcpy(sim_info_t->ApnGPRS, "general.t-mobile.uk"); + strcpy(sim_info_t->ApnUsername, "user"); + strcpy(sim_info_t->ApnPassword, "wap"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "general.t-mobile.uk"); + strcpy(puiPara->URL, "http://mmsc.t-mobile.co.uk:8002/"); + strcpy(puiPara->IP, "149.254.211.10"); + strcpy(puiPara->PORT, "9201"); + strcpy(puiPara->USERNAME, "user"); + strcpy(puiPara->PASSWORD, "one2one"); + #endif + } + else if(strncmp(operatorName, "23420", 5) == 0)//United Kingdom 3 + { + strcpy(sim_info_t->ApnGPRS, "three.co.uk"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.three.co.uk"); + strcpy(puiPara->URL, "http://mms.um.three.co.uk:10021/mmsc"); + strcpy(puiPara->IP, "217.171.129.2"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "24403", 5) == 0) || (strncmp(operatorName, "24412", 5) == 0))// Finland DNA + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.dnafinland.fi"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.1.1.2"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24421", 5) == 0)// Finland Saunalahti + { + strcpy(sim_info_t->ApnGPRS, "internet.saunalahti"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.saunalahti.fi:8002/"); + strcpy(puiPara->APNMMS, "mms.saunalahti.fi"); + strcpy(puiPara->IP, "62.142.4.197"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24405", 5) == 0)// Finland Elisa + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.elisa.fi"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "213.161.41.57"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24491", 5) == 0)// Finland Sonera + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.sonera.net:8002/"); + strcpy(puiPara->APNMMS, "wap.sonera.net"); + strcpy(puiPara->IP, "195.156.25.33"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24410", 5) == 0)// Finland TDC + { + strcpy(sim_info_t->ApnGPRS, "inet.tdc.fi"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.tdc.fi"); + strcpy(puiPara->APNMMS, "mms.tdc.fi"); + strcpy(puiPara->IP, "10.1.12.2"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "65507", 5) == 0)// South Africa Cell C + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.cmobile.co.za/"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "196.31.116.250"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "65510", 5) == 0)// South Africa MTN + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "guest"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.mtn.co.za/mms/wapenc"); + strcpy(puiPara->APNMMS, "mymtn"); + strcpy(puiPara->IP, "196.11.240.241"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "65501", 5) == 0)// South Africa Vodacom + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "guest"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.vodacom4me.co.za/"); + strcpy(puiPara->APNMMS, "mms.vodacom.net"); + strcpy(puiPara->IP, "196.6.128.13"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "65502", 5) == 0)// South Africa 8ta + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "guest"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.8ta.com:38090/was"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "41.151.254.162"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "guest"); + strcpy(puiPara->PASSWORD, "guest"); + #endif + } + else if(strncmp(operatorName, "22201", 5) == 0)// Italy TIM + { + strcpy(sim_info_t->ApnGPRS, "ibox.tim.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.tim.it/servlets/mms"); + strcpy(puiPara->APNMMS, "mms.tim.it"); + strcpy(puiPara->IP, "213.230.130.89"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22210", 5) == 0)// Italy Vodafone + { + strcpy(sim_info_t->ApnGPRS, "mobile.vodafone.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.vodafone.it/servlets/mms"); + strcpy(puiPara->APNMMS, "mms.vodafone.it"); + strcpy(puiPara->IP, "10.128.224.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22288", 5) == 0)// Italy wind + { + strcpy(sim_info_t->ApnGPRS, "internet.wind"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.wind.it"); + strcpy(puiPara->APNMMS, "mms.wind"); + strcpy(puiPara->IP, "212.245.244.11"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22208", 5) == 0) //Italy Fastweb Mobile + { + strcpy(sim_info_t->ApnGPRS, "apn.fastweb.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22207", 5) == 0) //Italy Kena Mobile + { + strcpy(sim_info_t->ApnGPRS, "web.kenamobile.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22215", 5) == 0) //Italy Iliad + { + strcpy(sim_info_t->ApnGPRS, "iliad"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22233", 5) == 0) //Italy PosteMobile + { + strcpy(sim_info_t->ApnGPRS, "wap.postemobile.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20815", 5) == 0)// France Free Mobile + { + strcpy(sim_info_t->ApnGPRS, "free"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.free.fr"); + strcpy(puiPara->APNMMS, "mmsfree"); + strcpy(puiPara->IP, "212.27.40.225"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20801", 5) == 0) // France Orange + { + strcpy(sim_info_t->ApnGPRS, "orange"); + strcpy(sim_info_t->ApnUsername, "orange"); + strcpy(sim_info_t->ApnPassword, "orange"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.orange.fr"); + strcpy(puiPara->APNMMS, "orange.acte"); + strcpy(puiPara->IP, "192.168.10.200"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20820", 5) == 0)// France Bouygues Telecom + { + strcpy(sim_info_t->ApnGPRS, "mmsbouygtel.com"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.bouyguestelecom.fr/mms/wap"); + strcpy(puiPara->APNMMS, "mmsbouygtel.com"); + strcpy(puiPara->IP, "62.201.137.17"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20810", 5) == 0)// France SFR + { + strcpy(sim_info_t->ApnGPRS, "sl2sfr"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms1"); + strcpy(puiPara->APNMMS, "sl2sfr"); + strcpy(puiPara->IP, "10.151.0.1"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "31003", 5) == 0) || (strncmp(operatorName, "31009", 5) == 0) \ + || (strncmp(operatorName, "31015", 5) == 0) || (strncmp(operatorName, "31017", 5) == 0) \ + || (strncmp(operatorName, "31041", 5) == 0) || (strncmp(operatorName, "31056", 5) == 0) \ + || (strncmp(operatorName, "31068", 5) == 0) || (strncmp(operatorName, "31028", 5) == 0))// United States AT&T + { + strcpy(sim_info_t->ApnGPRS, "nxtgenphone"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.mobile.att.net"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "proxy.mobile.att.net"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + + else if((strncmp(operatorName, "31002", 5) == 0) || (strncmp(operatorName, "31016", 5) == 0) || (strncmp(operatorName, "31020", 5) == 0)|| (strncmp(operatorName, "31021", 5) == 0)|| (strncmp(operatorName, "31022", 5) == 0)|| (strncmp(operatorName, "31023", 5) == 0)|| (strncmp(operatorName, "31024", 5) == 0) + + || (strncmp(operatorName, "31025", 5) == 0) || (strncmp(operatorName, "31026", 5) == 0) || (strncmp(operatorName, "31027", 5) == 0) || (strncmp(operatorName, "31029", 5) == 0) || (strncmp(operatorName, "31031", 5) == 0) || (strncmp(operatorName, "31033", 5) == 0) + || (strncmp(operatorName, "31058", 5) == 0) || (strncmp(operatorName, "31066", 5) == 0) || (strncmp(operatorName, "31080", 5) == 0))// United States T-Mobile + { + strcpy(sim_info_t->ApnGPRS, "fast.t-mobile.com"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.msg.eng.t-mobile.com/mms/wapenc"); + strcpy(puiPara->APNMMS, "wap.voicestream.com"); + strcpy(puiPara->IP, "216.155.165.50"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if ((strncmp(operatorName, "26206", 5) == 0) || (strncmp(operatorName, "26212", 5) == 0)) + { + // Germany Telekom + strcpy(sim_info_t->ApnGPRS, "internet.telekom"); + strcpy(sim_info_t->ApnUsername, "t-mobile"); + strcpy(sim_info_t->ApnPassword, "tm"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.t-mobile.de/servlets/mms"); + strcpy(puiPara->APNMMS, "mms.t-d1.de"); + strcpy(puiPara->IP, "172.28.23.131"); + strcpy(puiPara->PORT, "8008"); + strcpy(puiPara->USERNAME, "t-mobile"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "26201", 5) == 0) + { + // Germany T-Mobile + strcpy(sim_info_t->ApnGPRS, "internet.t-mobile"); + strcpy(sim_info_t->ApnUsername, "t-mobile"); + strcpy(sim_info_t->ApnPassword, "tm"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.t-mobile.de/servlets/mms"); + strcpy(puiPara->APNMMS, "internet.t-mobile"); + strcpy(puiPara->IP, "172.28.23.131"); + strcpy(puiPara->PORT, "8008"); + strcpy(puiPara->USERNAME, "t-mobile"); + strcpy(puiPara->PASSWORD, "tm"); + #endif + } + else if ((strncmp(operatorName, "26202", 5) == 0) || (strncmp(operatorName, "26204", 5) == 0) || (strncmp(operatorName, "26209", 5) == 0)) + { + // Germany Vodafone + strcpy(sim_info_t->ApnGPRS, "web.vodafone.de"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://139.7.24.1/servlets/mms"); + strcpy(puiPara->APNMMS, "event.vodafone.de"); + strcpy(puiPara->IP, "139.7.29.17"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "26203", 5) == 0) || (strncmp(operatorName, "26205", 5) == 0) || (strncmp(operatorName, "26277", 5) == 0)) + { + // Germany E-Plus + strcpy(sim_info_t->ApnGPRS, "internet.eplus.de"); + strcpy(sim_info_t->ApnUsername, "eplus"); + strcpy(sim_info_t->ApnPassword, "internet"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms/eplus"); + strcpy(puiPara->APNMMS, "mms.eplus.de"); + strcpy(puiPara->IP, "212.23.97.153"); + strcpy(puiPara->PORT, "5080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "eplus"); + #endif + } + else if ((strncmp(operatorName, "26207", 5) == 0) || (strncmp(operatorName, "26208", 5) == 0) || (strncmp(operatorName, "26211", 5) == 0)) + { + // Germany O2 + strcpy(sim_info_t->ApnGPRS, "pinternet.interkom.de"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://10.81.0.7:8002/"); + strcpy(puiPara->APNMMS, "pinternet.interkom.de"); + strcpy(puiPara->IP, "82.113.100.6"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "29331", 5) == 0) || (strncmp(operatorName, "29341", 5) == 0) || (strncmp(operatorName, "29351", 5) == 0)) + { + // Slovenia Telekom + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "mobitel"); + strcpy(sim_info_t->ApnPassword, "internet"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.telekom.si"); + strcpy(puiPara->APNMMS, "internet"); + strcpy(puiPara->IP, "213.229.249.40"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mobitel"); + strcpy(puiPara->PASSWORD, "internet"); + #endif + } + else if (strncmp(operatorName, "29340", 5) == 0) + { + // Slovenia Simobil + strcpy(sim_info_t->ApnGPRS, "internet.simobil.si"); + strcpy(sim_info_t->ApnUsername, "simobil"); + strcpy(sim_info_t->ApnPassword, "internet"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmc"); + strcpy(puiPara->APNMMS, "mms.simobil.si"); + strcpy(puiPara->IP, "80.95.224.46"); + strcpy(puiPara->PORT, "9201"); + strcpy(puiPara->USERNAME, "simobil"); + strcpy(puiPara->PASSWORD, "internet"); + #endif + } + else if (strncmp(operatorName, "29364", 5) == 0) + { + // Slovenia T2 + strcpy(sim_info_t->ApnGPRS, "mms.t-2.net"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://www.mms.t-2.net:8002"); + strcpy(puiPara->APNMMS, "mms.t-2.net"); + strcpy(puiPara->IP, "172.20.18.137"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "23106", 5) == 0) + { + //Slovakia O2 + strcpy(sim_info_t->ApnGPRS, "o2internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.o2world.sk:8002"); + strcpy(puiPara->APNMMS, "o2mms"); + strcpy(puiPara->IP, "10.97.1.11"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if ((strncmp(operatorName, "23102", 5) == 0) || (strncmp(operatorName, "23104", 5) == 0)) + { + //Slovakia T-Mobile + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.1.1"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "23101", 5) == 0) + { + //Slovakia Orange + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://imms.orange.sk"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "213.151.208.145"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "23103", 5) == 0) + { + //Slovakia 4Ka + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.1.1"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "42501", 5) == 0) + { + //Israel orange + strcpy(sim_info_t->ApnGPRS, "uinternet"); + strcpy(sim_info_t->ApnUsername, "orange"); + strcpy(sim_info_t->ApnPassword, "orange"); + + #if MMS_SET + strcpy(puiPara->URL, "http://192.168.220.15/servlets/mms"); + strcpy(puiPara->APNMMS, "uwap.orange.co.il"); + strcpy(puiPara->IP, "192.118.11.55"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24801", 5) == 0) + { + //Estonia(Telia) + strcpy(sim_info_t->ApnGPRS, "internet.emt.ee"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.emt.ee"); + strcpy(puiPara->URL, "mms.emt.ee/servlets/mms"); + strcpy(puiPara->IP, "217.71.32.82"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24802", 5) == 0) + { + //Estonia(Elisa) + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "194.204.2.10"); + strcpy(puiPara->IP, "194.204.2.6"); + strcpy(puiPara->PORT, "8000"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24803", 5) == 0) + { + //Estonia(Tele2) + strcpy(sim_info_t->ApnGPRS, "internet.tele2.ee"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.tele2.ee"); + strcpy(puiPara->URL, "mmsc.tele2.ee"); + strcpy(puiPara->IP, "193.12.40.6"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "20416", 5) == 0) + { + //Netherlands T-Mobile + strcpy(sim_info_t->ApnGPRS, "smartsites.t-mobile"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://t-mobilemms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.10.10.11"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "tmobilemms"); + strcpy(puiPara->PASSWORD, "tmobilemms"); + #endif + } + else if (strncmp(operatorName, "24201", 5) == 0) //norway Telenor + { + strcpy(sim_info_t->ApnGPRS, "telenor.smart"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc"); + strcpy(puiPara->APNMMS, "telenor"); + strcpy(puiPara->IP, "10.10.10.11"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24202", 5) == 0) //norway Telia/Chilli Mobil + { + strcpy(sim_info_t->ApnGPRS, "telia"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mm"); + strcpy(puiPara->APNMMS, "telia"); + strcpy(puiPara->IP, "212.169.66.4"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24205", 5) == 0) //norway Ice Net + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.nwn.no"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "188.149.250.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if ((strncmp(operatorName, "24206", 5) == 0) || (strncmp(operatorName, "24214", 5) == 0)) //norway ice net + { + strcpy(sim_info_t->ApnGPRS, "ice.net"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "mms.ice.net"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24208", 5) == 0) //norway Get + { + strcpy(sim_info_t->ApnGPRS, "internet.no"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.tdc.dk:8002"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "inetproxy.tdc.dk"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + + #endif + } + else if (strncmp(operatorName, "26801", 5) == 0) //Portugal vodafone + { + strcpy(sim_info_t->ApnGPRS, "net2.vodafone.pt"); + strcpy(sim_info_t->ApnUsername, "vodafone"); + strcpy(sim_info_t->ApnPassword, "vodafone"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.vodafone.pt/servlets/mms"); + strcpy(puiPara->APNMMS, "net2.vodafone.pt"); + strcpy(puiPara->IP, "Iproxy.vodafone.pt"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "vodafone"); + strcpy(puiPara->PASSWORD, "vodafone"); + #endif + } + else if(strncmp(operatorName, "26002", 5) == 0) //Polish Tmobile + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mms/servlets/mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "213.158.194.226"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "26003", 5) == 0) //Polish Orange + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "internet"); + strcpy(sim_info_t->ApnPassword, "internet"); + + #if MMS_SET + strcpy(puiPara->URL, "mms.orange.pl"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.6.104"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "26001", 5) == 0) //Polish Plus + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mms.plusgsm.pl:8002"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "212.2.96.16"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "26006", 5) == 0) //Polish Play + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mmsc.play.pl/mms/wapenc"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.10.25.5"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "30261", 5) == 0) || (strncmp(operatorName, "30269", 5) == 0) || (strncmp(operatorName, "30263", 5) == 0)) //Canada Bell + { + strcpy(sim_info_t->ApnGPRS, "pda.bell.ca"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.bell.ca/mms/wapenc"); + strcpy(puiPara->APNMMS, "pda.bell.ca"); + strcpy(puiPara->IP, "web.wireless.bell.ca"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "30232", 5) == 0) || (strncmp(operatorName, "30272", 5) == 0))//Canada Rogers + { + strcpy(sim_info_t->ApnGPRS, "rogers-core-appl1.apn"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.gprs.rogers.com"); + strcpy(puiPara->APNMMS, "rogers-core-appl1.apn"); + strcpy(puiPara->IP, "10.128.1.69"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "wap@wap"); + strcpy(puiPara->PASSWORD, "wap125"); + #endif + } + /* + else if(strncmp(operatorName, "30222", 5) == 0) //Canada Telus + { + strcpy(sim_info_t->ApnGPRS, "sp.telus.com"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://aliasredirect.net/proxy/mmsc"); + strcpy(puiPara->APNMMS, "sp.telus.com"); + strcpy(puiPara->IP, "74.49.0.18"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + */ + else if((strncmp(operatorName, "30268", 5) == 0) || (strncmp(operatorName, "30278", 5) == 0)) //Canada SaskTel + { + strcpy(sim_info_t->ApnGPRS, "pda.stm.sk.ca"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.sasktel.com"); + strcpy(puiPara->APNMMS, "pda.stm.sk.ca"); + strcpy(puiPara->IP, "mig.sasktel.com"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23002", 5) == 0) //Czech O2 + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.o2active.cz:8002"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "160.218.160.218"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23003", 5) == 0) //Czech Vodafone + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms/"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.11.10.111"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23001", 5) == 0) //Czech T-mobile + { + strcpy(sim_info_t->ApnGPRS, "internet.t-mobile.cz"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "mms.t-mobile.cz"); + strcpy(puiPara->IP, "10.0.0.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28601", 5) == 0) //Turkey Turkcell + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mms.turkcell.com.tr/servlets/mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "212.252.169.217"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28602", 5) == 0) //Turkey Vodafone + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "vodafone"); + strcpy(sim_info_t->ApnPassword, "vodafone"); + + #if MMS_SET + strcpy(puiPara->URL, "mms:6001/MM1Servlet"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "217.31.233.18"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "vodafone"); + strcpy(puiPara->PASSWORD, "vodafone"); + #endif + } + else if((strncmp(operatorName, "28603", 5) == 0) ||(strncmp(operatorName, "28604", 5) == 0))//Turkey Avea + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mms.avea.com.tr/servlets/mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "213.161.151.201"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28401", 5) == 0) //Bulgaria A1 + { + strcpy(sim_info_t->ApnGPRS, "internet.a1.bg"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc/"); + strcpy(puiPara->APNMMS, "mms.a1.bg"); + strcpy(puiPara->IP, "10.150.0.33"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28405", 5) == 0) //Bulgaria Telenor + { + strcpy(sim_info_t->ApnGPRS, "telenorbg"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc/"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.87.11"); + strcpy(puiPara->PORT, "8004"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28403", 5) == 0) //Bulgaria VIVACOM + { + strcpy(sim_info_t->ApnGPRS, "internet.vivacom.bg"); + strcpy(sim_info_t->ApnUsername, "VIVACOM"); + strcpy(sim_info_t->ApnPassword, "VIVACOM"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.vivacom.bg"); + strcpy(puiPara->APNMMS, "mms.vivacom.bg"); + strcpy(puiPara->IP, "192.168.123.123"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25503", 5) == 0) //Ukraine KYIVSTAR + { + strcpy(sim_info_t->ApnGPRS, "www.kyivstar.net"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.kyivstar.net"); + strcpy(puiPara->APNMMS, "mms.kyivstar.net"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25501", 5) == 0) //Ukraine Vodafone + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc:8002/"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25506", 5) == 0) //Ukraine LifeCell + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.life"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21407", 5) == 0) //Spain Movistar + { + strcpy(sim_info_t->ApnGPRS, "telefonica.es"); + strcpy(sim_info_t->ApnUsername, "telefonica"); + strcpy(sim_info_t->ApnPassword, "telefonica"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.movistar.es"); + strcpy(puiPara->APNMMS, "telefonica.es"); + strcpy(puiPara->IP, "10.138.255.5"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21401", 5) == 0) //Spain Vodafone + { + strcpy(sim_info_t->ApnGPRS, "airtelwap.es"); + strcpy(sim_info_t->ApnUsername, "wap@wap"); + strcpy(sim_info_t->ApnPassword, "wap125"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.vodafone.es/servlets/mms"); + strcpy(puiPara->APNMMS, "mms.vodafone.net"); + strcpy(puiPara->IP, "212.73.32.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "wap@wap"); + strcpy(puiPara->PASSWORD, "wap125"); + #endif + } + else if(strncmp(operatorName, "21403", 5) == 0) //Spain Simyo + { + strcpy(sim_info_t->ApnGPRS, "orangeworld"); + strcpy(sim_info_t->ApnUsername, "orange"); + strcpy(sim_info_t->ApnPassword, "orange"); + + #if MMS_SET + strcpy(puiPara->URL, "https://mms.orange.es"); + strcpy(puiPara->APNMMS, "orangemms"); + strcpy(puiPara->IP, "172.22.188.25"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "20628", 5) == 0) || (strncmp(operatorName, "20601", 5) == 0) + || (strncmp(operatorName, "52505", 5) == 0) || (strncmp(operatorName, "30222", 5) == 0) + || (strncmp(operatorName, "20809", 5) == 0)) + { + if((strstr(sim_info_t->ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) || (strstr(sim_info_t->ModuleVersion, GPRS_MODULE_TYPE_EG95_V)) \ + || (strstr(sim_info_t->ModuleVersion, GPRS_MODULE_TYPE_EG91_NAXD)) || (strstr(sim_info_t->ModuleVersion, GPRS_MODULE_TYPE_EG95_NAXD))) + { + strcpy(sim_info_t->ApnGPRS, "America.bics"); + } + else + { + strcpy(sim_info_t->ApnGPRS, "bicsapn"); + } + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + } + else if(strncmp(operatorName, "20408", 5) == 0) //kpn sim + { + strcpy(sim_info_t->ApnGPRS, "fast.m2m"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20404", 5) == 0) // wodafeng sim + { + + strcpy(sim_info_t->ApnGPRS, "spe.inet4gd.gdsp"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + /* + else if(strncmp(operatorName, "20601", 5) == 0) //Belgium Proximus + { + strcpy(sim_info_t->ApnGPRS, "internet.proximus.be"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.proximus.be/mms"); + strcpy(puiPara->APNMMS, "event.proximus.be"); + strcpy(puiPara->IP, "10.55.14.75"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + */ + else + { + strcpy(sim_info_t->ApnGPRS, "\0"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + // return SF_4G_ERROR_AT_APN; // TODO: + return SF_FAILURE; + } + + return SF_SUCCESS; +} + diff --git a/code/application/sifarsdk/component/AtCommand/src/sf_opera_adapt_v2.h b/code/application/sifarsdk/component/AtCommand/src/sf_opera_adapt_v2.h new file mode 100644 index 000000000..902d358c7 --- /dev/null +++ b/code/application/sifarsdk/component/AtCommand/src/sf_opera_adapt_v2.h @@ -0,0 +1,54 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: jiamin + * Ver: 1.0.0 2020.09.17 + * Description: creat + **************************************************************************/ +#ifndef _SF_OPERATION_ADAPTATION_V2_H_ +#define _SF_OPERATION_ADAPTATION_V2_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "SfTypeDefine.h" + +#define GPRS_MODULE_TYPE_EG91_V "EG91VX" +#define GPRS_MODULE_TYPE_EG95_V "EG95VX" +#define GPRS_MODULE_TYPE_EG91_NAXD "EG91NAXD" +#define GPRS_MODULE_TYPE_EG95_NAXD "EG95NAXD" +#define SF_APN_MAX_LEN (40) +#define SF_OPERATOR_CODE_MAX_LEN (8) +#define SF_APN_PASSWORD_MAX_LEN (20) +#define SF_MODULE_VER_MAX_LEN (50) + + typedef struct SIM_INFO_S + { + char ApnGPRS[SF_APN_MAX_LEN]; + char OperatorCode[SF_OPERATOR_CODE_MAX_LEN]; + char ApnUsername[SF_APN_MAX_LEN]; + char ApnPassword[SF_APN_PASSWORD_MAX_LEN]; + char ModuleVersion[SF_MODULE_VER_MAX_LEN]; + } SIM_INFO_S; + + UINT16 sf_auto_operation_adaptation(SF_CHAR *operatorName, SIM_INFO_S *sim_info_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/component/CMakeLists.txt b/code/application/sifarsdk/component/CMakeLists.txt new file mode 100644 index 000000000..1b09615d0 --- /dev/null +++ b/code/application/sifarsdk/component/CMakeLists.txt @@ -0,0 +1,23 @@ + +# cmake_minimum_required(VERSION 2.8.0) +add_subdirectory(Log) +add_subdirectory(ReturnCode) +add_subdirectory(PeripheralManager) +add_subdirectory(StateMachineManager) +add_subdirectory(DualCoreManager) +add_subdirectory(cJSON) +add_subdirectory(base64) +add_subdirectory(CameraManager) +add_subdirectory(SignatureManager) +add_subdirectory(FileManager) +add_subdirectory(utils) +add_subdirectory(Config) +add_subdirectory(SystemTime) +add_subdirectory(UpgradeManager) +add_subdirectory(HttpBase) +add_subdirectory(McuManager) +add_subdirectory(Qrcode) +add_subdirectory(LiveManager) +add_subdirectory(AtCommand) +add_subdirectory(Servers) +add_subdirectory(FtpManager) \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/CMakeLists.txt b/code/application/sifarsdk/component/CameraManager/CMakeLists.txt new file mode 100644 index 000000000..cf72b0028 --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/CMakeLists.txt @@ -0,0 +1,27 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/McuManager/include + ${COMPONENT_SOURCE_PATH}/DualCoreManager/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME CameraManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} McuManager DualCoreManager ReturnCode Log) \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/include/ICameraManager.h b/code/application/sifarsdk/component/CameraManager/include/ICameraManager.h new file mode 100644 index 000000000..6b6183098 --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/include/ICameraManager.h @@ -0,0 +1,72 @@ +#ifndef I_CAMERA_MANAGER_H +#define I_CAMERA_MANAGER_H +#include "VReturnCode.h" +#include "IHalCommon.h" +#include +#include +#include +enum class CameraManagerReturnCodeDefine +{ + CAMERA_TASK_CAN_EXECUTE_MORE = static_cast(VReturnCodeDefine::END), + END +}; +class CameraTaskResponse +{ +public: + CameraTaskResponse() + { + } + ~CameraTaskResponse() + { + } + SF_FILE_TYPE_E enFileTye; // TODO: It't better not include IHalCommon.h + std::string mThumbFileName; + std::string mThumbFilePath; + // unsigned int thumbfileSize; +}; +constexpr int UNDEFINE_GET_NIGHT = -1; +class VCameraTask +{ +public: + VCameraTask() = default; + virtual ~VCameraTask() = default; + virtual const CameraTaskType GetTaskType(void) { return CameraTaskType::END; } + virtual void Response(const std::vector &response) {} + virtual bool IsTaskFinished(void) { return false; } + virtual const signed int GetIsNight(void) { return UNDEFINE_GET_NIGHT; } + virtual const unsigned int GetIsMultShot(void) { return false; } +}; +class VMediaMonitor +{ +public: + VMediaMonitor() = default; + virtual ~VMediaMonitor() = default; + virtual int AudioStream_write(const char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp) { return 0; } + virtual int VideoStream_write(char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp, const unsigned int &key_frame) { return 0; } +}; +class VCameraHandle +{ +public: + VCameraHandle() = default; + virtual ~VCameraHandle() = default; + virtual RETURN_CODE ExecuteTask(std::shared_ptr &task) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE StopTask(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE ClearTask(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetSpontaneousTaskMonitor(std::shared_ptr &task) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE BeReadyForLive(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetMediaMonitor(std::shared_ptr &monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE StartMedia(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE StopMedia(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +class ICameraManager +{ +public: + ICameraManager() = default; + virtual ~ICameraManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetCameraHandle(const CameraType &type, std::shared_ptr &camera) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreateCameraManager(void); +#endif // !I_CAMERA_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/CameraHandle.cpp b/code/application/sifarsdk/component/CameraManager/src/CameraHandle.cpp new file mode 100644 index 000000000..eb2e04552 --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/CameraHandle.cpp @@ -0,0 +1,168 @@ +#include "CameraHandle.h" +#include "CameraManagerReturnCode.h" +#include "Log.h" +#include "IMcuManager.h" +#include "IDualCoreManager.h" +CameraHandle::CameraHandle(const CameraType &cameraType) : mCameraType(cameraType) +{ + mCameraHal = std::make_shared(); + mMediaMonitor = std::make_shared(); +} +void CameraHandle::Init(void) +{ + IHal::GetInstance()->GetCameraHal(CameraType::MAIN_CAMERA, mCameraHal); + std::shared_ptr owner = shared_from_this(); + mCameraHal->SetCameraOwner(owner); +} +void CameraHandle::UnInit(void) +{ + mCameraHal = std::make_shared(); +} +RETURN_CODE CameraHandle::ExecuteTask(std::shared_ptr &task) +{ + std::lock_guard locker(mMutex); + LogInfo("CameraHandle::ExecuteTask.\n"); + auto runingTask = mRuningTask.lock(); + if (!mRuningTask.expired()) + { + if (!runingTask->IsTaskFinished()) + { + LogError("Camera is runing task, can't execute more task.\n"); + auto code = CameraManagerReturnCode::NewCode(CameraManagerReturnCodeDefine::CAMERA_TASK_CAN_EXECUTE_MORE); + return code; + } + } + CameraTaskData data(task->GetTaskType(), task->GetIsNight(), task->GetIsMultShot()); + auto code = mCameraHal->StartSingleTask(data); + if (code->IsCodeOK()) + { + mRuningTask = task; + } + else + { + LogError("Execute task failed.\n"); + } + return code; +} +void CameraHandle::CameraFinshTask(const std::vector &files) +{ + std::lock_guard locker(mMutex); + LogInfo("CameraHandle::CameraFinshTask.\n"); + auto runingTask = mRuningTask.lock(); + if (mRuningTask.expired()) + { + LogWarning("Task was cancel.\n"); + return; + } + if (files.empty()) + { + LogWarning("Files is empty.\n"); + } + else + { + std::vector allResponse; + TypeConersion(files, allResponse); + runingTask->Response(allResponse); + mRuningTask.reset(); + } +} +void CameraHandle::SpontaneousTaskFromCamera(const std::vector &files) +{ + std::lock_guard locker(mMutex); + if (mTaskMonitor) + { + LogInfo("CameraHandle::SpontaneousTaskFromCamera.\n"); + std::vector allResponse; + TypeConersion(files, allResponse); + mTaskMonitor->Response(allResponse); + } + else + { + LogInfo("CameraHandle::AddSpontaneousFiles.\n"); + AddSpontaneousFiles(files); + } +} +RETURN_CODE CameraHandle::SetSpontaneousTaskMonitor(std::shared_ptr &task) +{ + std::lock_guard locker(mMutex); + mTaskMonitor = task; + if (mTaskMonitor) + { + std::vector allResponse; + TypeConersion(mSpontaneousFiles, allResponse); + mTaskMonitor->Response(allResponse); + mSpontaneousFiles.clear(); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraHandle::StopTask(void) +{ + std::lock_guard locker(mMutex); + mCameraHal->StopTask(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraHandle::BeReadyForLive(void) +{ + RefreshEnvironmentData(); + mCameraHal->HalBeReadyForLive(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +int CameraHandle::AudioStream_write(const char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp) +{ + mMediaMonitor->AudioStream_write(pu8Addr, u32Len, TimeStamp); + return 0; +} +int CameraHandle::VideoStream_write(char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp, const unsigned int &key_frame) +{ + mMediaMonitor->AudioStream_write(pu8Addr, u32Len, TimeStamp); + return 0; +} +RETURN_CODE CameraHandle::SetMediaMonitor(std::shared_ptr &monitor) +{ + mMediaMonitor = monitor; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraHandle::StartMedia(void) +{ + RefreshEnvironmentData(); + mCameraHal->sf_venc_stream_start(); + mCameraHal->sf_audio_stream_start(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraHandle::StopMedia(void) +{ + mCameraHal->sf_venc_stream_stop(); + mCameraHal->sf_audio_stream_stop(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void CameraHandle::TypeConersion(const std::vector &files, std::vector &allResponse) +{ + std::vector fileMessage = files; + std::vector::iterator iter; + for (iter = fileMessage.begin(); iter != fileMessage.end();) + { + CameraFileMessage tmp = *iter; + CameraTaskResponse response; + response.enFileTye = tmp.enFileTye; + response.mThumbFileName = tmp.mThumbFileName; + response.mThumbFilePath = tmp.mThumbFilePath; + allResponse.push_back(response); + ++iter; + } +} +void CameraHandle::AddSpontaneousFiles(const std::vector &files) +{ + std::copy(files.begin(), files.end(), std::back_inserter(mSpontaneousFiles)); +} +void CameraHandle::RefreshEnvironmentData(void) +{ + unsigned char isNight = 0; + std::shared_ptr mcuDevice = std::make_shared(); + IMcuManager::GetInstance()->GetMcuDevice(mcuDevice); + EnvironmentData data = mcuDevice->GetEnvironmentData(); + mCameraHal->SetNightMode(data.mIsNight); + constexpr int IS_NIGHT = 1; + constexpr int IS_NOT_NIGHT = 0; + isNight = data.mIsNight ? IS_NIGHT : IS_NOT_NIGHT; + IDualCoreManager::GetInstance()->SetEnvironmentData(isNight, data.mLightValue); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/CameraHandle.h b/code/application/sifarsdk/component/CameraManager/src/CameraHandle.h new file mode 100644 index 000000000..f207e109e --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/CameraHandle.h @@ -0,0 +1,40 @@ +#ifndef CAMERA_HANDLE_H +#define CAMERA_HANDLE_H +#include "ICameraManager.h" +#include "IHal.h" +#include +#include +class CameraHandle : public VCameraHandle, public VCameraHalOwner, public std::enable_shared_from_this +{ +public: + CameraHandle(const CameraType &cameraType); + virtual ~CameraHandle() = default; + void Init(void); + void UnInit(void); + RETURN_CODE ExecuteTask(std::shared_ptr &task) override; + void CameraFinshTask(const std::vector &files) override; + void SpontaneousTaskFromCamera(const std::vector &files) override; + RETURN_CODE SetSpontaneousTaskMonitor(std::shared_ptr &task) override; + RETURN_CODE StopTask(void) override; + RETURN_CODE BeReadyForLive(void) override; + int AudioStream_write(const char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp) override; + int VideoStream_write(char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp, const unsigned int &key_frame); + RETURN_CODE SetMediaMonitor(std::shared_ptr &monitor) override; + RETURN_CODE StartMedia(void) override; + RETURN_CODE StopMedia(void) override; + +private: + void TypeConersion(const std::vector &files, std::vector &allResponse); + void AddSpontaneousFiles(const std::vector &files); + void RefreshEnvironmentData(void); + +private: + std::mutex mMutex; + const CameraType mCameraType; + std::shared_ptr mCameraHal; + std::weak_ptr mRuningTask; + std::shared_ptr mTaskMonitor; + std::shared_ptr mMediaMonitor; + std::vector mSpontaneousFiles; +}; +#endif // !CAMERA_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/CameraManager.cpp b/code/application/sifarsdk/component/CameraManager/src/CameraManager.cpp new file mode 100644 index 000000000..9452f5521 --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/CameraManager.cpp @@ -0,0 +1,37 @@ +#include "CameraManager.h" +#include "CameraManagerMakePtr.h" +CameraManager::CameraManager() +{ + for (int i = 0; i < static_cast(CameraType::END); i++) + { + mCameraHandle[static_cast(i)] = std::make_shared(); + } +} +RETURN_CODE CameraManager::Init(void) +{ + for (int i = 0; i < static_cast(CameraType::END); i++) + { + CameraManagerMakePtr::GetInstance()->CreateCameraHandle(CameraType::MAIN_CAMERA, mCameraHandle[static_cast(i)]); + std::dynamic_pointer_cast(mCameraHandle[static_cast(i)])->Init(); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraManager::UnInit(void) +{ + for (int i = 0; i < static_cast(CameraType::END); i++) + { + mCameraHandle[static_cast(i)] = std::make_shared(); + // std::dynamic_pointer_cast(mCameraHandle[static_cast(i)])->UnInit(); + auto tmp = std::dynamic_pointer_cast(mCameraHandle[static_cast(i)]); + if (tmp) + { + tmp->UnInit(); + } + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraManager::GetCameraHandle(const CameraType &type, std::shared_ptr &camera) +{ + camera = mCameraHandle[type]; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/CameraManager.h b/code/application/sifarsdk/component/CameraManager/src/CameraManager.h new file mode 100644 index 000000000..e5468f603 --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/CameraManager.h @@ -0,0 +1,18 @@ +#ifndef CAMERA_MANAGER_H +#define CAMERA_MANAGER_H +#include "ICameraManager.h" +#include "CameraHandle.h" +#include +class CameraManager : public ICameraManager +{ +public: + CameraManager(); + virtual ~CameraManager() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + RETURN_CODE GetCameraHandle(const CameraType &type, std::shared_ptr &camera) override; + +private: + std::map> mCameraHandle; +}; +#endif // !CAMERA_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/CameraManagerMakePtr.cpp b/code/application/sifarsdk/component/CameraManager/src/CameraManagerMakePtr.cpp new file mode 100644 index 000000000..e9ede3442 --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/CameraManagerMakePtr.cpp @@ -0,0 +1,37 @@ +#include "CameraManagerMakePtr.h" +#include "Log.h" +#include "VReturnCode.h" +#include "CameraHandle.h" +#include "CameraManager.h" +#include +bool CreateCameraManager(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = CameraManagerMakePtr::GetInstance()->CreateCameraManager(instance); + if (code->IsCodeOK()) + { + LogInfo("Camera manager instance is ok.\n"); + ICameraManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &CameraManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + instance = *impl; + } + return instance; +} +RETURN_CODE CameraManagerMakePtr::CreateCameraManager(std::shared_ptr &impl) +{ + impl = std::make_shared(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE CameraManagerMakePtr::CreateCameraHandle(const CameraType &cameraType, std::shared_ptr &impl) +{ + impl = std::make_shared(cameraType); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/CameraManagerMakePtr.h b/code/application/sifarsdk/component/CameraManager/src/CameraManagerMakePtr.h new file mode 100644 index 000000000..29dbd510e --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/CameraManagerMakePtr.h @@ -0,0 +1,17 @@ +#ifndef CAMERA_MANAGER_MAKE_PTR_H +#define CAMERA_MANAGER_MAKE_PTR_H +#include "VReturnCode.h" +#include "ICameraManager.h" +#include +class CameraManagerMakePtr +{ +public: + CameraManagerMakePtr() = default; + virtual ~CameraManagerMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE CreateCameraManager(std::shared_ptr &impl); + virtual RETURN_CODE CreateCameraHandle(const CameraType &cameraType, std::shared_ptr &impl); +}; +#endif // !CAMERA_MANAGER_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/CameraManagerReturnCode.cpp b/code/application/sifarsdk/component/CameraManager/src/CameraManagerReturnCode.cpp new file mode 100644 index 000000000..37fa8dbf6 --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/CameraManagerReturnCode.cpp @@ -0,0 +1,34 @@ +#include "CameraManagerReturnCode.h" +#include "Log.h" +const std::string CameraManagerReturnCodeDefineStr[static_cast(CameraManagerReturnCodeDefine::END) - static_cast(VReturnCodeDefine::END) + 1] = { + "CAMERA_TASK_CAN_EXECUTE_MORE", + "END"}; +const std::string UNDEFINED_CODE = "Print failed, undefined state machine code."; +std::shared_ptr CameraManagerReturnCode::NewCode(const CameraManagerReturnCodeDefine &code) +{ + class MakeShared : public CameraManagerReturnCode + { + public: + MakeShared(const int &code) : CameraManagerReturnCode(code) {} + }; + return std::make_shared(static_cast(code)); +} +std::string CameraManagerReturnCode::PrintStringCode() +{ + if (static_cast(VReturnCode::GetIntCode()) < static_cast(VReturnCodeDefine::END)) + { + return VReturnCode::PrintStringCode(); + } + else + { + if (static_cast(CameraManagerReturnCodeDefine::END) <= static_cast(VReturnCode::GetIntCode())) + { + LogError("%s\n", UNDEFINED_CODE.c_str()); + return UNDEFINED_CODE; + } + LogInfo("Return code:[ %s %s]\n", + CameraManagerReturnCodeDefineStr[static_cast(VReturnCode::GetIntCode()) - static_cast(VReturnCodeDefine::END) + 1].c_str(), + GetTips().c_str()); + return CameraManagerReturnCodeDefineStr[static_cast(VReturnCode::GetIntCode()) - static_cast(VReturnCodeDefine::END) + 1]; + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/CameraManagerReturnCode.h b/code/application/sifarsdk/component/CameraManager/src/CameraManagerReturnCode.h new file mode 100644 index 000000000..88300b02f --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/CameraManagerReturnCode.h @@ -0,0 +1,17 @@ +#ifndef CAMERA_MANAGER_RETURN_CODE_H +#define CAMERA_MANAGER_RETURN_CODE_H +#include "VReturnCode.h" +#include "ICameraManager.h" +class CameraManagerReturnCode : public VReturnCode +{ +private: + CameraManagerReturnCode(const int &code) : VReturnCode(code) + { + } + +public: + ~CameraManagerReturnCode() = default; + std::string PrintStringCode() override; + static std::shared_ptr NewCode(const CameraManagerReturnCodeDefine &code); +}; +#endif // !CAMERA_MANAGER_RETURN_CODE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/CameraManager/src/ICameraManager.cpp b/code/application/sifarsdk/component/CameraManager/src/ICameraManager.cpp new file mode 100644 index 000000000..447bc3c25 --- /dev/null +++ b/code/application/sifarsdk/component/CameraManager/src/ICameraManager.cpp @@ -0,0 +1,31 @@ +#include "ICameraManager.h" +#include "Log.h" +#include +std::shared_ptr &ICameraManager::GetInstance(std::shared_ptr *impl) +{ + static std::shared_ptr instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Don't sleep and make sure that start fast. + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + // instance->UnInit(); + // (*impl)->Init(); // TODO: Don't need to Init is better? + instance = *impl; + } + else + { + LogError("[ error ] instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static std::shared_ptr tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Common/include/SfTypeDefine.h b/code/application/sifarsdk/component/Common/include/SfTypeDefine.h new file mode 100644 index 000000000..08d7ba953 --- /dev/null +++ b/code/application/sifarsdk/component/Common/include/SfTypeDefine.h @@ -0,0 +1,42 @@ +#ifndef SF_TYPE_DEFINE_H +#define SF_TYPE_DEFINE_H + +// typedef unsigned long int UINT64; +typedef unsigned int UINT32; +typedef unsigned short UINT16; +typedef unsigned char UINT8; + +typedef signed long int SINT64; +typedef signed int SINT32; +typedef signed short SINT16; +typedef signed char SINT8; + +typedef unsigned char UCHAR; +typedef unsigned char U8; +typedef unsigned short U16; +typedef unsigned int U32; +typedef unsigned int long ULONG; +typedef unsigned long int U64; + +typedef signed char CHAR; +typedef char S8; +typedef short S16; +typedef int S32; +typedef long SLONG; +typedef signed long int S64; +typedef char SF_CHAR; +typedef unsigned char SF_BOOL; +typedef void SF_VOID; + +#define SF_NULL 0L +#define SF_SUCCESS 0 +#define SF_FAILURE (-1) +#define SF_SUCCESS 0 +#define SF_FAIL 1 +// #define SUCCESS 0 +// #define FAIL 1 +#define SF_TRUE 1 +#define SF_FALSE 0 + +#define SF_ENABLE 0 +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/CMakeLists.txt b/code/application/sifarsdk/component/Config/CMakeLists.txt new file mode 100644 index 000000000..96e6247db --- /dev/null +++ b/code/application/sifarsdk/component/Config/CMakeLists.txt @@ -0,0 +1,36 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ./src/src_c/include + ./src/src_c/src + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) +aux_source_directory(./src/src_c/src SRC_FILES) + +set(TARGET_NAME Config) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} ReturnCode Log) + +add_custom_target( + ConfigOutput + DEPENDS Config + COMMAND echo "Build Config output." + COMMAND cp ${COMPONENT_SOURCE_PATH}/Config/include/*.h ${LIBS_OUTPUT_PATH}/include + COMMAND cp ${COMPONENT_SOURCE_PATH}/Config/README.md ${LIBS_OUTPUT_PATH}/readme/README_Config.md + WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/ +) \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/README.md b/code/application/sifarsdk/component/Config/README.md new file mode 100644 index 000000000..aa1e67600 --- /dev/null +++ b/code/application/sifarsdk/component/Config/README.md @@ -0,0 +1,22 @@ +# 1. 配置库 + +## 1.1. 概述 +   配置库适配C/C++混编项目,提供C使用的头文件,内部统一转到C++接口,实现多态属性。 + +## 1.2. 使用方法 +头文件:IConfig.h +链接库:libReturnCode.a libLog.a +详见:/test/component/Config/src/IConfigTest.cpp +``` +#inclde "IConfig.h" + +CreateConfig(); +ConfigInitV2(); +Param paramSet; +paramSet.numberUInt = 2; +SetParam(paramSet, PARAM_CAMERA_MODE); +Param param; +memset(¶m, 0, sizeof(Param)); +param = GetParam(PARAM_CAMERA_MODE); +printf("PARAM_CAMERA_MODE = %d\n", param.numberUInt); +``` \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/include/IConfig.h b/code/application/sifarsdk/component/Config/include/IConfig.h new file mode 100644 index 000000000..49a87fe3a --- /dev/null +++ b/code/application/sifarsdk/component/Config/include/IConfig.h @@ -0,0 +1,93 @@ +#ifndef I_CONFGI_H +#define I_CONFGI_H +#ifdef __cplusplus +extern "C" +{ +#endif +#define SD_LOOP_ENABLE (1) +#define RESET_ENABLE (1) +#define RESET_DISABLE (0) +#define DCF_FILE_NAME_PREFIX SF_DCF_FILE_NAME_PREFIX + typedef enum PARAM_NAME + { + PARAM_NAME_ACM_IP = 0, + PARAM_NAME_MULTI_SHOT, + PARAM_NAME_WEB_IP, + PARAM_NAME_APP_VERSION, + PARAM_SD_LOOP, + PARAM_RESET_FLAG, + PARAM_GPS_ENTER_RESET_MODE_FLAG, + PARAM_PIR_SWITCH, + PARAM_GPRS_MODE, + PARAM_TIMELAPSE_SWITCH, + PARAM_TIMELAPSE_TIME, + PARAM_PIR_DELAY_SWITCH, + PARAM_PIR_DELAY_TIME, + PARAM_PIR_SENSITIVITY, + PARAM_GPRS_SWITCH, + PARAM_DIGIT_PIR_SENSITIVITY, + PARAM_GPS_WAIT_RESTART_FLAG, + PARAM_DAILY_REPORT_TIME, + PARAM_WORK_MODE, + PARAM_TIME_SEND_1, + PARAM_WORK_TIME_1_SWITCH, + PARAM_WORK_TIME_2_SWITCH, + PARAM_WORK_TIME, + PARAM_CAMERA_MODE, + PARAM_DID, + PARAM_BATTERY_TYPE, + PARAM_STAMP_SWITCH, + PARAM_IMAGE_SIZE, + PARAM_FLASH_LED, + PARAM_VIDEO_SIZE, + PARAM_VIDEO_LENGTH, + PARAM_DAILY_REPORT_SWITCH, + PARAM_LATITUDE, + PARAM_LONGITUDE, + PARAM_GPS_FLAG, + PARAM_PARAM_SYNC, + PARAM_P2P_ID, + PARAM_P2P_NAME, + PARAM_P2P_SECRET, + PARAM_MQTT_IP, + PARAM_MQTT_PORT, + PARAM_DCF_FILE_NAME_PREFIX, + PARAM_NAME_END + } PARAM_NAME; + typedef struct SF_PARAM_TIME_S + { + unsigned short Year; + unsigned short Mon; + unsigned short Day; + unsigned short Hour; + unsigned short Min; + unsigned short Sec; + } PARAM_TIME_S; + typedef struct PARAM_WORKTIME_S + { + PARAM_TIME_S StartTime; + PARAM_TIME_S StopTime; + } PARAM_WORKTIME_S; +#define PARAM_STRING_LENGTH 160 +#define WORK_TIME_MAX 2 + typedef struct Param + { + char str[PARAM_STRING_LENGTH]; + int numberInt; + unsigned int numberUInt; + PARAM_TIME_S time; + PARAM_WORKTIME_S workTime[WORK_TIME_MAX]; + } Param; + void ConfigInit(const char *FilePath, const char *StstaticsticsFilePath); + void ConfigInitV2(void); + void ConfigUnInit(void); + Param NewConfigParam(void); + void SetParam(const Param param, const PARAM_NAME name); + const Param GetParam(PARAM_NAME name); + void ResetParam(void); + void SaveConfig(void); + int CreateConfig(void); +#ifdef __cplusplus +} +#endif +#endif // !I_CONFGI_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/src/ConfigCpp.cpp b/code/application/sifarsdk/component/Config/src/ConfigCpp.cpp new file mode 100644 index 000000000..e5b465186 --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/ConfigCpp.cpp @@ -0,0 +1,725 @@ +#include "ConfigCpp.h" +#include "Log.h" +#include +ConfigCpp::ConfigCpp() +{ + InitSetFunc(); + InitGetFunc(); + InitSetFuncStaticstics(); + InitGetFuncStaticstics(); +} +void ConfigCpp::Init(const char *FilePath, const char *StstaticsticsFilePath) +{ + if (!FilePath || !StstaticsticsFilePath) + { + LogError("Nullptr FilePath.\n"); + return; + } + sf_customer_param_init(FilePath); + sf_customer_param_load(sf_customer_param_get()); + mParam = sf_customer_param_get(); + sf_statistics_param_init(StstaticsticsFilePath); + sf_statistics_param_load(sf_statistics_param_get()); + mParamStaticstics = sf_statistics_param_get(); +} +void ConfigCpp::InitV2(void) +{ + Init(CONFIG_FILE_PATH, CONFIG_FILE_STATIC_PATH); +} +void ConfigCpp::UnInit(void) +{ + sf_customer_param_save(sf_customer_param_get()); +} +Param ConfigCpp::NewConfigParam(void) +{ + Param param; + memset(¶m, 0, sizeof(Param)); + return param; +} +void ConfigCpp::SetParam(const Param ¶m, const PARAM_NAME &name) +{ + // mSetParam[name](mParam, param); + std::map::iterator iter; + iter = mSetParam.find(name); + if (iter != mSetParam.end()) + { + if (mSetParam[name]) + { + mSetParam[name](mParam, param); + return; + } + } + std::map::iterator iter2; + iter2 = mSetParamStaticstics.find(name); + if (iter2 != mSetParamStaticstics.end()) + { + if (mSetParamStaticstics[name]) + { + mSetParamStaticstics[name](mParamStaticstics, param); + return; + } + } + LogError("Null callback func.\n"); +} +const Param ConfigCpp::GetParam(const PARAM_NAME &name) +{ + // LogInfo("GetParam = %d\n", name); + std::map::iterator iter; + iter = mGetParam.find(name); + if (iter != mGetParam.end()) + { + if (mGetParam[name]) + { + return mGetParam[name](mParam); + } + } + std::map::iterator iter2; + iter2 = mGetParamStaticstics.find(name); + if (iter2 != mGetParamStaticstics.end()) + { + if (mGetParamStaticstics[name]) + { + return mGetParamStaticstics[name](mParamStaticstics); + } + LogError("Null callback func.\n"); + } + LogError("Can't find the param.\n"); + Param nullData; + memset(&nullData, 0, sizeof(Param)); + return nullData; +} +void ConfigCpp::SaveConfig(void) +{ + sf_statistics_param_save(sf_statistics_param_get()); + sf_customer_param_save(sf_customer_param_get()); +} +void ConfigCpp::ResetConfig(void) +{ + sf_customer_param_reset(sf_customer_param_get(), 0); + sf_statistics_param_reset(sf_statistics_param_get()); + SaveConfig(); +} +void ConfigCpp::InitSetFunc(void) +{ + auto func = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) { + + }; + mSetParam[PARAM_NAME_ACM_IP] = func; + auto func2 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->Multishot = param.numberUInt; + }; + mSetParam[PARAM_NAME_MULTI_SHOT] = func2; + auto func3 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->SdLoop = param.numberUInt; + }; + mSetParam[PARAM_SD_LOOP] = func3; + auto func4 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->ResetFlag = param.numberUInt; + }; + mSetParam[PARAM_RESET_FLAG] = func4; + auto func5 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->GPSEnterResetModeFlag = param.numberUInt; + }; + mSetParam[PARAM_GPS_ENTER_RESET_MODE_FLAG] = func5; + auto func6 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->PirSwitch = param.numberUInt; + }; + mSetParam[PARAM_PIR_SWITCH] = func6; + auto func7 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->GprsMode = param.numberUInt; + }; + mSetParam[PARAM_GPRS_MODE] = func7; + auto func8 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->TimelapseSwitch = param.numberUInt; + }; + mSetParam[PARAM_TIMELAPSE_SWITCH] = func8; + auto func9 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->PirDelaySwitch = param.numberUInt; + }; + mSetParam[PARAM_PIR_DELAY_SWITCH] = func9; + auto func10 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->PirSensitivity = param.numberUInt; + }; + mSetParam[PARAM_PIR_SENSITIVITY] = func10; + auto func11 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->GprsSwitch = param.numberUInt; + }; + mSetParam[PARAM_GPRS_SWITCH] = func11; + auto func12 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->DigitPirSensitivity = param.numberUInt; + }; + mSetParam[PARAM_DIGIT_PIR_SENSITIVITY] = func12; + auto func13 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->TimelapseTime.Year = param.time.Year; + config->TimelapseTime.Mon = param.time.Mon; + config->TimelapseTime.Day = param.time.Day; + config->TimelapseTime.Hour = param.time.Hour; + config->TimelapseTime.Min = param.time.Min; + config->TimelapseTime.Sec = param.time.Sec; + }; + mSetParam[PARAM_TIMELAPSE_TIME] = func13; + auto func14 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->PirDelayTime.Year = param.time.Year; + config->PirDelayTime.Mon = param.time.Mon; + config->PirDelayTime.Day = param.time.Day; + config->PirDelayTime.Hour = param.time.Hour; + config->PirDelayTime.Min = param.time.Min; + config->PirDelayTime.Sec = param.time.Sec; + }; + mSetParam[PARAM_PIR_DELAY_TIME] = func14; + auto func15 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->GPSWaitRestartFlag = param.numberUInt; + }; + mSetParam[PARAM_GPS_WAIT_RESTART_FLAG] = func15; + auto func16 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->DailyReportTime.Year = param.time.Year; + config->DailyReportTime.Mon = param.time.Mon; + config->DailyReportTime.Day = param.time.Day; + config->DailyReportTime.Hour = param.time.Hour; + config->DailyReportTime.Min = param.time.Min; + config->DailyReportTime.Sec = param.time.Sec; + }; + mSetParam[PARAM_DAILY_REPORT_TIME] = func16; + auto func17 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->WorkMode = param.numberUInt; + }; + mSetParam[PARAM_WORK_MODE] = func17; + auto func18 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->TimeSend1.Year = param.time.Year; + config->TimeSend1.Mon = param.time.Mon; + config->TimeSend1.Day = param.time.Day; + config->TimeSend1.Hour = param.time.Hour; + config->TimeSend1.Min = param.time.Min; + config->TimeSend1.Sec = param.time.Sec; + }; + mSetParam[PARAM_TIME_SEND_1] = func18; + auto func19 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->WorkTime1Switch = param.numberUInt; + }; + mSetParam[PARAM_WORK_TIME_1_SWITCH] = func19; + auto func20 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + for (int i = 0; i < WORK_TIME_MAX; i++) + { + config->WorkTime[i].StartTime.Year = param.workTime->StartTime.Year; + config->WorkTime[i].StartTime.Mon = param.workTime->StartTime.Mon; + config->WorkTime[i].StartTime.Day = param.workTime->StartTime.Day; + config->WorkTime[i].StartTime.Hour = param.workTime->StartTime.Hour; + config->WorkTime[i].StartTime.Min = param.workTime->StartTime.Min; + config->WorkTime[i].StartTime.Sec = param.workTime->StartTime.Sec; + config->WorkTime[i].StopTime.Year = param.workTime->StopTime.Year; + config->WorkTime[i].StopTime.Mon = param.workTime->StopTime.Mon; + config->WorkTime[i].StopTime.Day = param.workTime->StopTime.Day; + config->WorkTime[i].StopTime.Hour = param.workTime->StopTime.Hour; + config->WorkTime[i].StopTime.Min = param.workTime->StopTime.Min; + config->WorkTime[i].StopTime.Sec = param.workTime->StopTime.Sec; + } + }; + mSetParam[PARAM_WORK_TIME] = func20; + auto func21 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->WorkTime2Switch = param.numberUInt; + }; + mSetParam[PARAM_WORK_TIME_2_SWITCH] = func21; + auto func22 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->CamMode = param.numberUInt; + }; + mSetParam[PARAM_CAMERA_MODE] = func22; + auto func23 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->BatteryType = param.numberUInt; + }; + mSetParam[PARAM_BATTERY_TYPE] = func23; + auto func24 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->StampSwitch = param.numberUInt; + }; + mSetParam[PARAM_STAMP_SWITCH] = func24; + auto func25 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->ImgSize = param.numberUInt; + }; + mSetParam[PARAM_IMAGE_SIZE] = func25; + auto func26 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->FlashLed = param.numberUInt; + }; + mSetParam[PARAM_FLASH_LED] = func26; + auto func27 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->VideoSize = param.numberUInt; + }; + mSetParam[PARAM_VIDEO_SIZE] = func27; + auto func28 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->VideoLenth = param.numberUInt; + }; + mSetParam[PARAM_VIDEO_LENGTH] = func28; + auto func29 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->DailyReportswitch = param.numberUInt; + }; + mSetParam[PARAM_DAILY_REPORT_SWITCH] = func29; + auto func30 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->GPSFlag = param.numberUInt; + }; + mSetParam[PARAM_GPS_FLAG] = func30; + auto func31 = [](SF_PDT_PARAM_CFG_S *config, const Param ¶m) + { + config->ParaSync = param.numberUInt; + }; + mSetParam[PARAM_PARAM_SYNC] = func31; +} +const char *CONFIG_WEB_IP = "acenter.wuyuantech.com"; +void ConfigCpp::InitGetFunc(void) +{ + auto func = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + return data; + }; + mGetParam[PARAM_NAME_ACM_IP] = func; + auto func2 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->Multishot; + return data; + }; + mGetParam[PARAM_NAME_MULTI_SHOT] = func2; + auto func3 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->SdLoop; + return data; + }; + mGetParam[PARAM_SD_LOOP] = func3; + auto func4 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->ResetFlag; + return data; + }; + mGetParam[PARAM_RESET_FLAG] = func4; + auto func5 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->GPSEnterResetModeFlag; + return data; + }; + mGetParam[PARAM_GPS_ENTER_RESET_MODE_FLAG] = func5; + auto func6 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->PirSwitch; + return data; + }; + mGetParam[PARAM_PIR_SWITCH] = func6; + auto func7 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->GprsMode; + return data; + }; + mGetParam[PARAM_GPRS_MODE] = func7; + auto func8 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->TimelapseSwitch; + return data; + }; + mGetParam[PARAM_TIMELAPSE_SWITCH] = func8; + auto func9 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->PirDelaySwitch; + return data; + }; + mGetParam[PARAM_PIR_DELAY_SWITCH] = func9; + auto func10 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->PirSensitivity; + return data; + }; + mGetParam[PARAM_PIR_SENSITIVITY] = func10; + auto func11 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->GprsSwitch; + return data; + }; + mGetParam[PARAM_GPRS_SWITCH] = func11; + auto func12 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->DigitPirSensitivity; + return data; + }; + mGetParam[PARAM_DIGIT_PIR_SENSITIVITY] = func12; + auto func13 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.time.Year = config->TimelapseTime.Year; + data.time.Mon = config->TimelapseTime.Mon; + data.time.Day = config->TimelapseTime.Day; + data.time.Hour = config->TimelapseTime.Hour; + data.time.Min = config->TimelapseTime.Min; + data.time.Sec = config->TimelapseTime.Sec; + return data; + }; + mGetParam[PARAM_TIMELAPSE_TIME] = func13; + auto func14 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.time.Year = config->PirDelayTime.Year; + data.time.Mon = config->PirDelayTime.Mon; + data.time.Day = config->PirDelayTime.Day; + data.time.Hour = config->PirDelayTime.Hour; + data.time.Min = config->PirDelayTime.Min; + data.time.Sec = config->PirDelayTime.Sec; + return data; + }; + mGetParam[PARAM_PIR_DELAY_TIME] = func14; + auto func15 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->GPSWaitRestartFlag; + return data; + }; + mGetParam[PARAM_GPS_WAIT_RESTART_FLAG] = func15; + auto func16 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.time.Year = config->DailyReportTime.Year; + data.time.Mon = config->DailyReportTime.Mon; + data.time.Day = config->DailyReportTime.Day; + data.time.Hour = config->DailyReportTime.Hour; + data.time.Min = config->DailyReportTime.Min; + data.time.Sec = config->DailyReportTime.Sec; + return data; + }; + mGetParam[PARAM_DAILY_REPORT_TIME] = func16; + auto func17 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->WorkMode; + return data; + }; + mGetParam[PARAM_WORK_MODE] = func17; + auto func18 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.time.Year = config->TimeSend1.Year; + data.time.Mon = config->TimeSend1.Mon; + data.time.Day = config->TimeSend1.Day; + data.time.Hour = config->TimeSend1.Hour; + data.time.Min = config->TimeSend1.Min; + data.time.Sec = config->TimeSend1.Sec; + return data; + }; + mGetParam[PARAM_TIME_SEND_1] = func18; + auto func19 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->WorkTime1Switch; + return data; + }; + mGetParam[PARAM_WORK_TIME_1_SWITCH] = func19; + auto func20 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + for (int i = 0; i < WORK_TIME_MAX; i++) + { + data.workTime[i].StartTime.Year = config->WorkTime[i].StartTime.Year; + data.workTime[i].StartTime.Mon = config->WorkTime[i].StartTime.Mon; + data.workTime[i].StartTime.Day = config->WorkTime[i].StartTime.Day; + data.workTime[i].StartTime.Hour = config->WorkTime[i].StartTime.Hour; + data.workTime[i].StartTime.Min = config->WorkTime[i].StartTime.Min; + data.workTime[i].StartTime.Sec = config->WorkTime[i].StartTime.Sec; + data.workTime[i].StopTime.Year = config->WorkTime[i].StopTime.Year; + data.workTime[i].StopTime.Mon = config->WorkTime[i].StopTime.Mon; + data.workTime[i].StopTime.Day = config->WorkTime[i].StopTime.Day; + data.workTime[i].StopTime.Hour = config->WorkTime[i].StopTime.Hour; + data.workTime[i].StopTime.Min = config->WorkTime[i].StopTime.Min; + data.workTime[i].StopTime.Sec = config->WorkTime[i].StopTime.Sec; + } + return data; + }; + mGetParam[PARAM_WORK_TIME] = func20; + auto func21 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->WorkTime2Switch; + return data; + }; + mGetParam[PARAM_WORK_TIME_2_SWITCH] = func21; + auto func22 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->CamMode; + return data; + }; + mGetParam[PARAM_CAMERA_MODE] = func22; + auto func23 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->BatteryType; + return data; + }; + mGetParam[PARAM_BATTERY_TYPE] = func23; + auto func24 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->StampSwitch; + return data; + }; + mGetParam[PARAM_STAMP_SWITCH] = func24; + auto func25 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->ImgSize; + return data; + }; + mGetParam[PARAM_IMAGE_SIZE] = func25; + auto func26 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->FlashLed; + return data; + }; + mGetParam[PARAM_FLASH_LED] = func26; + auto func27 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->VideoSize; + return data; + }; + mGetParam[PARAM_VIDEO_SIZE] = func27; + auto func28 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->VideoLenth; + return data; + }; + mGetParam[PARAM_VIDEO_LENGTH] = func28; + auto func29 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->DailyReportswitch; + return data; + }; + mGetParam[PARAM_DAILY_REPORT_SWITCH] = func29; + auto func30 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->GPSFlag; + return data; + }; + mGetParam[PARAM_GPS_FLAG] = func30; + auto func31 = [](SF_PDT_PARAM_CFG_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberUInt = config->ParaSync; + return data; + }; + mGetParam[PARAM_PARAM_SYNC] = func31; +} +void ConfigCpp::InitSetFuncStaticstics(void) +{ + LogInfo("InitSetFuncStaticstics.\n"); + auto func = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + memset(config->WebIP, 0, SF_FTP_MAX_LEN); + memcpy(config->WebIP, param.str, strlen(param.str)); + }; + mSetParamStaticstics[PARAM_NAME_WEB_IP] = func; + auto func3 = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + config->Did = param.numberInt; + }; + mSetParamStaticstics[PARAM_DID] = func3; + auto func4 = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + memset(config->Latitude, 0, SF_GPS_INFO_MAX_LEN); + memcpy(config->Latitude, param.str, SF_GPS_INFO_MAX_LEN); + }; + mSetParamStaticstics[PARAM_LATITUDE] = func4; + auto func5 = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + memset(config->Longitude, 0, SF_GPS_INFO_MAX_LEN); + memcpy(config->Longitude, param.str, SF_GPS_INFO_MAX_LEN); + }; + mSetParamStaticstics[PARAM_LONGITUDE] = func5; + auto func6 = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + memset(config->p2pId, 0, P2P_BUF_LEN); + memcpy(config->p2pId, param.str, P2P_BUF_LEN); + }; + mSetParamStaticstics[PARAM_P2P_ID] = func6; + auto func7 = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + memset(config->p2pName, 0, P2P_BUF_LEN); + memcpy(config->p2pName, param.str, P2P_BUF_LEN); + }; + mSetParamStaticstics[PARAM_P2P_NAME] = func7; + auto func8 = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + memset(config->p2pSecret, 0, P2P_BUF_LEN); + memcpy(config->p2pSecret, param.str, P2P_BUF_LEN); + }; + mSetParamStaticstics[PARAM_P2P_SECRET] = func8; + auto func9 = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + memset(config->MQTTIp, 0, SF_ALIVE_IP_MAX_LEN); + memcpy(config->MQTTIp, param.str, SF_ALIVE_IP_MAX_LEN); + }; + mSetParamStaticstics[PARAM_MQTT_IP] = func9; + auto func10 = [](SF_PDT_PARAM_STATISTICS_S *config, const Param ¶m) + { + config->MQTTPort = param.numberInt; + }; + mSetParamStaticstics[PARAM_MQTT_PORT] = func10; +} +void ConfigCpp::InitGetFuncStaticstics(void) +{ + LogInfo("InitGetFuncStaticstics.\n"); + auto func = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, config->WebIP, strlen(config->WebIP)); + return data; + }; + mGetParamStaticstics[PARAM_NAME_WEB_IP] = func; + auto func2 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, APP_VERSION, strlen(APP_VERSION)); + return data; + }; + mGetParamStaticstics[PARAM_NAME_APP_VERSION] = func2; + auto funcDcfFileNamePrefix = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, SF_DCF_FILE_NAME_PREFIX, strlen(SF_DCF_FILE_NAME_PREFIX)); + return data; + }; + mGetParamStaticstics[PARAM_DCF_FILE_NAME_PREFIX] = funcDcfFileNamePrefix; + auto func3 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberInt = config->Did; + return data; + }; + mGetParamStaticstics[PARAM_DID] = func3; + auto func4 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, config->Latitude, SF_GPS_INFO_MAX_LEN); + return data; + }; + mGetParamStaticstics[PARAM_LATITUDE] = func4; + auto func5 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, config->Longitude, SF_GPS_INFO_MAX_LEN); + return data; + }; + mGetParamStaticstics[PARAM_LONGITUDE] = func5; + auto func6 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, config->p2pId, P2P_BUF_LEN); + return data; + }; + mGetParamStaticstics[PARAM_P2P_ID] = func6; + auto func7 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, config->p2pName, P2P_BUF_LEN); + return data; + }; + mGetParamStaticstics[PARAM_P2P_NAME] = func7; + auto func8 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, config->p2pSecret, P2P_BUF_LEN); + return data; + }; + mGetParamStaticstics[PARAM_P2P_SECRET] = func8; + auto func9 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + memcpy(data.str, config->MQTTIp, SF_ALIVE_IP_MAX_LEN); + return data; + }; + mGetParamStaticstics[PARAM_MQTT_IP] = func9; + auto func10 = [](SF_PDT_PARAM_STATISTICS_S *config) -> const Param + { + Param data; + memset(&data, 0, sizeof(Param)); + data.numberInt = config->MQTTPort; + return data; + }; + mGetParamStaticstics[PARAM_MQTT_PORT] = func10; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/src/ConfigCpp.h b/code/application/sifarsdk/component/Config/src/ConfigCpp.h new file mode 100644 index 000000000..8be53f70c --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/ConfigCpp.h @@ -0,0 +1,36 @@ +#ifndef CONFIG_CPP_H +#define CONFIG_CPP_H +#include "IConfigCpp.h" +#include "sf_param_common.h" +#include +// #define APP_VERSION "4SA1HKrD503" +constexpr const char *APP_VERSION = "4SA1HKrD503"; +class ConfigCpp : public IConfigCpp +{ +public: + ConfigCpp(); + virtual ~ConfigCpp() = default; + void Init(const char *FilePath, const char *StstaticsticsFilePath) override; + void InitV2(void) override; + void UnInit(void) override; + Param NewConfigParam(void) override; + void SetParam(const Param ¶m, const PARAM_NAME &name) override; + const Param GetParam(const PARAM_NAME &name) override; + void SaveConfig(void) override; + void ResetConfig(void) override; + +private: + void InitSetFunc(void); + void InitGetFunc(void); + void InitSetFuncStaticstics(void); + void InitGetFuncStaticstics(void); + +private: + std::map mSetParam; + std::map mGetParam; + SF_PDT_PARAM_CFG_S *mParam; + std::map mSetParamStaticstics; + std::map mGetParamStaticstics; + SF_PDT_PARAM_STATISTICS_S *mParamStaticstics; +}; +#endif // !CONFIG_CPP_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/src/ConfigMakePtr.cpp b/code/application/sifarsdk/component/Config/src/ConfigMakePtr.cpp new file mode 100644 index 000000000..1cc7f919a --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/ConfigMakePtr.cpp @@ -0,0 +1,34 @@ +#include "ConfigMakePtr.h" +#include "Log.h" +#include "ConfigCpp.h" +int CreateConfig(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = ConfigMakePtr::GetInstance()->CreateConfig(instance); + if (code->IsCodeOK()) + { + LogInfo("Config module instance is ok.\n"); + IConfigCpp::GetInstance(&instance); + return 0; + } + return -1; +} +std::shared_ptr &ConfigMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + /** + * @brief + * The non-thread-safe changing is only for gtest. + */ + instance = *impl; + } + return instance; +} +RETURN_CODE ConfigMakePtr::CreateConfig(std::shared_ptr &impl) +{ + auto tmp = std::make_shared(); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/src/ConfigMakePtr.h b/code/application/sifarsdk/component/Config/src/ConfigMakePtr.h new file mode 100644 index 000000000..dc57eccc8 --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/ConfigMakePtr.h @@ -0,0 +1,14 @@ +#ifndef CONFIG_MAKE_PTR_H +#define CONFIG_MAKE_PTR_H +#include "IConfigCpp.h" +#include "VReturnCode.h" +#include +class ConfigMakePtr +{ +public: + ConfigMakePtr() = default; + virtual ~ConfigMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE CreateConfig(std::shared_ptr &impl); +}; +#endif // !CONFIG_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/src/IConfig.cpp b/code/application/sifarsdk/component/Config/src/IConfig.cpp new file mode 100644 index 000000000..8ca67d06f --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/IConfig.cpp @@ -0,0 +1,34 @@ +#include "IConfig.h" +#include "IConfigCpp.h" +void ConfigInit(const char *FilePath, const char *StstaticsticsFilePath) +{ + IConfigCpp::GetInstance()->Init(FilePath, StstaticsticsFilePath); +} +void ConfigInitV2(void) +{ + IConfigCpp::GetInstance()->InitV2(); +} +void ConfigUnInit(void) +{ + IConfigCpp::GetInstance()->UnInit(); +} +Param NewConfigParam(void) +{ + return IConfigCpp::GetInstance()->NewConfigParam(); +} +void SetParam(const Param param, const PARAM_NAME name) +{ + IConfigCpp::GetInstance()->SetParam(param, name); +} +const Param GetParam(PARAM_NAME name) +{ + return IConfigCpp::GetInstance()->GetParam(name); +} +void ResetParam(void) +{ + IConfigCpp::GetInstance()->ResetConfig(); +} +void SaveConfig(void) +{ + IConfigCpp::GetInstance()->SaveConfig(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/src/IConfigCpp.cpp b/code/application/sifarsdk/component/Config/src/IConfigCpp.cpp new file mode 100644 index 000000000..8beacbd26 --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/IConfigCpp.cpp @@ -0,0 +1,29 @@ +#include "IConfigCpp.h" +#include "Log.h" +#include +std::shared_ptr &IConfigCpp::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/src/IConfigCpp.h b/code/application/sifarsdk/component/Config/src/IConfigCpp.h new file mode 100644 index 000000000..64b22cb90 --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/IConfigCpp.h @@ -0,0 +1,28 @@ +#ifndef I_CONFIG_CPP_H +#define I_CONFIG_CPP_H +#include "IConfig.h" +#include +class IConfigCpp +{ +public: + IConfigCpp() = default; + virtual ~IConfigCpp() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual void Init(const char *FilePath, const char *StstaticsticsFilePath) {} + virtual void InitV2(void) {} + virtual void UnInit(void) {} + virtual Param NewConfigParam(void) + { + Param param; + return param; + } + virtual void SetParam(const Param ¶m, const PARAM_NAME &name) {} + virtual const Param GetParam(const PARAM_NAME &name) + { + Param data; + return data; + } + virtual void SaveConfig(void) {} + virtual void ResetConfig(void) {} +}; +#endif // !I_CONFIG_CPP_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_common.h b/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_common.h new file mode 100644 index 000000000..6cbdf931e --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_common.h @@ -0,0 +1,57 @@ +#ifndef __SF_PARAM_COMMON_H__ +#define __SF_PARAM_COMMON_H__ +#include "SfTypeDefine.h" +#include "sf_param_enum.h" +#include "sf_param_struct.h" +#if __cplusplus +extern "C" +{ +#endif + + void sf_sleep_ms(S32 millisecond); + + void sf_sleep_s(S32 second); + + const SF_CHAR *sf_poweron_type_string(SF_STARTUP_TYPE_E enType); + + SF_STARTUP_TYPE_E sf_poweron_type_get(); + + SINT32 sf_poweron_type_set(SF_STARTUP_TYPE_E enType); + + void sf_customer_param_init(const char *ParamFilePath); + + SF_PDT_PARAM_CFG_S *sf_customer_param_get(); + + void sf_customer_param_set(SF_PDT_PARAM_CFG_S *pSfCustomerPara); + + void sf_customer_param_reset(SF_PDT_PARAM_CFG_S *psfpdtparam, UINT8 sysRet); + + SINT32 sf_customer_param_save(SF_PDT_PARAM_CFG_S *pSfCustomerPara); + + SINT32 sf_customer_param_load(SF_PDT_PARAM_CFG_S *pSfCustomerPara); + + void sf_statistics_param_init(const char *filePath); + + SF_PDT_PARAM_STATISTICS_S *sf_statistics_param_get(); + + void sf_statistics_param_reset(SF_PDT_PARAM_STATISTICS_S *pSfPara); + + void sf_statistics_param_specify(SF_PDT_PARAM_STATISTICS_S *pStatisticsParam); + + SINT32 sf_statistics_param_save(SF_PDT_PARAM_STATISTICS_S *pStatisticsParam); + + SINT32 sf_statistics_param_load(SF_PDT_PARAM_STATISTICS_S *pStatisticsParam); + + void sf_all_param_reset(); + + void sf_cap_status_set(UINT8 capStatus); + + UINT8 sf_cap_status_get(); + + SF_URL_S *sf_ota_url_get(void); + +#if __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_enum.h b/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_enum.h new file mode 100644 index 000000000..7e3aaa634 --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_enum.h @@ -0,0 +1,418 @@ +#ifndef __SF_PARAM_ENUM_H__ +#define __SF_PARAM_ENUM_H__ +#if __cplusplus +extern "C" +{ +#endif + +#define SF_MUTEX_INIT_LOCK(mutex) \ + do \ + { \ + (void)pthread_mutex_init(&mutex, NULL); \ + } while (0) + +#define SF_MUTEX_LOCK(mutex) \ + do \ + { \ + (void)pthread_mutex_lock(&mutex); \ + } while (0) + +#define SF_MUTEX_UNLOCK(mutex) \ + do \ + { \ + (void)pthread_mutex_unlock(&mutex); \ + } while (0) + +#define SF_MUTEX_DESTROY(mutex) \ + do \ + { \ + (void)pthread_mutex_destroy(&mutex); \ + } while (0) + +#define SF_APPCOMM_CHECK_RETURN(ret, errcode) \ + do \ + { \ + if (SF_SUCCESS != ret) \ + { \ + LogError("Error Code: [0x%08X]\n\n", ret); \ + return errcode; \ + } \ + } while (0) +#define SF_APPCOMM_CHECK_OPENFILE_RETURN(ret, str, errcode) \ + do \ + { \ + if (ret < 0) \ + { \ + LogError("open file: [%s] failed!!!\n\n", str); \ + return errcode; \ + } \ + } while (0) + +#define SF_CS_CHECK_BERAK(ret) \ + if (SF_SUCCESS != ret) \ + { \ + LogError("Error Code: [0x%08X]\n\n", ret); \ + break; \ + } +#define SF_COMM_CHECK_POINTER(p, errcode) \ + do \ + { \ + if (!(p)) \ + { \ + LogError("pointer[%s] is NULL\n", #p); \ + return errcode; \ + } \ + } while (0) + +#define SF_TTYUSB_RECV_MAX 580 +#define SF_HTTP_RECV_MAX 4096 + +#define CFG_FLAT_ANGLE_LEN + // #define CFG_WIDE_ANGLE_LEN + +#define SF_VER_MAX_LEN 12 + +#define SF_TIMER_MAX_NUMBER (2) + +#define SF_BATCH_MAX_NUMBER (2) +#define SF_TIMER_MAX_NUMBER (2) +#define SF_CAMERA_NAME_MAX_LEN (12) +#define SF_ICCID_MAX_LEN (22) +#define SF_DAILY_MAX_NUMBER (2) +#define SF_IMEI_MAX_LEN (32) +#define SF_OPERATOR_CODE_MAX_LEN (8) +#define SF_APN_MAX_LEN (40) +#define SF_APN_PASSWORD_MAX_LEN (20) +#define SF_FTP_MAX_LEN (40) +#define SF_FTP_PORT_MAX_LEN (5) +#define SF_GPS_INFO_MAX_LEN (16) +#define SF_MODULE_VER_MAX_LEN (50) +#define SF_BIND_ACCOUNT_MAX_LEN (50) +#define SF_TOKEN_MAX_LEN (64) +// #define SF_ALIVE_IP_MAX_LEN (32) +#define SF_UUID_MAX_LEN (32) +#define P2P_BUF_LEN 64 +#define SF_ALIVE_IP_MAX_LEN (48) + +#define SF_MAX_PATH_LEN 128 +#define SF_MAX_PIC_LEN 64 +#define SF_SRCFILE_MAX 4 +#define SF_THUMB_FILE_MAX_LEN 20 + +#define GPIOID_PIR_TEST 3 +#define GPIOID_SIM_INSRET 4 +#define GPIOID_USB_INSERT 61 +#define GPIOID_WIFI_POWER 6 +#define GPIOID_USB_MUX1 16 // t100 only one usb mux +#define GPIOID_USB_MUX2 16 + +#define GPIOID_ADC_MUXA 52 +#define GPIOID_ADC_MUXB 53 + +#define GPIOID_IRCUT_MEN1 50 +#define GPIOID_IRCUT_MEN2 51 + +#define SD_WARNING_SPACE 30 /*30MB*/ + +#define HTTP_PORT 80 +#define HTTPS_PORT 443 +#define HTTPCLIENT_REV_SIZE 512 +#define BUFFER_SIZE 2048 + +#define SF_DEV_NOT_EXIST 20002 +#define SF_DEV_NOT_BIND 20006 +#define SF_SYS_ERR 1 +#define SF_PARA_ERR 3 +#define SF_USER_NOT_EXIST 10006 +#define SF_SIM_NOT_EXIST 30002 +#define SF_SIM_NET_NOT_TURN_ON 30004 +#define SF_SIM_DEV_NOT_BIND 20011 +#define SF_DEV_DETAILS_NOT_VILLAGE 20009 +#define SF_DEV_AUTH_INVALID 401 + +#define MSYS_IOCTL_MAGIC 'S' +#define IOCTL_MSYS_GET_RTOSSTATUS _IO(MSYS_IOCTL_MAGIC, 0x95) +#define IOCTL_MSYS_GET_MODULE_DATA _IO(MSYS_IOCTL_MAGIC, 0x96) +#define IOCTL_MSYS_GET_SY_RTOS_DATA _IO(MSYS_IOCTL_MAGIC, 0x97) +#define IOCTL_MSYS_SET_RTOS_CMD _IO(MSYS_IOCTL_MAGIC, 0x98) + +#define DEFAULT_RTC_DEVICE "/dev/rtc0" + +#define SF_SD_ROOT "/mnt/mmc/" + +#define SIFAR_CUSTOMER_PARAM_PATH "/misc/sfSysParm.bin" // TODO: Get from Hal is better. +#define SIFAR_STATISTICS_PARAM_PATH "/mnt/mmc/DCIM/THUMB/sfStatisticsParm.bin" + +#define GPIO_DIR_OUT "out" +#define GPIO_DIR_IN "in" + +#define AMZ_HOST "s3.amazonaws.com" +#define AMZ_PW_TITLE "AWS4" +#define SECRET_TYPE "AWS4-HMAC-SHA256" +#define SECRET_VER "aws4_request" +#define AMZ "s3" + +#define SF_4G_PIC_THUMB_PATH SF_SD_ROOT "DCIM/THUMB/" +#define SF_4G_SMALL_VIDEO_STREAM_PATH SF_SD_ROOT "DCIM/SMALL/" +#define SIM_AUTO_MATCH_FILE_PATH SF_SD_ROOT "SIM Auto Match.TXT" + +#define SF_DCF_DIR_NAME_SUFFIX "SYCAM" /**< DCF Directory Name (it must be 5-characters) */ +#define SF_DCF_ROOT_DIR_NAME "DCIM" /**< DCF Root Directory Name */ +#define SF_DCF_THM_DIR_NAME "THUMB" /**< DCF Directory Name (it must be 5-characters) */ + +#define SF_DCF_EXT_PHOTO "jpg" /**< File extenstion name for Date DB */ +#define SF_DCF_EXT_MOV "mp4" /**< File extenstion name for Date DB */ +#define SF_DCF_EXT_AUDIO "WAV" /**< File extenstion name for Date DB */ +#define SF_DCF_EXT_THM "jpg" /**< File extenstion name for Date DB */ + +#define SF_QLOG_ENABLE 1 +// #define SF_VERSION_RELEASE +// #define SF_HARDWARE_TEST +// #define SF_FACTORY_TEST +// #define SF_GPS_TEST +#define SF_EMC_TEST + +#define CMD_SHORT_LONG_CLICK_OFFSET (128) + +#ifdef SF_VERSION_RELEASE +#define ACCESS_KEY "ACT1CSHKRO01" +#else +#define ACCESS_KEY "AC40CSHKRO01" +#endif + +#define SF_ERR_ID(module, err) ((SINT16)(((module) << 8) | (err))) + /** SF Module ID */ + typedef enum SF_MOD_e + { + + SF_MOD_4G = 1, + SF_MOD_GPS, + SF_MOD_FILE, + SF_MOD_HTTP, + SF_MOD_TTY, + SF_MOD_DATA, + SF_MOD_COM, + SF_MOD_LOG, + SF_MOD_STORE, + SF_MOD_SYS, + SF_MOD_APP, + SF_MOD_BUTT, + } SF_MOD_E; + + typedef enum ERR_CODE_e + { + ERROR_AT_APN, + ERROR_AT_TIMEOUT, + ERROR_AT_ACTIVE, + ERROR_AT_READ, + ERROR_AT_WRITE, + ERROR_AT_OPEN, + ERROR_AT_DISCONNECT, + ERROR_NO_SIMCARD, + ERROR_NO_SUPPORT, + ERROR_NO_SIGNAL, + ERROR_NO_FILE, + ERROR_FILE_SEND, + ERROR_INS_EXIT, + ERROR_NOT_MATCH, + ERROR_IP_ADDR, + ERROR_IP_CHANGE, + ERROR_REQUEST, + ERROR_WRITE, + ERROR_DATA_FORMAT, + ERROR_MODULE_OPEN, + ERROR_REG_NET, + ERROR_BUTT, + } ERR_CODE_E; + typedef enum sf_FILE_TYPE_E + + { + SF_FILE_TYPE_PIC_THUM_3M = 0x00, + SF_FILE_TYPE_PIC_3M = 0x01, + SF_FILE_TYPE_VIDEO_THUM_WVGA = 0X02, + SF_FILE_TYPE_VIDEO_WVGA = 0X03, + SF_FILE_TYPE_VIDEO_THUM_720P = 0X04, + SF_FILE_TYPE_VIDEO_720P = 0X05, + SF_FILE_TYPE_VIDEO_THUM_1080P = 0X06, + SF_FILE_TYPE_VIDEO_1080P = 0X07, + SF_FILE_TYPE_PIC_THUM_5M = 0x08, + SF_FILE_TYPE_PIC_5M = 0x09, + SF_FILE_TYPE_LOG_ERROR = 0x0A, + SF_FILE_TYPE_CFG = 0x0B, + SF_FILE_TYPE_TRIGGER = 0x0C, + + SF_FILE_TYPE_PIC_BIG, + SF_FILE_TYPE_PIC_SMALL, + SF_FILE_TYPE_PIC_VIDEO, + SF_FILE_TYPE_VIDEO, + SF_FILE_TYPE_LOG_DP, /*dailyreport file*/ + SF_FILE_TYPE_GPS, + SF_FILE_TYPE_TXT, + SF_FILE_TYPE_UPDATE, + SF_FILE_TYPE_FOTA, + SF_FILE_TYPE_BT_ALARM, /*Bettery Alarm*/ + SF_FILE_TYPE_OTHER, + SF_FILE_TYPE_BUTT, + } SF_FILE_TYPE_E; + + typedef enum + { + SF_USB_MUX_HOST_4G = 0, + SF_USB_MUX_PC_4G = 1, + SF_USB_MUX_PC_HOST = 2, + SF_USB_MUX_MAX = 3, + } SF_USB_MUX_FUN_e; + + typedef enum sfSD_STATUS_E + { + SF_SD_UNPLUGED = 0x00, + SF_SD_OUT, + SF_SD_OK, + SF_SD_FULL, + SF_SD_ERROR, + SF_SD_PLUGED, + SF_SD_BUTT, + } SF_SD_STATUS_E; + + typedef enum sf_STARTUP_TYPE_E + { + SF_MCU_STARTUP_OFF = 0x00, /* POWER OFF*/ + SF_MCU_STARTUP_ONKEY = 0x01, /*key on SETUP*/ + SF_MCU_STARTUP_TIMELAPSE = 0x02, /*timelapse power on*/ + SF_MCU_STARTUP_NORMAL = 0x03, /*Dial the key to ON*/ + SF_MCU_STARTUP_RING = 0x04, /*ring power on*/ + SF_MCU_STARTUP_PIR = 0x05, /*pir power on*/ + SF_MCU_STARTUP_WARNING = 0x06, /*low bat worning power on*/ + SF_MCU_STARTUP_SERVER = 0x07, /*server power on(reserve)*/ + SF_MCU_STARTUP_DP = 0x08, /*DailyReport power on*/ + SF_MCU_STARTUP_USB = 0x09, /*USB power on*/ + SF_MCU_STARTUP_RESET = 0x0A, /*power on to reset(reserve)*/ + SF_MCU_STARTUP_SYN_PARAM = 0x0B, /*power on to syn param(reserve)*/ + SF_MCU_STARTUP_BATCH_SEND = 0x0C, /*power on to send batch*/ + SF_MCU_STARTUP_BUTT = 0X0D, + } SF_STARTUP_TYPE_E; + + typedef enum sfPOWEROFF_TYPE_E + { + SF_POWEROFF_NOT = 0x00, + SF_POWEROFF_AUTO = 0x01, /*auto power when 3min no operation*/ + SF_POWEROFF_REBOOT = 0x02, /*poweroff to reboot*/ + SF_POWEROFF_KEYON = 0x03, + SF_POWEROFF_KEYOFF = 0x04, + SF_POWEROFF_SYNC_PARAM = 0x05, + SF_POWEROFF_GPS_DP = 0x06, + SF_POWEROFF_SD_FULL = 0x07, + SF_POWEROFF_LOW_BAT = 0x08, + SF_POWEROFF_NO_SD = 0x09, + SF_POWEROFF_BUTT, + } SF_POWEROFF_TYPE_E; + + typedef enum sf_CAMMODE_E + { + SF_CAMMODE_PIC = 0, + SF_CAMMODE_VIDEO, + SF_CAMMODE_PV, /* pic+video*/ + SF_CAMMODE_BUTT + } SF_CAMMODE_E; + typedef enum sf_IMG_SIZE_E + { + SF_IMG_SIZE_32M = 0, + SF_IMG_SIZE_24M, + SF_IMG_SIZE_12M, + SF_IMG_SIZE_8M, + SF_IMG_SIZE_5M, + SF_IMG_SIZE_3M, + SF_IMG_SIZE_BUTT + } SF_IMG_SIZE_E; + typedef enum sf_VIDEO_SIZE_E + { + SF_VIDEO_SIZE_1080 = 0, + SF_VIDEO_SIZE_720, + SF_VIDEO_SIZE_WVGA, + SF_VIDEO_SIZE_BUTT + } SF_VIDEO_SIZE_E; + typedef enum sfBAT_TYPE_E + { + SF_BAT_AL = 0x00, + SF_BAT_NI = 0x01, + SF_BAT_LI = 0x02, + SF_BAT_CUS_LI = 0x03, + SF_BAT_BUTT, + } BAT_TYPE_E; + typedef enum sf_MESSAGE_TYPE_E + { + CMD_KEY = 0x1A00, + CMD_SD = 0x1B00, + CMD_LED = 0x1C00, + CMD_FILE = 0x1D00, + CMD_POWEROFF = 0x1E00, + CMD_VENC = 0x1F00, + + } SF_MESSAGE_TYPE_E; + + typedef enum sf_MESSAGE_CMD_SD_e + { + CMD_SD_MOUNT_SUCCESS = 0x01, + CMD_SD_ERROR = 0x02, + CMD_SD_OUT = 0x03, + CMD_SD_FULL = 0x04, + CMD_SD_MOUNT_FAILURE = 0x05, + + } SF_MESSAGE_CMD_SD_E; + + typedef enum sf_MESSAGE_CMD_LEDD_e + { + + CMD_LED_EVT = 0x01, + + } SF_MESSAGE_CMD_LED_E; + + typedef enum sf_MESSAGE_CMD_VENC_e + { + + CMD_VENC_START_SUCCESS = 0x01, + CMD_VENC_START_FAILURE = 0x02, + CMD_VENC_STOP_SUCCESS = 0x03, + CMD_VENC_STOP_FAILURE = 0x04, + CMD_VENC_STREAM_START = 0x05, + CMD_VENC_STREAM_STOP = 0x06, + } SF_MESSAGE_CMD_VENC_E; +#ifdef CFG_TRANSDATA_AT + + typedef enum sf_UPLOAD_STATUS_E + { + SF_UPLOAD_FTP = 0x01, + SF_UPLOAD_OSS, + SF_UPLOAD_AMZ, + SF_UPLOAD_BUTT, + } SF_UPLOAD_STATUS_E; +#else +typedef enum sf_UPLOAD_STATUS_E +{ + SF_UPLOAD_FTP = 0x00, + SF_UPLOAD_OSS, + SF_UPLOAD_AMZ, + SF_UPLOAD_BUTT, +} SF_UPLOAD_STATUS_E; +#endif + + typedef enum sf_DATE_TYPE_E + { + DATE_TYPE_YYMMDD = 0, + DATE_TYPE_MMDDYY, + DATE_TYPE_DDMMYY, + DATE_TYPE_BUTT, + } SF_DATE_TYPE_E; + typedef enum sf_SIM_TYPE_E + { + SF_SIM_MEGA = 0, // normal mega sim, use in abroad + SF_SIM_MEGA_IOT, // special mega sim, only use in T110 + SF_SIM_OTHER, // other sim + SF_SIM_BUTT + } SF_SIM_TYPE_E; + +#if __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_struct.h b/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_struct.h new file mode 100644 index 000000000..8397a7848 --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/src_c/include/sf_param_struct.h @@ -0,0 +1,360 @@ +#ifndef __SF_PARAM_STRUCT_H__ +#define __SF_PARAM_STRUCT_H__ +#include +#include "SfTypeDefine.h" +#include "sf_param_enum.h" +#if __cplusplus +extern "C" +{ +#endif + + typedef struct sf_URL_s + { + SF_CHAR url[160]; + } SF_URL_S; + + typedef struct sf_OSS_s + { + UINT8 szIP[64]; + UINT8 szBucket[32]; + UINT8 szUsername[32]; + UINT8 szPassword[48]; + } SF_OSS_S; + + typedef struct sf_THREAD_CFG_S + { + unsigned char IsRun; + unsigned char IsStopFlag; + pthread_t TskId; + } SF_THREAD_CFG_S; + + typedef struct SF_PARA_TIME_S + { + + UINT16 Year; + UINT16 Mon; + UINT16 Day; + + UINT16 Hour; + UINT16 Min; + UINT16 Sec; + } SF_PARA_TIME_S; + + typedef struct SF_WORKTIME_S + { + SF_PARA_TIME_S StartTime; + SF_PARA_TIME_S StopTime; + } SF_WORKTIME_S; + typedef struct sf_subscribe_ATTR_S + { + UINT8 subscribeType; + char subscribeFileName[40]; + } SF_SUBSCRIBE_ATTR_S; + + typedef struct sf_subscribe_file_ATTR_S + { + UINT8 subscribeCnt; + SF_SUBSCRIBE_ATTR_S *pSubscribe; + } SF_SUBSCRIBE_FILE_ATTR_S; + +#ifndef SF_PDT_PARAM_CFG_S + typedef struct sfPDT_PARAM_CFG_S + { + /*camera param*/ + UINT8 WorkMode; + UINT8 CamMode; // Picture, Video, Picture+Video + UINT8 ImgSize; // 8M, 16M, 32M + UINT8 VideoSize; // WVGA, 720P, 1080P + UINT8 VideoLenth; + UINT8 Multishot; // shot picture number 1~5,1 single shot 2~5 continuous shot + UINT8 MultishotInterval; // shot interval. 0: shot in one second; 1: 1 pic per sec; 2: 2 pic per sec + UINT8 NightMode; + UINT8 FlashLed; + UINT8 PirSensitivity; + UINT8 PirDelaySwitch; /*DelayFlag;*/ + UINT8 TimelapseSwitch; + UINT8 WorkTime1Switch; /*WorkTime*/ + UINT8 WorkTime2Switch; /*WorkTime*/ + UINT8 CameraNameFlag; + UINT8 PirSwitch; + UINT8 SdLoop; /*SdCycle*/ + UINT8 DigitPirSensitivity; + + UINT8 DailyReportswitch; + UINT8 ReDailyReport; /*if network error, reboot an hour later,liteOS need this param,not separete*/ + UINT8 FristSendDailyAndGps; + + UINT8 GprsMode; /*0:Daily, 1:Intant*/ + UINT8 GprsSwitch; /*0:gprs off, 1:gprs on*/ + UINT8 SendMaxNum; + UINT8 SendPicSize; // thumbnail 0:640*480, 1:1920*1440 + UINT8 SendType; /*0:send immediately, 1:send once per day, 2:send twice per day*/ + UINT8 SendMultishot; + UINT8 SendVideo; + UINT8 SendPhoto; + + UINT8 BatteryType; + UINT8 StampSwitch; + UINT8 DateStyle; + UINT8 DebugMode; + UINT8 Zoom; // APP preview magnification, 1x,2x,4z + UINT8 LightFreq; // 50HZ, 60H + SINT8 TimeZone; + + UINT8 GpsSwitch; /*0:OFF 1:ON*/ + UINT8 GpsSendType; /*0:when camera trun on 1: one time 2:twice time*/ + UINT8 DateAuto; + UINT8 PicUponDailyReport; + UINT8 FtpSwitch; + UINT8 VideoFrame; + UINT8 ParaSync; + UINT16 RTCYear; + UINT8 RtcMonth; + UINT8 RTCDay; + UINT8 RTCHour; + UINT8 RTCMinute; + UINT8 RTCSecond; + UINT8 FirstUpdateFlag; /*1: indicate first update start*/ + UINT8 FormateFlag; + UINT8 Formatestatus; + UINT8 ResetFlag; + UINT8 GPSFlag; + UINT8 BatchSendTimelapse; + UINT8 GPSEnterResetModeFlag; + UINT8 GPSWaitRestartFlag; + UINT8 GPSMapeUpdateFlag; + UINT8 GPSAntitheftFlag; + UINT8 Lastsetuptype; + UINT8 OtaFlag; + SF_PARA_TIME_S TimelapseTime; + SF_WORKTIME_S WorkTime[SF_TIMER_MAX_NUMBER]; + SF_PARA_TIME_S PirDelayTime; + SF_PARA_TIME_S DailyReportTime; + SF_PARA_TIME_S TimeSend1; /*batch send1 time*/ + + char CameraNameStr[SF_CAMERA_NAME_MAX_LEN]; + UINT32 CheckSum; + } SF_PDT_PARAM_CFG_S; +#endif + typedef struct sfPDT_PARAM_STATISTICS_S + { + /*DailyReport Part*/ + UINT8 DailyReportNum; /*0:OFF, 1:one time per day, 2:two Times per day*/ + UINT16 DialyReportFailCnt; + UINT16 Year; + UINT16 Mon; + UINT16 Day; + + UINT16 TriggerTimes; + UINT8 SubscribeSendCnt; + UINT8 SubVideoSendCnt; + UINT8 SendBatchAgain; /*copy from 3.8CG needReConcentratedSend*/ + UINT8 DailyReportAgain; /* copy from 3.8CG ReDailyFlag:if network error, reboot an hour later*/ + UINT16 SendPicDayCnt; /*copy from 3.8CG picSendMax, send success pic number per day*/ + UINT16 SendDailyCnt; /*send pic count success+fail*/ + UINT16 SendDailyThumbCnt; /* send small pic times, success + fail*/ + UINT16 SendSuccessThumbCnt; /* send small pic times, success*/ + UINT16 SendDailyOriginalCnt; + UINT16 SendSuccessOriginalCnt; + UINT16 SendDailyVideoCnt; /* send video times, success + fail*/ + UINT16 SendSuccessVideoCnt; /* send video times,success*/ + UINT32 SendThumbTotalTime; /* send small pic time, uint:second*/ + UINT32 SendOriginalTotalTime; + UINT32 SendVideoTotalTime; /* send video time, uint:second*/ + + UINT32 OldFileKey; + UINT16 SdTotalFile; + UINT16 SendDailyFailCnt; + UINT16 SendDailyTimeoutCnt; + UINT16 SynParamFlag; + UINT16 SynMcuSet; /* 1: set sync 0: not set (void)*/ + UINT8 InstantFtpRecfg; /*1: must cfg ftps , 0 : do not cfg ftps*/ + UINT8 GpsPowerONSendFlag; /*1: send gps txt when first time to on 0: send gps txt base gps num setting*/ + UINT8 LoginACMFailedCnt; + UINT8 u8GetPicFlag; + UINT8 u8ResetLimited; + UINT8 bindFlag; + UINT8 GPSInfoGetFailed; + UINT8 SimType; + + /*SIM Card Info*/ + char OperatorCode[SF_OPERATOR_CODE_MAX_LEN]; + // char Carrier[64]; + char ApnGPRS[SF_APN_MAX_LEN]; + char ApnUsername[SF_APN_MAX_LEN]; + char ApnPassword[SF_APN_PASSWORD_MAX_LEN]; + char ServiceProvider[64]; + + char MMSC[SF_APN_MAX_LEN]; + char MMSAPN[SF_APN_MAX_LEN]; + char Proxy[SF_APN_MAX_LEN]; + char Port[SF_APN_MAX_LEN]; + char UserName[SF_APN_MAX_LEN]; + char Password[SF_APN_MAX_LEN]; + /*ftp info*/ + char WebIP[SF_FTP_MAX_LEN]; + char AcmIP[64]; + + /*SIM Card Info*/ + char IMEI[SF_IMEI_MAX_LEN]; + char SimID[SF_ICCID_MAX_LEN]; + char ModuleVersion[SF_MODULE_VER_MAX_LEN]; + char ModuleSubversion[SF_MODULE_VER_MAX_LEN]; + /*GPS INFO*/ + UINT16 GpsSendFlag; + UINT16 GpsSendYear; + UINT16 GspSendMon; + UINT16 GpsSendDay; + SINT32 Did; + SINT32 AlivePort; + UINT8 UploadMode; + char GpsInfo[SF_GPS_INFO_MAX_LEN]; + char Latitude[SF_GPS_INFO_MAX_LEN]; + char Longitude[SF_GPS_INFO_MAX_LEN]; + char BindAccount[SF_BIND_ACCOUNT_MAX_LEN]; + + char Token[SF_TOKEN_MAX_LEN]; + char AliveIp[SF_ALIVE_IP_MAX_LEN]; + char Uuid[SF_UUID_MAX_LEN]; + /*Low Power Alarm */ + UINT16 LowPowerAlarmFlag; /*0: no alarm upload, 1: alarm already upload.*/ + char PicPlan; + UINT8 startup; + UINT8 FcTemper; + UINT8 BatRemainCap; + UINT8 OtaUpgradeFlag; + + UINT8 netGeneration; + UINT8 SimSignal; + SF_SUBSCRIBE_FILE_ATTR_S stSubscribe; + SF_OSS_S stOssCfg; + SF_PARA_TIME_S httpTime; + + UINT32 CheckSum; + char p2pId[P2P_BUF_LEN]; + char p2pName[P2P_BUF_LEN]; + char p2pSecret[P2P_BUF_LEN]; + char MQTTIp[SF_ALIVE_IP_MAX_LEN]; + SINT32 MQTTPort; + } SF_PDT_PARAM_STATISTICS_S; + + typedef struct sf_FILE_ATTR_S + { + + SF_FILE_TYPE_E enFileTye; + SF_CHAR thumbfileName[SF_MAX_PIC_LEN]; + SF_CHAR thumbfilePath[SF_MAX_PATH_LEN]; + SF_CHAR txtfilePath[SF_MAX_PATH_LEN]; + SF_CHAR txtfileName[SF_MAX_PIC_LEN]; + UINT32 thumbfileSize; + + } SF_FILE_ATTR_S; + + typedef struct sf_SEND_FILE_ATTR_S + { + + SF_FILE_TYPE_E enFileTye; // upload sub hd or video file type; upload batch send thumb file type; + SF_CHAR SubFileName[SF_MAX_PIC_LEN]; // sub hd or video file name, use as bind file; when batch send thumb file, this is null. + SF_CHAR SendFileName[SF_MAX_PIC_LEN]; // upload sub hd or video file name; upload batch send thumb file name; + UINT32 SendFileSize; // upload sub hd or video file size; upload batch send thumb file size; + UINT32 SendRet; // 0:send success; other:error code + UINT8 SameFlag; + + } SF_SEND_FILE_ATTR_S; + + typedef struct sf_SRCFILE_ATTR_S + { + UINT8 filecnt; + SF_FILE_ATTR_S stfileattr[SF_SRCFILE_MAX]; + } SF_SRCFILE_ATTR_S; + typedef struct sf_REPORT_FILE_ATTR_S + { + UINT8 filecnt; + SF_SEND_FILE_ATTR_S stSendFileAttr[100]; + } SF_REPORT_FILE_ATTR_S; + + typedef struct sf_MESSAGE_Buf_S + { + long mtype; + SINT32 cmdId; + SINT32 s32Wait; + SINT32 arg1; + SINT32 arg2; + SINT32 arg3; + } SF_MESSAGE_BUF_S; + typedef struct sf_RtosInfo_t + { + unsigned int test1; + unsigned int test2; + unsigned int test3; + unsigned int IsNight; + unsigned int BatPer; + unsigned int Fctemp; + unsigned short McuVer; + unsigned char McuSubVer; + unsigned int rtosBootTime; + } SF_RTOSINFO_S; + typedef struct SF_RTOS_CMD_s + { + unsigned char cmd; + unsigned char arg[8]; + unsigned char info[256]; + } SF_RTOS_CMD_T; + +#if defined(CFG_TRANSDATA_AT) + typedef struct sf_DATA_ATTR_S + { + UINT8 databuf[SF_TTYUSB_RECV_MAX]; + UINT32 dataSize; + } SF_DATA_ATTR_S; +#else +typedef struct sf_DATA_ATTR_S +{ + UINT8 databuf[SF_HTTP_RECV_MAX]; + UINT32 dataSize; +} SF_DATA_ATTR_S; +#endif + typedef struct + { + int devResetCommand; // + int hdCommand; // + int offset; // + int otaCommand; // + int resetUrlCommand; // + int sdFormatCommand; // + int synConfigCommand; // + int logCommand; // + int leftOverPic; + int getPic; + int RegionalChange; + char date[32]; // + char downloadUrl[160]; // + char ip[24]; // + char name[32]; // + char passwd[48]; // + char port[32]; // + char serverIp[24]; // + char url[64]; // + char userEmail[16]; // + char uuid[13]; // + char p2pId[32]; + char p2pName[64]; + char p2pSecret[64]; + } LOGIN_ACM_RESPONSE_S; + + typedef SF_BOOL (*sf_at_exit_callback_fn_ptr)(SF_VOID *param); + typedef SINT32 (*sf_Cross_callback_fn_ptr)(SF_VOID *param); + + typedef struct sf_FN_PARAM_s + { + sf_at_exit_callback_fn_ptr pfn_AT_instruction_exit; + SF_VOID *pstParam; + SF_VOID *pstaticParam; + SF_CHAR arrttyData[SF_TTYUSB_RECV_MAX]; + } SF_FN_PARAM_S; + +#if __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/component/Config/src/src_c/src/sf_param_common.c b/code/application/sifarsdk/component/Config/src/src_c/src/sf_param_common.c new file mode 100644 index 000000000..b582ba61e --- /dev/null +++ b/code/application/sifarsdk/component/Config/src/src_c/src/sf_param_common.c @@ -0,0 +1,571 @@ +// #include +// #include +// #include +// #include +// #include +// #include +#include +// #include +#include + +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// #include +// #include +// #include +// #include + +#include "Log.h" +// #include "sf_message_queue.h" +#include "sf_param_common.h" +// #include "sf_storeMng.h" + +UINT8 isCapRunning = 0; +static SF_STARTUP_TYPE_E StartMode = SF_MCU_STARTUP_ONKEY; + +SF_URL_S sfStOtaUrl = {0}; + +SF_PDT_PARAM_CFG_S StCustomerParam = {0}; +SF_PDT_PARAM_STATISTICS_S Ststatistics = {0}; + +char *PARAM_FILE_PATH = SIFAR_CUSTOMER_PARAM_PATH; +char *PARAM_STSTATISTICS_FILE_PATH = SIFAR_STATISTICS_PARAM_PATH; + +void sf_sleep_ms(S32 millisecond) +{ + usleep(millisecond * 1000); +} + +void sf_sleep_s(S32 second) +{ + sleep(second); +} +const SF_CHAR *sf_poweron_type_string(SF_STARTUP_TYPE_E enType) +{ + switch (enType) + { + case SF_MCU_STARTUP_OFF: + return "SF_MCU_STARTUP_OFF"; + case SF_MCU_STARTUP_ONKEY: + return "SF_MCU_STARTUP_ONKEY"; + case SF_MCU_STARTUP_TIMELAPSE: + return "SF_MCU_STARTUP_TIMELAPSE"; + case SF_MCU_STARTUP_NORMAL: + return "SF_MCU_STARTUP_NORMAL"; + case SF_MCU_STARTUP_RING: + return "SF_MCU_STARTUP_RING"; + case SF_MCU_STARTUP_PIR: + return "SF_MCU_STARTUP_PIR"; + case SF_MCU_STARTUP_WARNING: + return "SF_MCU_STARTUP_WARNING"; + case SF_MCU_STARTUP_SERVER: + return "SF_MCU_STARTUP_SERVER"; + case SF_MCU_STARTUP_DP: + return "SF_MCU_STARTUP_DP"; + case SF_MCU_STARTUP_USB: + return "SF_MCU_STARTUP_USB"; + case SF_MCU_STARTUP_RESET: + return "SF_MCU_STARTUP_RESET"; + case SF_MCU_STARTUP_SYN_PARAM: + return "SF_MCU_STARTUP_SYN_PARAM"; + case SF_MCU_STARTUP_BATCH_SEND: + return "SF_MCU_STARTUP_BATCH_SEND"; + default: + return "unknown poweron type!!!"; + } +} + +SF_STARTUP_TYPE_E sf_poweron_type_get() +{ + return StartMode; +} + +SINT32 sf_poweron_type_set(SF_STARTUP_TYPE_E enType) +{ + + StartMode = enType; + + LogInfo("poweron type :[%d,%s]\n", StartMode, sf_poweron_type_string(StartMode)); + return SF_SUCCESS; +} + +SF_URL_S *sf_ota_url_get(void) +{ + return &sfStOtaUrl; +} + +void sf_customer_param_init(const char *ParamFilePath) +{ + if (ParamFilePath != SF_NULL) + { + PARAM_FILE_PATH = ParamFilePath; + } + memset(&StCustomerParam, 0, sizeof(SF_PDT_PARAM_CFG_S)); +} + +SF_PDT_PARAM_CFG_S *sf_customer_param_get() +{ + return &StCustomerParam; +} +void sf_customer_param_set(SF_PDT_PARAM_CFG_S *pSfCustomerPara) +{ + memcpy(&StCustomerParam, pSfCustomerPara, sizeof(SF_PDT_PARAM_CFG_S)); +} + +void sf_customer_param_reset(SF_PDT_PARAM_CFG_S *psfpdtparam, UINT8 sysRet) +{ + + /*sms setting param*/ + psfpdtparam->CamMode = SF_CAMMODE_PIC; /*0:pic, 1:pic+video*/ + psfpdtparam->ImgSize = SF_IMG_SIZE_5M; /*0:5M, 1:3M*/ + +#ifdef SF_HARDWARE_TEST + psfpdtparam->CamMode = SF_CAMMODE_PV; + psfpdtparam->VideoSize = SF_VIDEO_SIZE_1080; +#else + psfpdtparam->VideoSize = SF_VIDEO_SIZE_720; /*0:1080P, 1:720P, 2:480P*/ +#endif + if (psfpdtparam->VideoSize == SF_VIDEO_SIZE_720) + psfpdtparam->VideoLenth = 20; + else if (psfpdtparam->VideoSize == SF_VIDEO_SIZE_WVGA) + psfpdtparam->VideoLenth = 30; + else + psfpdtparam->VideoLenth = 10; + + psfpdtparam->Multishot = 1; /*1-3*/ + psfpdtparam->MultishotInterval = 1; + psfpdtparam->Zoom = 0; + + psfpdtparam->NightMode = 2; /*0:max, 1:middle, 2:min*/ + psfpdtparam->FlashLed = 0; /*0:all/high, 1:part/low*/ + + psfpdtparam->PirDelaySwitch = 0; /*0:OFF, 1:ON*/ + + psfpdtparam->WorkTime1Switch = 0; + psfpdtparam->WorkTime2Switch = 0; + + psfpdtparam->PirDelayTime.Hour = 0; + psfpdtparam->PirDelayTime.Min = 0; + psfpdtparam->PirDelayTime.Sec = 0; +#ifdef SF_HARDWARE_TEST + psfpdtparam->TimelapseSwitch = 1; /*0:all, 1:part*/ + psfpdtparam->TimelapseTime.Hour = 0; + psfpdtparam->TimelapseTime.Min = 2; + psfpdtparam->TimelapseTime.Sec = 0; +#else + psfpdtparam->TimelapseSwitch = 0; /*0:all, 1:part*/ + psfpdtparam->TimelapseTime.Hour = 0; + psfpdtparam->TimelapseTime.Min = 0; + psfpdtparam->TimelapseTime.Sec = 0; +#endif + psfpdtparam->WorkTime[0].StartTime.Hour = 0; + psfpdtparam->WorkTime[0].StartTime.Min = 0; + psfpdtparam->WorkTime[0].StartTime.Sec = 0; + + psfpdtparam->WorkTime[0].StopTime.Hour = 0; + psfpdtparam->WorkTime[0].StopTime.Min = 0; + psfpdtparam->WorkTime[0].StopTime.Sec = 0; + + psfpdtparam->WorkTime[1].StartTime.Hour = 0; + psfpdtparam->WorkTime[1].StartTime.Min = 0; + psfpdtparam->WorkTime[1].StartTime.Sec = 0; + + psfpdtparam->WorkTime[1].StopTime.Hour = 0; + psfpdtparam->WorkTime[1].StopTime.Min = 0; + psfpdtparam->WorkTime[1].StopTime.Sec = 0; +#ifdef SF_HARDWARE_TEST + psfpdtparam->PirSwitch = 0; +#else + psfpdtparam->PirSwitch = 1; +#endif + psfpdtparam->SdLoop = 1; /*0:OFF, 1:ON*/ + psfpdtparam->DigitPirSensitivity = 9; /* not use*/ + psfpdtparam->PirSensitivity = 0; /*0:high, 1:middle, 2:low*/ + + psfpdtparam->DailyReportswitch = 1; + psfpdtparam->ReDailyReport = 0; + psfpdtparam->FristSendDailyAndGps = 1; + + psfpdtparam->DailyReportTime.Hour = 24; + psfpdtparam->DailyReportTime.Min = 0; + psfpdtparam->GprsSwitch = 1; + psfpdtparam->GprsMode = 9; + psfpdtparam->SendMaxNum = 0; + psfpdtparam->BatteryType = SF_BAT_AL; + psfpdtparam->StampSwitch = 1; + psfpdtparam->DateStyle = DATE_TYPE_MMDDYY; + psfpdtparam->DebugMode = 0; + psfpdtparam->VideoFrame = 0; + psfpdtparam->ParaSync = 1; + psfpdtparam->GPSFlag = 1; + if (!sysRet) + { + psfpdtparam->RTCYear = 2022; + psfpdtparam->RtcMonth = 1; + psfpdtparam->RTCDay = 1; + psfpdtparam->RTCHour = 8; + psfpdtparam->RTCMinute = 0; + psfpdtparam->RTCSecond = 0; + } + + psfpdtparam->SendMultishot = 0; + psfpdtparam->FirstUpdateFlag = 1; /*1: indicate first update start*/ + + psfpdtparam->CheckSum = 0; +} + +SINT32 sf_customer_param_save(SF_PDT_PARAM_CFG_S *pSfCustomerPara) +{ + // SF_COMM_CHECK_POINTER(pSfCustomerPara, SF_FAILURE); + if (!pSfCustomerPara) + { + LogError("nullptr.\n"); + return SF_FAILURE; + } + SINT32 i = 0; + SINT32 ret = 0; + SINT32 fd = 0; + UINT32 CheckSum = 0; + UINT32 lenth = 0; + + lenth = sizeof(SF_PDT_PARAM_CFG_S); + + fd = open(PARAM_FILE_PATH, O_CREAT | O_RDWR, 0); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd, PARAM_FILE_PATH, SF_FAILURE); + for (i = 0; i < (lenth - 4); i++) + CheckSum += *((UINT8 *)pSfCustomerPara + i); + pSfCustomerPara->CheckSum = CheckSum; + + ret = write(fd, pSfCustomerPara, lenth); + if (ret != lenth) + LogError("save param failed!!!\n"); + fsync(fd); + close(fd); + + return SF_SUCCESS; +} + +SINT32 sf_customer_param_load(SF_PDT_PARAM_CFG_S *pSfCustomerPara) +{ + // SF_COMM_CHECK_POINTER(pSfCustomerPara, SF_FAILURE); + if (!pSfCustomerPara) + { + LogError("nullptr.\n"); + return SF_FAILURE; + } + SINT32 ret = SF_SUCCESS; + SINT32 fd = 0; + UINT16 i = 0; + UINT32 CheckSum = 0; + UINT32 lenth = 0; + + lenth = sizeof(SF_PDT_PARAM_CFG_S); + LogInfo("Open file %s.\n", PARAM_FILE_PATH); + if (access((char *)PARAM_FILE_PATH, F_OK) == 0) + { + fd = open(PARAM_FILE_PATH, O_RDWR); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd, PARAM_FILE_PATH, SF_FAILURE); + read(fd, pSfCustomerPara, lenth); + + for (i = 0; i < (lenth - 4); i++) + CheckSum += *((UINT8 *)pSfCustomerPara + i); + + if (CheckSum != pSfCustomerPara->CheckSum) + { + sf_customer_param_reset(pSfCustomerPara, 0); + for (i = 0; i < (lenth - 4); i++) + CheckSum += *((UINT8 *)pSfCustomerPara + i); + pSfCustomerPara->CheckSum = CheckSum; + + ret = write(fd, pSfCustomerPara, lenth); + if (ret != lenth) + LogError("save param failed!!!\n"); + fsync(fd); + } + close(fd); + } + else + { + fd = open(PARAM_FILE_PATH, O_CREAT | O_RDWR, 0); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd, PARAM_FILE_PATH, SF_FAILURE); + sf_customer_param_reset(pSfCustomerPara, 0); + for (i = 0; i < (lenth - 4); i++) + CheckSum += *((UINT8 *)pSfCustomerPara + i); + pSfCustomerPara->CheckSum = CheckSum; + + ret = write(fd, pSfCustomerPara, lenth); + if (ret != lenth) + LogError("save param failed!!!\n"); + fsync(fd); + close(fd); + } + + return ret; +} + +void sf_statistics_param_init(const char *filePath) +{ + if (filePath != SF_NULL) + { + PARAM_STSTATISTICS_FILE_PATH = filePath; + } + memset(&Ststatistics, 0, sizeof(SF_PDT_PARAM_STATISTICS_S)); +} + +SF_PDT_PARAM_STATISTICS_S *sf_statistics_param_get() +{ + return &Ststatistics; +} +void sf_statistics_param_reset(SF_PDT_PARAM_STATISTICS_S *pSfPara) +{ + LogWarning("statistics param all reset!!!\n"); + pSfPara->DailyReportNum = 0; + pSfPara->DialyReportFailCnt = 0; + pSfPara->Year = 0; + pSfPara->Mon = 0; + pSfPara->Day = 0; + pSfPara->TriggerTimes = 0; + pSfPara->SubscribeSendCnt = 0; + pSfPara->SubVideoSendCnt = 0; + pSfPara->SendBatchAgain = 0; + pSfPara->DailyReportAgain = 0; + pSfPara->SendDailyCnt = 0; + pSfPara->SendPicDayCnt = 0; + pSfPara->SendDailyThumbCnt = 0; + pSfPara->SendSuccessThumbCnt = 0; + pSfPara->SendDailyOriginalCnt = 0; + pSfPara->SendSuccessOriginalCnt = 0; + pSfPara->SendDailyVideoCnt = 0; + pSfPara->SendSuccessVideoCnt = 0; + pSfPara->SendThumbTotalTime = 0; + pSfPara->SendOriginalTotalTime = 0; + pSfPara->SendVideoTotalTime = 0; + pSfPara->OldFileKey = 0; + pSfPara->SdTotalFile = 0; + pSfPara->SendDailyFailCnt = 0; + pSfPara->SendDailyTimeoutCnt = 0; + pSfPara->SynParamFlag = 0; + pSfPara->SynMcuSet = 0; + pSfPara->InstantFtpRecfg = 0; + pSfPara->GpsPowerONSendFlag = 0; + pSfPara->GpsSendFlag = 0; + pSfPara->GpsSendYear = 0; + pSfPara->GpsSendDay = 0; + pSfPara->GspSendMon = 0; + pSfPara->LowPowerAlarmFlag = 0; + pSfPara->LoginACMFailedCnt = 0; + pSfPara->bindFlag = 0; + +#ifdef SF_VERSION_RELEASE + sprintf(pSfPara->WebIP, "%s", "a-cen.wuyuantech.com"); +#else + sprintf(pSfPara->WebIP, "%s", "acenter.wuyuantech.com"); +#endif + + memset(pSfPara->AcmIP, '\0', sizeof(pSfPara->AcmIP)); + memset(pSfPara->IMEI, '\0', sizeof(pSfPara->IMEI)); + memset(pSfPara->OperatorCode, '\0', sizeof(pSfPara->OperatorCode)); + memset(pSfPara->ApnGPRS, '\0', sizeof(pSfPara->ApnGPRS)); + memset(pSfPara->ApnUsername, '\0', sizeof(pSfPara->ApnUsername)); + memset(pSfPara->ApnPassword, '\0', sizeof(pSfPara->ApnPassword)); + memset(pSfPara->SimID, '\0', sizeof(pSfPara->SimID)); + memset(pSfPara->ModuleVersion, '\0', sizeof(pSfPara->ModuleVersion)); + memset(pSfPara->ModuleSubversion, '\0', sizeof(pSfPara->ModuleSubversion)); + memset(pSfPara->GpsInfo, '\0', sizeof(pSfPara->GpsInfo)); + memset(pSfPara->Latitude, '\0', sizeof(pSfPara->Latitude)); + memset(pSfPara->Longitude, '\0', sizeof(pSfPara->Longitude)); + memset(pSfPara->BindAccount, '\0', sizeof(pSfPara->BindAccount)); + memset(pSfPara->p2pId, '\0', sizeof(pSfPara->p2pId)); + memset(pSfPara->p2pName, '\0', sizeof(pSfPara->p2pName)); + memset(pSfPara->p2pSecret, '\0', sizeof(pSfPara->p2pSecret)); + sprintf(pSfPara->MQTTIp, "%s", "public.iot-as-mqtt.cn-shanghai.aliyuncs.com"); + pSfPara->MQTTPort = 1883; +} +void sf_statistics_param_specify(SF_PDT_PARAM_STATISTICS_S *pStatisticsParam) +{ +#ifdef SF_VERSION_RELEASE + sprintf(pStatisticsParam->WebIP, "%s", "a-cen.wuyuantech.com"); +#else + sprintf(pStatisticsParam->WebIP, "%s", "acenter.wuyuantech.com"); + +#endif +} + +SINT32 sf_statistics_param_save(SF_PDT_PARAM_STATISTICS_S *pStatisticsParam) +{ + // SF_COMM_CHECK_POINTER(pStatisticsParam, SF_FAILURE); + if (!pStatisticsParam) + { + LogError("nullptr.\n"); + return SF_FAILURE; + } + + SINT32 i = 0; + SINT32 fd = 0; + SINT32 ret = 0; + UINT32 CheckSum = 0; + UINT32 lenth = 0; + + lenth = sizeof(SF_PDT_PARAM_STATISTICS_S); + + fd = open(PARAM_STSTATISTICS_FILE_PATH, O_CREAT | O_RDWR, 0); + if (fd < 0) + { + // LogError("errno = [%d,%s]\n",errno,strerror(errno)); + // SF_MESSAGE_BUF_S stMessageBuf = {0}; // TODO: + // stMessageBuf.cmdId = 0x0113; + // stMessageBuf.arg1 = 0; + // sf_com_message_send_to_cardv(&stMessageBuf); + // usleep(500000); + fd = open(PARAM_STSTATISTICS_FILE_PATH, O_CREAT | O_RDWR, 0); /*open jpg file*/ + if (fd < 0) + { + LogError("errno = [%d,%s]\n", errno, strerror(errno)); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd, PARAM_STSTATISTICS_FILE_PATH, SF_FAILURE); + } + } + + for (i = 0; i < (lenth - 4); i++) + CheckSum += *((UINT8 *)pStatisticsParam + i); + pStatisticsParam->CheckSum = CheckSum; + + ret = write(fd, pStatisticsParam, lenth); + if (ret != lenth) + LogError("save param failed!!!\n"); + fsync(fd); + close(fd); + + return SF_SUCCESS; +} + +SINT32 sf_statistics_param_load(SF_PDT_PARAM_STATISTICS_S *pStatisticsParam) +{ + // SF_COMM_CHECK_POINTER(pStatisticsParam, SF_FAILURE); + if (!pStatisticsParam) + { + LogError("nullptr.\n"); + return SF_FAILURE; + } + SINT32 i = 0; + SINT32 fd = 0; + UINT32 CheckSum = 0; + UINT32 lenth = 0; + SINT32 ret = SF_SUCCESS; + SF_PDT_PARAM_CFG_S *pSfCustomerPara = sf_customer_param_get(); + + lenth = sizeof(SF_PDT_PARAM_STATISTICS_S); + memset(pStatisticsParam, 0, lenth); + if (pSfCustomerPara->FirstUpdateFlag == SF_TRUE) + { + + sf_statistics_param_reset(pStatisticsParam); + sf_statistics_param_save(pStatisticsParam); + pSfCustomerPara->FirstUpdateFlag = SF_FALSE; + LogInfo("FirstUpdateFlag = [%d],First start!!!,reset all param \n", pSfCustomerPara->FirstUpdateFlag); + return SF_SUCCESS; + } + if (access((char *)PARAM_STSTATISTICS_FILE_PATH, F_OK) == 0) + { + fd = open(PARAM_STSTATISTICS_FILE_PATH, O_RDWR); + if (fd < 0) + { + + // SF_MESSAGE_BUF_S stMessageBuf = {0};// TODO: + // stMessageBuf.cmdId = 0x0113; + // stMessageBuf.arg1 = 0; + // sf_com_message_send_to_cardv(&stMessageBuf); + // usleep(500000); + fd = open(PARAM_STSTATISTICS_FILE_PATH, O_RDWR); /*open jpg file*/ + if (fd < 0) + { + // char buf[1024] = {0}; + // snprintf(buf, 1024, "%s", strerror(errno)); + // printf("errno = [%d,%s]\n", errno, buf); + // LogError("errno = [%d,%s]\n", errno, strerror(errno)); // TODO: SEGV on unknown address + LogError("errno = [%d]\n", errno); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd, PARAM_STSTATISTICS_FILE_PATH, SF_FAILURE); + } + } + + read(fd, pStatisticsParam, lenth); + + for (i = 0; i < (lenth - 4); i++) + CheckSum += *((UINT8 *)pStatisticsParam + i); + + if (CheckSum != pStatisticsParam->CheckSum) + { + sf_statistics_param_reset(pStatisticsParam); + for (i = 0; i < (lenth - 4); i++) + CheckSum += *((UINT8 *)pStatisticsParam + i); + pStatisticsParam->CheckSum = CheckSum; + + ret = write(fd, pStatisticsParam, lenth); + if (ret != lenth) + LogError("save param failed!!!\n"); + fsync(fd); + } + close(fd); + } + else + { + fd = open(PARAM_STSTATISTICS_FILE_PATH, O_CREAT | O_RDWR, 0); + if (fd < 0) + { + // SF_MESSAGE_BUF_S stMessageBuf = {0}; // TODO: + // stMessageBuf.cmdId = 0x0113; + // stMessageBuf.arg1 = 0; + // sf_com_message_send_to_cardv(&stMessageBuf); + // usleep(500000); + fd = open(PARAM_STSTATISTICS_FILE_PATH, O_CREAT | O_RDWR, 0); /*open jpg file*/ + if (fd < 0) + { + // LogError("errno = [%d,%s]\n", errno, strerror(errno)); + LogError("errno = [%d]\n", errno); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd, PARAM_STSTATISTICS_FILE_PATH, SF_FAILURE); + } + } + + sf_statistics_param_reset(pStatisticsParam); + for (i = 0; i < (lenth - 4); i++) + CheckSum += *((UINT8 *)pStatisticsParam + i); + pStatisticsParam->CheckSum = CheckSum; + + ret = write(fd, pStatisticsParam, lenth); + if (ret != lenth) + LogError("save param failed!!!\n"); + fsync(fd); + close(fd); + } + + LogInfo("SendPicDayCnt::%d\n", pStatisticsParam->SendPicDayCnt); + if (strlen(pStatisticsParam->WebIP) < 1) + sf_statistics_param_specify(pStatisticsParam); + + return SF_SUCCESS; +} +void sf_all_param_reset() +{ + sf_customer_param_reset(sf_customer_param_get(), 0); + sf_statistics_param_reset(sf_statistics_param_get()); + sf_customer_param_save(sf_customer_param_get()); + sf_statistics_param_save(sf_statistics_param_get()); + LogInfo("param reset successful !!!\n"); +} +void sf_cap_status_set(UINT8 capStatus) +{ + if ((capStatus == 0) || (capStatus == 1) || (capStatus == 2)) + isCapRunning = capStatus; + LogInfo("isCapRunning:%d\n", isCapRunning); +} + +UINT8 sf_cap_status_get() +{ + return isCapRunning; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/DualCoreManager/CMakeLists.txt b/code/application/sifarsdk/component/DualCoreManager/CMakeLists.txt new file mode 100644 index 000000000..ceeee9d7a --- /dev/null +++ b/code/application/sifarsdk/component/DualCoreManager/CMakeLists.txt @@ -0,0 +1,27 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/SystemTime/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME DualCoreManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} SystemTime ReturnCode Log) \ No newline at end of file diff --git a/code/application/sifarsdk/component/DualCoreManager/README.md b/code/application/sifarsdk/component/DualCoreManager/README.md new file mode 100644 index 000000000..d11a4fa2c --- /dev/null +++ b/code/application/sifarsdk/component/DualCoreManager/README.md @@ -0,0 +1,24 @@ +# 双核模式 + +## 概述 +   基于双核体系芯片设计的模块,用于和小核进行数据通讯。 + +## 共用的数据结构 +   相机应用和小核使用共用的数据结构进行数据通讯: +``` +typedef struct sf_RtosInfo_t +{ + unsigned int test1; + unsigned int test2; + unsigned int test3; + unsigned int IsNight; + unsigned int BatPer; + unsigned int LiveBatPer; + unsigned int recorddone; + unsigned int Fctemp; + unsigned short McuVer; + unsigned char McuSubVer; + unsigned int rtosBootTime; +} SF_RTOSINFO_S; +``` +该数据结构必须保持小核,相机应用,cardv一致。 \ No newline at end of file diff --git a/code/application/sifarsdk/component/DualCoreManager/include/IDualCoreManager.h b/code/application/sifarsdk/component/DualCoreManager/include/IDualCoreManager.h new file mode 100644 index 000000000..2adac8615 --- /dev/null +++ b/code/application/sifarsdk/component/DualCoreManager/include/IDualCoreManager.h @@ -0,0 +1,59 @@ +#ifndef I_DUAL_CORE_MANAGER_H +#define I_DUAL_CORE_MANAGER_H +#include "VReturnCode.h" +#include +#include +enum class BatteryLevel +{ + NO_POWER = 0, + LEVEL_0, + LEVEL_1, + LEVEL_2, + LEVEL_3, + LEVEL_4, + END +}; +class VBatteryMonitor +{ +public: + VBatteryMonitor() = default; + virtual ~VBatteryMonitor() = default; + virtual void BatteryChanged(const BatteryLevel &level) {} + virtual void LiveBatteryGoesToZero(void) {} +}; +class BatteryInfo +{ +public: + BatteryInfo(const BatteryLevel &level, const unsigned int &batteryPercent) + : mLevel(level), mBatteryPercent(batteryPercent) + { + } + ~BatteryInfo() = default; + const BatteryLevel mLevel; + const unsigned int mBatteryPercent; +}; +class IDualCoreManager +{ +public: + IDualCoreManager() = default; + virtual ~IDualCoreManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual unsigned int GetStartupMode(void) { return -1; } + virtual RETURN_CODE SetMcuTime(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetEnvironmentData(const unsigned char &isNight, const unsigned short &lightVal) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual const signed int IsNight(void) { return false; } + virtual unsigned char GetFcTemper(void) { return 0; } + virtual unsigned char GetBatRemainCap(void) { return 0; } + virtual unsigned short GetMcuVersion(void) { return 0; } + virtual unsigned char GetSubMcuVersion(void) { return 0; } + virtual RETURN_CODE SetBatteryMonitor(const std::shared_ptr &monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual const BatteryInfo GetBetteryData(void) + { + BatteryInfo info(BatteryLevel::END, 0); + return info; + } +}; +bool CreateDualManager(void); +#endif // !I_DUAL_CORE_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManager.cpp b/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManager.cpp new file mode 100644 index 000000000..da7c20111 --- /dev/null +++ b/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManager.cpp @@ -0,0 +1,176 @@ +#include "DualCoreManager.h" +#include "ISystemTime.h" +#include "Log.h" +DualCoreManager::DualCoreManager() +{ + mLCPU = std::make_shared(); + mBatteryCheck = false; + mBatteryPercent = 0; + mBatteryLevelConvert[SF_BATT_LEVEL_0] = BatteryLevel::LEVEL_0; + mBatteryLevelConvert[SF_BATT_LEVEL_1] = BatteryLevel::LEVEL_1; + mBatteryLevelConvert[SF_BATT_LEVEL_2] = BatteryLevel::LEVEL_2; + mBatteryLevelConvert[SF_BATT_LEVEL_3] = BatteryLevel::LEVEL_3; + mBatteryLevelConvert[SF_BATT_LEVEL_4] = BatteryLevel::LEVEL_4; +} +RETURN_CODE DualCoreManager::Init(void) +{ + IHal::GetInstance()->GetLightWeightCPU(mLCPU); + mLCPU->Read((char *)&mMcuInfo, sizeof(SF_RTOSINFO_S)); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE DualCoreManager::UnInit(void) +{ + mLCPU = std::make_shared(); + mBatteryCheck = false; + if (mThread.joinable()) + { + mThread.join(); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +unsigned int DualCoreManager::GetStartupMode(void) +{ + SF_RTOSINFO_S info = {0}; + mLCPU->Read((char *)&info, sizeof(SF_RTOSINFO_S)); + return info.test2; +} +RETURN_CODE DualCoreManager::SetMcuTime(void) +{ + SF_RTOS_CMD_T rtos_cmd; + SystemTime date = GetSystemTime(); + rtos_cmd.cmd = LINUX2RTK_CMD_SET_RTCTIME; + rtos_cmd.arg[0] = date.Year - 2000; + rtos_cmd.arg[1] = date.Mon; + rtos_cmd.arg[2] = date.Day; + rtos_cmd.arg[3] = date.Hour; + rtos_cmd.arg[4] = date.Min; + rtos_cmd.arg[5] = date.Sec; + mLCPU->Write((const char *)&rtos_cmd, sizeof(SF_RTOSINFO_S)); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE DualCoreManager::SetEnvironmentData(const unsigned char &isNight, const unsigned short &lightVal) +{ + SF_RTOS_CMD_T rtos_cmd; + rtos_cmd.cmd = LINUX2RTK_CMD_ENVIRONMENT_DATA; + rtos_cmd.arg[0] = isNight; + rtos_cmd.arg[1] = (lightVal & 0xff00) >> 8; + rtos_cmd.arg[2] = lightVal & 0x00ff; + mLCPU->Write((const char *)&rtos_cmd, sizeof(SF_RTOSINFO_S)); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +const signed int DualCoreManager::IsNight(void) +{ + SF_RTOSINFO_S info = {0}; + mLCPU->Read((char *)&info, sizeof(SF_RTOSINFO_S)); + return info.IsNight; +} +unsigned char DualCoreManager::GetFcTemper(void) +{ + SF_RTOSINFO_S info = {0}; + mLCPU->Read((char *)&info, sizeof(SF_RTOSINFO_S)); + return info.Fctemp; +} +unsigned char DualCoreManager::GetBatRemainCap(void) +{ + SF_RTOSINFO_S info = {0}; + mLCPU->Read((char *)&info, sizeof(SF_RTOSINFO_S)); // TODO: to read very time? + return info.BatPer; +} +unsigned short DualCoreManager::GetMcuVersion(void) +{ + return mMcuInfo.McuVer; +} +unsigned char DualCoreManager::GetSubMcuVersion(void) +{ + return mMcuInfo.McuSubVer; +} +RETURN_CODE DualCoreManager::SetBatteryMonitor(const std::shared_ptr &monitor) +{ + mBatteryMonitor = monitor; + auto batteryCheck = [](std::shared_ptr dualManager) + { + LogInfo("battery check thread started.\n"); + dualManager->BatteryCheck(); + }; + mBatteryCheck = true; + mThread = std::thread(batteryCheck, shared_from_this()); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +const BatteryInfo DualCoreManager::GetBetteryData(void) +{ + UINT8 batLevel = -1; + batLevel = sf_sys_battery_level_get(mBatteryPercent); + BatteryInfo info(mBatteryLevelConvert[static_cast(batLevel)], mBatteryPercent); + return info; +} +void DualCoreManager::BatteryCheck(void) +{ + SINT32 batPercentVal = 1; + SINT32 batPercentValLive = 1; + SINT32 lastbatPercentVal = 1; + UINT8 batLevel = -1; + UINT16 lastBatLevel = -1; + constexpr int BATTERY_NO_POWER = 0; + bool reportStopLive = false; + StartDetectBatteryThread(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 4)); + SF_RTOSINFO_S pstRtosData; + while (mBatteryCheck) + { + mLCPU->Read((char *)&pstRtosData, sizeof(SF_RTOSINFO_S)); + batPercentVal = pstRtosData.BatPer; + batPercentValLive = pstRtosData.LiveBatPer; + mBatteryPercent = batPercentVal; + // pStaticParam->BatRemainCap = batPercentVal; // TODO: + if (BATTERY_NO_POWER == batPercentVal) + { + if (BATTERY_NO_POWER == lastbatPercentVal) + { + mBatteryMonitor->BatteryChanged(BatteryLevel::NO_POWER); + } + else + { + lastbatPercentVal = batPercentVal; + } + } + else + { + batLevel = sf_sys_battery_level_get(batPercentVal); + if (batLevel != lastBatLevel) + { + lastBatLevel = batLevel; + mBatteryMonitor->BatteryChanged(mBatteryLevelConvert[static_cast(batLevel)]); + } + } + if (batPercentValLive <= 0 && false == reportStopLive) + { + mBatteryMonitor->LiveBatteryGoesToZero(); + } + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 3)); + } +} +SINT8 DualCoreManager::sf_sys_battery_level_get(SINT32 batValue) +{ + if (batValue >= 90) + { + return SF_BATT_LEVEL_4; + } + else if (batValue >= 30) + { + return SF_BATT_LEVEL_3; + } + else if (batValue > 0) + { + return SF_BATT_LEVEL_2; + } + else + { + return SF_BATT_LEVEL_0; + } +} +void DualCoreManager::StartDetectBatteryThread(void) +{ + SF_RTOS_CMD_T rtos_cmd; + rtos_cmd.cmd = LINUX2RTK_CMD_DETECT_BATTERY; + mLCPU->Write((const char *)&rtos_cmd, sizeof(SF_RTOSINFO_S)); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManager.h b/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManager.h new file mode 100644 index 000000000..555d8df6b --- /dev/null +++ b/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManager.h @@ -0,0 +1,98 @@ +#ifndef DUAL_CORE_MANAGER_H +#define DUAL_CORE_MANAGER_H +#include "IDualCoreManager.h" +#include "IHal.h" +#include "SfTypeDefine.h" +#include +#include +#include +typedef enum +{ + LINUX2RTK_CMD_STOP_RECORD = 1, // stop record venc chn + LINUX2RTK_CMD_SET_RTKMODE = 2, // set work mode to rtk,for manual control mode + LINUX2RTK_CMD_SET_POWEROFF = 3, // set POWEROFF type + LINUX2RTK_CMD_SET_RTCTIME = 4, // set rtc time + LINUX2RTK_CMD_SET_DEVINFO = 5, // set dev info + LINUX2RTK_CMD_SET_UVCCTRL = 6, // set rtos uvc ctrl,open/close + LINUX2RTK_CMD_SET_P2PCTRL = 7, // set rtos p2p live ctrl,open/close + LINUX2RTK_CMD_ENVIRONMENT_DATA = 8, + LINUX2RTK_CMD_DETECT_BATTERY = 10, + LINUX2RTK_CMD_SET_DATEFORMAT = 11, + LINUX2RTK_CMD_SET_IRLED_SWITCH = 12, +} CUS_LINUX2RTK_CMD_E; +typedef enum sfBATTERY_LEVEL_E +{ + SF_BATT_LEVEL_0 = 0, + SF_BATT_LEVEL_1 = 1, /* 1/3 */ + SF_BATT_LEVEL_2 = 2, /* 2/3 */ + SF_BATT_LEVEL_3 = 3, + SF_BATT_LEVEL_4 = 4, /* battery full */ + SF_BATT_LEVEL_0_1 = 5, /* battery empty */ + SF_BATT_LEVEL_TOTAL, +} SF_BATTERY_LEVEL_E; +typedef struct sf_RtosInfo_t +{ + // unsigned int test1; + // unsigned int test2; + // unsigned int test3; + // unsigned int IsNight; + // unsigned int BatPer; + // unsigned int LiveBatPer; + // unsigned int recorddone; + // unsigned int Fctemp; + // unsigned short McuVer; + // unsigned char McuSubVer; + // unsigned int rtosBootTime; + unsigned int test1; + unsigned int test2; + unsigned int test3; + unsigned int IsNight; + unsigned int BatPer; + unsigned int LiveBatPer; + unsigned int currentBatvalue; + unsigned int recorddone; + unsigned int Fctemp; + unsigned short McuVer; + unsigned char McuSubVer; + unsigned int rtosBootTime; +} SF_RTOSINFO_S; +typedef struct SF_RTOS_CMD_s +{ + unsigned char cmd; + unsigned char arg[8]; + unsigned char info[256]; +} SF_RTOS_CMD_T; +class DualCoreManager : public IDualCoreManager, public std::enable_shared_from_this +{ +public: + DualCoreManager(); + ~DualCoreManager() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + unsigned int GetStartupMode(void) override; + RETURN_CODE SetMcuTime(void) override; + RETURN_CODE SetEnvironmentData(const unsigned char &isNight, const unsigned short &lightVal) override; + const signed int IsNight(void) override; + unsigned char GetFcTemper(void) override; + unsigned char GetBatRemainCap(void) override; + unsigned short GetMcuVersion(void) override; + unsigned char GetSubMcuVersion(void) override; + RETURN_CODE SetBatteryMonitor(const std::shared_ptr &monitor) override; + const BatteryInfo GetBetteryData(void) override; + +private: + void BatteryCheck(void); + SINT8 sf_sys_battery_level_get(SINT32 batValue); + void StartDetectBatteryThread(void); + +private: + std::shared_ptr mLCPU; + SF_RTOSINFO_S mMcuInfo; + std::shared_ptr mBatteryMonitor; + bool mBatteryCheck; + std::thread mThread; + std::map mBatteryLevelConvert; + UINT8 mBatLevel; + SINT32 mBatteryPercent; +}; +#endif // !DUAL_CORE_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManagerMakePtr.cpp b/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManagerMakePtr.cpp new file mode 100644 index 000000000..e6436ebc5 --- /dev/null +++ b/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManagerMakePtr.cpp @@ -0,0 +1,33 @@ +#include "DualCoreManagerMakePtr.h" +#include "Log.h" +bool CreateDualManager(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = DualCoreManagerMakePtr::GetInstance()->CreateDualCoreManager(instance); + if (code->IsCodeOK()) + { + LogInfo("Dual core manager instance is ok.\n"); + IDualCoreManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &DualCoreManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + /** + * @brief + * The non-thread-safe changing is only for gtest. + */ + instance = *impl; + } + return instance; +} +RETURN_CODE DualCoreManagerMakePtr::CreateDualCoreManager(std::shared_ptr &impl) +{ + auto tmp = std::make_shared(); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManagerMakePtr.h b/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManagerMakePtr.h new file mode 100644 index 000000000..4f841f092 --- /dev/null +++ b/code/application/sifarsdk/component/DualCoreManager/src/DualCoreManagerMakePtr.h @@ -0,0 +1,13 @@ +#ifndef DUAL_CORE_MANAGER_MAKE_PTR_H +#define DUAL_CORE_MANAGER_MAKE_PTR_H +#include "DualCoreManager.h" +#include +class DualCoreManagerMakePtr +{ +public: + DualCoreManagerMakePtr() = default; + virtual ~DualCoreManagerMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE CreateDualCoreManager(std::shared_ptr &impl); +}; +#endif // !DUAL_CORE_MANAGER_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/DualCoreManager/src/IDualCoreManager.cpp b/code/application/sifarsdk/component/DualCoreManager/src/IDualCoreManager.cpp new file mode 100644 index 000000000..eb22c9a61 --- /dev/null +++ b/code/application/sifarsdk/component/DualCoreManager/src/IDualCoreManager.cpp @@ -0,0 +1,29 @@ +#include "IDualCoreManager.h" +#include "Log.h" +#include +std::shared_ptr &IDualCoreManager::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/FileManager/CMakeLists.txt b/code/application/sifarsdk/component/FileManager/CMakeLists.txt new file mode 100644 index 000000000..31fe89a71 --- /dev/null +++ b/code/application/sifarsdk/component/FileManager/CMakeLists.txt @@ -0,0 +1,26 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME FileManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +# 这个模块暴露头文件过多,待梳理和优化 \ No newline at end of file diff --git a/code/application/sifarsdk/component/FileManager/include/FileManager.h b/code/application/sifarsdk/component/FileManager/include/FileManager.h new file mode 100644 index 000000000..e904d37ea --- /dev/null +++ b/code/application/sifarsdk/component/FileManager/include/FileManager.h @@ -0,0 +1,15 @@ +#ifndef FILE_MANAGER_H +#define FILE_MANAGER_H +#include "SfTypeDefine.h" +#ifdef __cplusplus +extern "C" +{ +#endif + SINT32 sf_file_IsExsit(const char *fileName); + SINT32 sf_file_remove(const char *fileName); + SINT32 sf_file_size_get(const char *filePath, UINT32 *pFileSize); + int sf_get_video_pic_num(const char *path); +#ifdef __cplusplus +} +#endif +#endif // !FILE_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/FileManager/src/FileManager.c b/code/application/sifarsdk/component/FileManager/src/FileManager.c new file mode 100644 index 000000000..b1e16970d --- /dev/null +++ b/code/application/sifarsdk/component/FileManager/src/FileManager.c @@ -0,0 +1,113 @@ +#include "FileManager.h" +#include "Log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +SINT32 sf_file_IsExsit(const char *fileName) +{ + return (access((char *)fileName, F_OK) == 0) ? SF_TRUE : SF_FALSE; +} +SINT32 sf_file_remove(const char *fileName) +{ + SINT8 count = 0; + SF_CHAR cmdstring[64] = {0}; + SINT32 s32ret = SF_SUCCESS; + do + { + LogInfo("removing [%s]\n", fileName); + sprintf(cmdstring, "rm -rf %s", fileName); + s32ret = system(cmdstring); + sync(); + + if (s32ret != SF_SUCCESS) + { + // SF_MESSAGE_BUF_S stMessageBuf = {0}; // TODO: + // stMessageBuf.cmdId = 0x0113; + // stMessageBuf.arg1 = 0; + // sf_com_message_send_to_cardv(&stMessageBuf); + // usleep(500000); + } + count++; + } while (sf_file_IsExsit(fileName) == SF_TRUE && count < 10); + + if (sf_file_IsExsit(fileName) != SF_TRUE) + LogInfo("removed [%s]\n", fileName); + if (count >= 10) + { + LogError("remove [%s] failed !!!\n", fileName); + return SF_FAILURE; + } + return SF_SUCCESS; +} +SINT32 sf_file_size_get(const char *filePath, UINT32 *pFileSize) +{ + if (!filePath) + { + LogError("Nullptr pointer.\n"); + return SF_FAILURE; + } + SINT32 fd = 0; + struct stat statBuf; + fd = open(filePath, O_RDWR); /*open jpg file*/ + if (fd < 0) + { + LogError("Open failed, file = [%s].\n", filePath); + return SF_FAILURE; + // SF_MESSAGE_BUF_S stMessageBuf = {0}; // TODO: + // stMessageBuf.cmdId = 0x0113; + // stMessageBuf.arg1 = 0; + // sf_com_message_send_to_cardv(&stMessageBuf); + // usleep(500000); + // fd = open(filePath, O_RDWR); /*open jpg file*/ + // if (fd < 0) + // { + // LogError("open [%s] failed !!!,errno = [%d,%s]\n", filePath, errno, strerror(errno)); + // return SF_FAILURE; + // } + } + fstat(fd, &statBuf); + *pFileSize = statBuf.st_size; + close(fd); + return SF_SUCCESS; +} + +int sf_get_video_pic_num(const char *path) +{ + int total = 0; + DIR *dir = opendir(path); + if (dir == NULL) + { + LogInfo("opendir error [%s]\r\n", path); + return 0; + } + struct dirent *dirObj = NULL; + char *dirName = NULL; + while (dirObj = readdir(dir)) + { + dirName = dirObj->d_name; + if (strcmp(dirName, ".") == 0 || strcmp(dirName, "..") == 0) + { + continue; + } + if (strstr(dirObj->d_name, "jpg") != NULL || strstr(dirObj->d_name, "mp4") != NULL) + { + total++; + } + if (dirObj->d_type == DT_DIR) + { + char temp[1024] = {0}; + sprintf(temp, "%s/%s", path, dirName); + total += sf_get_video_pic_num(temp); + } + } + LogInfo("dir[%s] pic and video total num is %d!\r\n", path, total); + return total; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/FtpManager/CMakeLists.txt b/code/application/sifarsdk/component/FtpManager/CMakeLists.txt new file mode 100755 index 000000000..1436e9d87 --- /dev/null +++ b/code/application/sifarsdk/component/FtpManager/CMakeLists.txt @@ -0,0 +1,33 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Servers/include +) +#do not rely on any other library +# link_directories( +# ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/build/lib +# ) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME FtpManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} Log) + +add_custom_target( + FtpManagerOutput + DEPENDS FtpManager curl + COMMAND echo "Build FtpManager output." + COMMAND cp ${COMPONENT_SOURCE_PATH}/FtpManager/include/*.h ${LIBS_OUTPUT_PATH}/include + # COMMAND cp ${COMPONENT_SOURCE_PATH}/Config/README.md ${LIBS_OUTPUT_PATH}/readme/README_Config.md + WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/ +) \ No newline at end of file diff --git a/code/application/sifarsdk/component/FtpManager/include/ftp_manager.h b/code/application/sifarsdk/component/FtpManager/include/ftp_manager.h new file mode 100644 index 000000000..68488f628 --- /dev/null +++ b/code/application/sifarsdk/component/FtpManager/include/ftp_manager.h @@ -0,0 +1,26 @@ +#ifndef FTP_MANAGER_H +#define FTP_MANAGER_H +#ifdef __cplusplus +extern "C" +{ +#endif + typedef enum + { + FTP_SSL_FLAG_ENABLE = 0, + FTP_SSL_FLAG_DISABLE, + FTP_SSL_FLAG_END + } FtpSslFlag; + typedef struct ftp_config + { + const char *url; + const FtpSslFlag ftpsFlag; + const char *user; + const char *password; + } FtpConfig; + int ftp_manager_init(const FtpConfig config); + int ftp_manager_uninit(void); + int ftp_upload_file(const char *file_name, const char *file_path, unsigned int time_out); +#ifdef __cplusplus +} +#endif +#endif // !FTP_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/FtpManager/src/ftp_manager.c b/code/application/sifarsdk/component/FtpManager/src/ftp_manager.c new file mode 100644 index 000000000..bdf9f9adf --- /dev/null +++ b/code/application/sifarsdk/component/FtpManager/src/ftp_manager.c @@ -0,0 +1,147 @@ +#include "ftp_manager.h" +#include "servers.h" +#include "Log.h" +#include +#include +#include +#define FTP_FREE_CONFIG NULL +#define FTP_GET_CONFIG -1 +static void free_ftp_config(FtpConfig *config) +{ + if (config) + { + if (config->url) + { + free((char *)config->url); + config->url = NULL; + } + if (config->user) + { + free((char *)config->user); + config->user = NULL; + } + if (config->password) + { + free((char *)config->password); + config->password = NULL; + } + free((char *)config); + config = NULL; + LogInfo("free ftp config.\n"); + } +} +static FtpConfig *set_ftp_config(const FtpConfig *config) +{ + // asan can't detect global variable memory leaks. + static FtpConfig *g_ftp_config = NULL; + unsigned int length = 0; + char *url = NULL; + char *user = NULL; + char *password = NULL; + if ((FtpConfig *)FTP_GET_CONFIG == config) + { + return g_ftp_config; + } + if (!config) + { + if (g_ftp_config) + { + free_ftp_config(g_ftp_config); + g_ftp_config = NULL; + } + return g_ftp_config; + } + if (g_ftp_config) + { + free_ftp_config(g_ftp_config); + g_ftp_config = NULL; + } + if (config->url) + { + length = strlen(config->url) + 1; + url = (char *)malloc(length); + if (url) + { + memset(url, 0, length); + memcpy(url, config->url, strlen(config->url)); + } + } + if (config->user) + { + length = strlen(config->user) + 1; + user = (char *)malloc(length); + if (user) + { + memset(user, 0, length); + memcpy(user, config->user, strlen(config->user)); + } + } + if (config->password) + { + length = strlen(config->password) + 1; + password = (char *)malloc(length); + if (password) + { + memset(password, 0, length); + memcpy(password, config->password, strlen(config->password)); + } + } + FtpConfig save_config = { + .url = url, + .user = user, + .password = password, + .ftpsFlag = config->ftpsFlag}; + g_ftp_config = (FtpConfig *)malloc(sizeof(FtpConfig)); + if (g_ftp_config) + { + LogInfo("Save ftp config.\n"); + memcpy(g_ftp_config, &save_config, sizeof(FtpConfig)); + } + return g_ftp_config; +} +int ftp_manager_init(const FtpConfig config) +{ + SERVERS_INIT init = { + .logFlag = LOG_FLAG_ENABLE, + .sslVerifyFlag = SSL_VERIFY_DISABLE, + }; + servers_init(init); + set_ftp_config(&config); + return 0; +} +int ftp_manager_uninit(void) +{ + set_ftp_config(FTP_FREE_CONFIG); + return 0; +} +int ftp_upload_file(const char *file_name, const char *file_path, unsigned int time_out) +{ +#define BUF_LENGTH 256 + int result = 0; + char user_password[BUF_LENGTH] = {0}; + char upload_file[BUF_LENGTH] = {0}; + char url[BUF_LENGTH] = {0}; + FtpConfig *config = set_ftp_config((FtpConfig *)FTP_GET_CONFIG); + FtpsFlag ssl = config->ftpsFlag == FTP_SSL_FLAG_ENABLE ? FTPS_FLAG_ENABLE : FTPS_FLAG_DISABLE; + snprintf(url, BUF_LENGTH, "%s/%s", config->url, file_name); + SERVERS_FTP *ftp = new_servers_ftp(url, ssl); + if (ftp) + { + snprintf(user_password, BUF_LENGTH, "%s:%s", config->user, config->password); + snprintf(upload_file, BUF_LENGTH, "%s%s", file_path, file_name); + ftp->user_password = (char *)user_password; + ftp->filePath = (char *)upload_file; + ftp_upload(ftp); + if (SERVERS_CODE_OK == ftp->code) + { + LogInfo("ftp succeed.\n"); + } + else + { + LogError("ftp failed, code = %d.\n", ftp->code); + } + result = ftp->code; + delete_servers_ftp(ftp); + } + return result; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/FtpServers/CMakeLists.txt b/code/application/sifarsdk/component/FtpServers/CMakeLists.txt new file mode 100644 index 000000000..6c378298e --- /dev/null +++ b/code/application/sifarsdk/component/FtpServers/CMakeLists.txt @@ -0,0 +1,23 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Log/include +) +#do not rely on any other library +# link_directories( +# ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/build/lib +# ) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME FtpServers) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} Log) \ No newline at end of file diff --git a/code/application/sifarsdk/component/FtpServers/include/ftp_servers.h b/code/application/sifarsdk/component/FtpServers/include/ftp_servers.h new file mode 100644 index 000000000..3c866ff5e --- /dev/null +++ b/code/application/sifarsdk/component/FtpServers/include/ftp_servers.h @@ -0,0 +1,28 @@ +#ifndef FTP_SERVERS_H +#define FTP_SERVERS_H +#ifdef __cplusplus +extern "C" +{ +#endif + typedef struct ftp_config + { + const char *url; + const char *subject; + const char *from; + const char *to; + const char *userName; + const char *password; + const char *date; + char *inlineText; + char **toList; + unsigned int toListLength; + // char *text; + // unsigned int textLength; + char **attachment; + int code; + } FtpConfig; + int ftp_config(const FtpConfig config); +#ifdef __cplusplus +} +#endif +#endif // !FTP_SERVERS_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/FtpServers/include/ftp_servers_manager.h b/code/application/sifarsdk/component/FtpServers/include/ftp_servers_manager.h new file mode 100644 index 000000000..21c1b7f93 --- /dev/null +++ b/code/application/sifarsdk/component/FtpServers/include/ftp_servers_manager.h @@ -0,0 +1,28 @@ +#ifndef FTP_SERVERS_MANAGER_H +#define FTP_SERVERS_MANAGER_H +#ifdef __cplusplus +extern "C" +{ +#endif + typedef struct ftp_config + { + const char *url; + const char *subject; + const char *from; + const char *to; + const char *userName; + const char *password; + const char *date; + char *inlineText; + char **toList; + unsigned int toListLength; + // char *text; + // unsigned int textLength; + char **attachment; + int code; + } FtpConfig; + int ftp_config(const FtpConfig config); +#ifdef __cplusplus +} +#endif +#endif // !FTP_SERVERS_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/FtpServers/src/ftp_servers.c b/code/application/sifarsdk/component/FtpServers/src/ftp_servers.c new file mode 100644 index 000000000..63d681e00 --- /dev/null +++ b/code/application/sifarsdk/component/FtpServers/src/ftp_servers.c @@ -0,0 +1,5 @@ +#include "ftp_servers.h" +int ftp_config(const FtpConfig config) +{ + return 0; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/FtpServers/src/ftp_servers_manager.c b/code/application/sifarsdk/component/FtpServers/src/ftp_servers_manager.c new file mode 100644 index 000000000..199b67fed --- /dev/null +++ b/code/application/sifarsdk/component/FtpServers/src/ftp_servers_manager.c @@ -0,0 +1,5 @@ +#include "ftp_servers_manager.h" +int ftp_config(const FtpConfig config) +{ + return 0; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/HttpBase/CMakeLists.txt b/code/application/sifarsdk/component/HttpBase/CMakeLists.txt new file mode 100644 index 000000000..a64119703 --- /dev/null +++ b/code/application/sifarsdk/component/HttpBase/CMakeLists.txt @@ -0,0 +1,25 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + # ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME HttpBase) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) \ No newline at end of file diff --git a/code/application/sifarsdk/component/HttpBase/include/HttpBase.h b/code/application/sifarsdk/component/HttpBase/include/HttpBase.h new file mode 100644 index 000000000..8c1d5aca3 --- /dev/null +++ b/code/application/sifarsdk/component/HttpBase/include/HttpBase.h @@ -0,0 +1,21 @@ +#ifndef HTTP_BASE_H +#define HTTP_BASE_H +#include "SfTypeDefine.h" +#include +constexpr int HTTP_PORT = 80; +constexpr int INVALID_SOCKET_FD = -1; +class HttpBase +{ +public: + HttpBase(const std::string &hostName); + virtual ~HttpBase() = default; + SINT32 Create(void); + SINT32 Send(const char *data, const int &length); + SINT32 Rece(char *data, const int &length); + SINT32 Close(void); + +private: + int mSocketFd; + const std::string mHostName; +}; +#endif // !HTTP_BASE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/HttpBase/src/HttpBase.cpp b/code/application/sifarsdk/component/HttpBase/src/HttpBase.cpp new file mode 100644 index 000000000..d9cc15626 --- /dev/null +++ b/code/application/sifarsdk/component/HttpBase/src/HttpBase.cpp @@ -0,0 +1,123 @@ +#include "HttpBase.h" +#include "Log.h" +#include +#include +#include +#include +#include +#include +#include +#include +HttpBase::HttpBase(const std::string &hostName) : mHostName(hostName) +{ + mSocketFd = INVALID_SOCKET_FD; +} +SINT32 HttpBase::Create(void) +{ + struct sockaddr_in address; + int clt_sock; + int opvalue = 8; + socklen_t slen; + int i = 0; + int ret = 0; + + slen = sizeof(opvalue); + memset(&address, 0, sizeof(address)); + if ((clt_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 || + setsockopt(clt_sock, IPPROTO_IP, IP_TOS, &opvalue, slen) < 0) + { + LogInfo("socket socket error.\n"); + return -1; + } + struct timeval timeo = {120, 0}; + + setsockopt(clt_sock, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo)); + setsockopt(clt_sock, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); + + address.sin_family = AF_INET; + address.sin_port = htons((unsigned short)HTTP_PORT); + + LogInfo("Host name = %s\n", mHostName.c_str()); + struct hostent *server = gethostbyname(mHostName.c_str()); + if (!server) + { + LogError("dns error.\n"); + return -1; + } + + for (i = 0; server->h_addr_list[i]; i++) + LogInfo("...server ip addr%d: %s \n", i, inet_ntoa(*(struct in_addr *)server->h_addr_list[i])); + + address.sin_addr = *(struct in_addr *)server->h_addr_list[0]; + ret = connect(clt_sock, (struct sockaddr *)&address, sizeof(address)); + if (ret != 0) + { + LogInfo("socket socket connect error. ret = %d\n", ret); + return -1; + } + + mSocketFd = clt_sock; + + return 0; +} +SINT32 HttpBase::Send(const char *data, const int &length) +{ + int written_len = 0; + int writelen = 0; + int ret = 0; + if (INVALID_SOCKET_FD == mSocketFd) + { + LogError("INVALID_SOCKET_FD.\n"); + return SF_FAILURE; + } + while (written_len < length) + { + if (length - written_len > 1024 * 20) + writelen = 1024 * 20; + else + writelen = length - written_len; + + ret = send(mSocketFd, data + written_len, writelen, 0); + if (ret > 0) + { + written_len += ret; + continue; + } + else if (ret == 0) + { + return written_len; + } + else + { + LogInfo("written_len:%d,ret:%d\n", written_len, ret); + LogInfo("HTTP Send:%d\n", ret); + return -1; /* Connnection error */ + } + } + + LogInfo("Send End,written_len:%d\n", written_len); + return SF_SUCCESS; +} +SINT32 HttpBase::Rece(char *data, const int &length) +{ + // TODO: + SINT32 recv_byte = 0; + if (INVALID_SOCKET_FD == mSocketFd) + { + LogError("INVALID_SOCKET_FD.\n"); + return SF_FAILURE; + } + recv_byte = recv(mSocketFd, data, length, 0); + if (recv_byte == 0) + { + sleep(3); + recv_byte = recv(mSocketFd, data, length, 0); + } + return recv_byte; +} +SINT32 HttpBase::Close(void) +{ + SINT32 result = close(mSocketFd); + mSocketFd = INVALID_SOCKET_FD; + return result; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/CMakeLists.txt b/code/application/sifarsdk/component/LiveManager/CMakeLists.txt new file mode 100644 index 000000000..a81c57eec --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/CMakeLists.txt @@ -0,0 +1,45 @@ +add_subdirectory(src/override) + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${APPLICATION_SOURCE_PATH}/StateManager/include + ${APPLICATION_SOURCE_PATH}/NetworkManager/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Config/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/cJSON/include + ${COMPONENT_SOURCE_PATH}/CameraManager/include + ${HAL_SOURCE_PATH}/include + ${AT_COMMAND_PATH} +) + +#Rely on other library +# message("======================== ${DEPENDENCY_LIBS_PATH}/live/${LIVE_PLATFORM_SRC_PATH}") +# link_directories( +# ${DEPENDENCY_LIBS_PATH}/live/${LIVE_PLATFORM_SRC_PATH} +# ) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) +# Config to choose live service platform. +# string(COMPARE EQUAL "${AT_COMMAND_PATH}" "" value) +# message("The at-command src code path is ${AT_COMMAND_PATH}.") +# if (value EQUAL 0) #变量被设置了 +# message("build at-command src code.") +# include(${AT_COMMAND_PATH}/at-command.cmake) +# endif() + +include(${COMPONENT_SOURCE_PATH}/LiveManager/src/${LIVE_PLATFORM_SRC_PATH}/live_service.cmake) + +set(TARGET_NAME LiveManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} NetworkManager StateManager CameraManager Config Hal ReturnCode Log ${LIVE_LINK_LIB}) \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/include/ILiveManager.h b/code/application/sifarsdk/component/LiveManager/include/ILiveManager.h new file mode 100644 index 000000000..806e7044b --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/include/ILiveManager.h @@ -0,0 +1,20 @@ +#ifndef I_LIVE_MANAGER_H +#define I_LIVE_MANAGER_H +#include "VReturnCode.h" +#include +class ILiveManager +{ +public: + ILiveManager() = default; + virtual ~ILiveManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual bool LiveEnable(void) { return false; } + virtual RETURN_CODE StartLiveService(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE StartLiveMedia(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE StopLiveMedia(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE KeepAlive(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreateLiveManager(void); +#endif // !I_LIVE_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/ILiveManager.cpp b/code/application/sifarsdk/component/LiveManager/src/ILiveManager.cpp new file mode 100644 index 000000000..05b8dc128 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ILiveManager.cpp @@ -0,0 +1,29 @@ +#include "ILiveManager.h" +#include "Log.h" +#include +std::shared_ptr &ILiveManager::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/LiveManagerMakePtr.cpp b/code/application/sifarsdk/component/LiveManager/src/LiveManagerMakePtr.cpp new file mode 100644 index 000000000..8401cdbd8 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/LiveManagerMakePtr.cpp @@ -0,0 +1,30 @@ +#include "LiveManagerMakePtr.h" +#include "Log.h" +#include "VReturnCode.h" +#include +bool CreateLiveManager(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = LiveManagerMakePtr::GetInstance()->CreateLiveManager(instance); + if (code->IsCodeOK()) + { + LogInfo("Peripheral manager instance is ok.\n"); + ILiveManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &LiveManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + instance = *impl; + } + return instance; +} +RETURN_CODE LiveManagerMakePtr::CreateLiveManager(std::shared_ptr &impl) +{ + CreateLiveManagerImpl(impl); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/LiveManagerMakePtr.h b/code/application/sifarsdk/component/LiveManager/src/LiveManagerMakePtr.h new file mode 100644 index 000000000..c70271e9a --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/LiveManagerMakePtr.h @@ -0,0 +1,17 @@ +#ifndef LIVE_MANAGER_MAKE_PTR_H +#define LIVE_MANAGER_MAKE_PTR_H +#include "ILiveManager.h" +#include "VReturnCode.h" +#include +class LiveManagerMakePtr +{ +public: + LiveManagerMakePtr() = default; + virtual ~LiveManagerMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE CreateLiveManager(std::shared_ptr &impl); +}; +bool CreateLiveManagerImpl(std::shared_ptr &impl); +#endif // !LIVE_MANAGER_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/SendMessage.cpp b/code/application/sifarsdk/component/LiveManager/src/SendMessage.cpp new file mode 100644 index 000000000..27234845b --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/SendMessage.cpp @@ -0,0 +1,12 @@ +#include "SendMessage.h" +#include "IStateManager.h" +void StartLiveMedia(void) +{ + std::shared_ptr message = std::make_shared(StateEvent::LIVE_START_MEDIA); + IStateManager::GetInstance()->SendStateMessage(message); +} +void StopLiveMedio(void) +{ + std::shared_ptr message = std::make_shared(StateEvent::LIVE_STOP_MEDIA); + IStateManager::GetInstance()->SendStateMessage(message); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/SendMessage.h b/code/application/sifarsdk/component/LiveManager/src/SendMessage.h new file mode 100644 index 000000000..ab7c03973 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/SendMessage.h @@ -0,0 +1,12 @@ +#ifndef SEND_MESSAGE_H +#define SEND_MESSAGE_H +#ifdef __cplusplus +extern "C" +{ +#endif + void StartLiveMedia(void); + void StopLiveMedio(void); +#ifdef __cplusplus +} +#endif +#endif // !SEND_MESSAGE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/AliLiveManager.cpp b/code/application/sifarsdk/component/LiveManager/src/ali_live/AliLiveManager.cpp new file mode 100644 index 000000000..0d27b51df --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/AliLiveManager.cpp @@ -0,0 +1,174 @@ + +#include "AliLiveManager.h" +#include "iot_export_linkkit.h" +#include "sdk_assistant.h" +#include "link_visual_enum.h" +#include "link_visual_struct.h" +#include "link_visual_api.h" +#include "linkvisual_client.h" +#include "linkkit_client.h" +#include "IConfig.h" +#include "Log.h" +#include "INetworkManager.h" +#include +bool CreateLiveManagerImpl(std::shared_ptr &impl) +{ + impl = std::make_shared(); + return true; +} +AliLiveManager::AliLiveManager() +{ + mLiveRuning = false; +} +RETURN_CODE AliLiveManager::Init(void) +{ + ICameraManager::GetInstance()->GetCameraHandle(CameraType::MAIN_CAMERA, mCamera); + std::shared_ptr mediaMonitor = shared_from_this(); + mCamera->SetMediaMonitor(mediaMonitor); + ::sf_ipc_live_init(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE AliLiveManager::UnInit(void) +{ + // mLiveRuning = false; + // if (mLiveThread.joinable()) + // { + // mLiveThread.join(); + // } + StopLiveMedia(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE AliLiveManager::StartLiveService(void) +{ + auto recvThread = [](std::shared_ptr live) + { + live->LiveServiceThread(); + }; + mLiveThread = std::thread(recvThread, shared_from_this()); + mCamera->BeReadyForLive(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE AliLiveManager::StartLiveMedia(void) +{ + mCamera->StartMedia(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE AliLiveManager::StopLiveMedia(void) +{ + mCamera->StopMedia(); + mLiveRuning = false; + if (mLiveThread.joinable()) + { + mLiveThread.join(); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE AliLiveManager::KeepAlive(void) +{ + INetworkManager::GetInstance()->KeepAliveWithLiveServers(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +int AliLiveManager::AudioStream_write(const char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp) +{ + lv_stream_send_media_param_s stmedia_param; + memset(&stmedia_param, 0, sizeof(lv_stream_send_media_param_s)); + + stmedia_param.common.type = LV_STREAM_MEDIA_AUDIO; + stmedia_param.common.p = (char *)pu8Addr; + stmedia_param.common.len = u32Len; + stmedia_param.common.timestamp_ms = TimeStamp / 1000; + stmedia_param.audio.format = LV_AUDIO_FORMAT_PCM; + + if (StreamServiceID > 0) + lv_stream_send_media(StreamServiceID, &stmedia_param); + return 0; +} +int AliLiveManager::VideoStream_write(char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp, const unsigned int &key_frame) +{ + lv_stream_send_media_param_s stmedia_param; + memset(&stmedia_param, 0, sizeof(lv_stream_send_media_param_s)); + + stmedia_param.common.type = LV_STREAM_MEDIA_VIDEO; + stmedia_param.common.p = pu8Addr; + stmedia_param.common.len = u32Len; + stmedia_param.common.timestamp_ms = TimeStamp / 1000; + stmedia_param.video.format = LV_VIDEO_FORMAT_H265; + stmedia_param.video.key_frame = (key_frame != 1) ? 1 : 0; + if (StreamServiceID > 0) + lv_stream_send_media(StreamServiceID, &stmedia_param); + return 0; +} +void AliLiveManager::LiveServiceThread(void) +{ + mLiveRuning = true; + AliLiveManager::sf_ipc_live_init(); +} +int AliLiveManager::sf_ipc_live_init() +{ + int ret = 0; + lv_log_level_e log_level = LV_LOG_ERROR; + unsigned char szMqttUrl[64] = {0}; + Param p2pId = GetParam(PARAM_P2P_ID); + Param p2pName = GetParam(PARAM_P2P_NAME); + Param p2pSecret = GetParam(PARAM_P2P_SECRET); + Param MQTTIp = GetParam(PARAM_MQTT_IP); + Param MQTTPort = GetParam(PARAM_MQTT_PORT); + ret = linkvisual_client_init(0, 0, log_level); + if (ret < 0) + { + LogInfo("linkvisual_client_init failed\n"); + linkvisual_client_assistant_stop(); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); + return -1; + } + + iotx_linkkit_dev_meta_info_t auth = {0}; + + string_safe_copy(auth.product_key, p2pId.str, PRODUCT_KEY_LEN); + string_safe_copy(auth.product_secret, "", PRODUCT_SECRET_LEN); + string_safe_copy(auth.device_name, p2pName.str, DEVICE_NAME_LEN); + string_safe_copy(auth.device_secret, p2pSecret.str, DEVICE_SECRET_LEN); + + sf_set_ipc_live_state(SF_LIVE_CONNECT_ALI_STATE); + + sf_live_check_stop_task_start(); + + ret = linkkit_client_start(&auth, 0, NULL); + if (ret < 0) + { + LogInfo("linkkit_client_start failed\n"); + linkvisual_client_destroy(); + linkvisual_client_assistant_stop(); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); + return -1; + } + + sf_set_ipc_live_state(SF_LIVE_CONNECT_ALI_STATE); + + unsigned char *p1 = NULL; + unsigned char *p2 = NULL; + sf_live_mqtt_url_get(szMqttUrl); + LogInfo("[%s,%d] mqtt url is %s\n", __FUNCTION__, __LINE__, szMqttUrl); + p1 = szMqttUrl; + p2 = (unsigned char *)strchr((const char *)szMqttUrl, ':'); + memcpy(MQTTIp.str, p1, p2 - p1); + MQTTPort.numberInt = atoi((const char *)(p2 + 1)); + SetParam(MQTTPort, PARAM_MQTT_PORT); + LogInfo("mqtt ip is %s\n", MQTTIp.str); + LogInfo("mqtt port is %d\n", MQTTPort.numberInt); + + /* 3. 运行,等待服务器命令 */ + while (mLiveRuning) + { + usleep(1000 * 500); + } + + /* 4. linkkit长连接断开,并释放资源 */ + linkkit_client_destroy(); + + /* 5. LinkVisual断开音视频连接,并释放资源 */ + linkvisual_client_destroy(); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); + + return 0; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/AliLiveManager.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/AliLiveManager.h new file mode 100644 index 000000000..d447d150b --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/AliLiveManager.h @@ -0,0 +1,31 @@ +#ifndef ALI_LIVE_MANAGER_H +#define ALI_LIVE_MANAGER_H +#include "ILiveManager.h" +#include "ICameraManager.h" +#include "sf_live.h" +#include +class AliLiveManager : public ILiveManager, public VMediaMonitor, public std::enable_shared_from_this +{ +public: + AliLiveManager(); + virtual ~AliLiveManager() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + bool LiveEnable(void) override { return true; } + RETURN_CODE StartLiveService(void) override; + RETURN_CODE StartLiveMedia(void) override; + RETURN_CODE StopLiveMedia(void) override; + RETURN_CODE KeepAlive(void) override; + int AudioStream_write(const char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp) override; + int VideoStream_write(char *pu8Addr, const unsigned int &u32Len, const unsigned int &TimeStamp, const unsigned int &key_frame) override; + +private: + void LiveServiceThread(void); + int sf_ipc_live_init(void); + +private: + std::shared_ptr mCamera; + std::thread mLiveThread; + bool mLiveRuning; +}; +#endif // !ALI_LIVE_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/aiot_authorize_api.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/aiot_authorize_api.h new file mode 100644 index 000000000..87f941eae --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/aiot_authorize_api.h @@ -0,0 +1,135 @@ +/** + * @file aiot_bind_api.h + * @brief bind module api header file + * @version 0.1 + * @date 2019-05-28 + * + * @copyright Copyright (c) 2015-2018 Alibaba Group Holding Limited + * + */ + +#ifndef _AIOT_AUTHORIZE_API_H_ +#define _AIOT_AUTHORIZE_API_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include "iot_import.h" + +// #define STATE_SUCCESS 0 +#define STATE_FAILED -1 +#define STATE_USER_INPUT_UNKNOWN_OPTION (-0x0103) +// #define STATE_USER_INPUT_OUT_RANGE (-0x0102) +#define STATE_SYS_DEPEND_MALLOC_FAILED (-0x0201) + + +/** + * @brief authorize option, all mandatory option shall be setup + * + */ +typedef enum { + AUTHORIZEOPT_MQTT_HANDLE, /**< dataType:(void *), mqtt handle, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_MAC, /**< dataType:(char *), authorize mac/sn..., @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_CODE, /**< dataType:(char *), authorize code, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_REQUEST, /**< dataType:(char *), authorize request, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_PARSE, /**< dataType:(char *), authorize reply data parse, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_CHECK, /**< dataType:(char *), authorize check, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_CHECK_CB, /**< dataType:(char *), pointer check result callback, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_RW_CB, /**< dataType:(authorize_cb_t), pointer data read/write function */ + AUTHORIZEOPT_MAX +} aiot_authorize_option_t; + +typedef int32_t(*authorize_check_cb_t)(char *random, char* digest); +typedef int32_t(*authorize_rw_cb_t)(char *data, int32_t rw); + +typedef struct { + void *mqtt_handle; + void *mutex; + authorize_check_cb_t check_result_cb; + authorize_rw_cb_t auth_rw_cb; + char *mac; + char *authcode; + uint8_t authcode_count; + uint8_t req_count; + uint8_t req_success; +} aiot_authorize_handle_t; + + +/** + * @brief initializes the authorize module + * + * @return void* + * @retval Not NULL handle of authorize module + * @retval NULL initializes failed, system callbacks not complete or malloc failed. + * + * @brief + * @brief -------------------------------------------------- + * + * @brief 初始化授权模块 + * + * @return void* + * @retval Not NULL 授权模块句柄 + * @retval NULL 初始化失败, 系统回调不完整或者内存分配失败. + * + */ +void *aiot_authorize_open(void *mqtt_handle); + +/** + * @brief set option of authorize moduel + * + * @param[in] handle handle of authorize module + * @param[in] option the configuration option, see @ref aiot_authorize_option_t + * @param[in] data the configuration data, see @ref aiot_authorize_option_t + * + * @return int32_t + * @retval ERRCODE_SUCCESS set option successfully + * @retval 0, reserved for other usage */ + +} iotx_err_t; +/* From utils_error.h */ + +#if defined(__cplusplus) +} +#endif +#endif /* __IOT_EXPORT_ERRNO__ */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_event.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_event.h new file mode 100644 index 000000000..d6b671d63 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_event.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef IOTX_EXPORT_EVENT_H +#define IOTX_EXPORT_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief event list used for iotx_regist_event_monitor_cb + */ +enum iotx_event_t { + IOTX_AWSS_START = 0x1000, // AWSS start without enbale, just supports device discover + IOTX_AWSS_ENABLE, // AWSS enable + IOTX_AWSS_LOCK_CHAN, // AWSS lock channel(Got AWSS sync packet) + IOTX_AWSS_CS_ERR, // AWSS AWSS checksum is error. For dev ap is awss packet content error + IOTX_AWSS_PASSWD_ERR, // AWSS decrypt passwd error + IOTX_AWSS_GOT_SSID_PASSWD, // AWSS parse ssid and passwd successfully + IOTX_AWSS_CONNECT_ADHA, // AWSS try to connnect adha (device discover, router solution) + IOTX_AWSS_CONNECT_ADHA_FAIL, // AWSS fails to connect adha + IOTX_AWSS_CONNECT_AHA, // AWSS try to connect aha (AP solution) + IOTX_AWSS_CONNECT_AHA_FAIL, // AWSS fails to connect aha + IOTX_AWSS_SETUP_NOTIFY, // AWSS sends out device setup information (AP and router solution) + IOTX_AWSS_CONNECT_ROUTER, // AWSS try to connect destination router + IOTX_AWSS_CONNECT_ROUTER_FAIL, // AWSS fails to connect destination router. + IOTX_AWSS_GOT_IP, // AWSS connects destination successfully and got ip address + IOTX_AWSS_SUC_NOTIFY, // AWSS sends out success notify (AWSS sucess) + IOTX_AWSS_BIND_NOTIFY, // AWSS sends out bind notify information to support bind between user and device + IOTX_AWSS_ENABLE_TIMEOUT, // AWSS enable timeout(user needs to call awss_config_press again to enable awss) + IOTX_CONN_CLOUD = 0x2000, // Device try to connect cloud + IOTX_CONN_CLOUD_FAIL, // Device fails to connect cloud, refer to net_sockets.h for error code + IOTX_CONN_CLOUD_SUC, // Device connects cloud successfully + IOTX_CONN_REPORT_TOKEN_SUC, // Device report token to cloud success + IOTX_RESET = 0x3000, // Linkkit reset success (just got reset response from cloud without any other operation) +}; + +/** + * @brief register callback to monitor all event from system. + * + * @param callback, when some event occurs, the system will trigger callback to user. + * refer to enum iotx_event_t for event list supported. + * + * @return 0 when success, -1 when fail. + * @note: user should make sure that callback is not block and runs to complete fast. + */ +extern int iotx_event_regist_cb(void (*monitor_cb)(int event)); + +/** + * @brief post event to trigger callback resitered by iotx_event_regist_cb + * + * @param event, event id, refer to iotx_event_t + * + * @return 0 when success, -1 when fail. + */ +extern int iotx_event_post(int event); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* IOTX_EXPORT_H */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_guider.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_guider.h new file mode 100644 index 000000000..0e0a0cdf3 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_guider.h @@ -0,0 +1,33 @@ +#ifndef __IOT_EXPORT_GUIDER_H__ +#define __IOT_EXPORT_GUIDER_H__ + +#define GUIDER_ENV_LEN (10) +#define GUIDER_ENV_KEY "env" + +typedef enum _region_type_e +{ + REGION_TYPE_ID = 0, + REGION_TYPE_MQTTURL, + REGION_TYPE_MAX +} region_type_e; + +typedef enum _guider_env_e +{ + GUIDER_ENV_DAILY = 1, + GUIDER_ENV_PRERELEASE, + GUIDER_ENV_ONLINE, + GUIDER_ENV_MAX +} guider_env_e; + +DLL_IOT_API int iotx_guider_set_dynamic_mqtt_url(char *p_mqtt_url); +DLL_IOT_API int iotx_guider_set_dynamic_region(int region); +DLL_IOT_API int iotx_guider_clear_dynamic_url(void); +DLL_IOT_API int iotx_guider_fill_conn_string(char *dst, int len, const char *fmt, ...); +DLL_IOT_API int iotx_redirect_region_subscribe(void); +DLL_IOT_API int iotx_reconnect_region_subscribe(void); +DLL_IOT_API int iotx_guider_get_kv_env(void); +DLL_IOT_API guider_env_e iotx_guider_get_env(void); +DLL_IOT_API iotx_cloud_region_types_t iotx_guider_get_region(void); +DLL_IOT_API int iotx_guider_get_region_id(void); +DLL_IOT_API int guider_set_direct_connect_count(unsigned char count); +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http.h new file mode 100644 index 000000000..2f6aa6c31 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOT_EXPORT_HTTP_H_ +#define _IOT_EXPORT_HTTP_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* IoTx http initial param */ +typedef struct { + iotx_device_info_t *device_info; + int keep_alive; + int timeout_ms; +} iotx_http_param_t; + +/* IoTx http context */ +typedef struct { + char *p_auth_token; + uint32_t auth_token_len; + char is_authed; + const char *version; + const char *signmethod; + const char *sign; + iotx_device_info_t *p_devinfo; + const char *timestamp; + void *httpc; + int keep_alive; + int timeout_ms; +} iotx_http_t, *iotx_http_pt; + +/* IoTx http message definition + * request_payload and response_payload need to be allocate in order to save memory. + * topic_path specify the topic url you want to publish message. + */ +typedef struct { + char *topic_path; + uint32_t request_payload_len; + char *request_payload; + uint32_t response_payload_len; + char *response_payload; + uint32_t timeout_ms; +} iotx_http_message_param_t; + +/* The response code from sever */ +typedef enum { + IOTX_HTTP_SUCCESS = 0, + IOTX_HTTP_COMMON_ERROR = 10000, + IOTX_HTTP_PARAM_ERROR = 10001, + IOTX_HTTP_AUTH_CHECK_ERROR = 20000, + IOTX_HTTP_TOKEN_EXPIRED_ERROR = 20001, + IOTX_HTTP_TOKEN_NULL_ERROR = 20002, + IOTX_HTTP_TOKEN_CHECK_ERROR = 20003, + IOTX_HTTP_UPDATE_SESSION_ERROR = 20004, + IOTX_HTTP_PUBLISH_MESSAGE_ERROR = 30001, + IOTX_HTTP_REQUEST_TOO_MANY_ERROR = 40000, +} iotx_http_upstream_response_t; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_http http + * @{ + */ + +/** + * @brief Initialize the HTTP client + * This function initialize the data. + * + * @param [in] pInitParams: Specify the init param infomation. + * + * @retval NULL : Initialize failed. + * @retval NOT_NULL : The contex of HTTP client. + * @see None. + */ +DLL_IOT_API void *IOT_HTTP_Init(iotx_http_param_t *pInitParams); + +/** + * @brief De-initialize the HTTP client + * This function release the related resource. + * + * @param [in] handle: pointer to http context pointer. + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_HTTP_DeInit(void **handle); + +/** + * @brief Handle device name authentication with remote server. + * + * @param [in] handle: Pointer of context, specify the HTTP client. + * + * @retval 0 : Authenticate success. + * @retval -1 : Authenticate failed. + * @see iotx_err_t. + */ +DLL_IOT_API int IOT_HTTP_DeviceNameAuth(void *handle); + +/** + * @brief Send a message with specific path to server. + * Client must authentication with server before send message. + * + * @param [in] handle: Pointer of contex, specify the HTTP client. + * @param [in] msg_param: Specify the topic path and http payload configuration. + * + * @retval 0 : Success. + * @retval -1 : Failed. + * @see iotx_err_t. + */ +DLL_IOT_API int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param); + +/** + * @brief close tcp connection from client to server. + * + * @param [in] handle: Pointer of contex, specify the HTTP client. + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_HTTP_Disconnect(void *handle); + +/** @} */ /* end of api_http */ +/** @} */ /* end of api */ + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http2.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http2.h new file mode 100644 index 000000000..4a9ea38e7 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http2.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef IOT_EXPORT_HTTP2_H +#define IOT_EXPORT_HTTP2_H + +#ifdef __cplusplus +extern "C" { +#endif +typedef enum { + + HTTP2_FLAG_NONE = 0, + + HTTP2_FLAG_END_STREAM = 0x01, + +} http2_flag; + +typedef struct http2_list_s { + struct http2_list_s *prev; + struct http2_list_s *next; +} http2_list_t; + +typedef void (*on_user_header_callback)(int32_t stream_id, int cat, const uint8_t *name, uint32_t namelen, + const uint8_t *value, uint32_t valuelen, uint8_t flags); + +typedef void (*on_user_chunk_recv_callback)(int32_t stream_id, + const uint8_t *data, uint32_t len, uint8_t flags); + +typedef void (*on_user_stream_close_callback)(int32_t stream_id, uint32_t error_code); + +typedef void (*on_user_frame_send_callback)(int32_t stream_id, int type, uint8_t flags); + +typedef void (*on_user_frame_recv_callback)(int32_t stream_id, int type, uint8_t flags); + +typedef struct { + on_user_header_callback on_user_header_cb; + on_user_chunk_recv_callback on_user_chunk_recv_cb; + on_user_stream_close_callback on_user_stream_close_cb; + on_user_frame_send_callback on_user_frame_send_cb; + on_user_frame_recv_callback on_user_frame_recv_cb; +} http2_user_cb_t; + +typedef struct http2_connection { + void *network; /* iot network ptr */ + void *session; /* http2 session */ + int flag; /* check the stream is end or not */ + int status; + http2_user_cb_t *cbs; +} http2_connection_t; + +typedef struct http2_header_struct { + char *name; /* header name */ + char *value; /* the value of name */ + int namelen; /* the length of header name */ + int valuelen; /* the length of value */ +} http2_header; + +typedef struct http2_data_struct { + http2_header *header; /* header data. */ + int header_count; /* the count of header data. */ + char *data; /* send data. */ + int len; /* send data length. */ + int stream_id; /* send data over specify stream */ + int flag; /* send data flag. */ +} http2_data; + +/** +* @brief the http2 client connect. +* @param[in] pclient: http client. +* @return http2 client connection handler. +*/ +extern http2_connection_t *iotx_http2_client_connect(void *pclient, char *url, int port); + +http2_connection_t *iotx_http2_client_connect_with_cb(void *pclient, char *url, int port, http2_user_cb_t *cb); +/** +* @brief the http2 client send data. +* @param[in] handler: http2 client connection handler. +* @param[in] data: send data. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_client_send(http2_connection_t *conn, http2_data *h2_data); +/** +* @brief the http2 client receive data. +* @param[in] handler: http2 client connection handler. +* @param[in] data: receive data buffer. +* @param[in] data_len: buffer length. +* @param[in] len: receive data length. +* @param[in] timeout: receive data timeout. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_client_recv(http2_connection_t *conn, char *data, int data_len, int *len, int timeout); +/** +* @brief the http2 client connect. +* @param[in] handler: http2 client connection handler. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_client_disconnect(http2_connection_t *conn); +/** +* @brief the http2 client send ping to keep alive. +* @param[in] handler: http2 client connection handler. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_client_send_ping(http2_connection_t *conn); +/** +* @brief the http2 client get available windows size. +* @param[in] handler: http2 client connection handler. +* @return The window size. +*/ +extern int iotx_http2_get_available_window_size(http2_connection_t *conn); +/** +* @brief the http2 client receive windows size packet to update window. +* @param[in] handler: http2 client connection handler. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_update_window_size(http2_connection_t *conn); +/** +* @brief the http2 client performs the network I/O. +* @param[in] handler: http2 client connection handler. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_exec_io(http2_connection_t *connection); +#ifdef __cplusplus +} +#endif + +#endif /* IOT_EXPORT_HTTP2_H */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http2_stream.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http2_stream.h new file mode 100644 index 000000000..3b9005f5f --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_http2_stream.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef IOT_EXPORT_HTTP2_STREAM_H +#define IOT_EXPORT_HTTP2_STREAM_H + +#include "iot_export_http2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IOT_HTTP2_RES_OVERTIME_MS (10000) +#define IOT_HTTP2_KEEP_ALIVE_CNT (2) +#define IOT_HTTP2_KEEP_ALIVE_TIME (30*1000) /* in seconds */ + +#define MAKE_HEADER(NAME, VALUE) \ + { \ + (char *) NAME, (char *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 \ + } + +#define MAKE_HEADER_CS(NAME, VALUE) \ + { \ + (char *) NAME, (char *)VALUE, strlen(NAME) , strlen(VALUE) \ + } + +typedef struct { + char *product_key; + char *device_name; + char *device_secret; + char *url; + int port; +} device_conn_info_t; + +typedef struct { + http2_header *nva; + int num; +} header_ext_info_t; + +typedef enum { + STREAM_TYPE_DOWNLOAD, + STREAM_TYPE_UPLOAD, + STREAM_TYPE_AUXILIARY, + STREAM_TYPE_NUM +} stream_type_t; + +typedef void (*on_stream_header_callback)(uint32_t stream_id, char *channel_id, int cat, const uint8_t *name, + uint32_t namelen, const uint8_t *value, uint32_t valuelen, uint8_t flags, void *user_data); + +typedef void (*on_stream_chunk_recv_callback)(uint32_t stream_id, char *channel_id, + const uint8_t *data, uint32_t len, uint8_t flags, void *user_data); + +typedef void (*on_stream_close_callback)(uint32_t stream_id, char *channel_id, uint32_t error_code, void *user_data); + +typedef void (*on_stream_frame_send_callback)(uint32_t stream_id, char *channel_id, int type, uint8_t flags, void *user_data); + +typedef void (*on_stream_frame_recv_callback)(uint32_t stream_id, char *channel_id, int type, uint8_t flags,void *user_data); + +typedef void (*on_reconnect_callback)(); +typedef void (*on_disconnect_callback)(); + +typedef struct { + on_stream_header_callback on_stream_header_cb; + on_stream_chunk_recv_callback on_stream_chunk_recv_cb; + on_stream_close_callback on_stream_close_cb; + on_stream_frame_send_callback on_stream_frame_send_cb; + on_stream_frame_recv_callback on_stream_frame_recv_cb; + on_reconnect_callback on_reconnect_cb; + on_disconnect_callback on_disconnect_cb; +} http2_stream_cb_t; + +typedef struct { + char *stream; /* point to stream data buffer */ + uint32_t stream_len; /* file content length */ + uint32_t send_len; /* data had sent length */ + uint32_t packet_len; /* one packet length */ + const char *identify; /* path string to identify a stream service */ + int h2_stream_id; /* stream identifier which is a field in HTTP2 frame */ + char *channel_id; /* string return by server to identify a specific stream channel, + different from stream identifier which is a field in HTTP2 frame */ + void *user_data; /* user data brought in at stream open */ +} stream_data_info_t; + +#ifdef FS_ENABLED +typedef enum { + UPLOAD_FILE_NOT_EXIST = -9, + UPLOAD_FILE_READ_FAILED = -8, + UPLOAD_STREAM_OPEN_FAILED = -7, + UPLOAD_STREAM_SEND_FAILED = -6, + UPLOAD_MALLOC_FAILED = -5, + UPLOAD_NULL_POINT = -2, + UPLOAD_ERROR_COMMON = -1, + UPLOAD_SUCCESS = 0, +} http2_file_upload_result_t; + +typedef void (* upload_file_result_cb)(const char *path, int result, void *user_data); +DLL_IOT_API int IOT_HTTP2_Stream_UploadFile(void *handle, const char *file_path, const char *identify, + header_ext_info_t *header, + upload_file_result_cb cb, void *user_data); +#endif +DLL_IOT_API void *IOT_HTTP2_Connect(device_conn_info_t *conn_info, http2_stream_cb_t *user_cb); +DLL_IOT_API int IOT_HTTP2_Stream_Open(void *handle, stream_data_info_t *info, header_ext_info_t *header); +DLL_IOT_API int IOT_HTTP2_Stream_Send(void *handle, stream_data_info_t *info, header_ext_info_t *header); +DLL_IOT_API int IOT_HTTP2_Stream_Query(void *handle, stream_data_info_t *info, header_ext_info_t *header); +DLL_IOT_API int IOT_HTTP2_Stream_Close(void *handle, stream_data_info_t *info); +DLL_IOT_API int IOT_HTTP2_Disconnect(void *handle); + +#ifdef __cplusplus +} +#endif + +#endif /* IOT_EXPORT_FILE_UPLOADER_H */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_linkkit.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_linkkit.h new file mode 100644 index 000000000..eeaf737cf --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_linkkit.h @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOT_EXPORT_LINKKIT_H_ +#define _IOT_EXPORT_LINKKIT_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "iot_export.h" + +#define PRODUCT_KEY_MAXLEN (20 + 1) +#define DEVICE_NAME_MAXLEN (32 + 1) +#define DEVICE_SECRET_MAXLEN (64 + 1) +#define PRODUCT_SECRET_MAXLEN (64 + 1) + +#ifdef DEVICE_MODEL_GATEWAY +typedef enum _gateway_subdev_event_e +{ + ITM_EVENT_TOPO_DELETE_REPLY, + ITM_EVENT_SUBDEV_RESET_REPLY, + ITM_EVENT_TOPO_ADD_REPLY, + ITM_EVENT_COMBINE_LOGIN_REPLY, + ITM_EVENT_COMBINE_LOGOUT_REPLY, + ITM_EVENT_COMBINE_BATCH_LOGIN_REPLY, + ITM_EVENT_COMBINE_BATCH_LOGOUT_REPLY +}gateway_subdev_event_e; +#endif + +typedef enum { + IOTX_LINKKIT_DEV_TYPE_MASTER, + IOTX_LINKKIT_DEV_TYPE_SLAVE, + IOTX_LINKKIT_DEV_TYPE_MAX +} iotx_linkkit_dev_type_t; + +typedef struct { + char product_key[PRODUCT_KEY_MAXLEN]; + char product_secret[PRODUCT_SECRET_MAXLEN]; + char device_name[DEVICE_NAME_MAXLEN]; + char device_secret[DEVICE_SECRET_MAXLEN]; +} iotx_linkkit_dev_meta_info_t; + +typedef enum { + /* post property value to cloud */ + ITM_MSG_POST_PROPERTY, + + /* post device info update message to cloud */ + ITM_MSG_DEVICEINFO_UPDATE, + + /* post device info delete message to cloud */ + ITM_MSG_DEVICEINFO_DELETE, + + /* post raw data to cloud */ + ITM_MSG_POST_RAW_DATA, + + /* only for slave device, send login request to cloud */ + ITM_MSG_LOGIN, + + /* only for slave device, send logout request to cloud */ + ITM_MSG_LOGOUT, + + /* only for slave device, send login request to cloud */ + ITM_MSG_BATCH_LOGIN, + + /* only for slave device, send logout request to cloud */ + ITM_MSG_BATCH_LOGOUT, + + /* only for slave device, send delete topo request to cloud */ + ITM_MSG_DELETE_TOPO, + + /* connect subdev use new way*/ + ITM_MSG_CONNECT_SUBDEV, + + /* query ntp time from cloud */ + ITM_MSG_QUERY_TIMESTAMP, + + /* only for master device, query topo list */ + ITM_MSG_QUERY_TOPOLIST, + + /* only for master device, request reset subdev */ + ITM_MSG_SUBDEV_RESET, + + /* only for master device, qurey subdev device id*/ + ITM_MSG_QUERY_SUBDEV_ID, + + /* only for master device, qurey firmware ota data */ + ITM_MSG_QUERY_FOTA_DATA, + + /* only for master device, qurey config ota data */ + ITM_MSG_QUERY_COTA_DATA, + + /* only for master device, request config ota data from cloud */ + ITM_MSG_REQUEST_COTA, + + /* only for master device, request fota image from cloud */ + ITM_MSG_REQUEST_FOTA_IMAGE, + + /* reply event notify to cloud */ + ITM_MSG_EVENT_NOTIFY_REPLY, + +#ifdef DM_UNIFIED_SERVICE_POST + /* post data to cloud and this this unify method*/ + ITM_MSG_UNIFIED_SERVICE_POST, +#endif + + IOTX_LINKKIT_MSG_MAX +} iotx_linkkit_msg_type_t; + +/** + * @brief create a new device + * + * @param dev_type. type of device which will be created. see iotx_linkkit_dev_type_t + * @param meta_info. The product key, product secret, device name and device secret of new device. + * + * @return success: device id (>=0), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Open(iotx_linkkit_dev_type_t dev_type, iotx_linkkit_dev_meta_info_t *meta_info); + +/** + * @brief start device network connection. + * for master device, start to connect aliyun server. + * for slave device, send message to cloud for register new device and add topo with master device + * + * @param devid. device identifier. + * + * @return success: device id (>=0), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Connect(int devid); + +/** + * @brief try to receive message from cloud and dispatch these message to user event callback + * + * @param timeout_ms. timeout for waiting new message arrived + * + * @return void. + * + */ +DLL_IOT_API void IOT_Linkkit_Yield(int timeout_ms); + +/** + * @brief close device network connection and release resources. + * for master device, disconnect with aliyun server and release all local resources. + * for slave device, send message to cloud for delete topo with master device and unregister itself, then release device's resources. + * + * @param devid. device identifier. + * + * @return success: 0, fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Close(int devid); + + +/** + * @brief Report message to cloud + * + * @param devid. device identifier. + * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows: + * ITM_MSG_POST_PROPERTY + * ITM_MSG_DEVICEINFO_UPDATE + * ITM_MSG_DEVICEINFO_DELETE + * ITM_MSG_POST_RAW_DATA + * ITM_MSG_LOGIN + * ITM_MSG_LOGOUT + * + * @param payload. message payload. + * @param payload_len. message payload length. + * + * @return success: 0 or message id (>=1), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Report_Ext(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload, + int payload_len, int sento); +/** + * @brief Report message to cloud + * + * @param devid. device identifier. + * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows: + * ITM_MSG_POST_PROPERTY + * ITM_MSG_DEVICEINFO_UPDATE + * ITM_MSG_DEVICEINFO_DELETE + * ITM_MSG_POST_RAW_DATA + * ITM_MSG_LOGIN + * ITM_MSG_LOGOUT + * + * @param payload. message payload. + * @param payload_len. message payload length. + * + * @return success: 0 or message id (>=1), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Report(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload, + int payload_len); + +/** + * @brief post message to cloud + * + * @param devid. device identifier. + * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows: + * ITM_MSG_QUERY_TIMESTAMP + * ITM_MSG_QUERY_TOPOLIST + * ITM_MSG_QUERY_FOTA_DATA + * ITM_MSG_QUERY_COTA_DATA + * ITM_MSG_REQUEST_COTA + * ITM_MSG_REQUEST_FOTA_IMAGE + * + * @param payload. message payload. + * @param payload_len. message payload length. + * + * @return success: 0 or message id (>=1), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Query(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload, + int payload_len); + +/** + * @brief post event to cloud + * + * @param devid. device identifier. + * @param eventid. tsl event id. + * @param eventid_len. length of tsl event id. + * @param payload. event payload. + * @param payload_len. event payload length. + * + * @return success: message id (>=1), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len); + +#ifdef LOG_REPORT_TO_CLOUD + int check_target_msg(const char *input, int len); + void get_msgid(char *payload, int is_cloud); + void send_permance_info(char *input, int input_len, char *comments, int report_format); +#endif + + + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_mqtt.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_mqtt.h new file mode 100644 index 000000000..69028120f --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_mqtt.h @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOT_EXPORT_MQTT_H_ +#define _IOT_EXPORT_MQTT_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#define MUTLI_SUBSCIRBE_MAX (5) + +/* From mqtt_client.h */ +typedef enum { + IOTX_MQTT_QOS0 = 0, + IOTX_MQTT_QOS1, + IOTX_MQTT_QOS2, + IOTX_MQTT_QOS3_SUB_LOCAL +} iotx_mqtt_qos_t; + +typedef enum { + + /* Undefined event */ + IOTX_MQTT_EVENT_UNDEF = 0, + + /* MQTT disconnect event */ + IOTX_MQTT_EVENT_DISCONNECT = 1, + + /* MQTT reconnect event */ + IOTX_MQTT_EVENT_RECONNECT = 2, + + /* A ACK to the specific subscribe which specify by packet-id be received */ + IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS = 3, + + /* No ACK to the specific subscribe which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT = 4, + + /* A failed ACK to the specific subscribe which specify by packet-id be received*/ + IOTX_MQTT_EVENT_SUBCRIBE_NACK = 5, + + /* A ACK to the specific unsubscribe which specify by packet-id be received */ + IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS = 6, + + /* No ACK to the specific unsubscribe which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT = 7, + + /* A failed ACK to the specific unsubscribe which specify by packet-id be received*/ + IOTX_MQTT_EVENT_UNSUBCRIBE_NACK = 8, + + /* A ACK to the specific publish which specify by packet-id be received */ + IOTX_MQTT_EVENT_PUBLISH_SUCCESS = 9, + + /* No ACK to the specific publish which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_PUBLISH_TIMEOUT = 10, + + /* A failed ACK to the specific publish which specify by packet-id be received*/ + IOTX_MQTT_EVENT_PUBLISH_NACK = 11, + + /* MQTT packet published from MQTT remote broker be received */ + IOTX_MQTT_EVENT_PUBLISH_RECEIVED = 12, + + /* MQTT packet buffer overflow which the remaining space less than to receive byte */ + IOTX_MQTT_EVENT_BUFFER_OVERFLOW = 13, +} iotx_mqtt_event_type_t; + +/* topic information */ +typedef struct { + uint16_t packet_id; + uint8_t qos; + uint8_t dup; + uint8_t retain; + uint16_t topic_len; + uint32_t payload_len; + const char *ptopic; + const char *payload; +} iotx_mqtt_topic_info_t, *iotx_mqtt_topic_info_pt; + + +typedef struct { + + /* Specify the event type */ + iotx_mqtt_event_type_t event_type; + + /* + * Specify the detail event information. @msg means different to different event types: + * + * 1) IOTX_MQTT_EVENT_UNKNOWN, + * IOTX_MQTT_EVENT_DISCONNECT, + * IOTX_MQTT_EVENT_RECONNECT : + * Its data type is string and the value is detail information. + * + * 2) IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS, + * IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT, + * IOTX_MQTT_EVENT_SUBCRIBE_NACK, + * IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS, + * IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT, + * IOTX_MQTT_EVENT_UNSUBCRIBE_NACK + * IOTX_MQTT_EVENT_PUBLISH_SUCCESS, + * IOTX_MQTT_EVENT_PUBLISH_TIMEOUT, + * IOTX_MQTT_EVENT_PUBLISH_NACK : + * Its data type is @uint32_t and the value is MQTT packet identifier. + * + * 3) IOTX_MQTT_EVENT_PUBLISH_RECEIVED: + * Its data type is @iotx_mqtt_packet_info_t and see detail at the declare of this type. + * + * */ + void *msg; +} iotx_mqtt_event_msg_t, *iotx_mqtt_event_msg_pt; + + +/** + * @brief It define a datatype of function pointer. + * This type of function will be called when a related event occur. + * + * @param pcontext : The program context. + * @param pclient : The MQTT client. + * @param msg : The event message. + * + * @return none + */ +typedef void (*iotx_mqtt_event_handle_func_fpt)(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg); + + +/* The structure of MQTT event handle */ +typedef struct { + iotx_mqtt_event_handle_func_fpt h_fp; + void *pcontext; +} iotx_mqtt_event_handle_t, *iotx_mqtt_event_handle_pt; + + +/* The structure of MQTT initial parameter */ +typedef struct { + + uint16_t port; /* Specify MQTT broker port */ + const char *host; /* Specify MQTT broker host */ + const char *client_id; /* Specify MQTT connection client id*/ + const char *username; /* Specify MQTT user name */ + const char *password; /* Specify MQTT password */ + + /* Specify MQTT transport channel and key. + * If the value is NULL, it means that use TCP channel, + * If the value is NOT NULL, it means that use SSL/TLS channel and + * @pub_key point to the CA certification */ + const char *pub_key; + + uint8_t clean_session; /* Specify MQTT clean session or not*/ + uint32_t request_timeout_ms; /* Specify timeout of a MQTT request in millisecond */ + uint32_t keepalive_interval_ms; /* Specify MQTT keep-alive interval in millisecond */ + uint32_t write_buf_size; /* Specify size of write-buffer in byte */ + uint32_t read_buf_size; /* Specify size of read-buffer in byte */ + + iotx_mqtt_event_handle_t handle_event; /* Specify MQTT event handle */ + +} iotx_mqtt_param_t, *iotx_mqtt_param_pt; + +#ifdef MAL_ENABLED +#define IOT_MQTT_Construct MAL_MQTT_Construct +#define IOT_MQTT_Destroy MAL_MQTT_Destroy +#define IOT_MQTT_Yield MAL_MQTT_Yield +#define IOT_MQTT_CheckStateNormal MAL_MQTT_CheckStateNormal +#define IOT_MQTT_Subscribe_Sync MAL_MQTT_Subscribe_Sync +#define IOT_MQTT_Subscribe MAL_MQTT_Subscribe +#define IOT_MQTT_Unsubscribe MAL_MQTT_Unsubscribe +#define IOT_MQTT_Publish MAL_MQTT_Publish +#define IOT_MQTT_Publish_Simple MAL_MQTT_Publish_Simple + +DLL_IOT_API void *MAL_MQTT_Construct(iotx_mqtt_param_t *pInitParams); +DLL_IOT_API int MAL_MQTT_Destroy(void **phandle); +DLL_IOT_API int MAL_MQTT_Yield(void *handle, int timeout_ms); +DLL_IOT_API int MAL_MQTT_Subscribe(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext); +DLL_IOT_API int MAL_MQTT_Subscribe_Sync(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext, + int timeout_ms); +DLL_IOT_API int MAL_MQTT_Unsubscribe(void *handle, const char *topic_filter); +DLL_IOT_API int MAL_MQTT_Publish(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg); +DLL_IOT_API int MAL_MQTT_Publish_Simple(void *handle, const char *topic_name, int qos, void *data, int len); +#else /* MAL_ENABLED */ +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_mqtt mqtt + * @{ + */ + +/** + * @brief Construct the MQTT client + * This function initialize the data structures, establish MQTT connection. + * + * @param [in] pInitParams: specify the MQTT client parameter. + * + * @retval NULL : Construct failed. + * @retval NOT_NULL : The handle of MQTT client. + * @see None. + */ +DLL_IOT_API void *IOT_MQTT_Construct(iotx_mqtt_param_t *pInitParams); + + +/** + * @brief Deconstruct the MQTT client + * This function disconnect MQTT connection and release the related resource. + * + * @param [in] phandle: pointer of handle, specify the MQTT client. + * + * @retval 0 : Deconstruct success. + * @retval -1 : Deconstruct failed. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Destroy(void **phandle); + + +/** + * @brief Handle MQTT packet from remote server and process timeout request + * which include the MQTT subscribe, unsubscribe, publish(QOS >= 1), reconnect, etc.. + * + * @param [in] handle: specify the MQTT client. + * @param [in] timeout_ms: specify the timeout in millisecond in this loop. + * + * @return status. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Yield(void *handle, int timeout_ms); + + +/** + * @brief Post log information to cloud. + * + * @param [in] handle: specify the MQTT client. + * @param [in] levle: log level string + * @param [in] moduel: module string. + * @param [in] msg: log information string. + * + * @retval 0 : Post successful. + * @retval -1 : Post fail. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_LogPost(void *pHandle, const char *level, const char *module, const char *msg); + +/** + * @brief check whether MQTT connection is established or not. + * + * @param [in] handle: specify the MQTT client. + * + * @retval true : MQTT in normal state. + * @retval false : MQTT in abnormal state. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_CheckStateNormal(void *handle); + + +/** + * @brief Subscribe MQTT topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] topic_handle_func: specify the topic handle callback-function. + * @param [in] pcontext: specify context. When call 'topic_handle_func', it will be passed back. + * + * @retval -1 : Subscribe failed. + * @retval >=0 : Subscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Subscribe(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext); + +/** + * @brief Subscribe MQTT topic and wait suback. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] topic_handle_func: specify the topic handle callback-function. + * @param [in] pcontext: specify context. When call 'topic_handle_func', it will be passed back. + * @param [in] timeout_ms: time in ms to wait. + * + * @retval -1 : Subscribe failed. + * @retval >=0 : Subscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Subscribe_Sync(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext, + int timeout_ms); + + +/** + * @brief Unsubscribe MQTT topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * + * @retval -1 : Unsubscribe failed. + * @retval >=0 : Unsubscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Unsubscribe(void *handle, const char *topic_filter); + + +/** + * @brief Publish message to specific topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_name: specify the topic name. + * @param [in] topic_msg: specify the topic message. + * + * @retval -1 : Publish failed. + * @retval 0 : Publish successful, where QoS is 0. + * @retval >0 : Publish successful, where QoS is >= 0. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Publish(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg); +/** + * @brief Publish message to specific topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_name: specify the topic name. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] data: specify the topic message payload. + * @param [in] len: specify the topic message payload len. + * + * @retval -1 : Publish failed. + * @retval 0 : Publish successful, where QoS is 0. + * @retval >0 : Publish successful, where QoS is >= 0. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Publish_Simple(void *handle, const char *topic_name, int qos, void *data, int len); +/* From mqtt_client.h */ +/** @} */ /* end of api_mqtt */ + +/** @} */ /* end of api */ +#endif /* MAL_ENABLED */ + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_ota.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_ota.h new file mode 100644 index 000000000..703d3301f --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_ota.h @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __OTA_EXPORT_H__ +#define __OTA_EXPORT_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "iot_import.h" + +#define OTA_CH_SIGNAL_MQTT (0) +#define OTA_CH_SIGNAL_COAP (1) +#define OTA_CH_FETCH_HTTP (1) + + +typedef enum { + + IOT_OTAE_GENERAL = -1, + IOT_OTAE_INVALID_PARAM = -2, + IOT_OTAE_INVALID_STATE = -3, + IOT_OTAE_STR_TOO_LONG = -4, + IOT_OTAE_FETCH_FAILED = -5, + IOT_OTAE_NOMEM = -6, + IOT_OTAE_OSC_FAILED = -7, + IOT_OTAE_NONE = 0, + +} IOT_OTA_Err_t; + + +/* State of OTA */ +typedef enum { + IOT_OTAS_UNINITED = 0, /* Uninitialized State */ + IOT_OTAS_INITED, /* Initialized State */ + IOT_OTAS_FETCHING, /* Fetching firmware */ + IOT_OTAS_FETCHED /* Fetching firmware finish */ +} IOT_OTA_State_t; + +typedef enum { + IOT_OTAT_NONE, + IOT_OTAT_COTA, + IOT_OTAT_FOTA, + IOT_OTAT_FOTA_OFFLINE +} IOT_OTA_Type_t; + +/* Progress of OTA */ +typedef enum { + + /* Burn firmware file failed */ + IOT_OTAP_BURN_FAILED = -4, + + /* Check firmware file failed */ + IOT_OTAP_CHECK_FALIED = -3, + + /* Fetch firmware file failed */ + IOT_OTAP_FETCH_FAILED = -2, + + /* Initialized failed */ + IOT_OTAP_GENERAL_FAILED = -1, + + + /* [0, 100], percentage of fetch progress */ + + /* The minimum percentage of fetch progress */ + IOT_OTAP_FETCH_PERCENTAGE_MIN = 0, + + /* The maximum percentage of fetch progress */ + IOT_OTAP_FETCH_PERCENTAGE_MAX = 100 + +} IOT_OTA_Progress_t; + + +typedef enum { + IOT_OTAG_COTA_CONFIG_ID, + IOT_OTAG_COTA_CONFIG_SIZE, + IOT_OTAG_COTA_SIGN, + IOT_OTAG_COTA_SIGN_METHOD, + IOT_OTAG_COTA_URL, + IOT_OTAG_COTA_GETTYPE, + IOT_OTAG_OTA_TYPE, + IOT_OTAG_FETCHED_SIZE, /* option for get already fetched size */ + IOT_OTAG_FILE_SIZE, /* size of file */ + IOT_OTAG_MD5SUM, /* md5 in string format */ + IOT_OTAG_VERSION, /* version in string format */ + IOT_OTAG_CHECK_FIRMWARE, /* Check firmware is valid or not */ + IOT_OTAG_CHECK_CONFIG, /* Check config file is valid or not */ + IOT_OTAG_RESET_FETCHED_SIZE /* reset the size_fetched parameter to be 0 */ +} IOT_OTA_CmdType_t; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_ota ota + * @{ + */ + +/** + * @brief Initialize OTA module, and return handle. + * The MQTT client must be construct before calling this interface. + * + * @param [in] product_key: specify the product key. + * @param [in] device_name: specify the device name. + * @param [in] ch_signal: specify the signal channel. + * + * @retval 0 : Successful. + * @retval -1 : Failed. + * @see None. + */ +DLL_IOT_API void *IOT_OTA_Init(const char *product_key, const char *device_name, void *ch_signal); + + +/** + * @brief Deinitialize OTA module specified by the 'handle', and release the related resource. + * You must call this interface to release resource if reboot is not invoked after downloading. + * + * @param [in] handle: specify the OTA module. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_Deinit(void *handle); + + +/** + * @brief Report firmware version information to OTA server (optional). + * NOTE: please + * + * @param [in] handle: specify the OTA module. + * @param [in] version: specify the firmware version in string format. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_ReportVersion(void *handle, const char *version); + +/** + * @brief Report detail progress to OTA server (optional). + * NOTE: please + * + * @param [in] handle: specify the OTA module. + * @param [in] progress: specify the progress defined by 'IOT_OTA_Progress_t'. + * @param [in] msg: detail progress information in string. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg); + + +/** + * @brief Check whether is on fetching state + * + * @param [in] handle: specify the OTA module. + * + * @retval 1 : Yes. + * @retval 0 : No. + * @see None. + */ +DLL_IOT_API int IOT_OTA_IsFetching(void *handle); + + +/** + * @brief Check whether is on end-of-fetch state. + * + * @param [in] handle: specify the OTA module. + * + * @retval 1 : Yes. + * @retval 0 : False. + * @see None. + */ +DLL_IOT_API int IOT_OTA_IsFetchFinish(void *handle); + + +/** + * @brief fetch firmware from remote server with specific timeout value. + * NOTE: If you want to download more faster, the bigger 'buf' should be given. + * + * @param [in] handle: specify the OTA module. + * @param [out] buf: specify the space for storing firmware data. + * @param [in] buf_len: specify the length of 'buf' in bytes. + * @param [in] timeout_s: specify the timeout value in second. + * + * @retval < 0 : Error occur.. + * @retval 0 : No any data be downloaded in 'timeout_s' timeout period. + * @retval (0, len] : The length of data be downloaded in 'timeout_s' timeout period in bytes. + * @see None. + */ +DLL_IOT_API int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s); + + +/** + * @brief Get OTA information specified by 'type'. + * By this interface, you can get information like state, size of file, md5 of file, etc. + * + * @param [in] handle: handle of the specific OTA + * @param [in] type: specify what information you want, see detail 'IOT_OTA_CmdType_t' + * @param [out] buf: specify buffer for data exchange + * @param [in] buf_len: specify the length of 'buf' in byte. + * @return + @verbatim + NOTE: + 1) When type is IOT_OTAG_FETCHED_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 2) When type is IOT_OTAG_FILE_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 3) When type is IOT_OTAG_MD5SUM, 'buf' should be a buffer, and 'buf_len' should be 33. + 4) When type is IOT_OTAG_VERSION, 'buf' should be a buffer, and 'buf_len' should be OTA_VERSION_LEN_MAX. + 5) When type is IOT_OTAG_CHECK_FIRMWARE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 0, firmware is invalid; 1, firmware is valid. + @endverbatim + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, size_t buf_len); + + +/** + * @brief Get last error code. + * + * @param [in] handle: specify the OTA module. + * + * @return The error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_GetLastError(void *handle); + +/** @} */ /* end of api_ota */ +/** @} */ /* end of api */ + +#if defined(__cplusplus) +} +#endif + +#endif /* __OTA_EXPORT_H__ */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_reset.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_reset.h new file mode 100644 index 000000000..b7dd29189 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_reset.h @@ -0,0 +1,8 @@ +#ifndef __IOT_EXPORT_RESET_H__ +#define __IOT_EXPORT_RESET_H__ + +extern int iotx_sdk_reset_local(void); +extern int iotx_sdk_reset_cloud(iotx_vendor_dev_reset_type_t *reset_type); +extern int iotx_sdk_reset(iotx_vendor_dev_reset_type_t *reset_type); + +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_shadow.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_shadow.h new file mode 100644 index 000000000..a2551973d --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_shadow.h @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __SHADOW_EXPORT_H__ +#define __SHADOW_EXPORT_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* From shadow.h */ +#include +typedef enum { + IOTX_SHADOW_ACK_TIMEOUT = -1, + IOTX_SHADOW_ACK_NONE = 0, + IOTX_SHADOW_ACK_SUCCESS = 200, + IOTX_SHADOW_ACK_ERR_JSON_FMT_IS_INVALID = 400, + IOTX_SHADOW_ACK_ERR_METHOD_IS_NULL = 401, + IOTX_SHADOW_ACK_ERR_STATE_IS_NULL = 402, + IOTX_SHADOW_ACK_ERR_VERSION_IS_INVALID = 403, + IOTX_SHADOW_ACK_ERR_REPORTED_IS_NULL = 404, + IOTX_SHADOW_ACK_ERR_REPORTED_ATTRIBUTE_IS_NULL = 405, + IOTX_SHADOW_ACK_ERR_METHOD_IS_INVALID = 406, + IOTX_SHADOW_ACK_ERR_SHADOW_DOCUMENT_IS_NULL = 407, + IOTX_SHADOW_ACK_ERR_ATTRIBUTE_EXCEEDED = 408, + IOTX_SHADOW_ACK_ERR_SERVER_FAILED = 500, +} iotx_shadow_ack_code_t; + +typedef enum { + IOTX_SHADOW_READONLY, + IOTX_SHADOW_WRITEONLY, + IOTX_SHADOW_RW +} iotx_shadow_datamode_t; + +typedef enum { + IOTX_SHADOW_NULL, + IOTX_SHADOW_INT32, + IOTX_SHADOW_STRING, +} iotx_shadow_attr_datatype_t; + +typedef struct { + int flag_new; + uint32_t buf_size; + uint32_t offset; + char *buf; +} format_data_t, *format_data_pt; + +typedef struct { + uint32_t base_system_time; /* in millisecond */ + uint32_t epoch_time; +} iotx_shadow_time_t, *iotx_shadow_time_pt; + +typedef void (*iotx_push_cb_fpt)( + void *pcontext, + int ack_code, + const char *ack_msg, /* NOTE: NOT a string. */ + uint32_t ack_msg_len); + +struct iotx_shadow_attr_st; + +typedef void (*iotx_shadow_attr_cb_t)(struct iotx_shadow_attr_st *pattr); + +typedef enum{ + SHADOW_DOWNSTREAM_METHOD_IGNORE, + SHADOW_DOWNSTREAM_METHOD_CONTROL, + SHADOW_DOWNSTREAM_METHOD_REPLY, +}shadow_downstream_method_type; + +typedef struct iotx_shadow_attr_st { + iotx_shadow_datamode_t mode; /* data mode */ + const char *pattr_name; /* attribute name */ + void *pattr_data; /* pointer to the attribute data */ + iotx_shadow_attr_datatype_t attr_type; /* data type */ + uint32_t timestamp; /* timestamp in Epoch(Unix) format */ + iotx_shadow_attr_cb_t callback; /* callback when related control message come. */ + char flag_update; + shadow_downstream_method_type method_type; +} iotx_shadow_attr_t, *iotx_shadow_attr_pt; + +typedef struct { + iotx_mqtt_param_t mqtt; +} iotx_shadow_para_t, *iotx_shadow_para_pt; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_shadow shadow + * @{ + */ + +/** + * @brief Construct the Device Shadow. + * This function initialize the data structures, establish MQTT connection. + * and subscribe the topic: "/shadow/get/${product_key}/${device_name}". + * + * @param [in] pparam: The specific initial parameter. + * @retval NULL : Construct shadow failed. + * @retval NOT_NULL : Construct success. + * @see None. + */ +DLL_IOT_API void *IOT_Shadow_Construct(iotx_shadow_para_pt pparam); + +/** + * @brief Deconstruct the specific device shadow. + * + * @param [in] handle: The handle of device shaodw. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_Destroy(void *handle); + +/** + * @brief Handle MQTT packet from cloud and wait list. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] timeout_ms: Specify the timeout value in millisecond. In other words, the API block 'timeout'_ms millisecond maximumly. + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_Shadow_Yield(void *handle, uint32_t timeout_ms); + +/** + * @brief Create a data type registered to the server. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] pattr: The parameter which registered to the server. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_RegisterAttribute(void *handle, iotx_shadow_attr_pt pattr); + +/** + * @brief Delete the specific attribute. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] pattr: The parameter to be deleted from server. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_DeleteAttribute(void *handle, iotx_shadow_attr_pt pattr); + +/** + * @brief Start a process the structure of the data type format. + * + * @param [in] handle: The handle of device shaodw. + * @param [out] pformat: The format struct of device shadow. + * @param [in] buf: The buf which store device shadow. + * @param [in] size: Maximum length of device shadow attribute. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_PushFormat_Init( + void *handle, + format_data_pt pformat, + char *buf, + uint16_t size); + +/** + * @brief Format the attribute name and value for update. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] pformat: The format struct of device shadow. + * @param [in] pattr: To have created the data type of the format in the add member attributes. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_PushFormat_Add( + void *handle, + format_data_pt pformat, + iotx_shadow_attr_pt pattr); + +/** + * @brief Complete a process the structure of the data type format. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] pformat: The format struct of device shadow. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_PushFormat_Finalize(void *handle, format_data_pt pformat); + +/** + * @brief Update data to Cloud. It is a synchronous interface. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] data: The buf which synchronization with the server. + * @param [in] data_len: The length, in bytes, of the data pointed to by the data parameter. + * @param [in] timeout_s: The timeout_s in second.In other word,the API will block timeout_s second. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_Push( + void *handle, + char *data, + uint32_t data_len, + uint16_t timeout_s); + +/** + * @brief Update data to Cloud. It is a asynchronous interface. + * The result of this update will be informed by calling the callback function cb_fpt. + * @param [in] handle: The handle of device shadow. + * @param [in] data: The buf which synchronization with the server. + * @param [in] data_len: The length, in bytes, of the data pointed to by the data parameter. + * @param [in] timeout_s: Specify the timeout value in second. Shadow will timeout after 'timeout_s' second if did not receive push response. + * @param [in] cb_fpt: Specify the callback function which recieve ack_code from server after push device shadow. + * @param [in] pcontext: Specify the context which passed to the callback function. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +DLL_IOT_API int IOT_Shadow_Push_Async( + void *handle, + char *data, + unsigned int data_len, + uint16_t timeout_s, + iotx_push_cb_fpt cb_fpt, + void *pcontext); + +/** + * @brief Synchronize device shadow data from cloud. + * It is a synchronous interface. + * @param [in] handle: The handle of device shaodw. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_Pull(void *handle); + +/* From shadow.h */ + +/** @} */ /* end of api_shadow */ +/** @} */ /* end of api */ + +#if defined(__cplusplus) +} +#endif +#endif /* __SHADOW_EXPORT_H__ */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_state.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_state.h new file mode 100644 index 000000000..b55665d51 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_state.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2015-2019 Alibaba Group Holding Limited + */ + +#ifndef __IOT_EXPORTS_STATE_H__ +#define __IOT_EXPORTS_STATE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define STATE_BASE (0x0000) + +/* General: 0x0000 ~ 0x00FF */ +#define STATE_SUCCESS (STATE_BASE - 0x0000) + +/* General: 0x0000 ~ 0x00FF */ + +/* User Input: 0x0100 ~ 0x01FF */ +#define STATE_USER_INPUT_BASE (-0x0100) +#define STATE_USER_INPUT_NULL_POINTER (STATE_USER_INPUT_BASE - 0x0001) +#define STATE_USER_INPUT_OUT_RANGE (STATE_USER_INPUT_BASE - 0x0002) + +/* User Input: 0x0100 ~ 0x01FF */ + +/* System: 0x0200 ~ 0x02FF */ +#define STATE_SYS_DEPEND_BASE (-0x0200) +#define STATE_SYS_DEPEND_MALLOC (STATE_SYS_DEPEND_BASE - 0x0001) +#define STATE_SYS_DEPEND_KV_GET (STATE_SYS_DEPEND_BASE - 0x0002) +#define STATE_SYS_DEPEND_KV_SET (STATE_SYS_DEPEND_BASE - 0x0003) +#define STATE_SYS_DEPEND_KV_DELETE (STATE_SYS_DEPEND_BASE - 0x0004) +#define STATE_SYS_DEPEND_TIMER_CREATE (STATE_SYS_DEPEND_BASE - 0x0005) +#define STATE_SYS_DEPEND_TIMER_START (STATE_SYS_DEPEND_BASE - 0x0006) +#define STATE_SYS_DEPEND_TIMER_STOP (STATE_SYS_DEPEND_BASE - 0x0007) +#define STATE_SYS_DEPEND_TIMER_DELETE (STATE_SYS_DEPEND_BASE - 0x0008) +#define STATE_SYS_DEPEND_MUTEX_CREATE (STATE_SYS_DEPEND_BASE - 0x0009) +#define STATE_SYS_DEPEND_MUTEX_LOCK (STATE_SYS_DEPEND_BASE - 0x000A) +#define STATE_SYS_DEPEND_MUTEX_UNLOCK (STATE_SYS_DEPEND_BASE - 0x000B) +#define STATE_SYS_DEPEND_NWK_CLOSE (STATE_SYS_DEPEND_BASE - 0x000C) +#define STATE_SYS_DEPEND_NWK_TIMEOUT (STATE_SYS_DEPEND_BASE - 0x000D) +#define STATE_SYS_DEPEND_NWK_INVALID_HANDLE (STATE_SYS_DEPEND_BASE - 0x000E) + +/* System: 0x0200 ~ 0x02FF */ + +/* MQTT: 0x0300 ~ 0x03FF */ +#define STATE_MQTT_BASE (-0x0300) + +/* Deserialized CONNACK from MQTT server says protocol version is unacceptable */ +#define STATE_MQTT_CONNACK_VERSION_UNACCEPT (STATE_MQTT_BASE - 0x0001) +/* Deserialized CONNACK from MQTT server says identifier is rejected */ +#define STATE_MQTT_CONNACK_IDENT_REJECT (STATE_MQTT_BASE - 0x0002) +/* Deserialized CONNACK from MQTT server says service is not available */ +#define STATE_MQTT_CONNACK_SERVICE_NA (STATE_MQTT_BASE - 0x0003) +/* Deserialized CONNACK from MQTT server says it failed to authorize */ +#define STATE_MQTT_CONNACK_NOT_AUTHORIZED (STATE_MQTT_BASE - 0x0004) +/* Deserialized CONNACK from MQTT server says username/password is invalid */ +#define STATE_MQTT_CONNACK_BAD_USERDATA (STATE_MQTT_BASE - 0x0005) + +/* MQTT: 0x0300 ~ 0x03FF */ + +/* WiFi Provision: 0x0400 ~ 0x04FF */ +#define STATE_WIFI_BASE (-0x0400) + +/* WiFi Provision: 0x0400 ~ 0x04FF */ + +/* COAP: 0x0500 ~ 0x05FF */ +#define STATE_COAP_BASE (-0x0500) + +/* COAP: 0x0500 ~ 0x05FF */ + +/* HTTP: 0x0600 ~ 0x06FF */ +#define STATE_HTTP_BASE (-0x0600) + +/* HTTP: 0x0600 ~ 0x06FF */ + +/* OTA: 0x0700 ~ 0x07FF */ +#define STATE_OTA_BASE (-0x0700) + +/* OTA: 0x0700 ~ 0x07FF */ + +/* Bind: 0x0800 ~ 0x08FF */ +#define STATE_BIND_BASE (-0x0800) +#define STATE_BIND_SET_APP_TOKEN (STATE_BIND_BASE - 0x0001) +#define STATE_BIND_ALREADY_RESET (STATE_BIND_BASE - 0x0002) +#define STATE_BIND_REPORT_TOKEN (STATE_BIND_BASE - 0x0003) +#define STATE_BIND_REPORT_TOKEN_TIMEOUT (STATE_BIND_BASE - 0x0004) +#define STATE_BIND_REPORT_TOKEN_SUCCESS (STATE_BIND_BASE - 0x0005) +#define STATE_BIND_COAP_INIT_FAIL (STATE_BIND_BASE - 0x0006) +#define STATE_BIND_NOTIFY_TOKEN_SENT (STATE_BIND_BASE - 0x0007) +#define STATE_BIND_RECV_TOKEN_QUERY (STATE_BIND_BASE - 0x0008) +#define STATE_BIND_SENT_TOKEN_RESP (STATE_BIND_BASE - 0x0009) +#define STATE_BIND_RST_IN_PROGRESS (STATE_BIND_BASE - 0x000A) +#define STATE_BIND_MQTT_MSG_INVALID (STATE_BIND_BASE - 0x000B) +#define STATE_BIND_COAP_MSG_INVALID (STATE_BIND_BASE - 0x000C) + + +/* Bind: 0x0800 ~ 0x08FF */ + +/* Device Model: 0x0900 ~ 0x09FF */ +#define STATE_DEV_MODEL_BASE (-0x0900) + +/* Device Model: 0x0900 ~ 0x09FF */ + +/* SubDevice Mgmt: 0x0A00 ~ 0x0AFF */ +#define STATE_SUB_DEVICE_BASE (-0x0A00) + +/* SubDevice Mgmt: 0x0A00 ~ 0x0AFF */ + +#ifdef __cplusplus +} +#endif +#endif /* __IOT_EXPORTS_STATE_H__ */ + diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_ticknotify.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_ticknotify.h new file mode 100644 index 000000000..931f0c4b3 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_ticknotify.h @@ -0,0 +1,10 @@ +#ifndef _TICK_NOTIFY_H +#define _TICK_NOTIFY_H 1 + +#include "stdint.h" + +void *iotx_tick_notify_init(); +int iotx_tick_notify_deinit(); +int iotx_get_notify_time(uint64_t *tick); + +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_timer.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_timer.h new file mode 100644 index 000000000..eead2bc8a --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/iot_export_timer.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_EXPORT_TIMER_H__ +#define __IOT_EXPORT_TIMER_H__ + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +extern "C" { +#endif +#ifdef AIOT_DEVICE_TIMER_ENABLE +#include "iotx_log.h" + + #define DEVICETIMER "DeviceTimer" + #define DeviceTimerSize 13 + + #define DS "dev_timer" + #define DS_ERR(...) log_err(TS, __VA_ARGS__) + #define DS_WRN(...) log_warning(TS, __VA_ARGS__) + #define DS_INFO(...) log_info(TS, __VA_ARGS__) + #define DS_DEBUG(...) log_debug(TS, __VA_ARGS__) + typedef void (*devicetimer_callback)(const char *report_data, const char *property_name, const char *data); + int aiot_device_timer_init(const char **devicetimer_list, uint8_t num_devicetimer_list, devicetimer_callback timer_service_cb); + int deviceTimerParse(const char *input, uint8_t src, int save); + int aiot_device_timer_inited(void); + int aiot_device_timer_clear(void); +#else +#define NUM_OF_CONTROL_TARGETS 30 +#define NUM_OF_TARGETS_FLOAT 10 +#define NUM_OF_TARGETS_STRING 3 +#define NUM_OF_TSL_TYPES 3 /* 1:int/enum/bool; 2:float/double; 3:text/date */ + +#define STRING_MAX_LEN 80 +#define DAYS_OF_WEEK 7 +// #define ENABLE_LED_HSV +// #define ENABLE_LED_RGB +// #define ENABLE_LED_HSL + +void timer_service_clear(void); + +typedef void (*callback_fun)(const char *report_data, const char *property_name, int i_value, + double d_value, const char * s_value, int prop_idx); +typedef void (*callback_ntp_fun)(); + +int timer_service_init(const char **control_list, uint8_t num_control_list, + const char **countdownlist_target, uint8_t num_countdownlist_target, + const char **localtimer_list, uint8_t num_localtimer_list, + callback_fun timer_service_cb, int *num_of_tsl_type, callback_ntp_fun timer_ntp_cb); +int timer_service_property_set(const char* data); +char *timer_service_property_get(const char *request); + +#endif + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif + +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/linkkit_export.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/linkkit_export.h new file mode 100644 index 000000000..e5e18c637 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/linkkit_export.h @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef LINKKIT_EXPORT_H +#define LINKKIT_EXPORT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +typedef void (*handle_post_cb_fp_t)(const void *thing_id, int respons_id, int code, const char *response_message, + void *ctx); +typedef void (*handle_subdev_cb_fp_t)(const void *thing_id, int code, const char *response_message, int success, + void *ctx); + +typedef struct _linkkit_ops { +#ifdef LOCAL_CONN_ENABLE + int (*on_connect)(void *ctx, int cloud); /* true: cloud connection; false: local connection */ + int (*on_disconnect)(void *ctx, int cloud); /* true: cloud connection; false: local connection */ +#else + int (*on_connect)(void *ctx); /* true: cloud connection; false: local connection */ + int (*on_disconnect)(void *ctx); /* true: cloud connection; false: local connection */ +#endif + int (*raw_data_arrived)(const void *thing_id, const void *data, int len, void *ctx); + int (*thing_create)(const void *thing_id, void *ctx); + int (*thing_enable)(const void *thing_id, void *ctx); + int (*thing_disable)(const void *thing_id, void *ctx); + int (*thing_call_service)(const void *thing_id, const char *service, int request_id, void *ctx); + int (*thing_prop_changed)(const void *thing_id, const char *property, void *ctx); + int (*linkit_data_arrived)(const void *thing_id, const void *data, int len, void *ctx); +} linkkit_ops_t; + +typedef enum _linkkit_loglevel { + linkkit_loglevel_emerg = 0, + linkkit_loglevel_crit, + linkkit_loglevel_error, + linkkit_loglevel_warning, + linkkit_loglevel_info, + linkkit_loglevel_debug, +} linkkit_loglevel_t; + +/* domain type */ +/* please sync with dm_cloud_domain_type_t */ +typedef enum { + /* shanghai */ + linkkit_cloud_domain_shanghai, + /* singapore */ + linkkit_cloud_domain_singapore, + /* japan */ + linkkit_cloud_domain_japan, + /* america */ + linkkit_cloud_domain_america, + /* germany */ + linkkit_cloud_domain_germany, + + linkkit_cloud_domain_max, +} linkkit_cloud_domain_type_t; + +/* device info related operation */ +typedef enum { + linkkit_extended_info_operate_update, + linkkit_extended_info_operate_delete, + + linkkit_deviceinfo_operate_max, +} linkkit_extended_info_operate_t; + +/** + * @brief dispatch message of queue for further process. + * + * @return void* + */ +DLL_IOT_API void *linkkit_dispatch(void); + +typedef enum { + linkkit_opt_property_post_reply, /* data type: int */ + linkkit_opt_event_post_reply, /* data type: int */ + linkkit_opt_property_set_reply /* data type: int */ +} linkkit_opt_t; + +/** + * @brief get leave signal. + * + * + * @return int,0 no leave signal, 1 get a leave signal + */ +DLL_IOT_API int being_deprecated linkkit_is_try_leave(); + +/** + * @brief start linkkit routines, and install callback funstions(async type for cloud connecting). + * + * @param opt, specify the option need to be set. + * @param data, specify the option value. + * + * @return int, 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_set_opt(linkkit_opt_t opt, void *data); + +/** + * @brief start linkkit routines, and install callback funstions(async type for cloud connecting). + * + * @param max_buffered_msg, specify max buffered message size. + * @param ops, callback function struct to be installed. + * @param get_tsl_from_cloud, config if device need to get tsl from cloud(!0) or local(0), if local selected, must invoke linkkit_set_tsl to tell tsl to dm after start complete. + * @param log_level, config log level. + * @param user_context, user context pointer. + * @param domain_type, specify the could server domain. + * + * @return int, 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_start(int max_buffered_msg, int get_tsl_from_cloud, + linkkit_loglevel_t log_level, + linkkit_ops_t *ops, + linkkit_cloud_domain_type_t domain_type, void *user_context); + +/** + * @brief stop linkkit routines. + * + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_end(void); + +/** + * @brief install user tsl. + * + * @param tsl, tsl string that contains json description for thing object. + * @param tsl_len, tsl string length. + * + * @return pointer to thing object, NULL when fails. + */ +DLL_IOT_API void *linkkit_set_tsl(const char *tsl, int tsl_len); + +/* patterns: */ +/* method: + * set_property_/event_output_/service_output_value: + * method_set, thing_id, identifier, value */ + +typedef enum { + linkkit_method_set_property_value = 0, + linkkit_method_set_event_output_value, + linkkit_method_set_service_output_value, + + linkkit_method_set_number, +} linkkit_method_set_t; + +/** + * @brief set value to property, event output, service output items. + * if identifier is struct type or service output type or event output type, use '.' as delimeter like "identifier1.ientifier2" + * to point to specific item. + * value and value_str could not be NULL at the same time; + * if value and value_str both as not NULL, value shall be used and value_str will be ignored. + * if value is NULL, value_str not NULL, value_str will be used. + * in brief, value will be used if not NULL, value_str will be used only if value is NULL. + * + * @param method_set, specify set value type. + * @param thing_id, pointer to thing object, specify which thing to set. + * @param identifier, property, event output, service output identifier. + * @param value. The value to be set, data type decided by data type of property as follows: + * int: int*, float: float*, double: double*, + * text: char*, enum: int*, date: char*, bool: int* + * + * @param value_str, value to set in string format if value is null. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_set_value(linkkit_method_set_t method_set, const void *thing_id, + const char *identifier, + const void *value, const char *value_str); + +typedef enum { + linkkit_method_get_property_value = 0, + linkkit_method_get_event_output_value, + linkkit_method_get_service_input_value, + linkkit_method_get_service_output_value, + + linkkit_method_get_number, +} linkkit_method_get_t; + +/** + * @brief get value from property, event output, service input/output items. + * if identifier is struct type or service input/output type or event output type, use '.' as delimeter like "identifier1.ientifier2" + * to point to specific item. + * value and value_str could not be NULL at the same time; + * if value and value_str both as not NULL, value shall be used and value_str will be ignored. + * if value is NULL, value_str not NULL, value_str will be used. + * in brief, value will be used if not NULL, value_str will be used only if value is NULL. + * @param method_get, specify get value type. + * @param thing_id, pointer to thing object, specify which thing to get. + * @param identifier, property, event output, service input/output identifier. + * @param value. The variable to store value, data type decided by data type of property as follows: + * int: int*, float: float*, double: double*, + * text: char**, enum: int*, date: char**, bool: int* + * + * @param value_str, value to get in string format. If success, memory of *value_str will be allocated, + * user should free the memory. + * + * @warning if data type is text or date, *value well be end with '\0'. + * the memory allocated to *value must be free by user. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_get_value(linkkit_method_get_t method_get, const void *thing_id, + const char *identifier, + void *value, char **value_str); + + +/** + * @brief answer to a service when a service requested by cloud. + * + * @param thing_id, pointer to thing object. + * @param service_identifier, service identifier to answer, user should get this identifier from handle_dm_callback_fp_t type callback + * report that "dm_callback_type_service_requested" happened, use this function to generate response to the service sender. + * @param response_id, id value in response payload. its value is from "dm_callback_type_service_requested" type callback function. + * use the same id as the request to send response as the same communication session. + * @param code, code value in response payload. for example, 200 when service successfully executed, 400 when not successfully executed. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_answer_service(const void *thing_id, const char *service_identifier, + int response_id, int code); + +/** + * @brief answer a down raw service when a raw service requested by cloud, or invoke a up raw service to cloud. + * + * @param thing_id, pointer to thing object. + * @param is_up_raw, specify up raw(not 0) or down raw reply(0). + * @param raw_data, raw data that sent to cloud. + * @param raw_data_length, raw data length that sent to cloud. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_invoke_raw_service(const void *thing_id, int is_up_raw, void *raw_data, + int raw_data_length); + +/** + * @brief trigger extended info update procedure. + * + * @param thing_id, pointer to thing object. + * @param params, json type string that user to send to cloud. + * @param linkkit_extended_info_operation, specify update type or delete type. + * + * @return 0 when success, -1 when fail. + */ + +DLL_IOT_API int being_deprecated linkkit_trigger_extended_info_operate(const void *thing_id, const char *params, + linkkit_extended_info_operate_t linkkit_extended_info_operation); + +/** + * @brief trigger a event to post to cloud. + * + * @param thing_id, pointer to thing object. + * @param event_identifier, event identifier to trigger. + * @param cb, callback function of event post. + * + * @return >=0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_trigger_event(const void *thing_id, const char *event_identifier, + handle_post_cb_fp_t cb); + +/** + * @brief post property to cloud. + * + * @param thing_id, pointer to thing object. + * @param property_identifier, used when trigger event with method "event.property.post", if set, post specified property, if NULL, post all. + * @param cb, callback function of property post. + * + * @return >=0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_post_property(const void *thing_id, const char *property_identifier, + handle_post_cb_fp_t cb); + +/** + * @brief this function used to yield when want to receive or send data. + * if multi-thread enabled, user should NOT call this function. + * + * @param timeout_ms, timeout value in ms. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_yield(int timeout_ms); + +typedef enum { + service_cota_callback_type_new_version_detected = 10, + + service_cota_callback_type_number, +} service_cota_callback_type_t; + +typedef void (*handle_service_cota_callback_fp_t)(service_cota_callback_type_t callback_type, const char *configid, + uint32_t configsize, + const char *gettype, + const char *sign, + const char *signmethod, + const char *cota_url); + +/** + * @brief this function used to register callback for config ota. + * + * @param callback_fp, user callback which register to cota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_cota_init(handle_service_cota_callback_fp_t callback_fp); + +/** + * @brief this function used to execute cota process. + * + * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin. + * @param data_buf_length, data buf length that used to do ota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_invoke_cota_service(void *data_buf, int data_buf_length); + +/** + * @brief this function used to trigger cota process. + * + * @param config_scope, remote config scope, should be "product". + * @param get_type, remote config file type, should be "file". + * @param attribute_Keys, reserved. + * @param option, reserved. + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_invoke_cota_get_config(const char *config_scope, const char *get_type, + const char *attribute_Keys, void *option); + +typedef enum { + service_fota_callback_type_new_version_detected = 10, + + service_fota_callback_type_number, +} service_fota_callback_type_t; + +typedef void (*handle_service_fota_callback_fp_t)(service_fota_callback_type_t callback_type, const char *version); + +/** + * @brief this function used to register callback for firmware ota. + * + * @param callback_fp, user callback which register to fota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_fota_init(handle_service_fota_callback_fp_t callback_fp); + +/** + * @brief this function used to execute fota process. + * + * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin. + * @param data_buf_length, data buf length that used to do ota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_invoke_fota_service(void *data_buf, int data_buf_length); + +/** + * @brief this function used to get NTP time from cloud. + * + * @param ntp_reply_cb, user callback which register to ntp request. + * when cloud returns ntp reply, sdk would trigger the callback function + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_ntp_time_request(void (*ntp_reply_cb)(const char *ntp_offset_time_ms)); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LINKKIT_EXPORT_H */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/linkkit_gateway_export.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/linkkit_gateway_export.h new file mode 100644 index 000000000..21724ad6d --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/exports/linkkit_gateway_export.h @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef LINKKIT_GATEWAY_EXPORT_H +#define LINKKIT_GATEWAY_EXPORT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef _WIN32 +#ifdef DLL_IOT_EXPORTS +#define DLL_IOT_API __declspec(dllexport) +#else +#define DLL_IOT_API __declspec(dllimport) +#endif +#else +#define DLL_IOT_API +#endif + +#if defined (__CC_ARM) +#define ssize_t int +#elif defined (__ICCARM__) +#define ssize_t int +#endif + +/***************************Gateway Interface***************************/ + +enum { + LINKKIT_EVENT_CLOUD_DISCONNECTED = 0, /* cloud disconnected */ + LINKKIT_EVENT_CLOUD_CONNECTED = 1, /* cloud connected */ + LINKKIT_EVENT_SUBDEV_DELETED = 2, /* subdev deleted */ + LINKKIT_EVENT_SUBDEV_PERMITED = 3, /* subdev permit join */ + LINKKIT_EVENT_SUBDEV_SETUP = 4, /* subdev install */ +}; + +/* + * option | default | minimum | maximum + *--------------------------------|---------|---------|--------- + * LINKKIT_OPT_MAX_MSG_SIZE | 20480 | 512 | 51200 + * LINKKIT_OPT_MAX_MSG_QUEUE_SIZE | 16 | 2 | 32 + * LINKKIT_OPT_THREAD_POOL_SIZE | 4 | 1 | 16 + * LINKKIT_OPT_THREAD_STACK_SIZE | 8192 | 1024 | 8388608 + * LINKKIT_OPT_LOG_LEVEL | 3 | 0 | 5 + */ + +enum { + LINKKIT_OPT_MAX_MSG_SIZE = 1, + LINKKIT_OPT_MAX_MSG_QUEUE_SIZE = 2, + LINKKIT_OPT_THREAD_POOL_SIZE = 3, + LINKKIT_OPT_THREAD_STACK_SIZE = 4, + LINKKIT_OPT_PROPERTY_POST_REPLY = 5, /* data type: int */ + LINKKIT_OPT_EVENT_POST_REPLY = 6, /* data type: int */ + LINKKIT_OPT_PROPERTY_SET_REPLY = 7 /* data type: int */ +}; + +typedef struct { + int event_type; /* see LINKKIT_EVENT_XXX for more details */ + + union { + struct { + char *productKey; + char *deviceName; + } subdev_deleted; + + struct { + char *productKey; + int timeoutSec; + } subdev_permited; + + struct { + char *subdevList; /* json format:[{"productKey":"","deviceName":""},...] */ + } subdev_install; + } event_data; +} linkkit_event_t; + +typedef struct linkkit_params_s { + int maxMsgSize; /* max message size */ + int maxMsgQueueSize; /* max message queue size */ + + int threadPoolSize; /* number threads in pool */ + int threadStackSize; /* default thread stack size */ + + int (*event_cb)(linkkit_event_t *ev, void *ctx); + + /* user private data */ + void *ctx; +} linkkit_params_t; + +/** + * @brief get default initialize parameters + * + * @return linkkit default parameters. + */ +linkkit_params_t *linkkit_gateway_get_default_params(void); + +/** + * @brief set option in paremeters + * + * @param params, linkkit initialize parameters, return from linkkit_gateway_get_default_params(). + * @param option, see LINKKIT_OPT_XXX for more detail. + * @param value, value of option. + * @param value_len, value length. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_setopt(linkkit_params_t *params, int option, void *value, int value_len); + +/** + * @brief set event callback + * + * @param params, linkkit initialize parameters, return from linkkit_gateway_get_default_params(). + * @param event_cb, event callback. + * @param ctx, user private data. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_set_event_callback(linkkit_params_t *params, int (*event_cb)(linkkit_event_t *ev, + void *ctx), + void *ctx); + +/** + * @brief linkkit initialization. + * + * @param initParams, linkkit initialize parameters, see linkkit_params_t for more detail. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_init(linkkit_params_t *initParams); + +/** + * @brief linkkit deinitialization. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_exit(void); + +typedef struct { + + int (*register_complete)(void *ctx); + /** + * @brief get property callback. + * + * @param in, properties to be get, in JSON array format, terminated by NULL. + * @param out, output buffer fill by user, in json format, terminated by NULL. + * @param out_len, out buffer length. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create() + * + * @return 0 when success, -1 when fail. + */ + int (*get_property)(char *in, char *out, int out_len, void *ctx); + + /** + * @brief set property callback. + * + * @param in, properties to be set, in JSON object format, terminated by NULL. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create() + * + * @return 0 when success, -1 when fail. + */ + int (*set_property)(char *in, void *ctx); + + /** + * @brief call service callback. + * + * @param identifier, service identifier, available services define in TSL file. + * @param in, service input data, in JSON object format, terminated by NULL. + * @param out, service output, this buffer will be filled by user, in json format, terminated by NULL. + * @param out_len, out buffer length. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ + int (*call_service)(char *identifier, char *in, char *out, int out_len, void *ctx); + + /** + * @brief raw data from cloud. + * + * @param in, input data from cloud. + * @param in_len, input data length. + * @param out, output data to cloud, allocated by linkkit fill by user, no need to be free. + * @param out_len, out buffer length. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * + * @return output data size. < 0 when fail. + */ + ssize_t (*down_rawdata)(const void *in, int in_len, void *out, int out_len, void *ctx); + + /** + * @brief return data from cloud when calling linkkit_gateway_post_rawdata(). + * + * @param data, return raw data from cloud. + * @param len, data length. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ + int (*post_rawdata_reply)(const void *data, int len, void *ctx); +} linkkit_cbs_t; + +/** + * @brief start linkkit gateway routines and install callback funstions. + * + * @param cbs, callback function struct to be installed. + * @param ctx, user context pointer. + * + * @return device id, 0 > when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_start(linkkit_cbs_t *cbs, void *ctx); + +/** + * @brief stop linkkit gateway. + + * @param devid, device id return from linkkit_gateway_start(). + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_stop(int devid); + +/** + * @brief register subdev to gateway. + + * @param productKey, subdev's product key. + * @param deviceName, subdev's device name. + * @param deviceSecret, subdev's device secret. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_register(char *productKey, char *deviceName, char *deviceSecret); + +/** + * @brief deregister subdev from gateway. + + * @param productKey, subdev's product key. + * @param deviceName, subdev's device name. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_unregister(char *productKey, char *deviceName); + +/** + * @brief create subdev and install callback funstions. + * + * @param productKey, subdev's product key. + * @param deviceName, subdev's device name. + * @param cbs, callback function struct to be installed. + * @param ctx, user context pointer. + * + * @return device id, 0 > when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_create(char *productKey, char *deviceName, linkkit_cbs_t *cbs, void *ctx); + +/** + * @brief destroy subdev by device id. + + * @param devid, device id return from linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_destroy(int devid); + +/** + * @brief make subdev accessible from cloud. + + * @param devid, device id return from linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_login(int devid); + +/** + * @brief make subdev inaccessible on cloud. + + * @param devid, device id return from linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_logout(int devid); + +enum { + LINKKIT_STATE_ENABLED = 0, /* device is enabled by cloud */ + LINKKIT_STATE_DISABLED, /* device is disabled by cloud */ + LINKKIT_STATE_REMOVED, /* device is deleted by cloud */ +}; + +typedef struct { + char *productKey; /* device's product key */ + char *deviceName; /* device's device name */ + + int devtype; /* Device Type: 0 - gateway, 1 - subdev */ + int login; /* Login State: 0 - logout, 1 - login */ + int state; /* Device State: see LINKKIT_STATE_xxx */ + int online; /* 0 - offline, 1 - online */ +} linkkit_devinfo_t; + +/** + * @brief get device infomation specific by devid. + * + * @param devinfo, device information, see linkkit_devinfo_t for more detail. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_get_devinfo(int devid, linkkit_devinfo_t *devinfo); + +/** + * @brief post event to cloud. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param identifier, event identifier, see tsl file for more detail. + * @param event, event data, in JSON format. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_trigger_event_json_sync(int devid, char *identifier, char *event, int timeout_ms); + +/** + * @brief post event to cloud asynchronously. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param identifier, event identifier, see tsl file for more detail. + * @param event, event data, in JSON format. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * @param func, callback function when success(retval > 0), timeout(retval = 0) or failed(retval < 0). + * @param ctx, user data passed to 'func'. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_trigger_event_json(int devid, char *identifier, char *event, int timeout_ms, + void (*func)(int retval, void *ctx), void *ctx); + + +/** + * @brief post property to cloud. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param property, property data, in JSON format. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_post_property_json_sync(int devid, char *property, int timeout_ms); + +/** + * @brief post property to cloud asynchronously. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param property, property data, in JSON format. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * @param func, callback function when success(retval > 0), timeout(retval = 0) or failed(retval < 0). + * @param ctx, user data passed to 'func'. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_post_property_json(int devid, char *property, int timeout_ms, + void (*func)(int retval, void *ctx), + void *ctx); + +/** + * @brief post raw data to cloud. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param data, raw data buffer pointer. + * @param len, raw data length. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_post_rawdata(int devid, void *data, int len); + +typedef enum { + LINKKIT_OTA_EVENT_NEW_VERSION_DETECTED = 1, +} linkkit_ota_event_t; + +typedef enum { + service_fota_callback_type_new_version_detected = 10, + + service_fota_callback_type_number, +} service_fota_callback_type_t; + +typedef void (*handle_service_fota_callback_fp_t)(service_fota_callback_type_t callback_type, const char *version); + +/** + * @brief this function used to register callback for firmware ota. + * + * @param callback_fp, user callback which register to fota. (NULL for unregister) + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_fota_init(handle_service_fota_callback_fp_t callback_fp); + +/** + * @brief this function used to execute fota process. + * + * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin. + * @param data_buf_length, data buf length that used to do ota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_invoke_fota_service(void *data_buf, int data_buf_length); + +typedef struct { + char *attrKey; /* the key of extend info. */ + char *attrValue; /* the value of extend info. */ +} linkkit_extinfo_t; + +/** + * @brief post group of extend info to cloud + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param extinfos, group of extend info to be post. + * @param nb_extinfos, number of extend infos in extinfos. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_post_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos, + int timeout_ms); + +/** + * @brief delete extend info specific by key + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param extinfos, group of extend info to be deleted, attrValue in linkkit_extinfo_t will be ignore. + * @param nb_extinfos, number of extend infos in extinfos. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_delete_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos, + int timeout_ms); + +/** + * @brief get number devices currently in gateway + * + * @return number devinfos. + */ +DLL_IOT_API int linkkit_gateway_get_num_devices(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LINKKIT_GATEWAY_EXPORT_H */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_awss.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_awss.h new file mode 100644 index 000000000..64ff0062e --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_awss.h @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_IMPORT_AWSS_H__ +#define __IOT_IMPORT_AWSS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _IN_OPT_ +#define _IN_OPT_ +#endif + +#ifndef DLL_HAL_API +#define DLL_HAL_API +#endif + +#ifndef _IN_ +#define _IN_ +#endif + +#ifndef _OU_ +#define _OU_ +#endif + + +#define STR_SHORT_LEN (32) +#ifndef ETH_ALEN +#define ETH_ALEN (6) +#endif +#define HAL_MAX_SSID_LEN (32 + 1) /* ssid: 32 octets at most, include the NULL-terminated */ +#define HAL_MAX_PASSWD_LEN (64 + 1) /* password: 8-63 ascii */ +#define WLAN_CONNECTION_TIMEOUT_MS (30 * 1000) + +/** + * @brief 获取配网服务(`AWSS`)的超时时间长度, 单位是毫秒 + * + * @return 超时时长, 单位是毫秒 + * @note 推荐时长是60,0000毫秒 + */ +DLL_HAL_API int HAL_Awss_Get_Timeout_Interval_Ms(void); + +/** + * @brief 获取在每个信道(`channel`)上扫描的时间长度, 单位是毫秒 + * + * @return 时间长度, 单位是毫秒 + * @note 推荐时长是200毫秒到400毫秒 + */ +DLL_HAL_API int HAL_Awss_Get_Channelscan_Interval_Ms(void); + +/* link type */ +enum AWSS_LINK_TYPE { + /* rtos HAL choose this type */ + AWSS_LINK_TYPE_NONE, + + /* linux HAL may choose the following type */ + AWSS_LINK_TYPE_PRISM, + AWSS_LINK_TYPE_80211_RADIO, + AWSS_LINK_TYPE_80211_RADIO_AVS, + AWSS_LINK_TYPE_HT40_CTRL /* for espressif HAL, see struct ht40_ctrl */ +}; + +struct HAL_Ht40_Ctrl { + uint16_t length; + uint8_t filter; + signed char rssi; +}; + +/** + * @brief 802.11帧的处理函数, 可以将802.11 Frame传递给这个函数 + * + * @param[in] buf @n 80211 frame buffer, or pointer to struct ht40_ctrl + * @param[in] length @n 80211 frame buffer length + * @param[in] link_type @n AWSS_LINK_TYPE_NONE for most rtos HAL, + * and for linux HAL, do the following step to check + * which header type the driver supported. + @verbatim + a) iwconfig wlan0 mode monitor #open monitor mode + b) iwconfig wlan0 channel 6 #switch channel 6 + c) tcpdump -i wlan0 -s0 -w file.pacp #capture 80211 frame & save + d) open file.pacp with wireshark or omnipeek + check the link header type and fcs included or not + @endverbatim + * @param[in] with_fcs @n 80211 frame buffer include fcs(4 byte) or not + * @param[in] rssi @n rssi of packet, range of [-127, -1] + */ +typedef int (*awss_recv_80211_frame_cb_t)(char *buf, int length, + enum AWSS_LINK_TYPE link_type, int with_fcs, signed char rssi); + +/** + * @brief 设置Wi-Fi网卡工作在监听(Monitor)模式, 并在收到802.11帧的时候调用被传入的回调函数 + * + * @param[in] cb @n A function pointer, called back when wifi receive a frame. + */ +DLL_HAL_API void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb); + +/** + * @brief 设置Wi-Fi网卡离开监听(Monitor)模式, 并开始以站点(Station)模式工作 + */ +DLL_HAL_API void HAL_Awss_Close_Monitor(void); + +/** + * @brief 开启设备热点(SoftAP模式) + * + * @param[in] ssid @n 热点的ssid字符; + * @param[in] passwd @n 热点的passwd字符; + * @param[in] beacon_interval @n 热点的Beacon广播周期(广播间隔); + * @param[in] hide @n 是否是隐藏热点,hide:0, 非隐藏, 其它值:隐藏; + * @return, + @verbatim + = 0: success + = -1: unsupported + = -2: failure with system error + = -3: failure with no memory + = -4: failure with invalid parameters + @endverbatim + * @Note: + * 1)ssid和passwd都是以'\0'结尾的字符串,如果passwd字符串的 + * 长度为0,表示该热点采用Open模式(不加密); + * 2)beacon_interval表示热点的Beacon广播间隔(或周期),单 + * 位为毫秒,一般会采用默认100ms; + * 3)hide表示创建的热点是否是隐藏热点,hide=0表示非隐藏热 + * 点,其他值表示隐藏热点; + */ + +DLL_HAL_API int HAL_Awss_Open_Ap(const char *ssid, const char *passwd, int beacon_interval, int hide); + +/** + * @brief 关闭当前设备热点,并把设备由SoftAP模式切换到Station模式 + * + * @return, + @verbatim + = 0: success + = -1: unsupported + = -2: failure + @endverbatim + * @Note: + * 1)如果当前设备已经开启热点,关闭当前热点,如果当前设备正 + * 在开热点,取消开热点的操作; + * 2)如果当前设备不是以Station模式(包括Station+SoftAP模式和 + * SoftAP模式)工作,设备必须切换到Station模式; + * 3)Wi-Fi状态机需要切换到初始化状态,因为接下来很可能进行 + * 连接某一个路由器操作; + */ + +DLL_HAL_API int HAL_Awss_Close_Ap(); + +/** + * @brief 设置Wi-Fi网卡切换到指定的信道(channel)上 + * + * @param[in] primary_channel @n Primary channel. + * @param[in] secondary_channel @n Auxiliary channel if 40Mhz channel is supported, currently + * this param is always 0. + * @param[in] bssid @n A pointer to wifi BSSID on which awss lock the channel, most HAL + * may ignore it. + */ +DLL_HAL_API void HAL_Awss_Switch_Channel( + _IN_ char primary_channel, + _IN_OPT_ char secondary_channel, + _IN_OPT_ uint8_t bssid[ETH_ALEN]); + +/* auth type */ +enum AWSS_AUTH_TYPE { + AWSS_AUTH_TYPE_OPEN, + AWSS_AUTH_TYPE_SHARED, + AWSS_AUTH_TYPE_WPAPSK, + AWSS_AUTH_TYPE_WPA8021X, + AWSS_AUTH_TYPE_WPA2PSK, + AWSS_AUTH_TYPE_WPA28021X, + AWSS_AUTH_TYPE_WPAPSKWPA2PSK, + AWSS_AUTH_TYPE_MAX = AWSS_AUTH_TYPE_WPAPSKWPA2PSK, + AWSS_AUTH_TYPE_INVALID = 0xff, +}; + +/* encryt type */ +enum AWSS_ENC_TYPE { + AWSS_ENC_TYPE_NONE, + AWSS_ENC_TYPE_WEP, + AWSS_ENC_TYPE_TKIP, + AWSS_ENC_TYPE_AES, + AWSS_ENC_TYPE_TKIPAES, + AWSS_ENC_TYPE_MAX = AWSS_ENC_TYPE_TKIPAES, + AWSS_ENC_TYPE_INVALID = 0xff, +}; + +/** + * @brief 要求Wi-Fi网卡连接指定热点(Access Point)的函数 + * + * @param[in] connection_timeout_ms @n AP connection timeout in ms or HAL_WAIT_INFINITE + * @param[in] ssid @n AP ssid + * @param[in] passwd @n AP passwd + * @param[in] auth @n optional(AWSS_AUTH_TYPE_INVALID), AP auth info + * @param[in] encry @n optional(AWSS_ENC_TYPE_INVALID), AP encry info + * @param[in] bssid @n optional(NULL or zero mac address), AP bssid info + * @param[in] channel @n optional, AP channel info + * @return + @verbatim + = 0: connect AP & DHCP success + = -1: connect AP or DHCP fail/timeout + @endverbatim + * @see None. + * @note + * If the STA connects the old AP, HAL should disconnect from the old AP firstly. + * If bssid specifies the dest AP, HAL should use bssid to connect dest AP. + */ +DLL_HAL_API int HAL_Awss_Connect_Ap( + _IN_ uint32_t connection_timeout_ms, + _IN_ char ssid[HAL_MAX_SSID_LEN], + _IN_ char passwd[HAL_MAX_PASSWD_LEN], + _IN_OPT_ enum AWSS_AUTH_TYPE auth, + _IN_OPT_ enum AWSS_ENC_TYPE encry, + _IN_OPT_ uint8_t bssid[ETH_ALEN], + _IN_OPT_ uint8_t channel); + +/* 80211 frame type */ +typedef enum HAL_Awss_Frame_Type { + FRAME_ACTION, + FRAME_BEACON, + FRAME_PROBE_REQ, + FRAME_PROBE_RESPONSE, + FRAME_DATA +} HAL_Awss_Frame_Type_t; + +#define FRAME_ACTION_MASK (1 << FRAME_ACTION) +#define FRAME_BEACON_MASK (1 << FRAME_BEACON) +#define FRAME_PROBE_REQ_MASK (1 << FRAME_PROBE_REQ) +#define FRAME_PROBE_RESP_MASK (1 << FRAME_PROBE_RESPONSE) +#define FRAME_DATA_MASK (1 << FRAME_DATA) + +/** + * @brief 在当前信道(channel)上以基本数据速率(1Mbps)发送裸的802.11帧(raw 802.11 frame) + * + * @param[in] type @n see enum HAL_Awss_frame_type, currently only FRAME_BEACON + * FRAME_PROBE_REQ is used + * @param[in] buffer @n 80211 raw frame, include complete mac header & FCS field + * @param[in] len @n 80211 raw frame length + * @return + @verbatim + = 0, send success. + = -1, send failure. + = -2, unsupported. + @endverbatim + * @see None. + * @note awss use this API send raw frame in wifi monitor mode & station mode + */ +DLL_HAL_API int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type, + _IN_ uint8_t *buffer, _IN_ int len); + +/** + * @brief 管理帧的处理回调函数 + * + * @param[in] buffer @n 80211 raw frame or ie(information element) buffer + * @param[in] len @n buffer length + * @param[in] rssi_dbm @n rssi in dbm, range of [-127, -1], set it to -1 if not supported + * @param[in] buffer_type @n 0 when buffer is a 80211 frame, + * 1 when buffer only contain IE info + * @return None. + * @see None. + * @note None. + */ +typedef void (*awss_wifi_mgmt_frame_cb_t)(_IN_ uint8_t *buffer, _IN_ int len, + _IN_ signed char rssi_dbm, _IN_ int buffer_type); + +/** + * @brief 使能或禁用对管理帧的过滤 + * + * @param[in] filter_mask @n see mask macro in enum HAL_Awss_frame_type, + * currently only FRAME_PROBE_REQ_MASK & FRAME_BEACON_MASK is used + * @param[in] vendor_oui @n oui can be used for precise frame match, optional + * @param[in] callback @n see awss_wifi_mgmt_frame_cb_t, passing 80211 + * frame or ie to callback. when callback is NULL + * disable sniffer feature, otherwise enable it. + * @return + @verbatim + = 0, success + = -1, fail + = -2, unsupported. + @endverbatim + * @see None. + * @note awss use this API to filter specific mgnt frame in wifi station mode + */ +DLL_HAL_API int HAL_Wifi_Enable_Mgmt_Frame_Filter( + _IN_ uint32_t filter_mask, + _IN_OPT_ uint8_t vendor_oui[3], + _IN_ awss_wifi_mgmt_frame_cb_t callback); + +typedef struct { + enum AWSS_AUTH_TYPE auth; + enum AWSS_ENC_TYPE encry; + uint8_t channel; + signed char rssi_dbm; + char ssid[HAL_MAX_SSID_LEN]; + uint8_t mac[ETH_ALEN]; +} awss_ap_info_t; + +/** + * @brief handle one piece of AP information from wifi scan result + * + * @param[in] ssid @n name of AP + * @param[in] bssid @n mac address of AP + * @param[in] channel @n AP channel + * @param[in] rssi @n rssi range[-127, -1]. + * the higher the RSSI number, the stronger the signal. + * @param[in] is_last_ap @n this AP information is the last one if is_last_ap > 0. + * this AP information is not the last one if is_last_ap == 0. + * @return 0 for wifi scan is done, otherwise return -1 + * @see None. + * @note None. + */ +typedef int (*awss_wifi_scan_result_cb_t)( + const char ssid[HAL_MAX_SSID_LEN], + const uint8_t bssid[ETH_ALEN], + enum AWSS_AUTH_TYPE auth, + enum AWSS_ENC_TYPE encry, + uint8_t channel, signed char rssi, + int is_last_ap); + +/** + * @brief 启动一次Wi-Fi的空中扫描(Scan) + * + * @param[in] cb @n pass ssid info(scan result) to this callback one by one + * @return 0 for wifi scan is done, otherwise return -1 + * @see None. + * @note + * This API should NOT exit before the invoking for cb is finished. + * This rule is something like the following : + * HAL_Wifi_Scan() is invoked... + * ... + * for (ap = first_ap; ap <= last_ap; ap = next_ap){ + * cb(ap) + * } + * ... + * HAL_Wifi_Scan() exit... + */ +DLL_HAL_API int HAL_Wifi_Scan(awss_wifi_scan_result_cb_t cb); + +/** + * @brief 获取所连接的热点(Access Point)的信息 + * + * @param[out] ssid: array to store ap ssid. It will be null if ssid is not required. + * @param[out] passwd: array to store ap password. It will be null if ap password is not required. + * @param[out] bssid: array to store ap bssid. It will be null if bssid is not required. + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note + * If the STA dosen't connect AP successfully, HAL should return -1 and not touch the ssid/passwd/bssid buffer. + */ +DLL_HAL_API int HAL_Wifi_Get_Ap_Info( + _OU_ char ssid[HAL_MAX_SSID_LEN], + _OU_ char passwd[HAL_MAX_PASSWD_LEN], + _OU_ uint8_t bssid[ETH_ALEN]); + +/** + * @brief 获取`smartconfig`服务的安全等级 + * + * @param None. + * @return The security level: + @verbatim + 0: open (no encrypt) + 1: aes256cfb with default aes-key and aes-iv + 2: aes128cfb with default aes-key and aes-iv + 3: aes128cfb with aes-key per product and aes-iv = 0 + 4: aes128cfb with aes-key per device and aes-iv = 0 + 5: aes128cfb with aes-key per manufacture and aes-iv = 0 + others: invalid + @endverbatim + * @see None. + */ +DLL_HAL_API int HAL_Awss_Get_Encrypt_Type(void); + +/** + * @brief Get Security level for wifi configuration with connection. + * Used for AP solution of router and App. + * + * @param None. + * @return The security level: + @verbatim + 3: aes128cfb with aes-key per product and aes-iv = random + 4: aes128cfb with aes-key per device and aes-iv = random + 5: aes128cfb with aes-key per manufacture and aes-iv = random + others: invalid + @endverbatim + * @see None. + */ +DLL_HAL_API int HAL_Awss_Get_Conn_Encrypt_Type(void); + +/** + * @brief 获取当前Station模式与AP连接状态的信息 + * + * @param[out] p_rssi: rssi value of current link + * @param[out] p_channel: channel of current link + * + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + * @note awss use this API to get rssi and channel of current link + */ +DLL_HAL_API int HAL_Wifi_Get_Link_Stat(_OU_ int *p_rssi, + _OU_ int *p_channel); + +#ifdef __cplusplus +} +#endif + +#endif /* __IOT_IMPORT_AWSS_H__ */ + diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_config.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_config.h new file mode 100644 index 000000000..5a2bbd41c --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_config.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef __IOT_IMPORT_CONFIG_H__ +#define __IOT_IMPORT_CONFIG_H__ + +#ifndef CONFIG_HTTP_AUTH_TIMEOUT + #define CONFIG_HTTP_AUTH_TIMEOUT (5 * 1000) +#endif + +#ifndef CONFIG_MID_HTTP_TIMEOUT + #define CONFIG_MID_HTTP_TIMEOUT (5 * 1000) +#endif + +#ifndef CONFIG_GUIDER_AUTH_TIMEOUT + #define CONFIG_GUIDER_AUTH_TIMEOUT (10 * 1000) +#endif + +#ifndef CONFIG_COAP_AUTH_TIMEOUT + #define CONFIG_COAP_AUTH_TIMEOUT (3 * 1000) +#endif + +#ifndef CONFIG_MQTT_TX_MAXLEN + #ifndef LINK_VISUAL_ENABLE + #define CONFIG_MQTT_TX_MAXLEN (2048) + #else + #define CONFIG_MQTT_TX_MAXLEN (16*1024) + #endif +#endif + +#ifndef CONFIG_MQTT_RX_MAXLEN + #ifndef LINK_VISUAL_ENABLE + #define CONFIG_MQTT_RX_MAXLEN (2048) + #else + #define CONFIG_MQTT_RX_MAXLEN (16*1024) + #endif +#endif + +#ifndef CONFIG_SDK_THREAD_COST + #define CONFIG_SDK_THREAD_COST (0) +#endif + +#ifndef CONFIG_MBEDTLS_DEBUG_LEVEL + #define CONFIG_MBEDTLS_DEBUG_LEVEL (0) +#endif + +#ifndef CONFIG_RUNTIME_LOG_LEVEL + #define CONFIG_RUNTIME_LOG_LEVEL (2) +#endif + +#ifndef CONFIG_BLDTIME_MUTE_DBGLOG + #define CONFIG_BLDTIME_MUTE_DBGLOG (0) +#endif + +#ifndef CONFIG_DISPATCH_QUEUE_MAXLEN + #ifndef LINK_VISUAL_ENABLE + #define CONFIG_DISPATCH_QUEUE_MAXLEN (20) + #else + #define CONFIG_DISPATCH_QUEUE_MAXLEN (160) + #endif +#endif + +#ifndef CONFIG_DISPATCH_PACKET_MAXCOUNT + #define CONFIG_DISPATCH_PACKET_MAXCOUNT (0) +#endif + +#ifndef CONFIG_MSGCACHE_QUEUE_MAXLEN + #define CONFIG_MSGCACHE_QUEUE_MAXLEN (20) +#endif + +#endif /* __IOT_IMPORT_CONFIG_H__ */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_crypt.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_crypt.h new file mode 100644 index 000000000..aa05b667e --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_crypt.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef __IOT_IMPORT_CRYPT_H__ +#define __IOT_IMPORT_CRYPT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + HAL_AES_ENCRYPTION = 0, + HAL_AES_DECRYPTION = 1, +} AES_DIR_t; + +typedef void *p_HAL_Aes128_t; + +/** + * @brief 初始化AES加密的结构体 + * + * @param[in] key: + * @param[in] iv: + * @param[in] dir: AES_ENCRYPTION or AES_DECRYPTION + * @return AES128_t + @verbatim None + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API p_HAL_Aes128_t HAL_Aes128_Init( + _IN_ const uint8_t *key, + _IN_ const uint8_t *iv, + _IN_ AES_DIR_t dir); + +/** + * @brief 销毁AES加密的结构体 + * + * @param[in] aes: + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes); + +/** + * @brief 以`AES-CBC-128`方式, 根据`HAL_Aes128_Init()`时传入的密钥加密指定的明文 + * + * @param[in] aes: AES handler + * @param[in] src: plain data + * @param[in] blockNum: plain data number of 16 bytes size + * @param[out] dst: cipher data + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Aes128_Cbc_Encrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t blockNum, + _OU_ void *dst); + +/** + * @brief 以`AES-CBC-128`方式, 根据`HAL_Aes128_Init()`时传入的密钥解密指定的密文 + * + * @param[in] aes: AES handler + * @param[in] src: cipher data + * @param[in] blockNum: plain data number of 16 bytes size + * @param[out] dst: plain data + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Aes128_Cbc_Decrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t blockNum, + _OU_ void *dst); + +/** + * @brief 以`AES-CFB-128`方式, 根据`HAL_Aes128_Init()`时传入的密钥加密指定的明文 + * + * @param[in] aes: AES handler + * @param[in] src: plain data + * @param[in] blockNum: plain data number of 16 bytes size + * @param[out] dst: cipher data + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ + +DLL_HAL_API int HAL_Aes128_Cfb_Encrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t length, + _OU_ void *dst); + +/** + * @brief 以`AES-CFB-128`方式, 根据`HAL_Aes128_Init()`时传入的密钥解密指定的密文 + * + * @param[in] aes: AES handler + * @param[in] src: cipher data + * @param[in] blockNum: plain data number of 16 bytes size + * @param[out] dst: plain data + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Aes128_Cfb_Decrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t length, + _OU_ void *dst); + +#ifdef __cplusplus +} +#endif + +#endif /* __IOT_IMPORT_CRYPT_H__ */ + diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_dtls.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_dtls.h new file mode 100644 index 000000000..50a8acf6b --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_dtls.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IMPORT_DTLS_H__ +#define __IMPORT_DTLS_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include +#include +#include + +#define DTLS_ERROR_BASE (1<<24) +#define DTLS_SUCCESS (0) +#define DTLS_INVALID_PARAM (DTLS_ERROR_BASE | 1) +#define DTLS_INVALID_CA_CERTIFICATE (DTLS_ERROR_BASE | 2) +#define DTLS_HANDSHAKE_IN_PROGRESS (DTLS_ERROR_BASE | 3) +#define DTLS_HANDSHAKE_FAILED (DTLS_ERROR_BASE | 4) +#define DTLS_FATAL_ALERT_MESSAGE (DTLS_ERROR_BASE | 5) +#define DTLS_PEER_CLOSE_NOTIFY (DTLS_ERROR_BASE | 6) +#define DTLS_SESSION_CREATE_FAILED (DTLS_ERROR_BASE | 7) +#define DTLS_READ_DATA_FAILED (DTLS_ERROR_BASE | 8) + +typedef struct { + void *(*malloc)(uint32_t size); + void (*free)(void *ptr); +} dtls_hooks_t; + +typedef struct { + unsigned char *p_ca_cert_pem; + char *p_host; + unsigned short port; +} coap_dtls_options_t; + +typedef void DTLSContext; + +/** @defgroup group_platform platform + * @{ + */ + + +/** @defgroup group_platform_dtls dtls + * @{ + */ + +/** + * @brief Set malloc/free function. + * + * @param [in] hooks: @n Specify malloc/free function you want to use + * + * @retval DTLS_SUCCESS : Success. + @retval other : Fail. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_DTLSHooks_set(dtls_hooks_t *hooks); + +/** + * @brief Establish a DSSL connection. + * + * @param [in] p_options: @n Specify paramter of DTLS + @verbatim + p_host : @n Specify the hostname(IP) of the DSSL server + port : @n Specify the DSSL port of DSSL server + p_ca_cert_pem : @n Specify the root certificate which is PEM format. + @endverbatim + * @return DSSL handle. + * @see None. + * @note None. + */ +DLL_HAL_API DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options); + +/** + * @brief Write data into the specific DSSL connection. + * + * @param [in] context @n A descriptor identifying a connection. + * @param [in] p_data @n A pointer to a buffer containing the data to be transmitted. + * @param [in] p_datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + * @retval DTLS_SUCCESS : Success. + @retval other : Fail. + * @see None. + */ +DLL_HAL_API unsigned int HAL_DTLSSession_write(DTLSContext *context, + const unsigned char *p_data, + unsigned int *p_datalen); +/** + * @brief Read data from the specific DSSL connection with timeout parameter. + * The API will return immediately if len be received from the specific DSSL connection. + * + * @param [in] context @n A descriptor identifying a DSSL connection. + * @param [in] p_data @n A pointer to a buffer to receive incoming data. + * @param [in] p_datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * @return The result of read data from DSSL connection + * @retval DTLS_SUCCESS : Read success. + * @retval DTLS_FATAL_ALERT_MESSAGE : Recv peer fatal alert message. + * @retval DTLS_PEER_CLOSE_NOTIFY : The DTLS session was closed by peer. + * @retval DTLS_READ_DATA_FAILED : Read data fail. + * @see None. + */ +DLL_HAL_API unsigned int HAL_DTLSSession_read(DTLSContext *context, + unsigned char *p_data, + unsigned int *p_datalen, + unsigned int timeout_ms); +/** + * @brief Destroy the specific DSSL connection. + * + * @param[in] context: @n Handle of the specific connection. + * + * @return The result of free dtls session + * @retval DTLS_SUCCESS : Read success. + * @retval DTLS_INVALID_PARAM : Invalid parameter. + * @retval DTLS_INVALID_CA_CERTIFICATE : Invalid CA Certificate. + * @retval DTLS_HANDSHAKE_IN_PROGRESS : Handshake in progress. + * @retval DTLS_HANDSHAKE_FAILED : Handshake failed. + * @retval DTLS_FATAL_ALERT_MESSAGE : Recv peer fatal alert message. + * @retval DTLS_PEER_CLOSE_NOTIFY : The DTLS session was closed by peer. + * @retval DTLS_SESSION_CREATE_FAILED : Create session fail. + * @retval DTLS_READ_DATA_FAILED : Read data fail. + */ +DLL_HAL_API unsigned int HAL_DTLSSession_free(DTLSContext *context); + +/** @} */ /* end of platform_dtls */ +/** @} */ /* end of platform */ + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_kv.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_kv.h new file mode 100644 index 000000000..7a88decbf --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_kv.h @@ -0,0 +1,33 @@ +/** + * @file iot_import_kv.h + * @brief + * @date 2021-04-29 + * + * @copyright Copyright (C) 2017-2020 Alibaba Group Holding Limited + * + * @details + * + */ + +#ifndef __IOT_IMPORTS_KV_H__ +#define __IOT_IMPORTS_KV_H__ + +#if defined(__cplusplus) +extern "C" +{ +#endif + + extern int aos_kv_init(void); + extern int aiot_kv_init(void); + extern void aos_kv_deinit(void); + + extern int aos_kv_set(const char *key, const void *val, int len, int sync); + extern int aos_kv_get(const char *key, void *buffer, int *buffer_len); + extern int aos_kv_del(const char *key); + extern int aos_kv_del_by_prefix(const char *prefix); + +#if defined(__cplusplus) +} +#endif + +#endif /* #ifndef __AIOT_KV_API_H__ */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_ota.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_ota.h new file mode 100644 index 000000000..270ceb360 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_ota.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_IMPORT_OTA_H__ +#define __IOT_IMPORT_OTA_H__ + +/***************************** firmware upgrade interface *****************************/ + +/** @defgroup group_platform_ota ota + * @{ + */ + +/** + * @brief initialize a firmware upgrade. + * + * @param None + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Firmware_Persistence_Start(void); + + +/** + * @brief save firmware upgrade data to flash. + * + * @param[in] buffer: @n A pointer to a buffer to save data. + * @param[in] length: @n The length, in bytes, of the data pointed to by the buffer parameter. + * @return 0, Save success; -1, Save failure. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Firmware_Persistence_Write(_IN_ char *buffer, _IN_ uint32_t length); + + +/** + * @brief indicate firmware upgrade data complete, and trigger data integrity checking, + and then reboot the system. + * + * @param None. + * @return 0: Success; -1: Failure. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Firmware_Persistence_Stop(void); + +#endif /* __IOT_IMPORT_UOTA_H__ */ + diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_product.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_product.h new file mode 100644 index 000000000..237407c2a --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_product.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IMPORT_PRODUCT_H__ +#define __IMPORT_PRODUCT_H__ + +#define MAC_ADDR_LEN_MAX (10) +#define PID_STRLEN_MAX (64) +#define MID_STRLEN_MAX (64) +#define IOTX_URI_MAX_LEN (135) /* IoTx CoAP/HTTP uri & MQTT topic maximal length */ +#define PID_STR_MAXLEN (64) +#define MID_STR_MAXLEN (64) +#define PRODUCT_KEY_MAXLEN (20 + 1) +#define DEVICE_NAME_MAXLEN (32 + 1) +#define DEVICE_ID_MAXLEN (64 + 1) +#define DEVICE_SECRET_MAXLEN (64 + 1) +#define PRODUCT_SECRET_MAXLEN (64 + 1) +#define FIRMWARE_VERSION_MAXLEN (64 + 1) +#define HAL_CID_LEN (64 + 1) + +/** + * @brief 获取设备的固件版本字符串 + * + * @param version : 用来存放版本字符串的数组 + * @return 写到version[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetFirmwareVersion(_OU_ char version[FIRMWARE_VERSION_MAXLEN]); + +/** + * @brief 获取设备的`Partner ID`, 仅用于紧密合作伙伴 + * + * @param pid_str : 用来存放Partner ID字符串的数组 + * @return 写到pid_str[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetPartnerID(_OU_ char pid_str[PID_STR_MAXLEN]); + +/** + * @brief 获取设备的`Module ID`, 仅用于紧密合作伙伴 + * + * @param mid_str : 用来存放Module ID字符串的数组 + * @return 写到mid_str[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetModuleID(_OU_ char mid_str[MID_STR_MAXLEN]); + + +/** + * @brief 获取设备的`DeviceID`, 用于标识设备单品的ID + * + * @param device_id : 用来存放DeviceID字符串的数组 + * @return 写到device_id[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetDeviceID(_OU_ char device_id[DEVICE_ID_LEN]); + +/** + * @brief 获取唯一的芯片ID字符串 + * + * @param cid_str : 存放芯片ID字符串的缓冲区数组 + * @return 指向缓冲区数组的起始地址 + */ +char *HAL_GetChipID(_OU_ char cid_str[HAL_CID_LEN]); + +/** + * @brief 设置设备的`ProductKey`, 用于标识设备的品类, 三元组之一 + * + * @param product_key : 用来存放ProductKey字符串的数组 + * @return 写到product_key[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_SetProductKey(_IN_ char *product_key); + +/** + * @brief 设置设备的`DeviceName`, 用于标识设备单品的名字, 三元组之一 + * + * @param device_name : 用来存放DeviceName字符串的数组 + * @return 写到device_name[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_SetDeviceName(_IN_ char *device_name); + +/** + * @brief 设置设备的`DeviceSecret`, 用于标识设备单品的密钥, 三元组之一 + * + * @param device_secret : 用来存放DeviceSecret字符串的数组 + * @return 写到device_secret[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_SetDeviceSecret(_IN_ char *device_secret); + +/** + * @brief 设置设备的`ProductSecret`, 用于标识设备单品的密钥, 三元组之一 + * + * @param product_secret : 用来存放ProductSecret字符串的数组 + * @return 写到product_secret[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_SetProductSecret(_IN_ char *product_secret); + +/** + * @brief 获取设备的`ProductKey`, 用于标识设备的品类, 三元组之一 + * + * @param product_key : 用来存放ProductKey字符串的数组 + * @return 写到product_key[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetProductKey(_OU_ char product_key[PRODUCT_KEY_LEN]); + +/** + * @brief 获取设备的`DeviceName`, 用于标识设备单品的名字, 三元组之一 + * + * @param device_name : 用来存放DeviceName字符串的数组 + * @return 写到device_name[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetDeviceName(_OU_ char device_name[DEVICE_NAME_LEN]); + +/** + * @brief 获取设备的`DeviceSecret`, 用于标识设备单品的密钥, 三元组之一 + * + * @param device_secret : 用来存放DeviceSecret字符串的数组 + * @return 写到device_secret[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetDeviceSecret(_OU_ char device_secret[DEVICE_SECRET_LEN]); + +/** + * @brief 获取设备的`ProductSecret`, 用于标识设备单品的密钥, 三元组之一 + * + * @param product_secret : 用来存放ProductSecret字符串的数组 + * @return 写到product_secret[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetProductSecret(_OU_ char product_secret[DEVICE_SECRET_LEN]); + +#define NIF_STRLEN_MAX (160) + +/** + ** @brief Retrieves all the info of the current network interfaces, + ** including eth Mac, WiFi Mac, and IMEI/ICCID/IMSI/MSISDN for cellular connections. + ** Note that the network interface length MUST NOT exceed NIF_STRLEN_MAX + ** + ** @param [nif_str] give buffer to save network interface + ** @return the lenth of the nif_str info + ** @see None. + ** @note None. + **/ +DLL_HAL_API int HAL_GetNetifInfo(char *nif_str); + +/** + * 这个Hal主要用于解决三元组烧重的问题. 如果不涉及这个问题, 则请忽略这个Hal. + * + * @breif 获取设备的唯一标识符(uuid) + * 这里的uuid, 主要用于在多个设备都烧了相同三元组情况下能够区分不同设备,不要求全球唯一,但要求对同一个设备始终保持不变 + * 用户可以从IMEI/mac地址/cpu序列号等信息中择一作为设备的uuid + * + * 考虑到部分设备会用mac地址作为uuid, 而少量设备的mac地址会偶现无法读取成功的情况, 或者每次读出来都不一样的情况, + * 首选的方案为步骤3, 即将uuid+time的信息持久化到一片恢复出厂设置/固件升级也不会被erase掉的存储器件上 + * + * 如果步骤3无法实施, 但是设备的uuid的确每次都能读到, 而且每次读出来都一样, + * 则可优先用步骤4.a, 即将uuid的信息持久化到flash中, 每次开机优先读这片flash + * 如果4.a无法实现, 则可用4.b, 即每次直接从器件中读取出设备的uuid(器件可能不稳定,不推荐) + * + * 如果步骤3/4都无法实施, 则返回-1作为错误码 + * + * @param[in] buf 缓存的buf, 用以存储设备的唯一标识符 + * @param[in] len 缓存的最大长度. 默认是256 Byte + * + * @return int + * @retval <= 0 没有获取到uuid + * @retval > 0 返回的字节数 + **/ +DLL_HAL_API int HAL_GetUUID(uint8_t *buf, int len); + +#endif /* __IMPORT_PRODUCT_H__ */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_tcp.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_tcp.h new file mode 100644 index 000000000..256c378fb --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_tcp.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#ifndef __IMPORT_TCP_H__ +#define __IMPORT_TCP_H__ + +/** + * @brief Establish a TCP connection. + * + * @param [in] host: @n Specify the hostname(IP) of the TCP server + * @param [in] port: @n Specify the TCP port of TCP server + * + * @return The handle of TCP connection. + @retval 0 : Fail. + @retval > 0 : Success, the value is handle of this TCP connection. + */ +DLL_HAL_API uintptr_t HAL_TCP_Establish(_IN_ const char *host, _IN_ uint16_t port); + +/** + * @brief Destroy the specific TCP connection. + * + * @param [in] fd: @n Specify the TCP connection by handle. + * + * @return The result of destroy TCP connection. + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +DLL_HAL_API int32_t HAL_TCP_Destroy(_IN_ uintptr_t fd); + +/** + * @brief Write data into the specific TCP connection. + * The API will return immediately if 'len' be written into the specific TCP connection. + * + * @param [in] fd @n A descriptor identifying a connection. + * @param [in] buf @n A pointer to a buffer containing the data to be transmitted. + * @param [in] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * + * @retval < 0 : TCP connection error occur.. + * @retval 0 : No any data be write into the TCP connection in 'timeout_ms' timeout period. + * @retval (0, len] : The total number of bytes be written in 'timeout_ms' timeout period. + + * @see None. + */ +DLL_HAL_API int32_t HAL_TCP_Write(_IN_ uintptr_t fd, _IN_ const char *buf, _IN_ uint32_t len, _IN_ uint32_t timeout_ms); + +/** + * @brief Read data from the specific TCP connection with timeout parameter. + * The API will return immediately if 'len' be received from the specific TCP connection. + * + * @param [in] fd @n A descriptor identifying a TCP connection. + * @param [out] buf @n A pointer to a buffer to receive incoming data. + * @param [out] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * + * @retval -2 : TCP connection error occur. + * @retval -1 : TCP connection be closed by remote server. + * @retval 0 : No any data be received in 'timeout_ms' timeout period. + * @retval (0, len] : The total number of bytes be received in 'timeout_ms' timeout period. + + * @see None. + */ +DLL_HAL_API int32_t HAL_TCP_Read(_IN_ uintptr_t fd, _OU_ char *buf, _OU_ uint32_t len, _IN_ uint32_t timeout_ms); + +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_tls.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_tls.h new file mode 100644 index 000000000..aa608c27e --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_tls.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IMPORT_TLS_H__ +#define __IMPORT_TLS_H__ + +#include + +typedef struct { + void *(*malloc)(uint32_t size); + void (*free)(void *ptr); +} ssl_hooks_t; + +DLL_HAL_API int HAL_SSL_Del_KV_Session_Ticket(void); + +/** + * @brief Set malloc/free function. + * + * @param [in] hooks: @n Specify malloc/free function you want to use + * + * @retval < 0 : Fail. + * @retval 0 : Success. + * + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_SSLHooks_set(ssl_hooks_t *hooks); + +/** + * @brief Establish a SSL connection. + * + * @param [in] host: @n Specify the hostname(IP) of the SSL server + * @param [in] port: @n Specify the SSL port of SSL server + * @param [in] ca_crt @n Specify the root certificate which is PEM format. + * @param [in] ca_crt_len @n Length of root certificate, in bytes. + * @return SSL handle. + * @see None. + * @note None. + */ +DLL_HAL_API uintptr_t HAL_SSL_Establish( + _IN_ const char *host, + _IN_ uint16_t port, + _IN_ const char *ca_crt, + _IN_ size_t ca_crt_len); + +/** + * @brief Destroy the specific SSL connection. + * + * @param[in] handle: @n Handle of the specific connection. + * + * @return The result of destroy ssl + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +DLL_HAL_API int32_t HAL_SSL_Destroy(_IN_ uintptr_t handle); + +/** + * @brief Write data into the specific SSL connection. + * The API will return immediately if 'len' be written into the specific SSL connection. + * + * @param [in] handle @n A descriptor identifying a connection. + * @param [in] buf @n A pointer to a buffer containing the data to be transmitted. + * @param [in] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * @retval < 0 : SSL connection error occur.. + * @retval 0 : No any data be write into the SSL connection in 'timeout_ms' timeout period. + * @retval (0, len] : The total number of bytes be written in 'timeout_ms' timeout period. + * @see None. + */ +DLL_HAL_API int32_t HAL_SSL_Write(_IN_ uintptr_t handle, _IN_ const char *buf, _IN_ int len, _IN_ int timeout_ms); + +/** + * @brief Read data from the specific SSL connection with timeout parameter. + * The API will return immediately if 'len' be received from the specific SSL connection. + * + * @param [in] handle @n A descriptor identifying a SSL connection. + * @param [out] buf @n A pointer to a buffer to receive incoming data. + * @param [out] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * + * @retval -2 : SSL connection error occur. + * @retval -1 : SSL connection be closed by remote server. + * @retval 0 : No any data be received in 'timeout_ms' timeout period. + * @retval (0, len] : The total number of bytes be received in 'timeout_ms' timeout period. + * @see None. + */ +DLL_HAL_API int32_t HAL_SSL_Read(_IN_ uintptr_t handle, _OU_ char *buf, _OU_ int len, _IN_ int timeout_ms); + +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_udp.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_udp.h new file mode 100644 index 000000000..2f67d5ccb --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/imports/iot_import_udp.h @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IMPORT_UDP_H__ +#define __IMPORT_UDP_H__ + +/** + * @brief Establish a UDP connection. + * + * @param [in] host: @n Specify the hostname(IP) of the UDP server + * @param [in] port: @n Specify the UDP port of UDP server + * + * @retval < 0 : Fail. + * @retval >= 0 : Success, the value is handle of this UDP connection. + * @see None. + */ +DLL_HAL_API intptr_t HAL_UDP_create(_IN_ char *host, _IN_ unsigned short port); + +/** + * @brief Destroy the specific UDP connection. + * + * @param [in] p_socket: @n Specify the UDP connection by handle. + * @return None. + * @see None . + */ +DLL_HAL_API void HAL_UDP_close(_IN_ intptr_t p_socket); + +/** + * @brief Write data into the specific UDP connection. + * + * @param [in] p_socket @n A descriptor identifying a connection. + * @param [in] p_data @n A pointer to a buffer containing the data to be transmitted. + * @param [in] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + + * @retval < 0 : UDP connection error occur. + * @retval [0,datalen ] : The number of bytes sent. + * @see None. + */ +DLL_HAL_API int HAL_UDP_write( + _IN_ intptr_t p_socket, + _IN_ const unsigned char *p_data, + _IN_ unsigned int datalen); + +/** + * @brief Read data from the specific UDP connection by blocked + * + * @param [in] p_socket @n A descriptor identifying a UDP connection. + * @param [in] p_data @n A pointer to a buffer to receive incoming data. + * @param [out] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + * @return + * + * @retval < 0 : UDP connect error occur. + * @retval = 0 : End of file. + * @retval > 0 : The number of byte read. + * @see None. + */ +DLL_HAL_API int HAL_UDP_read( + _IN_ intptr_t p_socket, + _OU_ unsigned char *p_data, + _OU_ unsigned int datalen); + +/** + * @brief Read data from the specific UDP connection with timeout parameter. + * The API will return immediately if 'datalen' be received from the specific UDP connection. + * + * @param [in] p_socket @n A descriptor identifying a UDP connection. + * @param [out] p_data @n A pointer to a buffer to receive incoming data. + * @param [out] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + * @param [in] timeouf_ms @n Specify the timeout value in millisecond. In other words, the API block timeout_ms millisecond maximumly. + * + * @retval -4 : UDP connect error occur. + * @retval -3 : The call was interrupted by a signal before any data was read. + * @retval -2 : No any data be received in 'timeout_ms' timeout period. + * @retval -1 : Invalid parameter. + * @retval 0 : End of file. + * @retval (0,datalen] : The number of byte read. + * @see None. + */ +DLL_HAL_API int HAL_UDP_readTimeout( + _IN_ intptr_t p_socket, + _OU_ unsigned char *p_data, + _OU_ unsigned int datalen, + _IN_ unsigned int timeout_ms); + +/** @} */ /* end of platform_network */ +/** @} */ /* end of platform */ + + +/** + * @brief 创建一个本地的UDP socket, 但并不发起任何网络交互 + * + * @param host : UDP的源地址, 如果不指定地址,设为 NULL + * port : UDP的源端口 + * + * @retval -1 : 创建失败 + * @retval 其它 : 创建成功, 返回值是UDP socket的句柄 + */ +DLL_HAL_API intptr_t HAL_UDP_create_without_connect(_IN_ const char *host, _IN_ unsigned short port); + +/** + * @brief 设置UDP socket的目的地址和目的端口 + * + * @param host : UDP的目的地址 + * port : UDP的目的端口 + * + * @retval -1 : 失败 + * @retval 0 : 设置成功 + */ +DLL_HAL_API int HAL_UDP_connect(_IN_ intptr_t sockfd, + _IN_ const char *host, + _IN_ unsigned short port); + + +/** + * @brief 在指定的UDP socket上发送指定缓冲区的指定长度, 阻塞时间不超过指定时长, 且指定长度若发送完需提前返回 + * + * @param sockfd : UDP socket的句柄 + * @param p_remote : 目标网络地址结构体的首地址 + * @param p_data : 被发送的缓冲区起始地址 + * @param datalen: 被发送的数据长度, 单位是字节(Byte) + * @param timeout_ms : 可能阻塞的最大时间长度, 单位是毫秒 + * + * @retval < 0 : 发送过程中出现错误或异常 + * @retval 0 : 在指定的'timeout_ms'时间间隔内, 没有任何数据被成功发送 + * @retval (0, len] : 在指定的'timeout_ms'时间间隔内, 被成功发送的数据长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_UDP_sendto(_IN_ intptr_t sockfd, + _IN_ const NetworkAddr *p_remote, + _IN_ const unsigned char *p_data, + _IN_ unsigned int datalen, + _IN_ unsigned int timeout_ms); + + +/** + * @brief 从指定的UDP句柄接收指定长度数据到缓冲区, 阻塞时间不超过指定时长, 且指定长度若接收完需提前返回, 源地址保存在出参中 + * + * @param fd : UDP socket的句柄 + * @param p_remote : 存放源网络地址的结构体首地址 + * @param p_data : 存放被接收数据的缓冲区起始地址 + * @param datalen : 接收并存放到缓冲区中数据的最大长度, 单位是字节(Byte) + * @param timeout_ms : 可能阻塞的最大时间长度, 单位是毫秒 + * + * @retval < 0 : 接收过程中出现错误或异常 + * @retval 0 : 在指定的'timeout_ms'时间间隔内, 没有任何数据被成功接收 + * @retval (0, len] : 在指定的'timeout_ms'时间间隔内, 被成功接收的数据长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_UDP_recvfrom(_IN_ intptr_t sockfd, + _OU_ NetworkAddr *p_remote, + _OU_ unsigned char *p_data, + _IN_ unsigned int datalen, + _IN_ unsigned int timeout_ms); + + +/** + * @brief 在指定的UDP socket上发送加入组播组的请求 + * + * @param sockfd : 指定用来发送组播请求的UDP socket + * @param p_group : 指定需要加入的组播组名字 + * @retval < 0 : 发送过程中出现异常或失败 + * @retval 0 : 发送成功 + */ +DLL_HAL_API int HAL_UDP_joinmulticast(_IN_ intptr_t sockfd, + _IN_ char *p_group); + +/** + * @brief 绑定UDP socket到指定接口,只接收来自该接口的数据包 + * + * @param fd : 指定用来绑定的UDP socket + * @param ifname : 指定用来绑定socket的网络接口名字 + * + * @retval < 0 : 绑定异常或失败 + * @retval 0 : 发送成功 + */ +DLL_HAL_API int HAL_UDP_bindtodevice(_IN_ intptr_t fd, + _IN_ const char *ifname); + +/** + * @brief 销毁指定的UDP socket, 回收资源 + * + * @param sockfd : 将要关闭并销毁的UDP socket + * + * @return 操作的结果 + * @retval < 0 : 操作失败 + * @retval 0 : 操作成功 + */ +DLL_HAL_API int HAL_UDP_close_without_connect(_IN_ intptr_t sockfd); + +#endif diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/iot_export.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/iot_export.h new file mode 100644 index 000000000..ad719b633 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/iot_export.h @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_EXPORT_H__ +#define __IOT_EXPORT_H__ +#if defined(__cplusplus) +extern "C" { +#endif + +#undef being_deprecated +#define being_deprecated + +#ifdef _WIN32 +#if !defined(CC_IS_MINGW32) +#ifdef DLL_IOT_EXPORTS +#define DLL_IOT_API __declspec(dllexport) +#else +#define DLL_IOT_API __declspec(dllimport) +#endif +#else +#define DLL_IOT_API +#endif +#else +#define DLL_IOT_API +#endif + +#include + +#ifndef LINK_VISUAL_ENABLE +#define LINK_VISUAL_ENABLE //only for LV +#endif + +#ifdef LINK_VISUAL_ENABLE +#define REPORT_UUID_ENABLE +#endif + +#ifndef RDA5981A +#ifndef AIOT_AUTHORIZE_ENABLE + // #define AIOT_AUTHORIZE_ENABLE +#endif +#endif + +extern unsigned int g_report_id; +/* From device.h */ +#define PRODUCT_KEY_LEN (20) +#define DEVICE_NAME_LEN (32) +#define DEVICE_ID_LEN (64) +#define DEVICE_SECRET_LEN (64) +#define PRODUCT_SECRET_LEN (64) + +#define LIVING_SDK_VERSION "1.6.6-6" +#define LINKKIT_VERSION "2.3.0" "_FY_" LIVING_SDK_VERSION + +#define MODULE_VENDOR_ID (32) /* Partner ID */ + +#define HOST_ADDRESS_LEN (128) +#define HOST_PORT_LEN (8) +#define CLIENT_ID_LEN (384) /* Enlarge this buffer size due to add token params etc */ +#define USER_NAME_LEN (512) /* Extend length for ID2 */ +#define PASSWORD_LEN (256) /* Extend length for ID2 */ +#define AESKEY_STR_LEN (32) +#define AESKEY_HEX_LEN (128/8) + +typedef enum _IOT_LogLevel { + IOT_LOG_NONE = 0, + IOT_LOG_CRIT, + IOT_LOG_ERROR, + IOT_LOG_WARNING, + IOT_LOG_INFO, + IOT_LOG_DEBUG, +} IOT_LogLevel; + +#define IOTX_CLOUD_REGION_INVALID (-100) +/* region type */ +typedef enum IOTX_CLOUD_REGION_TYPES { + /* Shanghai */ + IOTX_CLOUD_REGION_SHANGHAI, + + /* Singapore */ + IOTX_CLOUD_REGION_SINGAPORE, + + /* Japan */ + IOTX_CLOUD_REGION_JAPAN, + + /* America east*/ + IOTX_CLOUD_REGION_USA_EAST, + + /* Germany */ + IOTX_CLOUD_REGION_GERMANY, + + /* America west*/ + IOTX_CLOUD_REGION_USA_WEST, + + /*Define the valid maximum region id is 19999*/ + IOTX_CLOUD_REGION_MAX = 19999, + + /* Custom setting */ + IOTX_CLOUD_REGION_CUSTOM = 20000, + + /* Maximum number of custom region */ + IOTX_CLOUD_CUSTOM_REGION_MAX +} iotx_cloud_region_types_t; + +typedef struct { + char product_key[PRODUCT_KEY_LEN + 1]; + char device_name[DEVICE_NAME_LEN + 1]; + char device_id[DEVICE_ID_LEN + 1]; + char device_secret[DEVICE_SECRET_LEN + 1]; + char module_vendor_id[MODULE_VENDOR_ID + 1]; +} iotx_device_info_t; + +typedef struct { + uint16_t port; + uint8_t init; + char *host_name; + char *client_id; + char *username; + char *password; + const char *pub_key; + +} iotx_conn_info_t, *iotx_conn_info_pt; + +/* data srutct define for IOTX_IOCTL_SET_SUBDEV_SIGN */ +typedef struct { + int devid; + const char *sign; +} iotx_ioctl_set_subdev_sign_t; + +/* data struct define for IOTX_IOCTL_GET_SUBDEV_LOGIN */ +typedef struct { + int devid; + int status; +} iotx_ioctl_get_subdev_info_t; + +typedef enum { + IOTX_IOCTL_SET_REGION, /* value(int*): iotx_cloud_region_types_t */ + IOTX_IOCTL_GET_REGION, /* value(int*) */ + IOTX_IOCTL_SET_MQTT_DOMAIN, /* value(const char*): point to mqtt domain string */ + IOTX_IOCTL_SET_MQTT_PORT, /* value(int*): point to mqtt port number*/ + IOTX_IOCTL_SET_ENV, /* value(int*): 0 - env is ONLINE; 1 - env is PRE; 2 - env is DAILY*/ + IOTX_IOCTL_SET_HTTP_DOMAIN, /* value(const char*): point to http domain string */ + IOTX_IOCTL_SET_DYNAMIC_REGISTER, /* value(int*): 0 - Disable Dynamic Register, 1 - Enable Dynamic Register */ + IOTX_IOCTL_GET_DYNAMIC_REGISTER, /* value(int*) */ + IOTX_IOCTL_RECV_PROP_REPLY, /* value(int*): 0 - Disable property post reply by cloud; 1 - Enable property post reply by cloud */ + IOTX_IOCTL_RECV_EVENT_REPLY, /* value(int*): 0 - Disable event post reply by cloud; 1 - Enable event post reply by cloud */ + IOTX_IOCTL_SEND_PROP_SET_REPLY, /* value(int*): 0 - Disable send post set reply by devid; 1 - Enable property set reply by devid */ + IOTX_IOCTL_SET_SUBDEV_SIGN, /* value(const char*): only for slave device, set signature of subdevice */ + IOTX_IOCTL_GET_SUBDEV_LOGIN, /* value(int*): 0 - SubDev is logout; 1 - SubDev is login */ + IOTX_IOCTL_QUERY_DEVID, /* value(iotx_linkkit_dev_meta_info_t*): device meta info, only productKey and deviceName is required, ret value is subdev_id or -1 */ +#ifdef REPORT_UUID_ENABLE + IOTX_IOCTL_SET_UUID_ENABLED, /* value(int*): 1 - anti duplicated uuid capability is enabled; 0 - anti duplicated uuid capability is disabled. */ +#endif + IOTX_IOCTL_SEND_EVENT_NOTIFY_REPLY /* value(int*): 0 - Disable send post set reply by devid; 1 - Enable event notify reply by devid */ +} iotx_ioctl_option_t; + +typedef enum { + ITE_AWSS_STATUS, + ITE_CONNECT_SUCC, + ITE_CONNECT_FAIL, + ITE_DISCONNECTED, + ITE_REDIRECT, + ITE_OFFLINE_RESET, + ITE_RAWDATA_ARRIVED, +#ifndef LINK_VISUAL_ENABLE + ITE_SERVICE_REQUEST, +#else + ITE_SERVICE_REQUST, +#endif + ITE_PROPERTY_SET, + ITE_PROPERTY_GET, + ITE_REPORT_REPLY, + ITE_TRIGGER_EVENT_REPLY, + ITE_TIMESTAMP_REPLY, + ITE_TOPOLIST_REPLY, + ITE_TOPO_CHANGE, + ITE_PERMIT_JOIN, + ITE_SUBDEV_MISC_OPS, + ITE_INITIALIZE_COMPLETED, + ITE_FOTA, + ITE_COTA, + ITE_MQTT_CONNECT_SUCC, + ITE_EVENT_NOTIFY, +#ifdef LINK_VISUAL_ENABLE + ITE_LINK_VISUAL, +#endif + ITE_CLOUD_ERROR, + ITE_STATE_EVERYTHING, + ITE_STATE_USER_INPUT, + ITE_STATE_SYS_DEPEND, + ITE_STATE_MQTT_COMM, + ITE_STATE_WIFI_PROV, + ITE_STATE_COAP_LOCAL, + ITE_STATE_HTTP_COMM, + ITE_STATE_OTA, + ITE_STATE_DEV_BIND, + ITE_STATE_SUB_DEVICE, +#ifdef DM_UNIFIED_SERVICE_POST + ITE_UNIFIED_SERVICE_POST, +#endif + + ITE_STATE_DEV_MODEL /* Must be last state relative event */ +} iotx_ioctl_event_t; + +#define IOT_RegisterCallback(evt, cb) iotx_register_for_##evt(cb); +#define DECLARE_EVENT_CALLBACK(evt, cb) DLL_IOT_API int iotx_register_for_##evt(cb); +#define DEFINE_EVENT_CALLBACK(evt, cb) DLL_IOT_API int iotx_register_for_##evt(cb) { \ + if (evt < 0 || evt >= sizeof(g_impl_event_map)/sizeof(impl_event_map_t)) {return -1;} \ + g_impl_event_map[evt].callback = (void *)callback;return 0;} + +DECLARE_EVENT_CALLBACK(ITE_AWSS_STATUS, int (*cb)(int)) +DECLARE_EVENT_CALLBACK(ITE_CONNECT_SUCC, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_CONNECT_FAIL, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_DISCONNECTED, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_REDIRECT, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_OFFLINE_RESET, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_RAWDATA_ARRIVED, int (*cb)(const int, const unsigned char *, const int)) +#ifndef LINK_VISUAL_ENABLE +DECLARE_EVENT_CALLBACK(ITE_SERVICE_REQUEST, int (*cb)(const int, const char *, const int, const char *, const int, + char **, int *)) +#else +DECLARE_EVENT_CALLBACK(ITE_LINK_VISUAL, int (*cb)(const int, const char *, const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_SERVICE_REQUST, int (*cb)(const int, const char *, const int, const char *, const int, const char *, const int, + char **, int *)) +#endif +DECLARE_EVENT_CALLBACK(ITE_PROPERTY_SET, int (*cb)(const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_PROPERTY_GET, int (*cb)(const int, const char *, const int, char **, int *)) +DECLARE_EVENT_CALLBACK(ITE_REPORT_REPLY, int (*cb)(const int, const int, const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_TRIGGER_EVENT_REPLY, int (*cb)(const int, const int, const int, const char *, const int, + const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_TIMESTAMP_REPLY, int (*cb)(const char *)) +DECLARE_EVENT_CALLBACK(ITE_TOPOLIST_REPLY, int (*cb)(const int, const int, const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_TOPO_CHANGE, int (*cb)(const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_SUBDEV_MISC_OPS, int (*cb)(const int, int, const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_PERMIT_JOIN, int (*cb)(const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_INITIALIZE_COMPLETED, int (*cb)(const int)) +DECLARE_EVENT_CALLBACK(ITE_FOTA, int (*cb)(const int, const char *)) +DECLARE_EVENT_CALLBACK(ITE_COTA, int (*cb)(const int, const char *, int, const char *, const char *, + const char *, const char *)) +DECLARE_EVENT_CALLBACK(ITE_MQTT_CONNECT_SUCC, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_CLOUD_ERROR, int (*cb)(const int, const char *, const char *)) +DECLARE_EVENT_CALLBACK(ITE_EVENT_NOTIFY, int (*cb)(const int, const char *, const int)) + +#ifdef DM_UNIFIED_SERVICE_POST +DECLARE_EVENT_CALLBACK(ITE_UNIFIED_SERVICE_POST, int (*cb)(const int, const int, const int, const char *, const int)) +#endif + +typedef int (*state_handler_t)(const int state_code, const char *state_message); +DECLARE_EVENT_CALLBACK(ITE_STATE_EVERYTHING, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_USER_INPUT, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_SYS_DEPEND, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_MQTT_COMM, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_WIFI_PROV, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_COAP_LOCAL, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_HTTP_COMM, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_OTA, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_DEV_BIND, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_SUB_DEVICE, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_DEV_MODEL, state_handler_t cb); + +int iotx_state_event(const int event, const int code, const char *msg_format, ...); +#define dump_user_input_status(...) iotx_state_event(ITE_STATE_USER_INPUT, __VA_ARGS__) +#define dump_sys_depend_status(...) iotx_state_event(ITE_STATE_SYS_DEPEND, __VA_ARGS__) +#define dump_mqtt_status(...) iotx_state_event(ITE_STATE_MQTT_COMM, __VA_ARGS__) +#define dump_awss_status(...) iotx_state_event(ITE_STATE_WIFI_PROV, __VA_ARGS__) +#define dump_coap_lcl_status(...) iotx_state_event(ITE_STATE_COAP_LOCAL, __VA_ARGS__) +#define dump_http_status(...) iotx_state_event(ITE_STATE_HTTP_COMM, __VA_ARGS__) +#define dump_ota_status(...) iotx_state_event(ITE_STATE_OTA, __VA_ARGS__) +#define dump_dev_bind_status(...) iotx_state_event(ITE_STATE_DEV_BIND, __VA_ARGS__) +#define dump_sub_dev_status(...) iotx_state_event(ITE_STATE_SUB_DEVICE, __VA_ARGS__) +#define dump_dev_model_status(...) iotx_state_event(ITE_STATE_DEV_MODEL, __VA_ARGS__) + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_log log + * @{ + */ + +/** + * @brief Set the print level. + * + * @param [in] level: @n level from 1 to 5, the greater the number, the more detailed the printing. + * + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_SetLogLevel(IOT_LogLevel level); + +/** + * @brief Print the memory usage statistics. + * + * @param [in] level: @n level from 1 to 5, the greater the number, the more detailed the printing. + * + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_DumpMemoryStats(IOT_LogLevel level); + +/** @} */ /* end of api_log */ + +/** @defgroup group_api_conninfo conninfo + * @{ + */ + + +/** + * @brief Based on the 'product_key' + 'device_name' + 'device_secret' produce an MQTT connection username and password. + * + * @param [in] product_key: @n Apply for 'product_key' in the AliYun Console. + * @param [in] device_name: @n Apply for 'device_name' in the AliYun Console. + * @param [in] device_secret: @n Apply for 'device_secret' in the AliYun Console. + * @param [out] info_ptr: @n return MQTT connection parameter. + * + * @retval -1 : Fail. + * @retval 0 : Success. + * @see None. + */ +DLL_IOT_API int IOT_SetupConnInfo(const char *product_key, + const char *device_name, + const char *device_secret, + void **info_ptr); + +/** + * @brief Setup Demain type, should be called before MQTT connection. + * + * @param [in] option: see iotx_ioctl_option_t. + * + * @return None. + * @see None. + */ +DLL_IOT_API int IOT_Ioctl(int option, void *data); + +void sf_live_mqtt_url_set(unsigned char* url); +void sf_live_mqtt_url_get(unsigned char* url); + +/** @} */ /* end of api_conninfo */ + +/** @} */ /* end of api */ + +#include "exports/iot_export_compat.h" +#include "exports/iot_export_errno.h" +#include "exports/iot_export_awss.h" +#include "exports/iot_export_mqtt.h" +#include "exports/iot_export_shadow.h" +#include "exports/iot_export_coap.h" +#include "exports/iot_export_ota.h" +#include "exports/iot_export_http.h" +#include "exports/iot_export_event.h" +#include "exports/iot_export_http2.h" +#include "exports/iot_export_http2_stream.h" +#include "exports/iot_export_diagnosis.h" +#include "exports/iot_export_guider.h" +#include "exports/iot_export_linkkit.h" +#include "exports/iot_export_reset.h" + +#if defined(__cplusplus) +} +#endif +#endif /* __IOT_EXPORT_H__ */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/iot_import.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/iot_import.h new file mode 100644 index 000000000..21b68c8e2 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/iot_import.h @@ -0,0 +1,537 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_IMPORT_H__ +#define __IOT_IMPORT_H__ +#if defined(__cplusplus) +extern "C" { +#endif + +#ifdef _WIN32 +#if !defined(CC_IS_MINGW32) +#ifdef DLL_HAL_EXPORTS +#define DLL_HAL_API __declspec(dllexport) +#else +#define DLL_HAL_API __declspec(dllimport) +#endif +#else +#define DLL_HAL_API +#endif +#else +#define DLL_HAL_API +#endif + +#include +#include +#include +#include +#include +#include +#if defined(_PLATFORM_IS_LINUX_) +#include +#endif + +#ifndef _IN_ +#define _IN_ +#endif +#ifndef _OU_ +#define _OU_ +#endif + +#define IOT_TRUE (1) /* indicate boolean value true */ +#define IOT_FALSE (0) /* indicate boolean value false */ + +/** @defgroup group_platform platform + * @{ + */ + +#ifdef SIM7000C_DAM +#include "qapi_ali_iot.h" +#else + +/*********************************** mutex interface ***********************************/ + +/** @defgroup group_platform_mutex mutex + * @{ + */ + +/** + * @brief Create a mutex. + * + * @retval NULL : Initialize mutex failed. + * @retval NOT_NULL : The mutex handle. + * @see None. + * @note None. + */ +DLL_HAL_API void *HAL_MutexCreate(void); + +/** + * @brief Destroy the specified mutex object, it will release related resource. + * + * @param [in] mutex @n The specified mutex. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_MutexDestroy(_IN_ void *mutex); + + + +/** + * @brief Waits until the specified mutex is in the signaled state. + * + * @param [in] mutex @n the specified mutex. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_MutexLock(_IN_ void *mutex); + +/** + * @brief Releases ownership of the specified mutex object.. + * + * @param [in] mutex @n the specified mutex. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_MutexUnlock(_IN_ void *mutex); + +#define PLATFORM_WAIT_INFINITE (~0) + +typedef enum { + os_thread_priority_idle = -3, /* priority: idle (lowest) */ + os_thread_priority_low = -2, /* priority: low */ + os_thread_priority_belowNormal = -1, /* priority: below normal */ + os_thread_priority_normal = 0, /* priority: normal (default) */ + os_thread_priority_aboveNormal = 1, /* priority: above normal */ + os_thread_priority_high = 2, /* priority: high */ + os_thread_priority_realtime = 3, /* priority: realtime (highest) */ + os_thread_priority_error = 0x84, /* system cannot determine priority or thread has illegal priority */ +} hal_os_thread_priority_t; + +typedef struct _hal_os_thread { + hal_os_thread_priority_t priority; /*initial thread priority */ + void *stack_addr; /* thread stack address malloced by caller, use system stack by . */ + size_t stack_size; /* stack size requirements in bytes; 0 is default stack size */ + int detach_state; /* 0: not detached state; otherwise: detached state. */ + char *name; /* thread name. */ +} hal_os_thread_param_t; + +/** + * @brief 按照指定入参创建一个线程 + * + * @param[out] thread_handle @n The new thread handle, memory allocated before thread created and return it, free it after thread joined or exit. + * @param[in] start_routine @n A pointer to the application-defined function to be executed by the thread. + This pointer represents the starting address of the thread. + * @param[in] arg @n A pointer to a variable to be passed to the start_routine. + * @param[in] hal_os_thread_param @n A pointer to stack params. + * @param[out] stack_used @n if platform used stack buffer, set stack_used to 1, otherwise set it to 0. + * @return + @verbatim + = 0: on success. + = -1: error occur. + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_ThreadCreate( + _OU_ void **thread_handle, + _IN_ void *(*work_routine)(void *), + _IN_ void *arg, + _IN_ hal_os_thread_param_t *hal_os_thread_param, + _OU_ int *stack_used); + +/** + * @brief 设置指定的线程为`Detach`状态 + * + * @param[in] thread_handle: pointer to thread handle. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_ThreadDetach(_IN_ void *thread_handle); + +/** + * @brief 杀死指定的线程 + * + * @param[in] thread_handle: pointer to thread handle, NULL means itself + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_ThreadDelete(_IN_ void *thread_handle); + +/** + * @brief 创建一个计数信号量 + * + * @return semaphore handle. + * @see None. + * @note The recommended value of maximum count of the semaphore is 255. + */ +DLL_HAL_API void *HAL_SemaphoreCreate(void); + +/** + * @brief 销毁一个计数信号量, 回收其所占用的资源 + * + * @param[in] sem @n the specified sem. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_SemaphoreDestroy(_IN_ void *sem); + +/** + * @brief 在指定的计数信号量上做自减操作并等待 + * + * @param[in] sem @n the specified semaphore. + * @param[in] timeout_ms @n timeout interval in millisecond. + If timeout_ms is PLATFORM_WAIT_INFINITE, the function will return only when the semaphore is signaled. + * @return + @verbatim + = 0: The state of the specified object is signaled. + = -1: The time-out interval elapsed, and the object's state is nonsignaled. + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_SemaphoreWait(_IN_ void *sem, _IN_ uint32_t timeout_ms); + +/** + * @brief 在指定的计数信号量上做自增操作, 解除其它线程的等待 + * + * @param[in] sem @n the specified semaphore. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_SemaphorePost(_IN_ void *sem); + +/** @} */ /* end of platform_mutex */ + + +/** @defgroup group_platform_memory_manage memory + * @{ + */ + +/** + * @brief Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. + * + * @param [in] size @n specify block size in bytes. + * @return A pointer to the beginning of the block. + * @see None. + * @note Block value is indeterminate. + */ +DLL_HAL_API void *HAL_Malloc(_IN_ uint32_t size); + +/** + * @brief Changes the size of the memory block pointed to by ptr to size bytes. + * + * @param [in] ptr @n pointer to be realloc + * @param [in] size @n specify block size in bytes for newly allocated memory + * @return A pointer to the beginning of newly allocated memory. + * @see None. + * @note Block value is indeterminate. + */ +DLL_HAL_API void *HAL_Realloc(_IN_ void *ptr, _IN_ uint32_t size); + +/** + * @brief Allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. + * + * @param [in] nmemb @n array elements item counts + * @param [in] size @n specify block size in bytes for every array elements + * @return A pointer to the beginning of allocated memory. + * @see None. + * @note Block value is indeterminate. + */ +DLL_HAL_API void *HAL_Calloc(_IN_ uint32_t nmemb, _IN_ uint32_t size); + +/** + * @brief Deallocate memory block + * + * @param[in] ptr @n Pointer to a memory block previously allocated with platform_malloc. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Free(_IN_ void *ptr); + + +/** @} */ /* end of platform_memory_manage */ + +/** @defgroup group_platform_other other + * @{ + */ + +/** + * @brief Retrieves the number of milliseconds that have elapsed since the system was boot. + * + * @return the number of milliseconds. + * @see None. + * @note None. + */ +DLL_HAL_API uint64_t HAL_UptimeMs(void); + +/** + * @brief Retrieves the timer string. + * + * @param [buf] give buffer to save timer string + * @param [len] the length of buffer + * @return the string of timer. + * @see None. + * @note None. + */ +DLL_HAL_API char *HAL_GetTimeStr(_IN_ char *buf, _IN_ int len); + +/** + * @brief Sleep thread itself. + * + * @param [in] ms @n the time interval for which execution is to be suspended, in milliseconds. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_SleepMs(_IN_ uint32_t ms); + +/** + * @brief Set seed for a sequence of pseudo-random integers, which will be returned by HAL_Random() + * + * @param [in] seed @n A start point for the random number sequence + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Srandom(_IN_ uint32_t seed); + +/** + * @brief Get a random integer + * + * @param [in] region @n Range of generated random numbers + * @return Random number + * @see None. + * @note None. + */ +DLL_HAL_API uint32_t HAL_Random(_IN_ uint32_t region); + +/** + * @brief Writes formatted data to stream. + * + * @param [in] fmt: @n String that contains the text to be written, it can optionally contain embedded format specifiers + that specifies how subsequent arguments are converted for output. + * @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Printf(_IN_ const char *fmt, ...); + +/** + * @brief Writes formatted data to string. + * + * @param [out] str: @n String that holds written text. + * @param [in] len: @n Maximum length of character will be written + * @param [in] fmt: @n Format that contains the text to be written, it can optionally contain embedded format specifiers + that specifies how subsequent arguments are converted for output. + * @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers. + * @return bytes of character successfully written into string. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Snprintf(_OU_ char *str, _IN_ const int len, _IN_ const char *fmt, ...); + +/** + * @brief Writes formatted data to string. + * + * @param [out] str: @n String that holds written text. + * @param [in] len: @n Maximum length of character will be written. + * @param [in] fmt: @n Format that contains the text to be written. + * @param [in] ap: @n the variable argument list. + * @return bytes of character successfully format into string. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Vsnprintf(_OU_ char *str, _IN_ const int len, _IN_ const char *fmt, _IN_ va_list ap); + +/** @} */ /* end of group_platform_other */ + +/** @defgroup group_platform_network network + * @{ + */ + +#define NETWORK_ADDR_LEN (16) /* IP网络地址的长度 */ +#define HAL_MAC_LEN (17 + 1) /* MAC地址的长度 */ + +typedef struct _network_addr_t { + unsigned char + addr[NETWORK_ADDR_LEN]; /* 目标UDP主机地址, 点分十进制IP地址 */ + unsigned short port; /* 目标UDP端口, 范围是0-65535 */ +} NetworkAddr; + +/** + * @brief 获取Wi-Fi网口的MAC地址, 格式应当是"XX:XX:XX:XX:XX:XX" + * + * @param mac_str : 用于存放MAC地址字符串的缓冲区数组 + * @return 指向缓冲区数组起始位置的字符指针 + */ +DLL_HAL_API char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]); + +/** + * @brief 获取Wi-Fi网口的IP地址, 点分十进制格式保存在字符串数组出参, 二进制格式则作为返回值, 并以网络字节序(大端)表达 + * + * @param ifname : 指定Wi-Fi网络接口的名字 + * @param ip_str : 存放点分十进制格式的IP地址字符串的数组 + * @return 二进制形式的IP地址, 以网络字节序(大端)组织 + */ +DLL_HAL_API uint32_t HAL_Wifi_Get_IP(_OU_ char ip_str[NETWORK_ADDR_LEN], _IN_ const char *ifname); + +/** + * @brief check system network is ready(get ip address) or not. + * + * @param None. + * @return 0, net is not ready; 1, net is ready. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Sys_Net_Is_Ready(); + +/** + * @brief reboot system immediately. + * + * @param None. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Reboot(void); + +DLL_HAL_API void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data); +DLL_HAL_API int HAL_Timer_Start(void *t, int ms); +DLL_HAL_API int HAL_Timer_Stop(void *t); +DLL_HAL_API int HAL_Timer_Delete(void *timer); + +/** + * @brief Set the UTC time in milliseconds. + * + * @param[in] ms: @the time value to be set in milliseconds. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_UTC_Set(long long ms); + +/** + * @brief Get the UTC time in milliseconds. + * + * @param None. + * @return the UTC time in milliseconds. + * @see None. + * @note None. + */ +DLL_HAL_API long long HAL_UTC_Get(void); + +typedef enum { + HAL_SEEK_SET, + HAL_SEEK_CUR, + HAL_SEEK_END +} hal_fs_seek_type_t; + +/** + * @brief Opens the file whose name is specified in the parameter filename and associates it + * with a stream that can be identified in future operations by the void pointer returned. + * + * @param [in] path: @n The file path to open.With reference to fopen + * @param [in] mode: @n C string containing a file access mode. + * @return If the file is successfully opened, the function returns a pointer to void object that can be used to + * identify the stream on future operations.Otherwise, a null pointer is returned. + * @see None. + * @note None. + */ +DLL_HAL_API void *HAL_Fopen(const char *path, const char *mode); +/** + * @brief Reads an array of count elements, each one with a size of size bytes, from the stream and + * stores them in the block of memory specified by ptr. + * + * @param [in] buff: @n Pointer to a block of memory with a size of at least (size*count) bytes, converted to a void*. + * @param [in] size: @n size in bytes, of each element to be read. + * @param [in] count: @n Number of elements, each one with a size of size bytes. + * @param [in] stream: @n Pointer to void that specifies an input stream. + * @return The total number of elements successfully read is returned.If either size or count is zero, the function returns zero + * @see None. + * @note None. + */ +DLL_HAL_API uint32_t HAL_Fread(void *buff, uint32_t size, uint32_t count, void *stream); + +/** + * @brief Writes an array of count elements, each one with a size of size bytes, from the block of memory pointed + * by ptr to the current position in the stream. + * + * @param [in] ptr: @n Pointer to the array of elements to be written, converted to a const void*. + * @param [in] size: @n Size in bytes of each element to be written. + * @param [in] count: @n Number of elements, each one with a size of size bytes. + * @param [in] stream: @n Pointer to void that specifies an output stream. + * @return The total number of elements successfully written is returned.If either size or count is zero, the function returns zero. + * @see None. + * @note None. + */ +DLL_HAL_API uint32_t HAL_Fwrite(const void *ptr, uint32_t size, uint32_t count, void *stream); + +/** + * @brief Sets the position indicator associated with the stream to a new position. + * + * @param [in] stream: @n Pointer to void that identifies the stream. + * @param [in] offset: @n Binary files: Number of bytes to offset from origin. + * @param [in] origin: @n Position used as reference for the offset. It is specified by one of value enum in hal_fs_seek_type_t. + * + * @return If successful, the function returns zero.Otherwise, it returns non-zero value. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Fseek(void *stream, long offset, int origin); + +/** + * @brief Closes the file associated with the stream and disassociates it. + * + * @param [in] stream: @n Pointer to void that identifies the stream. + * + * @return If the stream is successfully closed, a zero value is returned.On failure, non-zero is returned. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Fclose(void *stream); + +/** + * @brief Returns the current value of the position indicator of the stream. + * + * @param [in] stream: @n Pointer to void that identifies the stream. + * + * @return On success, the current value of the position indicator is returned.On failure, -1L is returned. + * @see None. + * @note None. + */ +DLL_HAL_API long HAL_Ftell(void *stream); + +#include "iot_export.h" +#include "imports/iot_import_config.h" +#include "imports/iot_import_product.h" +#include "imports/iot_import_crypt.h" +#include "imports/iot_import_awss.h" +#include "imports/iot_import_dtls.h" +#include "imports/iot_import_tls.h" +#include "imports/iot_import_tcp.h" +#include "imports/iot_import_udp.h" +#include "imports/iot_import_ota.h" +#include "imports/iot_import_kv.h" + +/*for compatible with older version*/ +#define HAL_Kv_Set aos_kv_set +#define HAL_Kv_Get aos_kv_get +#define HAL_Kv_Del aos_kv_del +#define HAL_Kv_Del_By_Prefix aos_kv_del_by_prefix + +#endif /* SIM7000C_DAM */ +#if defined(__cplusplus) +} +#endif +#endif /* __IOT_IMPORT_H__ */ + diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_api.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_api.h new file mode 100644 index 000000000..b7c3d1288 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_api.h @@ -0,0 +1,422 @@ +#ifndef LINK_VISUAL_API_H +#define LINK_VISUAL_API_H + +#include "link_visual_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------——-- SDK业务相关的消息通知 ----------------------------*/ +/** +* @brief SDK需要发送消息(一般指MQTT) +* +* @param [IN] lv_message_publish_param_s: 消息上报参数 +* +* @retval < 0 : Fail. +* @retval 0 : Success. +* +*/ +typedef int (*lv_message_publish_cb)(const lv_message_publish_param_s *message); + +/** + * @brief 通知设备开始推流 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_start_push_stream_param_s: 开始推流的参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + * + * @notice: type == LV_STREAM_CMD_LIVE时,需要调用lv_stream_send_video()/lv_stream_send_audio()直接开始推流; + * type == LV_STREAM_CMD_STORAGE_RECORD_BY_FILE/LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME时, + * 需要等待lv_on_push_streaming_cmd_cb()中的消息通知;当lv_on_push_streaming_cmd_cb()中通知LV_STORAGE_RECORD_START时, + * 调用lv_stream_send_video()/lv_stream_send_audio()开始推流 + * @see lv_stream_start_service() lv_on_push_streaming_cmd_cb() + */ +typedef int (*lv_start_push_streaming_cb)(const lv_device_auth_s *auth, const lv_start_push_stream_param_s *param); + +/** + * @brief 通知设备停止推流 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_stop_push_stream_param_s: 停止推流的参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +typedef int (*lv_stop_push_streaming_cb)(const lv_device_auth_s *auth, const lv_stop_push_stream_param_s *param); + +/** + * @brief 推送直播/存储录像流的过程中,需要支持的命令 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_on_push_streaming_cmd_param_s: 推流过程中的参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +typedef int (*lv_on_push_streaming_cmd_cb)(const lv_device_auth_s *auth, const lv_on_push_stream_cmd_param_s *param); + +/** + * @brief 对接过程中,收到的数据 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_on_push_streaming_data_param_s: 推流过程中的参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +typedef int (*lv_on_push_streaming_data_cb)(const lv_device_auth_s *auth, const lv_on_push_streaming_data_param_s *param); + +/** + * @brief 查询存储录像列表 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_query_record_param_s: 录像查询参数 + * + * @return void + */ +typedef void (*lv_query_record_cb)(const lv_device_auth_s *auth, const lv_query_record_param_s *param); + +/** + * @brief 主动 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_query_record_param_s: 录像查询参数 + * + * @return void + */ +typedef void (*lv_trigger_picture_cb)(const lv_device_auth_s *auth, const lv_trigger_picture_param_s *param); + +/** + * @brief 云端事件通知 + * + * @param [IN] type: 事件类型 + * @param [IN] param: 事件附加参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +typedef int (*lv_cloud_event_cb)(const lv_device_auth_s *auth, const lv_cloud_event_param_s *param); + +/** + * @brief 功能强校验 + * @notice 请按照实际的功能对接情况进行返回: + * 预录功能已经实现时,返回LV_SDK_FEATURE_CHECK_PRE_EVENT;否则返回LV_SDK_FEATURE_CHECK_CLOSE + * + * + * @retval LV_FEATURE_CHECK_PRE_EVENT : 预录功能已实现. + * @retval LV_FEATURE_CHECK_CLOSE : 预录功能未实现 + */ +typedef int (*lv_feature_check_cb)(void); + +/** + * @brief 日志信息回调 + * + * @param [IN] level : 日志级别 + * @param [IN] file_name : 日志的源文件名称 + * @param [IN] line : 日志的源文件行数 + * @param [IN] fmt : 日志打印可变参数 + * + * @return void + */ +typedef void (*lv_log_cb)(lv_log_level_e level, const char *file_name, int line, const char *fmt, ...); + +/** + * @brief SDK异步处理结果通知 + * + * @param auth : 设备认证信息 + * @param result : 异步结果 + * + * @return void + */ +typedef void (*lv_async_result_cb)(const lv_device_auth_s *auth, const lv_async_result_data_s *result); + +/*-------------------------SDK配置相关内容----------------------------*/ +#define PATH_NAME_LEN (32) + +/* 配置类参数结构体 */ +typedef struct { + /* 设备类型设置: + * 1. 单IPC设备,device_type = 0, + * 2. NVR+IPC设备,device_type = 1; + * NOTICE:请查看结构体 lv_device_auth_s: + * device_type = 0时,只接受一个dev_id = 0的设备(IPC) + * device_type = 1时,只接受一个dev_id = 0的设备(NVR),接受不超过sub_num个dev_id > 0的设备(IPC) */ + unsigned int device_type; + /* 最大子设备数量配置 */ + /* device_type = 0时,sub_num不生效;device_type = 1时,取值范围:[1,128] */ + unsigned int sub_num; + + /* SDK的日志配置 */ + lv_log_level_e log_level; + lv_log_destination log_dest; + + /* 点播源在多客户端观看时,无论是云端转发还是P2P,客户端观看的码流都是独立的,不会进行分发 + * storage_record_source_solo_num为单设备最大点播路数, + * storage_record_source_solo_num值范围[1,8],默认值为1 + * storage_record_source_num为支持的点播最大路数;路数越多,网络带宽、内存占用越高 + * storage_record_source_num值范围[storage_record_source_solo_num, 256],该参数仅对NVR生效 + * */ + unsigned int storage_record_source_solo_num; + unsigned int storage_record_source_num; + + /* + * lv_post_intelligent_alarm/lv_post_alarm_image/lv_post_trigger_picture会对图片数据进行拷贝(如有), + * image_size_max用于设置总的图片拷贝内存值,单位:B。 + * 若单张图片超过总内存限制,则直接丢弃图片;若单张图片超过剩余内存限制,则从旧到新丢弃图片,直至新图片可被拷贝。丢弃后的行为见具体API。 + * */ + unsigned int image_size_max; + /* + * lv_post_intelligent_alarm/lv_post_alarm_image/lv_post_trigger_picture会异步上传图片, + * image_parallel用于设置图片并发上传数量,值范围[1,8]。 + * 并发越大,发送越快,内存消耗越高,带宽占用越大。WIFI设备建议为[2,3],有线IPC建议为[2,4],有线NVR建议为[4,8] + * */ + unsigned int image_parallel; + + /* 码流自检查功能,能帮助开发者发现码流本身问题,调试过程中请打开。 + * 0 - 关闭, >0 - 打开 */ + unsigned int stream_auto_check; + /* 码流数据自动保存功能,需要排查码流兼容性等问题才需要打开,在stream_auto_check打开后可使用 + * 0 - 关闭, >0 - 打开 */ + unsigned int stream_auto_save; + /* 码流数据自动保存的路径,路径需保证存在且可写,路径名末尾需要含有"/",如 "/tmp/" */ + char stream_auto_save_path[PATH_NAME_LEN + 1]; + + /* 设备取证服务功能(Device Attestation Service, 缩写为das),0-开启,1-关闭 */ + unsigned int das_close; + + /* + * DNS服务器配置 + * @Notice: dns_mode的值 + * = LV_DNS_SYSTEM:仅读取系统配置/etc/resolv.conf中的DNS服务器配置 + * = LV_DNS_EXTERNAL:仅读取外部配置dns_num和dns_servers中的DNS服务器配置 + * = LV_DNS_SYSTEM_AND_EXTERNAL:读取系统配置和外部配置 + * @Notice: + * 若未成功读取到DNS服务器配置,则使用内置的IP: 223.5.5.5/223.6.6.6/8.8.8.8 + * 总读取到的DNS配置不超过10个(系统配置优先/按读取顺序) + * 推荐使用LV_DNS_SYSTEM_AND_EXTERNAL,除系统自动获取的DNS配置外,外部另配置数个公共、可靠的服务器;推荐总配置3个以上 + * */ + lv_dns_mode_e dns_mode; + unsigned int dns_num; + char **dns_servers;//字符串数组 +} lv_init_config_s; + +/* 回调类参数结构体 */ +typedef struct { + /* 消息通道 */ + lv_message_publish_cb message_publish_cb; + + /* SDK的日志回调(如有) */ + lv_log_cb log_cb; + + /* 音视频推流服务 */ + lv_start_push_streaming_cb start_push_streaming_cb; + lv_stop_push_streaming_cb stop_push_streaming_cb; + lv_on_push_streaming_cmd_cb on_push_streaming_cmd_cb; + lv_on_push_streaming_data_cb on_push_streaming_data_cb; + + /* 存储录像查询命令 */ + lv_query_record_cb query_storage_record_cb; + + /* 主动抓图命令 */ + lv_trigger_picture_cb trigger_picture_cb; + + /* 云端事件通知 */ + lv_cloud_event_cb cloud_event_cb; + + /* 功能强校验 */ + lv_feature_check_cb feature_check_cb; + + /* 异步结果通知 */ + lv_async_result_cb async_result_cb; +} lv_init_callback_s; + +/* 配置参数结构体 */ +typedef struct { + int todo; +} lv_init_system_s; + +/*------------------------- SDK功能接口 ----------------------------*/ +/** + * @brief SDK初始化 + * + * @param [IN] config: SDK配置参数集合 + * @param [IN] callback: SDK回调参数集合 + * @param [IN] system: SDK系统参数集合 + * + * @return lv_error_e + */ +int lv_init(const lv_init_config_s *config, const lv_init_callback_s *callback, const lv_init_system_s *system); + +/** + * @brief SDK销毁 + * + * @param [IN] void + * + * @return lv_error_e + */ +int lv_destroy(void); + +/** + * @brief 消息适配器,将消息注入该函数中,由SDK代为处理 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_message_adapter_property_s: 消息内容入参 + * + * @return lv_error_e + */ +int lv_message_adapter(const lv_device_auth_s *auth, const lv_message_adapter_param_s *param); + +/** + * @brief 在发送实际视音频数据前发送视音频相关配置,用于直播推流和存储录像播放 + * + * @param [IN] service_id: 服务ID,来自回调 lv_start_push_streaming_cb + * @param [IN] lv_stream_send_config_param_s: 配置参数集合 + * @notice 通知开始推流、强制I帧请求后,需要调用此API。 + * + * @return lv_error_e + * @see lv_start_push_streaming_cb() + */ +int lv_stream_send_config(int service_id, const lv_stream_send_config_param_s *param); + +/** + * @brief 发送音视频数据 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_stream_send_media_param_s: 音视频参数 + * + * @return lv_error_e + */ +int lv_stream_send_media(int service_id, const lv_stream_send_media_param_s *param); + +/** + * @brief 卡录像点播模式时(LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME),在最后一个文件播放结束后调用 + * 含预录事件录像功能时(LV_STREAM_CMD_PRE_EVENT_RECORD),在预录缓冲数据消耗完第一次切换为实时码流时调用 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_push_stream_cmd_s: 命令名 + * + * @return lv_error_e + * + */ +int lv_stream_send_cmd(int service_id, lv_push_stream_cmd_s cmd); + +/** + * @brief 智能报警事件图片上传,通过该接口上报的图片和事件是绑定在一起的 + * + * @param [IN] param: 结构体lv_intelligent_alarm_param_s指针 + * + * @notice: + * 1. 调用间隔短于云端设定值,返回失败 + * 2. 附加字符串大于2048B时会被截断,但不会返回失败 + * 3. 单张图片数据最大为5MB(含),超过则返回失败 + * 4. 本接口为异步接口,存在图片数据时,SDK会进行图片数据的拷贝,拷贝受到image_size_max的限制; + * 5. 事件也会进行拷贝,不受限制。事件和图片随后加入任务队列中 + * 6. 任务队列遵循FIFO进行处理,并发处理量为image_parallel + * 7. 任务处理时,先上传图片。如果有图片数据,则进行图片上传,否则进入下一步。如果图片上传失败,不会进行重传,进入下一步 + * 8. 上报事件,如果事件上报失败,不会进行重传。 + * 9. 上传结果会回调至lv_async_result_cb + * + * + * 异步上报的结果会反馈到lv_async_result_cb。 + * + * @return lv_error_e + */ +int lv_post_intelligent_alarm(const lv_device_auth_s *auth, const lv_intelligent_alarm_param_s *param, int *service_id); + +/** + * @brief 报警事件图片上传或抓图上传,通过该接口上报的图片和事件是绑定在一起的 + * @notice 报警事件上传时,推荐使用lv_post_intelligent_alarm,该接口将逐渐废弃 + + * @notice: + * 1. 调用间隔短于云端设定值,返回失败 + * 2. 附加字符串大于2048B时会被截断,但不会返回失败 + * 3. 单张图片数据最大为5MB(含),超过则返回失败 + * 4. 本接口为异步接口,存在图片数据时,SDK会进行图片数据的拷贝,拷贝受到image_size_max的限制; + * 5. 事件也会进行拷贝,不受限制。事件和图片随后加入任务队列中 + * 6. 任务队列遵循FIFO进行处理,并发处理量为image_parallel + * 7. 任务处理时,先上传图片。如果有图片数据,则进行图片上传,否则进入下一步。如果图片上传失败,不会进行重传,进入下一步 + * 8. 上报事件,如果事件上报失败,不会进行重传。 + * 9. 上传结果会回调至lv_async_result_cb + * + * + * @return lv_error_e + * @see lv_trigger_pic_capture_cb() + */ +int lv_post_alarm_image(const lv_device_auth_s *auth, const lv_alarm_event_param_s *param, int *service_id); + +/** + * @brief 卡录像查询回复 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_query_record_response_s: 回复内容 + * + * @return lv_error_e + * + */ +int lv_post_query_record(int service_id, const lv_query_record_response_param_s *response); + +/** + * @brief 抓图回复 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_trigger_picture_response_param_s: 回复内容 + * + * @notice: + * 1. 本接口为异步接口,存在图片数据时,SDK会进行图片数据的拷贝,拷贝受到image_size_max的限制; + * 2. 图片上传随后加入任务队列中 + * 3. 任务队列遵循FIFO进行处理,并发处理量为image_parallel + * 4. 上传图片。如果有图片数据,则进行图片上传,否则不做操作。如果图片上传失败,不会进行重传 + * + * @return lv_error_e + * + */ +int lv_post_trigger_picture(int service_id, const lv_trigger_picture_response_param_s *response); + + +/** + * @brief 云端事件回复 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_cloud_event_response_param_s: 回复内容 + * + * + * @notice: + * 目前仅 LV_CLOUD_EVENT_DELETE_FILE 需要回复 + * + * @return lv_error_e + * + */ +int lv_post_cloud_event(int service_id, const lv_cloud_event_response_param_s *response); + +/** + * @brief 设备主动发起功能请求 + * + * @return lv_error_e + */ +int lv_post_device_request(const lv_device_auth_s *auth, const lv_device_request_param_s *param, int *service_id); + +/* + * @brief 用于调节SDK的某些功能,如日志级别,部分特殊需求等。 + * + * @param [IN] type: 功能类型,见enum lv_control_type_e. + * @param [IN] ...: 可变长参数,参数类型与功能类型有关 + * type:LV_CONTROL_LOG_LEVEL, 参数:int log_level;实时生效 + * type:LV_CONTROL_STREAM_AUTO_CHECK,参数:unsigned int flag;已启动的流不会生效,新启动的流会生效 + * type:LV_CONTROL_STREAM_AUTO_SAVE,参数:unsigned int flag,char *save_path;需要关闭时, + * save_path参数不会被使用。已启动的流不会生效,新启动的流会生效 + * type:LV_DEVELOP_TEST_PING, 参数:unsigned int times ,const char *address; + * 未避免此类型被滥用,SDK会限制调用次数为3次,重新初始化SDK即可重置次数 + * + * @return lv_error_e + */ +int lv_control(lv_control_type_e type, ...); + + + +#ifdef __cplusplus +} +#endif +#endif /* LINK_VISUAL_API_H */ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_enum.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_enum.h new file mode 100644 index 000000000..d54ff5907 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_enum.h @@ -0,0 +1,310 @@ +#ifndef LINK_VISUAL_ENUM_H_ +#define LINK_VISUAL_ENUM_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + LV_STORAGE_RECORD_PLAN = 0, //计划录像 + LV_STORAGE_RECORD_ALARM = 1, //报警录像 + LV_STORAGE_RECORD_INITIATIVE = 2, // 主动录像 + LV_STORAGE_RECORD_ANY = 99, //所有类型。 +} lv_storage_record_type_e; //如果不在这个范围内,则为用户自定义录像类型,由APP和设备侧自主协商含义,SDK不再明确列出具体类型. + +typedef enum { + LV_STREAM_CMD_LIVE = 0, //直播 + /* + * @NOTICE: + * 点播时(LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME/LV_STREAM_CMD_STORAGE_RECORD_BY_FILE), + * 时间戳和发流速率应严格按照推荐的方式值发送,发帧速度建议: + * 全帧倍数(<4倍): + * 按照实际播放速度*1.1系数来发帧,例如:视频文件帧率是25fps,每帧时间戳pts间隔差应稳定在40ms, 建议发帧速率:1/2倍为13fps、1倍为27fps、2倍为55fps。 + * + * 抽帧倍数(>=4倍): + * 抽帧倍数播放只需要发送I帧,按照实际播放速度*1.1系数来发帧,例如:视频文件帧率是25fps,GOP大小为50,即I帧pts间隔差值为2S,建议发I帧速率:4倍为2.2fps、8倍为4.4fps、16倍为8.8fps。 + * + * */ + LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME = 2,//按UTC时间播放设备存储录像 + LV_STREAM_CMD_PRE_EVENT_RECORD = 3,//事件录像(预录),LV_SDK_FEATURE_CHECK_PRE_EVENT打开时才会回调 + LV_STREAM_CMD_VOICE = 4,//对讲 + LV_STREAM_CMD_CLOUD_STORAGE = 5,//云存储,目前暂不可用 + LV_STREAM_CMD_STORAGE_RECORD_BY_FILE = 6,//按文件名播放设备存储录像 + LV_STREAM_CMD_PERFORMANCE = 7,//开发者无需处理 + LV_STREAM_CMD_MAX, +} lv_stream_cmd_type_e; + +typedef enum { + LV_QUERY_RECORD_BY_DAY = 0,//查询当天的录像 + LV_QUERY_RECORD_BY_MONTH,//查询当月的录像 +} lv_query_record_type_e; + +/* 收到来自远程的指令 */ +typedef enum { + LV_STORAGE_RECORD_START = 0,//开始播放,对于录像点播有效 + LV_STORAGE_RECORD_PAUSE,//暂停,对于录像点播有效 + LV_STORAGE_RECORD_UNPAUSE,// 继续播放,对于录像点播有效 + LV_STORAGE_RECORD_SEEK,// 定位,对于录像点播有效 + LV_STORAGE_RECORD_STOP,//停止,对于录像点播有效 + LV_STORAGE_RECORD_SET_PARAM,//设置点播倍速等参数信息 + LV_LIVE_REQUEST_I_FRAME,//强制编码I帧,对于直播有效 + LV_VOICE_DATA, + LV_VOICE_START_SEND_DATA,//对讲半双工模式下有效,开始发送对讲数据,同时停止接收对讲数据 + LV_VOICE_START_RECV_DATA,//对讲半双工模式下有效,停止发送对讲数据,同时开始接收对讲数据 +} lv_on_push_streaming_cmd_type_e; + +/* 发送给远程的指令 */ +typedef enum { + LV_STORAGE_RECORD_COMPLETE,//录像点播已经播放完成 + LV_PRE_EVENT_RECORD_COMPLETE,//事件录像的预录数据已经完成 +} lv_push_stream_cmd_s; + +/* 视频格式 */ +typedef enum { + // 编码类型切换后需保证首帧为I帧 + LV_VIDEO_FORMAT_H264 = 0, //AVC + LV_VIDEO_FORMAT_H265 = 1, //HEVC +} lv_video_format_e; + +/* 音频格式 */ +typedef enum { + //不支持同一设备切换音频编码类型,不支持切换编码参数 + LV_AUDIO_FORMAT_PCM = 0,//音频对讲功能不支持PCM + LV_AUDIO_FORMAT_G711A = 1, + LV_AUDIO_FORMAT_AAC = 2, + LV_AUDIO_FORMAT_G711U = 3, +} lv_audio_format_e; + +/* 音频采样率 */ +typedef enum { + LV_AUDIO_SAMPLE_RATE_96000 = 0, + LV_AUDIO_SAMPLE_RATE_88200 = 1, + LV_AUDIO_SAMPLE_RATE_64000 = 2, + LV_AUDIO_SAMPLE_RATE_48000 = 3, + LV_AUDIO_SAMPLE_RATE_44100 = 4, + LV_AUDIO_SAMPLE_RATE_32000 = 5, + LV_AUDIO_SAMPLE_RATE_24000 = 6, + LV_AUDIO_SAMPLE_RATE_22050 = 7, + LV_AUDIO_SAMPLE_RATE_16000 = 8, + LV_AUDIO_SAMPLE_RATE_12000 = 9, + LV_AUDIO_SAMPLE_RATE_11025 = 10, + LV_AUDIO_SAMPLE_RATE_8000 = 11, + LV_AUDIO_SAMPLE_RATE_7350 = 12, +} lv_audio_sample_rate_e; + +/* 音频位宽 */ +typedef enum { + LV_AUDIO_SAMPLE_BITS_8BIT = 0, + LV_AUDIO_SAMPLE_BITS_16BIT = 1, +} lv_audio_sample_bits_e; + +/* 音频声道 */ +typedef enum { + LV_AUDIO_CHANNEL_MONO = 0, + LV_AUDIO_CHANNEL_STEREO = 1, +} lv_audio_channel_e; + +/* 媒体封装或编码类型 */ +typedef enum { + LV_MEDIA_JPEG = 0, + LV_MEDIA_PNG, +} lv_media_format; + +/* 事件类型 */ +typedef enum { + /* 普通事件 */ + LV_EVENT_MOVEMENT = 1, //移动侦测 + LV_EVENT_SOUND = 2, //声音侦测 + LV_EVENT_HUMAN = 3, //人形侦测 + LV_EVENT_PET = 4, //宠物侦测 + LV_EVENT_CROSS_LINE = 5, //越界侦测 + LV_EVENT_REGIONAL_INVASION = 6, //区域入侵侦测 + LV_EVENT_FALL = 7, //跌倒检测 + LV_EVENT_FACE = 8, //人脸检测 + LV_EVENT_SMILING = 9, //笑脸检测 + LV_EVENT_ABNORMAL_SOUND = 10, //异响侦测 + LV_EVENT_CRY = 11, //哭声侦测 + LV_EVENT_LAUGH = 12, //笑声侦测 + LV_EVENT_MAX +} lv_event_type_e; + +/* 智能事件类型 */ +typedef enum { + LV_INTELLIGENT_EVENT_MOVING_CHECK = 1,//移动侦测 + LV_INTELLIGENT_EVENT_SOUND_CHECK = 2,//声音侦测 + LV_INTELLIGENT_EVENT_HUMAN_CHECK = 3,//人形侦测 + LV_INTELLIGENT_EVENT_PET_CHECK = 4,//宠物侦测 + LV_INTELLIGENT_EVENT_CROSS_LINE_CHECK = 5,//越界侦测 + LV_INTELLIGENT_EVENT_REGIONAL_INVASION = 6,//区域入侵侦测 + LV_INTELLIGENT_EVENT_FALL_CHECK = 7,//跌倒检测 + LV_INTELLIGENT_EVENT_FACE_CHECK = 8,//人脸检测 + LV_INTELLIGENT_EVENT_SMILING_CHECK = 9,//笑脸检测 + LV_INTELLIGENT_EVENT_ABNORMAL_SOUND_CHECK = 10,//异响侦测 + LV_INTELLIGENT_EVENT_CRY_CHECK = 11,//哭声侦测 + LV_INTELLIGENT_EVENT_LAUGH_CHECK = 12,//笑声侦测 + LV_INTELLIGENT_EVENT_ILLEGAL_PARKING = 10001,//违章停车 + LV_INTELLIGENT_EVENT_ILLEGAL_SALE = 10002,//占道经营 + LV_INTELLIGENT_EVENT_MOTORCYCLE_RECOGNITION = 10003,//摩托车识别 + LV_INTELLIGENT_EVENT_PEDESTRIAN_RECOGNITION = 10004,//行人识别 + LV_INTELLIGENT_EVENT_VEHICLES_RECOGNITION = 10005,//车辆识别 + LV_INTELLIGENT_EVENT_DELIVER_SALE = 10006,//到店经营 + LV_INTELLIGENT_EVENT_FACE_RECOGNITION = 10007,//人脸识别 + LV_INTELLIGENT_EVENT_FACE_DETECT = 10008,//人脸检测 + LV_INTELLIGENT_EVENT_PERSON_VEHICLE_DETECTION = 10009,//人车检测 + LV_INTELLIGENT_EVENT_IPC_OCCLUSION_DETECTION = 10010,//摄像头遮挡检测 + LV_INTELLIGENT_EVENT_IPC_MOVE_DETECTION = 10011,//摄像头移动检测 + LV_INTELLIGENT_EVENT_KEY_AREA_OCCUPY = 10012,//重点区域占用 + LV_INTELLIGENT_EVENT_REGIONAL_INVASION_GW = 11001,//区域入侵 + LV_INTELLIGENT_EVENT_CLIMBING_DETECT = 11002,//攀高检测 + LV_INTELLIGENT_EVENT_ARISE_DETECT = 11003,//起身检测 + LV_INTELLIGENT_EVENT_ABSENT_DETECT = 11004,//离岗检测 + LV_INTELLIGENT_EVENT_LOITERING_DETECT = 11005,//人员逗留检测 + LV_INTELLIGENT_EVENT_CROSS_LINE_DETECT = 11006,//拌线检测 + LV_INTELLIGENT_EVENT_RETROGRADE_DETECT = 11007,//逆行检测 + LV_INTELLIGENT_EVENT_QUICKLY_MOVING = 11008,//快速移动 + LV_INTELLIGENT_EVENT_GOODS_MOVED = 11009,//物品移动 + LV_INTELLIGENT_EVENT_GOODS_LEFT = 11010,//物品遗留 + LV_INTELLIGENT_EVENT_CROWD_DENSITY = 11011,//人群密度估计 + LV_INTELLIGENT_EVENT_CROWD_GATHERED = 11012,//人群聚集 + LV_INTELLIGENT_EVENT_CROWD_DISPERSED = 11013,//人群发散 + LV_INTELLIGENT_EVENT_STRENUOUS_EXERCISE = 11014,//剧烈运动 + LV_INTELLIGENT_EVENT_FALL_DETECT = 11015,//跌倒检测 + LV_INTELLIGENT_EVENT_KID_TRACK = 11016,//小孩防走失 + LV_INTELLIGENT_EVENT_MASK_DETECT = 11017,//口罩识别 + LV_INTELLIGENT_EVENT_PET_DETECT = 11018,//宠物检测 + LV_INTELLIGENT_EVENT_HUMAN_BODY_FACE_DETECT = 11022,//人体人脸检测 + LV_INTELLIGENT_EVENT_ELECTRICAL_BICYCLE_DETECT = 11023,//电瓶车识别 + LV_INTELLIGENT_EVENT_FALLING_OBJECTS_DETECT = 11027,//高空抛物检测 + LV_INTELLIGENT_EVENT_ILLEGAL_NON_MOTOR_VEHICLE_PARKING = 12001,//非机动车乱停 + LV_INTELLIGENT_EVENT_GARBAGE_EXPOSURE = 12002,//垃圾暴露 + LV_INTELLIGENT_EVENT_HANGING_ALONG_THE_STREET = 12003,//沿街晾挂 + LV_INTELLIGENT_EVENT_FIRE_DETECT = 13001,//火灾检测 + LV_INTELLIGENT_EVENT_FIRE_CHANNEL_OCCUPANCY = 13002,//消防通道占用 + LV_INTELLIGENT_EVENT_SMOKE_DETECT = 13003,//吸烟检测 + LV_INTELLIGENT_EVENT_PASSENGER_FLOW = 14001,//客流统计 +} lv_intelligent_event_type_e; + +/* 云端事件类型 */ +typedef enum { + LV_CLOUD_EVENT_MASK = 0,//检测口罩 + LV_CLOUD_EVENT_DOWNLOAD_FILE = 1,//下载文件 + LV_CLOUD_EVENT_UPLOAD_FILE = 2,//上传文件 + LV_CLOUD_EVENT_DELETE_FILE = 3,//删除文件 + LV_CLOUD_EVENT_ENCRYPT_KEY = 4,//秘钥 +} lv_cloud_event_type_e; + +/* SDK日志等级 */ +typedef enum { + LV_LOG_ERROR = 2, + LV_LOG_WARN = 3, + LV_LOG_INFO = 4, + LV_LOG_DEBUG = 5, + LV_LOG_VERBOSE = 6, + LV_LOG_MAX = 7, +} lv_log_level_e; + +/* SDK日志输出定向*/ +typedef enum { + LV_LOG_DESTINATION_FILE,//写文件,未实现;需写文件请使用 LV_LOG_DESTINATION_USER_DEFINE + LV_LOG_DESTINATION_STDOUT,//直接向stdout输出日志 + LV_LOG_DESTINATION_USER_DEFINE,//将日志消息放入回调函数 lv_log_cb 中。可在回调函数中实现写文件功能。 + LV_LOG_DESTINATION_MAX +} lv_log_destination; + +/* SDK的函数返回值枚举量 */ +typedef enum { + LV_WARN_BUF_FULL = 1, + LV_ERROR_NONE = 0, + LV_ERROR_DEFAULT = -1, + LV_ERROR_ILLEGAL_INPUT = -2, +} lv_error_e; + +/* 远程文件类型 */ +typedef enum { + LV_REMOTE_FILE_OTHERS = 0, + LV_REMOTE_FILE_VOICE_RECORD = 1, + LV_REMOTE_FILE_FACE_PICTURE = 2, + LV_REMOTE_FILE_ALARM_IMAGE = 3, + LV_REMOTE_FILE_VOICE_MESSAGE = 4, + LV_REMOTE_FILE_MY_RINGTONE = 5, +} lv_remote_file_type_e ; + +/* 消息适配器类型 */ +typedef enum { + LV_MESSAGE_ADAPTER_TYPE_TSL_PROPERTY = 0, //物模型属性消息,目前未使用 + LV_MESSAGE_ADAPTER_TYPE_TSL_SERVICE, //物模型服务消息 + LV_MESSAGE_ADAPTER_TYPE_LINK_VISUAL, // LinkVisual自定义消息 + LV_MESSAGE_ADAPTER_TYPE_CONNECTED, //上线信息 +} lv_message_adapter_type_s; + +/* 功能强校验类型 */ +typedef enum { + LV_FEATURE_CHECK_CLOSE = 0,//被检验功能是关闭的 + LV_FEATURE_STORAGE_RECORD_KEY_ONLY_CHECK_CLOSE = 10,//关闭点播高倍速时对I帧的检查,用于支持虚拟I帧 + LV_FEATURE_VOICE_MODE_HALF_DUPLEX = 100,//对讲从默认的全双工模式改为半双工模式 + /* + * 直播预建联功能说明: + * 在APP等准备开始观看时(例如APP进入到了设备列表页面),建立直播连接,此时仅交互少量心跳数据 + * APP开始观看时,正式发送音视频数据; + * 该功能能够提高首帧的速度 + * NOTICE: APP需要同时打开预建联功能; + * NOTICE: V2.1.6开始支持该功能,若打开了预建联功能,不能降级成不支持预建联的SDK(V2.1.6之前的版本) + * 0 - 关闭, >0 - 打开 + * */ + LV_FEATURE_CHECK_LIVE_PRE_PUBLISH = 1000,//支持功能:直播预建联功能 + LV_FEATURE_CHECK_PRE_EVENT = 10000,//支持功能:预录事件录像 +} lv_feature_check_e ; + +/* SDK控制类型 */ +typedef enum { + LV_CONTROL_LOG_LEVEL = 0, + LV_CONTROL_STREAM_AUTO_CHECK =1, + LV_CONTROL_STREAM_AUTO_SAVE = 2, + LV_CONTROL_DEVELOP_TEST_PING = 3,//用于验证SDK能否完成PING功能 +} lv_control_type_e; + +/* 流的媒体数据类型 */ +typedef enum { + LV_STREAM_MEDIA_VIDEO = 0, + LV_STREAM_MEDIA_AUDIO, +} lv_stream_media_type_e; + +/* dns的服务器类型 */ +typedef enum { + LV_DNS_SYSTEM = 0, + LV_DNS_EXTERNAL = 1, + LV_DNS_SYSTEM_AND_EXTERNAL = 2, +} lv_dns_mode_e; + +/* 设备主动请求类型 */ +typedef enum { + LV_DEVICE_REQUEST_ENCRYPT_KEY = 0,//秘钥 +} lv_device_request_type_e; + +typedef enum { + LV_ASYNC_RESULT_PICTURE_UPLOAD = 0 +} lv_async_result_type_e; + +/* 报警图片结果 */ +typedef enum { + LV_PICTURE_UPLOAD_SUCCESS = 0, + LV_PICTURE_UPLOAD_FAILED = 1, +} lv_picture_upload_result_e; + +typedef enum { + SF_PARAM_MAINSTREAM = 0, + SF_PARAM_SUBSTREAM = 1, + SF_PARAM_VOICE = 2, + SF_PARAM_STORAGE_RECORD_BY_UTC_TIME, + SF_PARAM_STORAGE_RECORD_BY_FILE, + SF_PARAM_BUTT +} SF_PARAM_VIDEO_AUDIO_e; + +#ifdef __cplusplus +} +#endif + +#endif // LINK_VISUAL_ENUM_H_ diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_struct.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_struct.h new file mode 100644 index 000000000..6845299ab --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/link_visual_struct.h @@ -0,0 +1,265 @@ +#ifndef LINK_VISUAL_STRUCT_H +#define LINK_VISUAL_STRUCT_H + +#include "link_visual_enum.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* 消息上报参数 */ +typedef struct { + char *topic;//消息主键 + char *message;//消息体 + int qos;//消息的服务质量(quality of service) + int dev_id; +} lv_message_publish_param_s; + +/* 设备认证信息 */ +typedef struct { + int dev_id;//0-主设备,>0-子设备,<0-illegal + char *product_key; + char *device_name; + char *device_secret; +} lv_device_auth_s; + +/* 视频参数结构体 */ +typedef struct { + lv_video_format_e format; //视频编码格式 + unsigned int fps; //帧率 + unsigned int key_frame_interval_ms;//最大关键帧间隔时间,单位:毫秒 + unsigned int duration;//按LV_STREAM_CMD_STORAGE_RECORD_BY_FILE时的文件时长,单位s +} lv_video_param_s; + +/* 音频参数结构体 */ +typedef struct { + lv_audio_format_e format; + lv_audio_sample_rate_e sample_rate; + lv_audio_sample_bits_e sample_bits; + lv_audio_channel_e channel; +} lv_audio_param_s; + +typedef struct { + /* + * bitrate_kbps为目标码率,单位为kbps; + * SDK根据码流来预设定内部视音频缓冲区,设置过大会导致弱网下延迟增大,设置过小会导致弱网时丢帧频繁,画面卡顿 + * 一路观看时,内存分配大小:[0,1000) : 128~256KB ; [1000,2048) : 256~600KB ; [2048,4096) : 512~1000KB ; [4096,6000) : 1~2MB ; [6144,∞) : 2~4MB; + * 每多一路观看,内存可能进一步增加,增加值为内存分配的下限值,例如[0,1000)时,内存增加128KB。 + * */ + unsigned int bitrate_kbps; + lv_video_param_s *video_param;//视频的相关参数配置 + lv_audio_param_s *audio_param;//音频的相关参数配置 +} lv_stream_send_config_param_s; + +typedef struct { + struct { + lv_stream_media_type_e type; + unsigned int len; + unsigned int timestamp_ms; + char *p; + } common; + struct { + lv_video_format_e format; + int key_frame; + } video; + struct { + lv_audio_format_e format; + } audio; +} lv_stream_send_media_param_s; + +/* 开始推流参数 */ +typedef struct { + struct { + int service_id;//服务ID + lv_stream_cmd_type_e stream_cmd_type;//推流命令类型 + } common; + struct { + int stream_type;//主、子码流等 + } live; + struct { + int pre_time;//预录事件录像的预录时间 + } pre; + struct { + unsigned int start_time;//播放当天0点的UTC时间,单位:s + unsigned int stop_time;//播放当天24点的UTC时间,单位:s + unsigned int seek_time;//播放的UTC时间相对于start_time的相对时间,即 seek_time + start_time = 播放的utc时间,单位:s + lv_storage_record_type_e record_type;//录像类型 + } by_utc; + struct { + int stream_type;//主、子码流等 + } cloud; + struct { + int mode;//0-全双工,1-半双工 + } voice; + struct { + unsigned int seek_time;//播放的时间相对于文件起始的相对时间 + char *file_name;//要点播的文件名 + } by_file; +} lv_start_push_stream_param_s; + +/* 结束推流参数 */ +typedef struct { + int service_id;//服务ID + lv_stream_cmd_type_e stream_cmd_type;//推流命令类型 +} lv_stop_push_stream_param_s; + +typedef struct { + struct { + int service_id;//服务ID + lv_stream_cmd_type_e stream_cmd_type;//推流命令类型 + lv_on_push_streaming_cmd_type_e cmd_type;//命令类型 + } common; + struct { + unsigned int timestamp_ms;//seek的时间戳,单位:ms. + } seek; + struct { + unsigned int speed;//倍速信息 + unsigned int key_only;//0-推送全数据帧,1-仅推送I帧 + } set_param; +} lv_on_push_stream_cmd_param_s; + +typedef struct { + int service_id;//服务ID + lv_stream_cmd_type_e stream_cmd_type;//推流命令类型 + unsigned int len; + unsigned int timestamp; + lv_audio_param_s *audio_param; + char *p; +} lv_on_push_streaming_data_param_s; + +typedef struct { + struct { + int service_id;//服务ID + lv_query_record_type_e type;//查询类型 + } common; + struct { + lv_storage_record_type_e type;//路线类型 + unsigned int start_time;//查询的开始时间,UTC时间,秒数 + unsigned int stop_time;//查询的结束时间,UTC时间,秒数 + unsigned int num; //录像查询的数量,等于0的时候 请求时间范围内的全部录像 + } by_day; + struct { + char* month;//查询的年月份,如201806 + } by_month; +} lv_query_record_param_s; + +typedef struct { + unsigned int start_time; // 录像开始时间,UTC时间,单位为秒 + unsigned int stop_time; // 录像结束时间,UTC时间,单位为秒 + unsigned int file_size; // 录像的文件大小,单位字节 + char *file_name; // 录像的文件名 + lv_storage_record_type_e record_type; //录像类型 +} lv_query_record_response_day; //结构体数组 + +/* 录像查询列表结构体 */ +typedef struct { + struct { + unsigned int num; //录像数量,days数组的长度 + lv_query_record_response_day *days; // + } by_day; + struct { + int *months; //months为int数组,长度为31.int值为0表示无录像,非0表示有录像,当前月份不足31天部分也置为0(如2月30) + } by_month; +} lv_query_record_response_param_s; + +/* 抓图回复结构体 */ +typedef struct { + char *p;//报警事件的媒体数据,不大于1MB(大于时会返回错误),为空时仅上传其他信息 + unsigned int len; +} lv_trigger_picture_response_param_s; + +/* 消息适配器内容 */ +typedef struct { + lv_message_adapter_type_s type; + char *msg_id; + unsigned int msg_id_len; + char *service_name; + unsigned int service_name_len; + char *request; + unsigned int request_len; +} lv_message_adapter_param_s; + +typedef struct { + int service_id;//服务ID +} lv_trigger_picture_param_s; + +typedef struct { + int service_id;//服务ID + lv_cloud_event_type_e event_type; + /* 口罩识别事件 */ + struct { + void *reserved; + } mask; + /* 文件下载事件 */ + struct { + lv_remote_file_type_e file_type; + unsigned int file_size; + char *file_name; + char *url; + char *md5; + } file_download; + struct { + lv_remote_file_type_e file_type; + char *file_name; + char *url; + } file_upload; + struct { + char *file_name; + } file_delete; + struct { + char *encrypt_key; + } encrypt_key; +} lv_cloud_event_param_s; + +typedef struct { + int result;//1-成功,!=1 -失败 + char *reason;//失败时的原因字符串 +} lv_cloud_event_response_param_s; + +/* 智能事件参数集 */ +typedef struct { + lv_intelligent_event_type_e type;//智能事件类型 + lv_media_format format;//智能事件的媒体数据类型,当前只支持图片类 + struct { + char *p; + unsigned int len; + } media;//智能事件的媒体数据,不大于1MB(大于时会返回错误),为空时仅上传其他信息 + struct { + char *p; + unsigned int len; + } addition_string;//智能事件的附加字符串信息,不大于2048B(大于时会截断),为空时仅上传其他信息 +} lv_intelligent_alarm_param_s; + +/* 报警事件参数集 */ +typedef struct { + lv_event_type_e type; + struct { + char *p; + unsigned int len; + } media; //报警事件的媒体数据,不大于1MB(大于时会返回错误),为空时仅上传其他信息 + struct { + char *p; + unsigned int len; + } addition_string;//告警内容,格式为字符串;不大于1024个字节,超过会被截断;若物模型里AlarmEvent里无data字段,p传NULL即可;若有data字段但不需要使用,p则传空字符串 +} lv_alarm_event_param_s; + +/* 请求参数集 */ +typedef struct { + lv_device_request_type_e type; +} lv_device_request_param_s; + +/* SDK异步处理结果通知内容 */ +typedef struct { + lv_async_result_type_e type; + struct { + int service_id; + lv_picture_upload_result_e result; + char *picture_id; + } picture_upload; +} lv_async_result_data_s; + +#ifdef __cplusplus +} +#endif + +#endif //LINK_VISUAL_STRUCT_H diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/linkkit_client.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/linkkit_client.h new file mode 100644 index 000000000..fc24516b0 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/linkkit_client.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#ifndef PROJECT_LINKKIT_DEMO_H +#define PROJECT_LINKKIT_DEMO_H + +#include "link_visual_struct.h" +#include "iot_export_linkkit.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define SF_MUTEX_INIT_LOCK(mutex) \ + do { \ + (void)pthread_mutex_init(&mutex, NULL); \ + } while (0) + +#define SF_MUTEX_LOCK(mutex) \ + do { \ + (void)pthread_mutex_lock(&mutex); \ + } while (0) + +#define SF_MUTEX_UNLOCK(mutex) \ + do { \ + (void)pthread_mutex_unlock(&mutex); \ + } while (0) + +#define SF_MUTEX_DESTROY(mutex) \ + do { \ + (void)pthread_mutex_destroy(&mutex); \ + } while (0) + +/** + * 文件用于描述linkkit的启动、结束过程,以及linkkit生命周期过程中对命令的收发处理 + */ + +/* linkkit支持一型一密模式,即通过product_key/product_secret/device_name获取到device_secret */ +//#define LINKKIT_DYNAMIC_REGISTER + +/* linkkit支持实例化 */ +//#define LINKKIT_INSTANCE + +/* ali-smartliving-sdk-c功能 */ +#define SMARTLIVING + +/* linkkit资源初始化,并连接服务器 */ +int linkkit_client_start(const iotx_linkkit_dev_meta_info_t *main, + unsigned int sub_num, const iotx_linkkit_dev_meta_info_t *sub); + +/* linkkit与服务器断开连接,并释放资源 */ +void linkkit_client_destroy(); + +int linkkit_message_publish_cb(const lv_message_publish_param_s *param); + +/* 属性设置回调 */ +void linkkit_client_set_property_handler(const lv_device_auth_s *auth, const char *value); +void GetAuth(int dev_id, lv_device_auth_s *auth, iotx_linkkit_dev_meta_info_t *sub_dev); + +#if defined(__cplusplus) +} +#endif +#endif //PROJECT_LINKKIT_DEMO_H diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/linkvisual_client.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/linkvisual_client.h new file mode 100644 index 000000000..2f1ceca0b --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/linkvisual_client.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#ifndef PROJECT_LINKVISUAL_DEMO_H +#define PROJECT_LINKVISUAL_DEMO_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "sdk_assistant.h" +#include "link_visual_enum.h" + +/** +* 文件用于描述LinkVisual的启动、结束过程,以及生命周期过程中对音视频的传输过程 +*/ +extern int StreamServiceID; +/* linkvisual资源初始化 */ +int linkvisual_client_init(unsigned int device_type, int sub_num, lv_log_level_e log_level); + +/* linkvisual资源销毁 */ +void linkvisual_client_destroy(); + +int linkvisual_client_assistant_start(unsigned int device_type, const lv_device_auth_s *main, unsigned int sub_num, const lv_device_auth_s *sub); + +void linkvisual_client_assistant_stop(); + +/* 来自IPC的视频帧数据回调 */ +int linkvisual_client_video_handler(int service_id, lv_video_format_e format, unsigned char *buffer, unsigned int buffer_size, + unsigned int present_time, int nal_type); + +/* 来自IPC的音频帧数据回调 */ +int linkvisual_client_audio_handler(int service_id, + lv_audio_format_e format, + unsigned char *buffer, + unsigned int buffer_size, + unsigned int present_time); + +/* 来自IPC的报警图片数据回调 */ +void linkvisual_client_picture_handler(const lv_device_auth_s *auth, unsigned char *buffer, unsigned int buffer_size); + + +/* 来自IPC的点播命令回调 */ +int linkvisual_client_vod_handler(int service_id, int vod_cmd, int param); + +/* 来自IPC的录像列表查询回调 */ +void linkvisual_client_query_record(int service_id, const lv_query_record_response_param_s* param); + +/* 调试过程中使用,可以读取交互式命令,改变部分SDK的行为,可改变的行为请参考:lv_control_type_e */ +void linkvisual_client_control_test(); + +#if defined(__cplusplus) +} +#endif +#endif // PROJECT_LINKVISUAL_DEMO_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/sdk_assistant.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/sdk_assistant.h new file mode 100644 index 000000000..03a606aee --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/sdk_assistant.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#ifndef PROJECT_SDK_ASSISTANT_H +#define PROJECT_SDK_ASSISTANT_H + +#include "link_visual_struct.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* 模拟IPC功能开关,该宏包含的内容都是模拟IPC生产流的功能,开发者集成到设备时需要删除宏内容并修改为实际IPC的功能 */ +//#define DUMMY_IPC + +#define string_safe_copy(target, source, max_len) \ + do { \ + if (target && source && max_len) \ + memcpy(target, source, (strlen(source) > max_len)?max_len:strlen(source));\ +} while(0) + + +lv_device_auth_s *lvDeviceAuthCopy(const lv_device_auth_s *auth, unsigned int num); + +void lvDeviceAuthDelete(lv_device_auth_s *auth, unsigned int num); + +unsigned int lvDeviceAuthCompares(const lv_device_auth_s *auth_1, unsigned int num, const lv_device_auth_s *auth_2); + +#if defined(__cplusplus) +} +#endif + +#endif //PROJECT_SDK_ASSISTANT_H diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/include/sf_live.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/sf_live.h new file mode 100644 index 000000000..b1203d935 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/include/sf_live.h @@ -0,0 +1,109 @@ +/* +* DCF.h - Sigmastar +* +* Copyright (C) 2019 Sigmastar Technology Corp. +* +* Author: jeff.li +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#ifndef _SF_LIVE_H_ +#define _SF_LIVE_H_ +#include "SfTypeDefine.h" +#if __cplusplus +extern "C" { +#endif + + typedef struct sf_THREAD_S + { + SF_BOOL IsRun; /** + +#include "link_visual_api.h" +#include "link_visual_enum.h" +#include "iot_export_linkkit.h" +#include "iot_export.h" +#include "iot_import.h" +#include "cJSON.h" +#include "sdk_assistant.h" +#include "Log.h" + + +static int g_master_dev_id = -1; +static int g_running = 0; +static void *g_thread = NULL; +static int g_thread_not_quit = 0; +static int g_connect = 0; +static int g_property[128] = {0}; + + +static void *g_sub_thread = NULL; +static int g_sub_thread_not_quit = 0; +static void *g_sem = NULL; +static unsigned int g_sub_num = 0;//保存子设备的信息 +static iotx_linkkit_dev_meta_info_t *g_sub = NULL; + +static iotx_linkkit_dev_meta_info_t *g_master_dev_info = NULL; + +/* 这个字符串数组用于说明LinkVisual需要处理的物模型服务 */ +static char *link_visual_service[] = { + "TriggerPicCapture",//触发设备抓图 + "StartVoiceIntercom",//开始语音对讲 + "StopVoiceIntercom",//停止语音对讲 + "StartVod",//开始录像观看 + "StartVodByTime",//开始录像按时间观看 + "StopVod",//停止录像观看 + "QueryRecordTimeList",//查询录像列表 + "QueryRecordList",//查询录像列表 + "StartP2PStreaming",//开始P2P直播 + "StartPushStreaming",//开始直播 + "StopPushStreaming",//停止直播 + "QueryMonthRecord",//按月查询卡录像列表 +}; +pthread_mutex_t run_mutexLock; + +/* 以下两个extern的函数在linkkit或者ali-smartliving中定义 */ +extern int iotx_dm_get_subdev_triples_by_devid(_IN_ int devid, iotx_linkkit_dev_meta_info_t *p_subdev); +void GetAuth(int dev_id, lv_device_auth_s *auth, iotx_linkkit_dev_meta_info_t *sub_dev) { + if (dev_id > 0) { + /* 此处请注意:需要使用devid准确查询出实际的三元组 */ + iotx_dm_get_subdev_triples_by_devid(dev_id, sub_dev); + auth->dev_id = dev_id; + auth->product_key = sub_dev->product_key; + auth->device_name = sub_dev->device_name; + auth->device_secret = sub_dev->device_secret; + } else if (dev_id == 0) { + /* Notice:这里本应该也使用iotx_dm_get_triple_by_devid进行查询,方便代码统一。 + * 但此函数查询devid=0时,会丢失掉device_secret数据(有bug) + * 此处改为直接使用主设备的三元组信息,不进行查询 */ + auth->dev_id = dev_id; + auth->product_key = g_master_dev_info->product_key; + auth->device_name = g_master_dev_info->device_name; +#ifdef LINKKIT_DYNAMIC_REGISTER + HAL_GetDeviceSecret(g_master_dev_info->device_secret); +#endif + auth->device_secret = g_master_dev_info->device_secret; + } +} + + +static void *sub_online(void *args) { + while (1) + { + SF_MUTEX_UNLOCK(run_mutexLock); + if (!g_running) {//方便退出 + SF_MUTEX_UNLOCK(run_mutexLock); + break; + } + SF_MUTEX_UNLOCK(run_mutexLock); + HAL_SemaphoreWait(g_sem, PLATFORM_WAIT_INFINITE);//无限等待 + + SF_MUTEX_UNLOCK(run_mutexLock); + if (!g_running) {//方便退出 + SF_MUTEX_UNLOCK(run_mutexLock); + break; + } + SF_MUTEX_UNLOCK(run_mutexLock); + + LogInfo("Start login sub dev\n"); + for (unsigned int i = 0; i < g_sub_num; i++) { + iotx_linkkit_dev_meta_info_t meta; + memset(&meta, 0, sizeof(iotx_linkkit_dev_meta_info_t)); + string_safe_copy(meta.product_key, g_sub[i].product_key, PRODUCT_KEY_MAXLEN - 1); + string_safe_copy(meta.device_name, g_sub[i].device_name, DEVICE_NAME_MAXLEN - 1); + string_safe_copy(meta.device_secret, g_sub[i].device_secret, DEVICE_SECRET_MAXLEN - 1); + string_safe_copy(meta.product_secret, g_sub[i].product_secret, PRODUCT_SECRET_MAXLEN - 1); + int devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_SLAVE, &meta); + if (devid == FAIL_RETURN) { + LogInfo("subdev open Failed\n"); + break; + } + + int res = IOT_Linkkit_Connect(devid); + if (res == FAIL_RETURN) { + LogInfo("subdev connect Failed\n"); + break; + } + + res = IOT_Linkkit_Report(devid, ITM_MSG_LOGIN, NULL, 0); + if (res == FAIL_RETURN) { + LogInfo("subdev login Failed\n"); + break; + } + + // 子设备上线消息同步给LinkVisual + lv_device_auth_s auth; + iotx_linkkit_dev_meta_info_t sub_dev = {0}; + GetAuth(devid, &auth, &sub_dev); + lv_message_adapter_param_s in = {0}; + in.type = LV_MESSAGE_ADAPTER_TYPE_CONNECTED; + lv_message_adapter(&auth, &in); + + //所有IPC子设备需要上线后上报IPC的属性 + //每次SDK启动只需要上报一次,SDK因网络等情况离线不需要重复上报。 + if (!g_property[devid]) {//demo未做严格的越界处理,开发者可以根据实际需要来改动。 + g_property[devid] = 1; + // dummy_ipc_get_all_property(&auth); + } + } + } + + g_sub_thread_not_quit = 0; + return NULL; +} + +static int user_connected_event_handler(void) { + LogInfo("Cloud Connected\n"); + g_connect = 1; + + /** + * Linkkit连接后,上报设备的属性值。 + * 当APP查询设备属性时,会直接从云端获取到设备上报的属性值,而不会下发查询指令。 + * 对于设备自身会变化的属性值(存储使用量等),设备可以主动隔一段时间进行上报。 + */ + lv_device_auth_s auth; + iotx_linkkit_dev_meta_info_t sub_dev = {0}; + GetAuth(0, &auth, &sub_dev);//这个回调只有主设备才会进入 + + /* Linkkit连接后,查询下ntp服务器的时间戳,用于同步服务器时间。查询结果在user_timestamp_reply_handler中 */ + IOT_Linkkit_Query(g_master_dev_id, ITM_MSG_QUERY_TIMESTAMP, NULL, 0); + + // linkkit上线消息同步给LinkVisual + lv_message_adapter_param_s in = {0}; + in.type = LV_MESSAGE_ADAPTER_TYPE_CONNECTED; + lv_message_adapter(&auth, &in); + + /* 含子设备时,主设备上线后,逐个上线子设备;当网络等原因导致主设备反复上下线时,也需要重新上线子设备 */ + if (g_sub_num && g_sub) { + HAL_SemaphorePost(g_sem); + } + + return 0; +} + +static int user_disconnected_event_handler(void) { + LogInfo("Cloud Disconnected\n"); + g_connect = 0; + + return 0; +} + +static int user_service_request_handler(const int devid, const char *id, const int id_len, + const char *serviceid, const int serviceid_len, + const char *request, const int request_len, + char **response, int *response_len) { + LogInfo("%s,%d:", __FUNCTION__, __LINE__); + LogInfo("Service Request Received, Devid: %d, ID %.*s, Service ID: %.*s, Payload: %s\n", + devid, id_len, id, serviceid_len, serviceid, request); + + /* 部分物模型服务消息由LinkVisual处理,部分需要自行处理。 */ + int link_visual_process = 0; + for (unsigned int i = 0; i < sizeof(link_visual_service)/sizeof(link_visual_service[0]); i++) { + /* 这里需要根据字符串的长度来判断 */ + if (!strncmp(serviceid, link_visual_service[i], strlen(link_visual_service[i]))) { + link_visual_process = 1; + break; + } + } + + if (link_visual_process) { + /* ISV将某些服务类消息交由LinkVisual来处理,不需要处理response */ + /* 此处请注意:需要使用devid准确查询出实际的三元组 */ + lv_device_auth_s auth; + iotx_linkkit_dev_meta_info_t sub_dev = {0}; + GetAuth(devid, &auth, &sub_dev); + + lv_message_adapter_param_s in = {0}; + in.type = LV_MESSAGE_ADAPTER_TYPE_TSL_SERVICE; + in.msg_id = (char *)id; + in.msg_id_len = id_len; + in.service_name = (char *)serviceid; + in.service_name_len = serviceid_len; + in.request = (char *)request; + in.request_len = request_len; + int ret = lv_message_adapter(&auth, &in); + if (ret < 0) { + LogInfo("LinkVisual process service request failed, ret = %d\n", ret); + return -1; + } + } + else { + + if(strstr((char *)request, "sifar_p2p")) + { + LogInfo("capture message sifar_p2p\n"); + sf_p2p_cmd_set(1); + } + } + + return 0; +} + +static int user_property_set_handler(const int devid, const char *request, const int request_len) { + LogInfo("Property Set Received, Devid: %d, Request: %s\n", devid, request); + + return 0; +} + +static int user_timestamp_reply_handler(const char *timestamp) { + LogInfo("Current Timestamp: %s \n", timestamp);//时间戳为字符串格式,单位:毫秒 + + return 0; +} + +static int user_fota_handler(int type, const char *version) { + char buffer[1024] = {0}; + int buffer_length = 1024; + + if (type == 0) { + LogInfo("New Firmware Version: %s\n", version); + + IOT_Linkkit_Query(g_master_dev_id, ITM_MSG_QUERY_FOTA_DATA, (unsigned char *)buffer, buffer_length); + } + + return 0; +} + +static int user_event_notify_event_handler(const int devid, const char *request, const int request_len) { + LogInfo("Event Notify Received, Devid: %d, Request: %s \n", devid, request); + return 0; +} + +static int user_link_visual_handler(const int devid, const char *service_id, + const int service_id_len, const char *payload, + const int payload_len) { + /* Linkvisual自定义的消息,直接全交由LinkVisual来处理 */ + if (payload == NULL || payload_len == 0) { + return 0; + } + + /* 此处请注意:需要使用devid准确查询出实际的三元组 */ + lv_device_auth_s auth; + iotx_linkkit_dev_meta_info_t sub_dev = {0}; + GetAuth(devid, &auth, &sub_dev); + + lv_message_adapter_param_s in = {0}; + in.type = LV_MESSAGE_ADAPTER_TYPE_LINK_VISUAL; + in.service_name = (char *)service_id; + in.service_name_len = service_id_len; + in.request = (char *)payload; + in.request_len = payload_len; + int ret = lv_message_adapter(&auth, &in); + if (ret < 0) { + LogInfo("LinkVisual process service request failed, ret = %d\n", ret); + return -1; + } + + return 0; +} + +static void *user_dispatch_yield(void *args) { + while (1) { + + SF_MUTEX_LOCK(run_mutexLock); + if(!g_running) + { + SF_MUTEX_UNLOCK(run_mutexLock); + break; + } + SF_MUTEX_UNLOCK(run_mutexLock); + IOT_Linkkit_Yield(10); + + } + + g_thread_not_quit = 0; + return NULL; +} + +int linkkit_client_start(const iotx_linkkit_dev_meta_info_t *main, + unsigned int sub_num, const iotx_linkkit_dev_meta_info_t *sub) { + LogInfo("Before start linkkit\n"); + SF_MUTEX_INIT_LOCK(run_mutexLock); + + SF_MUTEX_LOCK(run_mutexLock); + if (g_running) { + SF_MUTEX_UNLOCK(run_mutexLock); + LogInfo("Already running\n"); + return 0; + } + + g_running = 1; + SF_MUTEX_UNLOCK(run_mutexLock); + + if (!main) { + LogInfo("Illegal input\n"); + return -1; + } + + //存储子设备信息,异步使用 + if (sub_num && sub) { + g_sub_num = sub_num; + g_sub = (iotx_linkkit_dev_meta_info_t *)malloc(sizeof(iotx_linkkit_dev_meta_info_t) *sub_num); + if (!g_sub) { + return -1; + } + memcpy(g_sub, sub, sizeof(iotx_linkkit_dev_meta_info_t) * sub_num); + g_sem = HAL_SemaphoreCreate();//信号量用于线程上线子设备,也可以条件变量、定时器实现等 + if (!g_sem) { + return -1; + } + g_sub_thread_not_quit = 1; + if (HAL_ThreadCreate(&g_sub_thread, sub_online, NULL, NULL, NULL) != 0) { + LogInfo("HAL_ThreadCreate Failed\n"); + g_thread_not_quit = 0; + return -1; + } + } + + /* 设置调试的日志级别 */ + IOT_SetLogLevel(IOT_LOG_INFO); + +#ifdef SMARTLIVING + aiot_kv_init(); +#endif + + /* 注册链接状态的回调 */ + IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler); + IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_event_handler); + + /* 注册消息通知 */ + IOT_RegisterCallback(ITE_LINK_VISUAL, user_link_visual_handler);//linkvisual自定义消息 + IOT_RegisterCallback(ITE_SERVICE_REQUST, user_service_request_handler);//物模型服务类消息 + IOT_RegisterCallback(ITE_PROPERTY_SET, user_property_set_handler);//物模型属性设置 + IOT_RegisterCallback(ITE_TIMESTAMP_REPLY, user_timestamp_reply_handler);//NTP时间 + IOT_RegisterCallback(ITE_FOTA, user_fota_handler);//固件OTA升级事件 + IOT_RegisterCallback(ITE_EVENT_NOTIFY, user_event_notify_event_handler); + + if (!g_master_dev_info) { + g_master_dev_info = (iotx_linkkit_dev_meta_info_t *)malloc(sizeof(iotx_linkkit_dev_meta_info_t)); + if (!g_master_dev_info) { + LogInfo("Malloc failed \n"); + return -1; + } + memset(g_master_dev_info, 0, sizeof(iotx_linkkit_dev_meta_info_t)); + } + string_safe_copy(g_master_dev_info->product_key, main->product_key, PRODUCT_KEY_MAXLEN - 1); + string_safe_copy(g_master_dev_info->device_name, main->device_name, DEVICE_NAME_MAXLEN - 1); + string_safe_copy(g_master_dev_info->device_secret, main->device_secret, DEVICE_SECRET_MAXLEN - 1); + string_safe_copy(g_master_dev_info->product_secret, main->product_secret, PRODUCT_SECRET_MAXLEN - 1); + + /* 选择服务器地址,当前使用上海服务器 */ + int domain_type = IOTX_CLOUD_REGION_SHANGHAI; + IOT_Ioctl(IOTX_IOCTL_SET_DOMAIN, (void *)&domain_type); + + /* 动态注册 */ +#ifdef LINKKIT_DYNAMIC_REGISTER + int dynamic_register = 1; +#else + int dynamic_register = 0; +#endif + IOT_Ioctl(IOTX_IOCTL_SET_DYNAMIC_REGISTER, (void *)&dynamic_register); + +#ifdef LINKKIT_INSTANCE + int bootstrap_enabled = 1; + IOT_Ioctl(IOTX_IOCTL_SET_BOOTSTRAP_ENABLED, (void *)&bootstrap_enabled); +#endif + + /* 创建linkkit资源 */ + g_master_dev_id = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, g_master_dev_info); + if (g_master_dev_id < 0) { + LogInfo("IOT_Linkkit_Open Failed\n"); + return -1; + } + + /* 连接到服务器 */ + int ret = IOT_Linkkit_Connect(g_master_dev_id); + if (ret < 0) { + LogInfo("IOT_Linkkit_Connect Failed\n"); + return -1; + } + + /* 创建线程,线程用于轮训消息 */ + g_thread_not_quit = 1; + ret = HAL_ThreadCreate(&g_thread, user_dispatch_yield, NULL, NULL, NULL); + if (ret != 0) {//!= 0 而非 < 0 + LogInfo("HAL_ThreadCreate Failed, ret = %d\n", ret); + SF_MUTEX_LOCK(run_mutexLock); + g_running = 0; + SF_MUTEX_UNLOCK(run_mutexLock); + g_thread_not_quit = 0; + IOT_Linkkit_Close(g_master_dev_id); + return -1; + } + + /* 等待主设备链接成功(demo做了有限时长的等待,实际产品中,可设置为在网络可用时一直等待) */ + for(int i = 0; i < 100; i++) { + if(!g_connect) { + HAL_SleepMs(200); + } else { + break; + } + } + + if (!g_connect) { + LogInfo("linkkit connect Failed\n"); + linkkit_client_destroy(); + return -1; + } + + LogInfo("After start linkkit\n"); + + return 0; +} + +void linkkit_client_destroy() { + LogInfo("Before destroy linkkit\n"); + SF_MUTEX_LOCK(run_mutexLock); + if (!g_running) { + SF_MUTEX_UNLOCK(run_mutexLock); + return; + } + + g_running = 0; + SF_MUTEX_UNLOCK(run_mutexLock); + LogInfo("g_thread_not_quit:%d\n",g_thread_not_quit); + /* 等待线程退出,并释放线程资源,也可用分离式线程,但需要保证线程不使用linkkit资源后,再去释放linkkit */ +// while (g_thread_not_quit) { +// HAL_SleepMs(20); +// } + if (g_thread) { + HAL_ThreadDelete(g_thread); + g_thread = NULL; + } + + IOT_Linkkit_Close(g_master_dev_id); + g_master_dev_id = -1; + + if (g_master_dev_info) { + free(g_master_dev_info); + g_master_dev_info = NULL; + } + if (g_sub) { + free(g_sub); + g_sub = NULL; + } + if (g_sem) { + HAL_SemaphorePost(g_sem);//让线程退出 + } + while (g_sub_thread_not_quit) { + HAL_SleepMs(20); + } + if (g_sem) { + HAL_SemaphoreDestroy(g_sem); + g_sem = NULL; + } + if (g_sub_thread) { + HAL_ThreadDelete(g_sub_thread); + g_sub_thread = NULL; + } + LogInfo("After destroy linkkit\n"); +} + +int linkkit_message_publish_cb(const lv_message_publish_param_s *param) { + iotx_mqtt_topic_info_t topic_msg; + + /* Initialize topic information */ + memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); + topic_msg.qos = param->qos; + topic_msg.retain = 0; + topic_msg.dup = 0; + topic_msg.payload = param->message; + topic_msg.payload_len = strlen(param->message); + int rc = IOT_MQTT_Publish(NULL, param->topic, &topic_msg); + if (rc < 0) { + LogInfo("Publish msg error:%d\n", rc); + return -1; + } + + return 0; +} + + +/* 属性设置回调 */ +void linkkit_client_set_property_handler(const lv_device_auth_s *auth, const char *value) { + /** + * 当收到属性设置时,开发者需要修改设备配置、改写已存储的属性值,并上报最新属性值。demo只上报了最新属性值。 + */ + IOT_Linkkit_Report(auth->dev_id, ITM_MSG_POST_PROPERTY, (unsigned char *)value, strlen(value)); + +} diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/src/linkvisual_client.c b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/linkvisual_client.c new file mode 100644 index 000000000..7c2873ad9 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/linkvisual_client.c @@ -0,0 +1,539 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include +#include +#include "link_visual_struct.h" +#include "link_visual_enum.h" +#include "link_visual_api.h" +#include "iot_import.h" +#include "linkkit_client.h" +#include "sdk_assistant.h" +#include "IConfig.h" +#include "Log.h" +#include "SendMessage.h" + +#include "linkvisual_client.h" +#include "SfTypeDefine.h" +#include "sf_live.h" +typedef struct { + int live_main_service_id; + int live_sub_service_id; + int vod_utc_service_id; + int vod_file_service_id; + int voice_intercom_service_id; + int pre_record_service_id; +} IpcService; +static IpcService *g_ipc_service = NULL; +static lv_device_auth_s *g_ipc_auth = NULL; +int StreamServiceID = 0; +static unsigned int g_ipc_num = 0; + + +void sf_live_param_get(SF_PARAM_VIDEO_AUDIO_e entype,lv_video_param_s *pvparam, lv_audio_param_s *paparam) +{ + switch(entype) + { + case SF_PARAM_MAINSTREAM: + pvparam->fps = 30; + pvparam->format = LV_VIDEO_FORMAT_H265; + pvparam->duration = 30; + pvparam->key_frame_interval_ms = 0; + + paparam->channel = LV_AUDIO_CHANNEL_MONO; + paparam->format = LV_AUDIO_FORMAT_PCM; + paparam->sample_bits = LV_AUDIO_SAMPLE_BITS_16BIT; + paparam->sample_rate = LV_AUDIO_SAMPLE_RATE_8000; + break; + case SF_PARAM_SUBSTREAM: + pvparam->fps = 30; + pvparam->format = LV_VIDEO_FORMAT_H265; + pvparam->duration = 30; + pvparam->key_frame_interval_ms = 0; + + paparam->channel = LV_AUDIO_CHANNEL_MONO; + paparam->format = LV_AUDIO_FORMAT_PCM; + paparam->sample_bits = LV_AUDIO_SAMPLE_BITS_16BIT; + paparam->sample_rate = LV_AUDIO_SAMPLE_RATE_8000; + break; + case SF_PARAM_VOICE: + break; + case SF_PARAM_STORAGE_RECORD_BY_UTC_TIME: + break; + case SF_PARAM_STORAGE_RECORD_BY_FILE: + break; + default: + LogInfo("param undefined!!!\n"); + break; + + } + LogInfo("entype = %d\n",entype); + +} +static void query_storage_record_cb(const lv_device_auth_s *auth, const lv_query_record_param_s *param) +{ + LogInfo("query_storage_record_cb\n"); + /*lv_query_record_response_param_s *response = (lv_query_record_response_param_s *)malloc(sizeof(lv_query_record_response_param_s)); + memset(response, 0, sizeof(lv_query_record_response_param_s)); + + lv_post_query_record((param->common.service_id, response);*/ +} + +static void trigger_picture_cb(const lv_device_auth_s *auth, const lv_trigger_picture_param_s *param) { + +} + +static int cloud_event_cb(const lv_device_auth_s *auth, const lv_cloud_event_param_s *param) { + LogInfo("cloud_event_cb: %d \n", param->event_type); + if (param->event_type == LV_CLOUD_EVENT_DOWNLOAD_FILE) { + LogInfo("cloud_event_cb %d %u %s %s %s\n", + param->file_download.file_type, param->file_download.file_size, param->file_download.file_name, param->file_download.url, param->file_download.md5); + } else if (param->event_type == LV_CLOUD_EVENT_UPLOAD_FILE) { + LogInfo("cloud_event_cb %d %s %s\n", param->file_upload.file_type, param->file_upload.file_name, param->file_upload.url); + } else if (param->event_type == LV_CLOUD_EVENT_DELETE_FILE) { + LogInfo("cloud_event_cb %s\n", param->file_delete.file_name); +#if 0 //回复示例 + lv_cloud_event_response_param_s response; + response.reason = "http request error";//自定义内容 + response.result = 0; + lv_post_cloud_event(param->service_id, &response); +#endif + } else if (param->event_type == LV_CLOUD_EVENT_ENCRYPT_KEY) { + LogInfo("cloud_event_cb %s\n", param->encrypt_key.encrypt_key); + } + return 0; +} + +static int feature_check_cb(void) { +#if 1 + /* demo未实现预录事件录像,未启用预建联功能 */ + return LV_FEATURE_CHECK_CLOSE; +#else + return LV_FEATURE_CHECK_LIVE_PRE_PUBLISH + LV_FEATURE_CHECK_PRE_EVENT; +#endif +} + +static void async_result_cb(const lv_device_auth_s *auth, const lv_async_result_data_s *result) { + LogInfo("async_result_cb, dev_id = %d, type = %d \n", auth->dev_id, result->type); + if (result->type == LV_ASYNC_RESULT_PICTURE_UPLOAD) { + LogInfo("async_result_cb, service_id = %d picture id = %s, picture result = %d \n", + result->picture_upload.service_id, result->picture_upload.picture_id, result->picture_upload.result); + } +} + +static int on_push_streaming_cmd_cb(const lv_device_auth_s *auth, const lv_on_push_stream_cmd_param_s *param) { + LogInfo("on_push_streaming_cmd_cb service_id:%d, stream_cmd_type:%d cmd:%d %d\n", + param->common.service_id, param->common.stream_cmd_type, param->common.cmd_type, param->seek.timestamp_ms); + lv_video_param_s video_param; + lv_audio_param_s audio_param; + memset(&video_param, 0, sizeof(lv_video_param_s)); + memset(&audio_param, 0, sizeof(lv_audio_param_s)); + + lv_stream_send_config_param_s config_param = {0}; + config_param.audio_param = &audio_param; + config_param.video_param = &video_param; + config_param.bitrate_kbps = 1000; + switch(param->common.cmd_type) + { + case LV_STORAGE_RECORD_START://开始播放,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_PAUSE://暂停,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_UNPAUSE:// 继续播放,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_SEEK:// 定位,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_STOP://停止,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_SET_PARAM://设置点播倍速等参数信息 + + break; + case LV_LIVE_REQUEST_I_FRAME://强制编码I帧,对于直播有效 + + sf_live_param_get(SF_PARAM_SUBSTREAM,&video_param,&audio_param); + lv_stream_send_config(param->common.service_id, &config_param); + // sf_hal_message_send(CMD_SF_VENC_START_SUCCESS, NULL, NULL); + StartLiveMedia(); + StreamServiceID = param->common.service_id; + break; + case LV_VOICE_DATA: + + break; + default: + break; + } + return 0; +} + +static int on_push_streaming_data_cb(const lv_device_auth_s *auth, const lv_on_push_streaming_data_param_s *param) { + LogInfo("Receive voice data, param = %d %d %d %d, size = %u, timestamp = %u\n", + param->audio_param->format, param->audio_param->channel, param->audio_param->sample_bits, param->audio_param->sample_rate, param->len, param->timestamp); + return 0; +} + +static int start_push_streaming_cb(const lv_device_auth_s *auth, const lv_start_push_stream_param_s *param) { + LogInfo("start_push_streaming_cb:%d %d\n", param->common.service_id, param->common.stream_cmd_type); + + lv_video_param_s video_param; + lv_audio_param_s audio_param; + memset(&video_param, 0, sizeof(lv_video_param_s)); + memset(&audio_param, 0, sizeof(lv_audio_param_s)); + + lv_stream_send_config_param_s config_param = {0}; + config_param.audio_param = &audio_param; + config_param.video_param = &video_param; + config_param.bitrate_kbps = 1000; + // SF_PDT_PARAM_CFG_S *puiPara = sf_customer_param_get(); + // Param cameraMode = GetParam(PARAM_CAMERA_MODE); + UINT8 isNight = 0; + UINT16 lightVal = 0; + UINT8 para[3] = {0}; + switch(param->common.stream_cmd_type) + { + case LV_STREAM_CMD_LIVE: + sf_p2p_cmd_set(1); + sf_set_ipc_live_state(SF_LIVE_CONNECT_APP_STATE); + const int STARTUP_RING = 1; // TODO: + // if(sf_poweron_type_get() != SF_MCU_STARTUP_RING) + if (!STARTUP_RING) + { + // if((cameraMode.numberUInt) && (cardv_cap_status_get() == 2)) // TODO: 停止录像 + // { + // sf_cardv_message_send(0x0111, NULL, 0); + // LogInfo("stop record video for living\n"); + // sleep(1); + // } + if(sf_file_send_abort_get() == SF_ENABLE) + { + sf_file_send_abort_set(SF_ENABLE); + // sf_FileSend_stop(); // TODO: stop upload task. + // sf_acm_cmd_thread_stop(); // TODO: live highest priority + // sf_live_clear_fileAttr(); // TODO: + } + + isNight = sf_is_night_mode(1); + sf_cardv_message_send(0x0112, &isNight, 1); + lightVal = sf_get_light_value(); + sf_live_battery_monitoring_start(); + para[0] = isNight; + para[1] = (lightVal & 0xff00) >> 8; + para[2] = lightVal & 0x00ff; + sf_rtos_cmd_set(8, para); + usleep(100*1000); + system("echo p2p 1 > /tmp/cardv_fifo"); + usleep(1500*1000); + sf_live_streaming_state_set(SF_LIVE_STREAMING_ON_STATE); + } + else + { + if(sf_file_send_abort_get() == SF_ENABLE) + { + sf_file_send_abort_set(SF_ENABLE); + // sf_FileSend_stop(); // TODO: stop upload task. + // sf_acm_cmd_thread_stop(); // TODO: live highest priority + // sf_live_clear_fileAttr(); // TODO: + } + } + if (param->live.stream_type == 0) + { + sf_live_param_get(SF_PARAM_MAINSTREAM, &video_param, &audio_param); + } + else + { + sf_live_param_get(SF_PARAM_SUBSTREAM, &video_param, &audio_param); + } + lv_stream_send_config(param->common.service_id, &config_param); + StreamServiceID = param->common.service_id; + // sf_hal_message_send(CMD_SF_VENC_START_SUCCESS, NULL, NULL); + StartLiveMedia(); + sf_live_max_time_stop_task_start(); + break; + case LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME: + sf_live_param_get(SF_PARAM_STORAGE_RECORD_BY_UTC_TIME, &video_param, &audio_param); + lv_stream_send_config(param->common.service_id, &config_param); + break; + case LV_STREAM_CMD_VOICE: + sf_live_param_get(SF_PARAM_VOICE, &video_param, &audio_param); + lv_stream_send_config(param->common.service_id, &config_param); + break; + case LV_STREAM_CMD_STORAGE_RECORD_BY_FILE: + sf_live_param_get(SF_PARAM_STORAGE_RECORD_BY_FILE, &video_param, &audio_param); + lv_stream_send_config(param->common.service_id, &config_param); + break; + case LV_STREAM_CMD_PERFORMANCE: + break; + case LV_STREAM_CMD_PRE_EVENT_RECORD: + break; + case LV_STREAM_CMD_CLOUD_STORAGE: + break; + default: + LogInfo("undefined cmd !!!!\n"); + break; + } + return 0; +} + +static int stop_push_streaming_cb(const lv_device_auth_s *auth, const lv_stop_push_stream_param_s *param) { + + sf_set_ipc_live_state(SF_LIVE_DISCONNECT_APP_STATE); + LogInfo("stop_push_streaming_cb:%d %d\n", param->service_id, param->stream_cmd_type); + // sf_hal_message_send(CMD_SF_VENC_STREAM_STOP, NULL, NULL); + StopLiveMedio(); + sf_live_streaming_state_set(SF_LIVE_STREAMING_OFF_STATE); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); //it must be here + linkkit_client_destroy(); + linkvisual_client_destroy(); + StreamServiceID = 0; + + return 0; +} + +/** + * linkvisual_demo_init负责LinkVisual相关回调的注册。 + * 1. 开发者需要注册相关认证信息和回调函数,并进行初始化 + * 2. 根据回调函数中的信息,完成音视频流的上传 + * 3. 当前文件主要用于打印回调函数的命令,并模拟IPC的行为进行了音视频的传输 + */ +static int g_init = 0; +int linkvisual_client_init(unsigned int device_type, int sub_num, lv_log_level_e log_level) { + LogInfo("before init linkvisual\n"); + + if (g_init) { + LogInfo("linkvisual_demo_init already init\n"); + return 0; + } + + lv_init_config_s config; + memset(&config, 0, sizeof(lv_init_config_s)); + lv_init_callback_s callback; + memset(&callback, 0, sizeof(lv_init_callback_s)); + lv_init_system_s system; + memset(&system, 0, sizeof(lv_init_system_s)); + + /* SDK的类型配置 */ + config.device_type = device_type; + config.sub_num = sub_num; + + /* SDK的日志配置 */ + config.log_level = log_level; + config.log_dest = LV_LOG_DESTINATION_STDOUT; + + /* 码流路数限制 */ + config.storage_record_source_solo_num = 1; + config.storage_record_source_num = 4;//该参数仅对NVR有效 + + /* 图片性能控制 */ + config.image_size_max = 1024 * 1024;//内存申请不超过1M + config.image_parallel = 2;//2路并发 + + /* 码流检查功能 */ + config.stream_auto_check = 1; +#if 1 /* 码流保存为文件功能,按需使用 */ + config.stream_auto_save = 0; +#else + config.stream_auto_save = 1; + char *path = "/tmp/"; + memcpy(config.stream_auto_save_path, path, strlen(path)); +#endif + + /* das默认开启 */ + config.das_close = 0; + + +#if 1 + config.dns_mode = LV_DNS_SYSTEM; +#else + /* + * DNS配置默认使用系统内置和外部设置的 + */ + config.dns_mode = LV_DNS_SYSTEM_AND_EXTERNAL; + config.dns_num = 3; + const char *dns_ip_1 = "223.5.5.5"; + const char *dns_ip_2 = "223.6.6.6"; + const char *dns_ip_3 = "8.8.8.8"; + char *dns_servers[] = {dns_ip_1, dns_ip_2, dns_ip_3}; + config.dns_servers = dns_servers; +#endif + + callback.message_publish_cb = linkkit_message_publish_cb; + + //音视频推流服务 + callback.start_push_streaming_cb = start_push_streaming_cb; + callback.stop_push_streaming_cb = stop_push_streaming_cb; + callback.on_push_streaming_cmd_cb = on_push_streaming_cmd_cb; + callback.on_push_streaming_data_cb = on_push_streaming_data_cb; + + //获取存储录像录像列表 + callback.query_storage_record_cb = query_storage_record_cb; + + callback.trigger_picture_cb = trigger_picture_cb; + + /* 云端事件通知 */ + callback.cloud_event_cb = cloud_event_cb; + + callback.feature_check_cb = feature_check_cb; + + callback.async_result_cb = async_result_cb; + + //先准备好LinkVisual相关资源 + int ret = lv_init(&config, &callback, &system); + if (ret < 0) { + LogInfo("lv_init failed, result = %d\n", ret); + return -1; + } + +#if 0 + //测试SDK能否正常使用PING功能 + lv_control(LV_CONTROL_DEVELOP_TEST_PING, 3, "baidu.com"); +#endif + + g_init = 1; + + LogInfo("after init linkvisual\n"); + + return 0; +} + +void linkvisual_client_destroy() { + LogInfo("before destroy linkvisual\n"); + + if (!g_init) { + LogInfo("linkvisual_demo_destroy is not init\n"); + return; + } + g_init = 0; + + lv_destroy(); + + + + LogInfo("after destroy linkvisual\n"); +} + +int linkvisual_client_video_handler(int service_id, lv_video_format_e format, unsigned char *buffer, unsigned int buffer_size, + unsigned int present_time, int nal_type) { + //LogInfo("video service_id:%d, format:%d, present_time:%u nal_type:%d size %u\n", service_id, format, present_time, nal_type, buffer_size); + lv_stream_send_media_param_s param = {{0}}; + param.common.type = LV_STREAM_MEDIA_VIDEO; + param.common.p = (char *)buffer; + param.common.len = buffer_size; + param.common.timestamp_ms = present_time; + param.video.format = format; + param.video.key_frame = nal_type; + return lv_stream_send_media(service_id, ¶m); +} + +/* 音频帧数据回调 */ +int linkvisual_client_audio_handler(int service_id, + lv_audio_format_e format, + unsigned char *buffer, + unsigned int buffer_size, + unsigned int present_time) { + //LogInfo("audio service_id:%d, present_time:%u buffer_size:%u\n", service_id, present_time, buffer_size); +#ifdef DUMMY_IPC + lv_stream_send_media_param_s param = {{0}}; + param.common.type = LV_STREAM_MEDIA_AUDIO; + param.common.p = (char *)buffer; + param.common.len = buffer_size; + param.common.timestamp_ms = present_time; + param.audio.format = format; + int ret = lv_stream_send_media(service_id, ¶m); + + for (unsigned int i = 0; i < g_ipc_num; i++) {//对讲开启时,多发送一份对讲的音频 + if (sf_stream_service_ID.live_main_service_id == service_id || sf_stream_service_ID.live_sub_service_id == service_id) { + if (sf_stream_service_ID.voice_intercom_service_id > 0) { + lv_stream_send_media(sf_stream_service_ID.voice_intercom_service_id, ¶m); + } + } + } + return ret; +#endif // DUMMY_IPC + return 0; +} + +/* 报警图片数据回调 */ +void linkvisual_client_picture_handler(const lv_device_auth_s *auth, unsigned char *buffer, unsigned int buffer_size) { + static char *data = "test"; +#if 0 + lv_alarm_event_param_s param_1; + int service_id_1; + memset(¶m_1, 0, sizeof(lv_alarm_event_param_s)); + param_1.type = LV_EVENT_SOUND; + param_1.media.p = (char *)buffer; + param_1.media.len = buffer_size; + param_1.addition_string.p = data; + param_1.addition_string.len = strlen(data); + lv_post_alarm_image(auth, ¶m_1, &service_id_1); + LogInfo("lv_post_alarm_image, service id = %d\n", service_id_1); +#else + lv_intelligent_alarm_param_s param_2; + int service_id_2; + memset(¶m_2, 0, sizeof(lv_intelligent_alarm_param_s)); + param_2.type = LV_INTELLIGENT_EVENT_MOVING_CHECK; + param_2.media.p = (char *)buffer; + param_2.media.len = buffer_size; + param_2.addition_string.p = data; + param_2.addition_string.len = strlen(data); + param_2.format = LV_MEDIA_JPEG;//该字段目前无效 + lv_post_intelligent_alarm(auth, ¶m_2, &service_id_2); + LogInfo("lv_post_intelligent_alarm, service id = %d\n", service_id_2); +#endif +} + +int linkvisual_client_cmd_handler(int service_id, int cmd, int param) { + if (cmd == 0) { + lv_stream_send_cmd(service_id, LV_PRE_EVENT_RECORD_COMPLETE); + } else { + lv_stream_send_cmd(service_id, LV_STORAGE_RECORD_COMPLETE); + } + return 0; +} + +void linkvisual_client_query_record(int service_id, const lv_query_record_response_param_s *param) { + lv_post_query_record(service_id, param); +} + +void linkvisual_client_control_test() { + /* 一个十分简易的命令行解析程序,请按照示例命令来使用 */ +/*#define CMD_LINE_MAX (128) + char str[CMD_LINE_MAX] = {0}; + gets(str); + + char *key = strtok(str, " "); + if (!key) { + return; + } + char *value = strtok(NULL, " "); + if (!value) { + return; + } + + if (!strcmp(key, "-l")) {// 日志级别设置,使用示例: -l 3 + int log_level = value[0] - '0'; + lv_control(LV_CONTROL_LOG_LEVEL, log_level); + } else if (!strcmp(key, "-c")) {// 码流自检功能,使用示例: -c 0 + int check = value[0] - '0'; + lv_control(LV_CONTROL_STREAM_AUTO_CHECK, check); + } else if (!strcmp(key, "-s")) {// 码流自动功能,使用示例: -s 0 + int save = value[0] - '0'; + const char *path = "/tmp/";// 需要打开时,使用默认的保存路径 + lv_control(LV_CONTROL_STREAM_AUTO_SAVE, save, path); + } else { + return; + }*/ +} + +int linkvisual_client_assistant_start(unsigned int device_type, const lv_device_auth_s *main, unsigned int sub_num, const lv_device_auth_s *sub) +{ + return 0; +} + +void linkvisual_client_assistant_stop() +{ + +} diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sdk_assistant.c b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sdk_assistant.c new file mode 100644 index 000000000..28899abb0 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sdk_assistant.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include "sdk_assistant.h" + +#include +#include + +lv_device_auth_s *lvDeviceAuthCopy(const lv_device_auth_s *auth, unsigned int num) { + if (!(num && auth)) { + return NULL; + } + + lv_device_auth_s *auth_new = (lv_device_auth_s *)malloc(sizeof(lv_device_auth_s) * num); + if (!auth_new) { + return NULL; + } + memset(auth_new, 0, sizeof(lv_device_auth_s) * num); + + for (unsigned int i = 0; i < num; i++) { + auth_new[i].device_name = (char *)malloc(strlen(auth[i].device_name) + 1); + auth_new[i].product_key = (char *)malloc(strlen(auth[i].product_key) + 1); + auth_new[i].device_secret = (char *)malloc(strlen(auth[i].device_secret) + 1); + if (!(auth_new[i].device_name && auth_new[i].product_key && auth_new[i].device_secret)) { + lvDeviceAuthDelete(auth_new, i+1); + return NULL; + } + + memcpy(auth_new[i].product_key, auth[i].product_key, strlen(auth[i].product_key)); + auth_new[i].product_key[strlen(auth[i].product_key)] = '\0'; + memcpy(auth_new[i].device_name, auth[i].device_name, strlen(auth[i].device_name)); + auth_new[i].device_name[strlen(auth[i].device_name)] = '\0'; + memcpy(auth_new[i].device_secret, auth[i].device_secret, strlen(auth[i].device_secret)); + auth_new[i].device_secret[strlen(auth[i].device_secret)] = '\0'; + auth_new[i].dev_id = auth[i].dev_id; + } + + return auth_new; +} + +void lvDeviceAuthDelete(lv_device_auth_s *auth, unsigned int num) { + if (!auth) { + return; + } + + for (unsigned int i = 0; i < num; i++) { + if (auth[i].product_key) { + free(auth[i].product_key); + } + if (auth[i].device_secret) { + free(auth[i].device_secret); + } + if (auth[i].device_name) { + free(auth[i].device_name); + } + } + + free(auth); +} + +static int lvDeviceAuthCompare(const lv_device_auth_s *auth_1, const lv_device_auth_s *auth_2) { + if (!(auth_1 && auth_2 && + auth_1->product_key && auth_1->device_name && + auth_2->product_key && auth_2->device_name)) { + return -1; + } + + if (!((strlen(auth_1->product_key) == strlen(auth_2->product_key) && + memcmp(auth_1->product_key, auth_2->product_key, strlen(auth_1->product_key)) == 0))) { + return -1; + } + + if (!((strlen(auth_1->device_name) == strlen(auth_2->device_name) && + memcmp(auth_1->device_name, auth_2->device_name, strlen(auth_1->device_name)) == 0))) { + return -1; + } + + if (auth_1->dev_id != auth_2->dev_id) { + return -1; + } + + return 0; +} + +unsigned int lvDeviceAuthCompares(const lv_device_auth_s *auth_1, unsigned int num, const lv_device_auth_s *auth_2) { + if (!(auth_1 && num && auth_2)) { + return -1; + } + + unsigned int res = num; + unsigned int i = 0; + for (; i < num; i ++) { + if (lvDeviceAuthCompare(auth_1, &auth_2[i]) == 0) { + res = i; + break; + } + } + + return res; +} diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_live.c b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_live.c new file mode 100644 index 000000000..6a1739374 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_live.c @@ -0,0 +1,606 @@ +/* +* DCF.c - Sigmastar +* +* Copyright (C) 2019 Sigmastar Technology Corp. +* +* Author: jeff.li +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +//============================================================================== +// +// INCLUDE FILES +// +//============================================================================== + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SfTypeDefine.h" +#include "SendMessage.h" + +#include "sf_live.h" +#include "iot_export_linkkit.h" +#include "sdk_assistant.h" +#include "link_visual_enum.h" +#include "link_visual_struct.h" +#include "link_visual_api.h" +#include "linkvisual_client.h" +#include "linkkit_client.h" +#include "IConfig.h" +#include "Log.h" +#define DEBUG 1 +#define MAXBUF 2048 + +pthread_mutex_t LiveSync_mutexLock; +pthread_mutex_t LiveStatus_mutexLock; +SF_LIVE_ACCOUNT_S gstSFLiveAccount; +static SF_LIVE_APP_STATE_E eSfliveState = SF_LIVE_IDEL_STATE; +static SF_LIVE_STREAMING_STATE_E s_enSfStreamingState = SF_LIVE_STREAMING_INVALID_STATE; + +static SF_THREAD_S PictureHandleTskParam = +{ + .IsRun = 0, + .TskId = -1, +}; + + + +// void sig_handler(int signum) +// { +// LogInfo("recv signal %d\r\n", signum); +// if(sf_get_ipc_live_state() != SF_LIVE_CONNECT_APP_STATE) +// { +// linkkit_client_destroy(); +// linkvisual_client_destroy(); +// sf_send_poweroff_msg(); +// } +// } + +void sf_ipc_picture_send(int dev_id,char *filename, char *buffer, unsigned int buffer_size) +{ + lv_intelligent_alarm_param_s param_2; + int service_id_2; + + lv_device_auth_s auth; + iotx_linkkit_dev_meta_info_t sub_dev = {0}; + GetAuth(dev_id, &auth, &sub_dev); + memset(¶m_2, 0, sizeof(lv_intelligent_alarm_param_s)); + param_2.type = LV_INTELLIGENT_EVENT_MOVING_CHECK; + param_2.media.p = (char *)buffer; + param_2.media.len = buffer_size; + param_2.addition_string.p = filename; + param_2.addition_string.len = strlen(filename); + param_2.format = LV_MEDIA_JPEG;//该字段目前无效 + lv_post_intelligent_alarm(&auth, ¶m_2, &service_id_2); + LogInfo("lv_post_intelligent_alarm, service id = %d\n", service_id_2); +} + +int sf_ipc_picture_handle(SF_ARG_ATTR_S *parg) +{ + unsigned int buffer_len = 0; + FILE *fp = fopen(parg->filepath, "r"); + if (!fp) { + LogInfo("Open file failed: %s\n", parg->filepath); + return -1; + } + + fseek(fp, 0, SEEK_END); + unsigned int file_size = ftell(fp); + if (file_size > 64*1024) { + LogInfo("File is too large: %s\n", parg->filepath); + fclose(fp); + return -1; + } + + char *buffer_ = (char*)malloc(file_size); + + fseek(fp, 0, SEEK_SET); + buffer_len = fread(buffer_, 1, file_size, fp); + if(buffer_len != file_size) { + LogInfo("File read error: %s\n", parg->filepath); + fclose(fp); + return -1; + } + fclose(fp); + + sf_ipc_picture_send(parg->dev_id,parg->filename,buffer_,file_size); + + free(buffer_); + + return 0; +} + +void sf_ipc_picture_Task(void *arg) +{ + pthread_detach(pthread_self()); + SF_ARG_ATTR_S *pstarg = (SF_ARG_ATTR_S *)arg; + + sf_ipc_picture_handle(pstarg); + + PictureHandleTskParam.IsRun = 0; +} + +void sf_ipc_Picture_thread(SF_ARG_ATTR_S *parg) +{ + LOGD("RegisterNetTskParams.IsRun:%d\n", PictureHandleTskParam.IsRun); + if(!PictureHandleTskParam.IsRun) + { + pthread_create(&PictureHandleTskParam.TskId, NULL, (void*)sf_ipc_picture_Task, parg); + PictureHandleTskParam.IsRun = 1; + } +} + +int sf_ipc_httpsNet_init(void) +{ + int ret = 0; + //SF_PDT_PARAM_STATISTICS_S *sim_info_t2 = sf_statistics_param_get(); + char sysCmd[128] ={0}; + ret = system("insmod /customer/GobiNet.ko "); + //sprintf(sysCmd, "/customer/quectel-CM -s %s &",sim_info_t2->ApnGPRS); + sprintf(sysCmd, "/customer/quectel-CM -s bicsapn &"); + LogInfo("sysCmd[%s]\n",sysCmd); + ret = system(sysCmd); + return ret; +} + +int sf_ipc_live_stop(void) +{ + // sf_hal_message_send(CMD_SF_VENC_STREAM_STOP, NULL, NULL); //trigger sdk to call function stop_push_streaming_cb + StopLiveMedio(); + return 0; +} + + + +int sf_ipc_live_init() +{ + SF_MUTEX_INIT_LOCK(LiveStatus_mutexLock); + return 0; +} + +UINT32 liveSyncTimeStamp = 0; + +int sf_ipc_live_VideoStream_write(char *pu8Addr,UINT32 u32Len,UINT32 TimeStamp,UINT8 key_frame) +{ + lv_stream_send_media_param_s stmedia_param = {0}; + + stmedia_param.common.type = LV_STREAM_MEDIA_VIDEO; + stmedia_param.common.p = pu8Addr; + stmedia_param.common.len = u32Len; + stmedia_param.common.timestamp_ms = TimeStamp/1000; + + SF_MUTEX_LOCK(LiveSync_mutexLock); + liveSyncTimeStamp = TimeStamp; + SF_MUTEX_UNLOCK(LiveSync_mutexLock); + + stmedia_param.video.format = LV_VIDEO_FORMAT_H265; + stmedia_param.video.key_frame = (key_frame != 1)?1:0; + //LogInfo("TimeStamp =%ld,u32Len = %ld,key_frame = %d\n",TimeStamp,u32Len,key_frame); + if(StreamServiceID > 0) + lv_stream_send_media(StreamServiceID, &stmedia_param); +} + +int sf_ipc_live_AudioStream_write(char *pu8Addr,UINT32 u32Len,UINT32 TimeStamp) +{ + lv_stream_send_media_param_s stmedia_param = {0}; + + stmedia_param.common.type = LV_STREAM_MEDIA_AUDIO; + stmedia_param.common.p = pu8Addr; + stmedia_param.common.len = u32Len; + + SF_MUTEX_LOCK(LiveSync_mutexLock); + stmedia_param.common.timestamp_ms = liveSyncTimeStamp/1000; + SF_MUTEX_UNLOCK(LiveSync_mutexLock); + +// stmedia_param.common.timestamp_ms = TimeStamp/1000; + stmedia_param.audio.format = LV_AUDIO_FORMAT_PCM; + + //LogInfo("TimeStamp =%ld,u32Len = %ld\n",TimeStamp,u32Len); + if(StreamServiceID > 0) + lv_stream_send_media(StreamServiceID, &stmedia_param); + return SF_SUCCESS; +} + +SF_LIVE_APP_STATE_E sf_get_ipc_live_state(void) +{ + SF_LIVE_APP_STATE_E enLiveStatus = SF_LIVE_IDEL_STATE; + SF_MUTEX_LOCK(LiveStatus_mutexLock); + enLiveStatus = eSfliveState; + SF_MUTEX_UNLOCK(LiveStatus_mutexLock); + return enLiveStatus; +} + +void sf_set_ipc_live_state(SF_LIVE_APP_STATE_E state) +{ + LogInfo("[%s] set state %d\r\n", __FUNCTION__, state); + if(state >= SF_LIVE_INVALID_STATE) + return; + SF_MUTEX_LOCK(LiveStatus_mutexLock); + if(eSfliveState == SF_LIVE_DESTROY_STATE) { + SF_MUTEX_UNLOCK(LiveStatus_mutexLock); + return; + } + eSfliveState = state; + SF_MUTEX_UNLOCK(LiveStatus_mutexLock); +} + +static UINT8 sfLiveAppExit = 1; +static pthread_t sfWaitLiveTaskThread = 0; +static void * sf_wait_live_task(void * argv); + +static void * sf_wait_live_task(void * argv) +{ + if(sfLiveAppExit == 0) + { + sleep(20); + if(sf_get_ipc_live_state() != SF_LIVE_CONNECT_APP_STATE) + { + linkkit_client_destroy(); + linkvisual_client_destroy(); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); + sfLiveAppExit = 1; + } + } + pthread_exit(0); + return NULL; +} + +void sf_ipc_live_wait_connect(void) +{ + if(sfLiveAppExit == 1) + { + pthread_create(&sfWaitLiveTaskThread, NULL, sf_wait_live_task, NULL); + sfLiveAppExit = 0; + LogInfo("sf_wait_live_task\r\n"); + } +} + +static UINT8 s_u8SfLiveCheckStopExit = 1; +static pthread_t sfLiveCheckStopThread = 0; +static void * sf_live_check_stop_task(void * argv); + +static void * sf_live_check_stop_task(void * argv) +{ + UINT8 u8MinWaitTime = 0; + const int MAX_MAIT_TIME_MS = 15 * 1000; // TODO: parameter in + UINT8 u8MaxWaitTime = MAX_MAIT_TIME_MS; + while(s_u8SfLiveCheckStopExit == 0) + { + //recv poweroff msg and not live task running + // if(sf_p2p_cmd_get() || (sf_poweron_type_get() != SF_MCU_STARTUP_PIR && sf_poweron_type_get() != SF_MCU_STARTUP_TIMELAPSE)) // TODO: + // { + // u8MaxWaitTime = 15; + // LogInfo("u8MaxWaitTime:%d\n", u8MaxWaitTime); + // } + // else + // { + // u8MaxWaitTime = 0; + // LogInfo("u8MaxWaitTime:%d\n", u8MaxWaitTime); + // } + + if(sf_get_ipc_live_state() != SF_LIVE_CONNECT_APP_STATE + && sf_poweroff_state_get() == 1 + || (sf_prepare_to_stop_get() == 1 && u8MinWaitTime > u8MaxWaitTime)) + { + // if(sf_poweron_type_get() != SF_MCU_STARTUP_PIR && sf_poweron_type_get() != SF_MCU_STARTUP_TIMELAPSE) // TODO: + { + linkkit_client_destroy(); + linkvisual_client_destroy(); + } + + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); + s_u8SfLiveCheckStopExit = 1; + } + else if(sf_get_ipc_live_state() == SF_LIVE_CONNECT_APP_STATE) + { + s_u8SfLiveCheckStopExit = 1; + } + u8MinWaitTime++; + sleep(1); + } + pthread_exit(0); + return NULL; +} + +void sf_live_check_stop_task_start(void) +{ + if(s_u8SfLiveCheckStopExit == 1) + { + s_u8SfLiveCheckStopExit = 0; + pthread_create(&sfLiveCheckStopThread, NULL, sf_live_check_stop_task, NULL); + } +} + +void sf_live_check_stop_task_stop(void) +{ + if(s_u8SfLiveCheckStopExit == 0) + { + s_u8SfLiveCheckStopExit = 1; + pthread_join(sfLiveCheckStopThread, NULL); + } +} + +SF_LIVE_STREAMING_STATE_E sf_live_streaming_state_check(void) +{ + return s_enSfStreamingState; +} + +void sf_live_streaming_state_set(SF_LIVE_STREAMING_STATE_E enState) +{ + s_enSfStreamingState = enState; +} + +static UINT8 s_u8LiveMaxTimeExit = 1; +static pthread_t u32LiveMaxTimeThread = 0; +static void * sf_live_max_time_stop_task(void * argv); + +static void * sf_live_max_time_stop_task(void * argv) +{ + UINT8 u8MaxTime = 0; + while(s_u8LiveMaxTimeExit == 0) + { + if(sf_get_ipc_live_state() == SF_LIVE_CONNECT_APP_STATE) + { + u8MaxTime++; + if(u8MaxTime >= 15*60) + { + sf_set_ipc_live_state(SF_LIVE_DISCONNECT_APP_STATE); + LogInfo("[%s,%d]stop time 15min!\n", __FUNCTION__, __LINE__); + // sf_hal_message_send(CMD_SF_VENC_STREAM_STOP, NULL, NULL); + StopLiveMedio(); + sf_live_streaming_state_set(SF_LIVE_STREAMING_OFF_STATE); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); //it must be here + linkkit_client_destroy(); + linkvisual_client_destroy(); + s_u8LiveMaxTimeExit = 1; + } + } + else + { + u8MaxTime = 0; + } + sleep(1); + } + pthread_exit(0); + return NULL; +} + +void sf_live_max_time_stop_task_start(void) +{ + if(s_u8LiveMaxTimeExit == 1) + { + s_u8LiveMaxTimeExit = 0; + pthread_create(&u32LiveMaxTimeThread, NULL, sf_live_max_time_stop_task, NULL); + } +} + +void sf_live_max_time_stop_task_stop(void) +{ + if(s_u8LiveMaxTimeExit == 0) + { + s_u8LiveMaxTimeExit = 1; + pthread_join(u32LiveMaxTimeThread, NULL); + } +} +#if 1 +SF_THREAD_S stStreamLiveThread = +{ + .IsRun = 0, + .TskId = -1, +}; +static SINT32 s_s32SfFileSendCanAbort = SF_ENABLE; + +void sf_file_send_abort_set(SINT32 s32Status) +{ + s_s32SfFileSendCanAbort = s32Status; +} + +SINT32 sf_file_send_abort_get(void) +{ + return s_s32SfFileSendCanAbort; +} +static UINT8 s_u8SfPwroff = 0; + +void sf_poweroff_state_set(UINT8 u8Val) +{ + s_u8SfPwroff = u8Val; +} + +UINT8 sf_poweroff_state_get(void) +{ + return s_u8SfPwroff; +} + +static UINT8 s_u8SfPrepToStop = 0; + +void sf_prepare_to_stop_set(UINT8 u8Val) +{ + s_u8SfPrepToStop = u8Val; + LogInfo("s_u8SfPrepToStop = %d",s_u8SfPrepToStop); +} + +UINT8 sf_prepare_to_stop_get(void) +{ + return s_u8SfPrepToStop; +} +static UINT8 s_u8P2pCmd = 0; + +void sf_p2p_cmd_set(UINT8 u8Cmd) +{ + s_u8P2pCmd = u8Cmd; +} + +UINT8 sf_p2p_cmd_get(void) +{ + return s_u8P2pCmd; +} + +static void * Stream_Live_task(void * argv) +{ + int ret = 0; + int log_level = LV_LOG_ERROR; + unsigned char szMqttUrl[64] = {0}; + // SF_PDT_PARAM_STATISTICS_S *pStaticParam = sf_statistics_param_get(); + Param p2pId = GetParam(PARAM_P2P_ID); + Param p2pName = GetParam(PARAM_P2P_NAME); + Param p2pSecret = GetParam(PARAM_P2P_SECRET); + Param MQTTIp = GetParam(PARAM_MQTT_IP); + Param MQTTPort = GetParam(PARAM_MQTT_PORT); + ret = linkvisual_client_init(0, 0, log_level); + if (ret < 0) { + LogInfo("linkvisual_client_init failed\n"); + linkvisual_client_assistant_stop(); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); + return -1; + } + + SF_MUTEX_INIT_LOCK(LiveSync_mutexLock); + iotx_linkkit_dev_meta_info_t auth = {0}; + + string_safe_copy(auth.product_key, p2pId.str, PRODUCT_KEY_LEN); + string_safe_copy(auth.product_secret, "", PRODUCT_SECRET_LEN); + string_safe_copy(auth.device_name, p2pName.str, DEVICE_NAME_LEN); + string_safe_copy(auth.device_secret, p2pSecret.str, DEVICE_SECRET_LEN); + + sf_set_ipc_live_state(SF_LIVE_CONNECT_ALI_STATE); + + sf_live_check_stop_task_start(); + + ret = linkkit_client_start(&auth, 0, NULL); + if (ret < 0) { + LogInfo("linkkit_client_start failed\n"); + linkvisual_client_destroy(); + linkvisual_client_assistant_stop(); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); + return -1; + } + + sf_set_ipc_live_state(SF_LIVE_CONNECT_ALI_STATE); + +// if(sf_poweron_type_get() == 0x0A) + { + char * p1 = NULL; + char * p2 = NULL; + sf_live_mqtt_url_get(szMqttUrl); + LogInfo("[%s,%d] mqtt url is %s\n", __FUNCTION__, __LINE__, szMqttUrl); + p1 = szMqttUrl; + p2 = strchr(szMqttUrl, ':'); + memcpy(MQTTIp.str, p1, p2 - p1); + MQTTPort.numberInt = atoi(p2 + 1); + SetParam(MQTTIp, PARAM_MQTT_IP); + SetParam(MQTTPort, PARAM_MQTT_PORT); + LogInfo("mqtt ip is %s\n", MQTTIp.str); + LogInfo("mqtt port is %d\n", MQTTPort.numberInt); + } + + /* 3. 运行,等待服务器命令 */ + while(stStreamLiveThread.IsRun) { + usleep(1000 * 500); + } + + /* 4. linkkit长连接断开,并释放资源 */ + linkkit_client_destroy(); + SF_MUTEX_DESTROY(LiveSync_mutexLock); + + /* 5. LinkVisual断开音视频连接,并释放资源 */ + linkvisual_client_destroy(); + sf_set_ipc_live_state(SF_LIVE_DESTROY_STATE); + + return 0; +} + +UINT8 sf_Stream_Live_IsRuning(void) +{ + return stStreamLiveThread.IsRun; +} + +SINT32 sf_Stream_Live_start(void) +{ + + if(stStreamLiveThread.IsRun == 0) + { + pthread_create(&stStreamLiveThread.TskId, NULL, Stream_Live_task, NULL); + stStreamLiveThread.IsRun = 1; + } + return SF_SUCCESS; + +} +SINT32 sf_Stream_Live_stop(void) +{ + SINT32 s32ret = SF_SUCCESS; + + if(stStreamLiveThread.IsRun == 0) { + LogWarning("thread have already stop !!!\n"); + return SF_FAILURE; + } + stStreamLiveThread.IsRun = 0; + s32ret = pthread_join(stStreamLiveThread.TskId, NULL); + if(s32ret != SF_SUCCESS) + { + LogInfo("thread stop fail!\n"); + return s32ret; + } + + return SF_SUCCESS; +} +SINT32 sf_Stream_Live_init(void) +{ + SINT32 s32ret = SF_SUCCESS; + // MI_U8 isNight = 0; + // unsigned short lightVal = 0; + // MI_U8 para[3] = {0}; + // isNight = sf_is_night_mode(1); + // sf_cardv_message_send(0x0112, &isNight, 1); + // lightVal = sf_get_light_value(); + + // sf_live_battery_monitoring_start(); + + // para[0] = isNight; + // para[1] = (lightVal & 0xff00) >> 8; + // para[2] = lightVal & 0x00ff; + // sf_rtos_cmd_set(8, para); + // usleep(100*1000); + // system(" echo p2p 1 > /tmp/cardv_fifo"); + // sf_live_streaming_state_set(SF_LIVE_STREAMING_ON_STATE); + + // for(UINT8 i = 0; i < 40; i++) + // { + // if(sf_file_Isexsit("/dev/qcqmi0") == SF_SUCCESS) + // { + // LogInfo("usb net ko exist!\r\n"); + // break; + // } + // else + // { + // usleep(100*1000); + // } + // } + + // s32ret = sf_Stream_Live_start(); + return s32ret; +} + +#endif + diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_venc_stream.cpp b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_venc_stream.cpp new file mode 100644 index 000000000..3061a7a8f --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_venc_stream.cpp @@ -0,0 +1,377 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include "mi_venc.h" // TODO: +// #include "mi_ai.h" // TODO: +// #include "sf_type.h" +// #include "sf_common.h" +// #include "sf_param_common.h" +#include "SfTypeDefine.h" +#include "sf_live.h" +#include "Log.h" +#include "sf_venc_stream.h" + +#define STREAM_PACK_CNT (2) + +SF_THREAD_CFG_S stvencTask = +{ + .IsRun = 0, + .IsStopFlag = 0, +}; + +SF_THREAD_CFG_S staudioTask = +{ + .IsRun = 0, + .IsStopFlag = 0, +}; + +// MI_S32 _VencUserPollingStream(MI_S32 s32VencFd) +// { +// MI_U32 s32Ret = 0; +// fd_set read_fds; +// struct timeval TimeoutVal; + +// TimeoutVal.tv_sec = 0; +// TimeoutVal.tv_usec = 10000; + +// FD_ZERO(&read_fds); +// FD_SET(s32VencFd, &read_fds); +// s32Ret = select(s32VencFd + 1, &read_fds, NULL, NULL, &TimeoutVal); +// if (s32Ret < 0) { +// LogError("[%d] select failed\n", s32VencFd); +// return -1; +// } else if (0 == s32Ret) { +// return -1; +// } else if (!FD_ISSET(s32VencFd, &read_fds)) { +// LogError("not detect venc event!\n"); +// return -1; +// } + +// FD_CLR(s32VencFd, &read_fds); +// return 0; +// } +// void VideoUserGetFrame(MI_VENC_Pack_t *pstPack,MI_U32 u32FrameSize, MI_U64 framePts) +// { +// // Customers TODO: +// // Customers need to implement this function according to their own need. +// // Note that the function runs as short as possible, or it maybe drops frame! +// // Here SigmaStar just dump 300 frames to file for demo. + +// #if 0//(CARDV_ALINK_ENABLE) + +// static int frameCnt= 0; +// static int fd = 0; +// char fileName[32] = {0}; + +// if (frameCnt == 0) +// { +// sprintf(fileName,"/mnt/mmc/dump_cam0.h265"); +// fd = open(fileName,O_WRONLY|O_CREAT); +// } + +// if (-1 != fd && frameCnt < 3000) +// { + +// for (int i = 0; i = 3000) +// { +// close(fd); +// LogInfo("recod end!!!!\n"); +// } + +// frameCnt ++; +// #else + +// for (int i = 0; i < STREAM_PACK_CNT && pstPack[i].u32Len; i++) +// { +// //LogInfo("frame[%#x,%d]\n",pstPack[i].pu8Addr[4],frameType); +// sf_ipc_live_VideoStream_write((char*)pstPack[i].pu8Addr,pstPack[i].u32Len,framePts,pstPack[i].stDataType.eH265EType); +// //write(fd,(char*)pstPack[i].pu8Addr,pstPack[i].u32Len); +// } + + +// #endif +// } +// void sf_audioInUserGetFrame(MI_AUDIO_Frame_t *pstAudioFrame,MI_AUDIO_AecFrame_t *pstAecFrame) +// { + +// #if 1//(defined CFG_LIVE_ENBLE) + +// //LogInfo("audioInUserGetFrame Len:%d\n",pstAudioFrame->u32Len[0]); +// sf_ipc_live_AudioStream_write((char*)pstAudioFrame->apVirAddr[0],pstAudioFrame->u32Len[0],pstAudioFrame->u64TimeStamp); + +// #else + +// FILE *fp; +// if((fp =fopen("/mnt/mmc/live_audio.pcm","a+")) == NULL) +// { +// LogInfo("open audio failed!!!\n"); +// return; +// } +// fseek(fp, 0L, SEEK_END); +// LogInfo("audioInUserGetFrame Len:%d\n",pstAudioFrame->u32Len[0]); +// fwrite(pstAudioFrame->apVirAddr[0],1, (pstAudioFrame->u32Len[0]),fp); + +// fclose(fp); + + +// #endif +// } + +// MI_S32 _VideoUserGetFrame(void) +// { + +// MI_S32 _s32VencChn = 0; +// MI_VENC_DupChn(_s32VencChn); +// // MI_S32 s32VencFd = -1; +// MI_VENC_ChnStat_t stStat; +// MI_VENC_Stream_t *pstStream = NULL; +// MI_S32 s32Ret; +// MI_U32 u32FrameSize; +// /* +// s32VencFd = MI_VENC_GetFd(_s32VencChn); +// if(s32VencFd < 0) +// { +// LogInfo("[%s,%d] get venc fd error.\r\n", __FUNCTION__, __LINE__); +// } +// */ +// while(stvencTask.IsRun) +// { +// /* +// if (_VencUserPollingStream(s32VencFd) < 0) { +// continue; +// } +// */ +// memset(&stStat, 0, sizeof(MI_VENC_ChnStat_t)); +// s32Ret = MI_VENC_Query(_s32VencChn, &stStat); +// if (MI_SUCCESS != s32Ret || stStat.u32CurPacks == 0) { +// //LogInfo("VENC Query Error\n"); +// usleep(10000); // sleep 10 ms +// continue; +// } + +// pstStream = (MI_VENC_Stream_t *)malloc(sizeof(MI_VENC_Stream_t)); +// if (pstStream == NULL) { +// break; +// } + +// pstStream->u32PackCount = STREAM_PACK_CNT; +// pstStream->pstPack = (MI_VENC_Pack_t *)malloc(sizeof(MI_VENC_Pack_t) * STREAM_PACK_CNT); +// if (pstStream->pstPack == NULL) { +// free(pstStream); +// pstStream = NULL; +// break; +// } +// memset(pstStream->pstPack, 0, sizeof(MI_VENC_Pack_t) * STREAM_PACK_CNT); + +// s32Ret = MI_VENC_GetStream(_s32VencChn, pstStream, 0); +// if (MI_SUCCESS == s32Ret) { +// // stStat.u32CurPacks is from first frame in ring pool, +// // but we need get current frame info here, and we maybe already get more than one frame here. +// // so we need to calculate current frame packet count. +// pstStream->u32PackCount = 0; +// while (pstStream->pstPack[pstStream->u32PackCount++].bFrameEnd == 0) { +// if (pstStream->u32PackCount == STREAM_PACK_CNT) { +// LogInfo("STREAM_PACK_CNT not enough\n"); +// break; +// } +// } + +// u32FrameSize = 0; +// for (int i = 0; i < STREAM_PACK_CNT; i++) { +// u32FrameSize += pstStream->pstPack[i].u32Len; +// } + +// // VideoUserGetFrame(MI_VENC_Pack_t *pstPack, MI_U32 u32FrameSize, MI_U64 framePts) +// VideoUserGetFrame(pstStream->pstPack, u32FrameSize, pstStream->pstPack[pstStream->u32PackCount-1].u64PTS); + +// MI_VENC_ReleaseStream(_s32VencChn, pstStream); +// free(pstStream->pstPack); +// free(pstStream); +// pstStream->pstPack = NULL; +// pstStream = NULL; + +// } +// } +// } +// void *sf_venc_stream_thread(void *arg) +// { +// _VideoUserGetFrame(); +// return NULL; + +// } +void sf_venc_stream_start(void) +{ + + // if(!stvencTask.IsRun) + // { + // pthread_create(&stvencTask.TskId, NULL, sf_venc_stream_thread, NULL); + // stvencTask.IsRun = 1; + // stvencTask.IsStopFlag = 0; + // } + +} +void sf_venc_stream_stop(void) +{ + // if(stvencTask.IsRun == 0) + // return; + + // stvencTask.IsStopFlag = 1; + // stvencTask.IsRun = 0; + // pthread_join(stvencTask.TskId, NULL); +} + + +// SINT32 sf_audio_init(UINT8 AiDevId, UINT8 AiChn) +// { +// MI_S32 ret; +// MI_AUDIO_Attr_t stAttr = {0}; +// stAttr.eBitwidth = E_MI_AUDIO_BIT_WIDTH_16; +// stAttr.eSamplerate = E_MI_AUDIO_SAMPLE_RATE_8000; +// stAttr.eSoundmode = E_MI_AUDIO_SOUND_MODE_MONO; +// stAttr.eWorkmode = E_MI_AUDIO_MODE_I2S_SLAVE; +// stAttr.u32PtNumPerFrm = 160; +// stAttr.u32ChnCnt = 1; + +// /* set public attribute of AI device */ +// ret = MI_AI_SetPubAttr(AiDevId, &stAttr); +// if (MI_SUCCESS != ret) +// { +// LogInfo("set ai %d attr err:0x%x\n", AiDevId, ret); +// return ret; +// } +// ret = MI_AI_Enable(AiDevId); +// if (MI_SUCCESS != ret) +// { +// LogInfo("enable ai %d err:0x%x\n", AiDevId, ret); +// return ret; +// } + +// /* enable AI Channel */ +// ret = MI_AI_EnableChn(AiDevId, AiChn); +// if (MI_SUCCESS != ret) +// { +// LogInfo("enable Dev%d Chn%d err:0x%x\n", AiDevId, AiChn, ret); +// return ret; +// } +// return ret; +// } +// SINT32 sf_audio_outputdepth_set(UINT8 AiDevId,UINT8 AiChn ) +// { +// MI_SYS_ChnPort_t stAiChnOutputPort = {0}; +// stAiChnOutputPort.eModId = E_MI_MODULE_ID_AI; +// stAiChnOutputPort.u32DevId = AiDevId; +// stAiChnOutputPort.u32ChnId = AiChn; +// stAiChnOutputPort.u32PortId = 0; +// MI_SYS_SetChnOutputPortDepth(&stAiChnOutputPort, 1, 8); +// return SF_SUCCESS; +// } + + + + +// SINT32 sf_audio_frame_get(UINT8 AiDevId,UINT8 AiChn ) +// { +// MI_S32 ret; +// MI_AUDIO_Frame_t stAiChFrame; +// MI_AUDIO_AecFrame_t stAecFrame; + +// MI_AI_DupChn(AiDevId, AiChn); +// if (MI_SUCCESS != ret) +// { +// LogError("syn status failed!!!\n"); +// return SF_FAILURE; +// } + +// while(staudioTask.IsRun) +// { + +// ret = MI_AI_GetFrame(AiDevId, AiChn, &stAiChFrame, &stAecFrame, 0); +// if (MI_SUCCESS != ret) +// continue; + +// if( 0 < stAiChFrame.u32Len[0]) +// { +// sf_audioInUserGetFrame(&stAiChFrame, &stAecFrame); +// MI_AI_ReleaseFrame(AiDevId, AiChn, &stAiChFrame, &stAecFrame); +// } +// } + +// return ret; +// } + + + +// MI_S32 _AudioUserGetFrame(void) +// { +// MI_S32 ret; +// MI_AI_CHN AiChn = 0; +// MI_AUDIO_DEV AiDevId = 0; +// /* +// ret = sf_audio_init(AiChn,AiDevId); +// if(ret != SF_SUCCESS) +// LogInfo("sf_audio_init failed!!!\n"); + +// ret = sf_audio_outputdepth_set(AiChn,AiDevId); +// if(ret != SF_SUCCESS) +// LogInfo("sf_audio_outputdepth_set failed!!!\n"); +// */ +// ret = sf_audio_frame_get(AiChn,AiDevId); +// // if(ret != SF_SUCCESS) +// // LogInfo("sf_audio_frame_get failed!!!\n"); + +// return NULL; + + +// } + + + + + + + +// void *sf_audio_stream_thread(void *arg) +// { +// _AudioUserGetFrame(); +// return NULL; + +// } +void sf_audio_stream_start(void) +{ + + // if(!staudioTask.IsRun) + // { + // pthread_create(&staudioTask.TskId, NULL, sf_audio_stream_thread, NULL); + // staudioTask.IsRun = 1; + // staudioTask.IsStopFlag = 0; + // } + +} +void sf_audio_stream_stop(void) +{ + // if(staudioTask.IsRun == 0) + // return; + + // staudioTask.IsStopFlag = 1; + // staudioTask.IsRun = 0; + // pthread_join(staudioTask.TskId, NULL); +} + + diff --git a/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_venc_stream.h b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_venc_stream.h new file mode 100644 index 000000000..476adab38 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/ali_live/src/sf_venc_stream.h @@ -0,0 +1,21 @@ +#ifndef I_CONFGI_H +#define I_CONFGI_H +#include +#ifdef __cplusplus +extern "C" +{ +#endif + typedef struct sf_THREAD_CFG_S + { + unsigned char IsRun; + unsigned char IsStopFlag; + pthread_t TskId; + } SF_THREAD_CFG_S; + void sf_venc_stream_start(void); + void sf_venc_stream_stop(void); + void sf_audio_stream_start(void); + void sf_audio_stream_stop(void); +#ifdef __cplusplus +} +#endif +#endif // !I_CONFGI_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/linux_mock/LinuxMockLiveManager.cpp b/code/application/sifarsdk/component/LiveManager/src/linux_mock/LinuxMockLiveManager.cpp new file mode 100644 index 000000000..b2ba91982 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/linux_mock/LinuxMockLiveManager.cpp @@ -0,0 +1,12 @@ + +#include "LinuxMockLiveManager.h" +#include "Log.h" +#include +bool CreateLiveManagerImpl(std::shared_ptr &impl) +{ + impl = std::make_shared(); + return true; +} +LinuxMockLiveManager::LinuxMockLiveManager() +{ +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/linux_mock/LinuxMockLiveManager.h b/code/application/sifarsdk/component/LiveManager/src/linux_mock/LinuxMockLiveManager.h new file mode 100644 index 000000000..4df87acde --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/linux_mock/LinuxMockLiveManager.h @@ -0,0 +1,12 @@ +#ifndef LINUX_MOCK_LIVE_MANAGER_H +#define LINUX_MOCK_LIVE_MANAGER_H +#include "ILiveManager.h" +#include +#include +class LinuxMockLiveManager : public ILiveManager +{ +public: + LinuxMockLiveManager(); + virtual ~LinuxMockLiveManager() = default; +}; +#endif // !LINUX_MOCK_LIVE_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/linux_mock/live_service.cmake b/code/application/sifarsdk/component/LiveManager/src/linux_mock/live_service.cmake new file mode 100644 index 000000000..cdbc3edae --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/linux_mock/live_service.cmake @@ -0,0 +1,9 @@ + +INCLUDE(CMakeForceCompiler) + +include_directories( + ${COMPONENT_SOURCE_PATH}/LiveManager/src/${LIVE_PLATFORM_SRC_PATH}/include +) +aux_source_directory(${COMPONENT_SOURCE_PATH}/LiveManager/src/${LIVE_PLATFORM_SRC_PATH} SRC_FILES) + +# set(LIVE_LINK_LIB link_visual_device iot_sdk iot_hal iot_tls rt) \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/override/CMakeLists.txt b/code/application/sifarsdk/component/LiveManager/src/override/CMakeLists.txt new file mode 100644 index 000000000..e0f63d7f6 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/override/CMakeLists.txt @@ -0,0 +1,3 @@ + +# cmake_minimum_required(VERSION 2.8.0) +add_subdirectory(application) \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/override/README.md b/code/application/sifarsdk/component/LiveManager/src/override/README.md new file mode 100644 index 000000000..2bdc5fbd4 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/override/README.md @@ -0,0 +1,3 @@ +# 重载目录源码 +## 概述 +   由于在业务逻辑设计上,直播业务的新增导致服务器数据的差异化因素存在,所以需要对业务的相关类进行派生多态类,重新实例化实现服务器业务的多态属性,同时在代码上向下兼容。 \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/override/application/CMakeLists.txt b/code/application/sifarsdk/component/LiveManager/src/override/application/CMakeLists.txt new file mode 100644 index 000000000..18c94e569 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/override/application/CMakeLists.txt @@ -0,0 +1,3 @@ + +# cmake_minimum_required(VERSION 2.8.0) +add_subdirectory(NetworkManager) \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/CMakeLists.txt b/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/CMakeLists.txt new file mode 100644 index 000000000..ad602b673 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/CMakeLists.txt @@ -0,0 +1,40 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${APPLICATION_SOURCE_PATH}/StateManager/include + ${APPLICATION_SOURCE_PATH}/NetworkManager/include + ${APPLICATION_SOURCE_PATH}/NetworkManager/src + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/cJSON/include + ${COMPONENT_SOURCE_PATH}/base64/include + ${COMPONENT_SOURCE_PATH}/utils/include + ${COMPONENT_SOURCE_PATH}/SignatureManager/include + ${COMPONENT_SOURCE_PATH}/SystemTime/include + ${COMPONENT_SOURCE_PATH}/FileManager/include + ${COMPONENT_SOURCE_PATH}/DualCoreManager/include + ${COMPONENT_SOURCE_PATH}/HttpBase/include + ${COMPONENT_SOURCE_PATH}/Config/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME NetworkManagerLive) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} NetworkManager cJSON base64 utils HttpBase ReturnCode Log) + diff --git a/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/include/NetworkManagerLive.h b/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/include/NetworkManagerLive.h new file mode 100644 index 000000000..f8692a703 --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/include/NetworkManagerLive.h @@ -0,0 +1,4 @@ +#ifndef NETWORK_MANAGER_LIVE_H +#define NETWORK_MANAGER_LIVE_H +void NetworkManagerMakePtrOverride(void); +#endif // !NETWORK_MANAGER_LIVE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/src/NetworkManagerLiveMakePtr.cpp b/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/src/NetworkManagerLiveMakePtr.cpp new file mode 100644 index 000000000..670438ead --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/src/NetworkManagerLiveMakePtr.cpp @@ -0,0 +1,7 @@ + +#include "NetworkManagerLiveMakePtr.h" +void NetworkManagerMakePtrOverride(void) +{ + // std::shared_ptr makePtr = std::make_shared(); + // HalX86MakePtr::GetInstance(&makePtr); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/src/NetworkManagerLiveMakePtr.h b/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/src/NetworkManagerLiveMakePtr.h new file mode 100644 index 000000000..c414fe92a --- /dev/null +++ b/code/application/sifarsdk/component/LiveManager/src/override/application/NetworkManager/src/NetworkManagerLiveMakePtr.h @@ -0,0 +1,22 @@ +#ifndef NETWORK_MANAGER_LIVE_MAKE_PTR_H +#define NETWORK_MANAGER_LIVE_MAKE_PTR_H +#include "ReturnCode.h" +#include "NetworkManagerMakePtr.h" +#include +class NetworkManagerLiveMakePtr : public NetworkManagerMakePtr +{ +public: + NetworkManagerLiveMakePtr() = default; + virtual ~NetworkManagerLiveMakePtr() = default; + // RETURN_CODE CreateHalModuleInstance(std::shared_ptr &impl) override; + // RETURN_CODE CreateNetworkModuleHandle(std::shared_ptr &impl) override; + // virtual RETURN_CODE CreateGpioLedContrlInstance(const SfLedIndex &led, std::shared_ptr &ledContrl); + // virtual RETURN_CODE CreateGpioKeyContrlInstance(const SfKeyDefine &key, std::shared_ptr &keyContrl); + // virtual RETURN_CODE CreateGpioInputInstance(const GpioPin &gpio, std::shared_ptr &gpioInput); + // virtual RETURN_CODE CreateCameraChip(const CameraType &type, std::shared_ptr &camera); + // virtual RETURN_CODE CreateLightWeightCPU(std::shared_ptr &lcpu); + // virtual RETURN_CODE CreateSdCardHal(std::shared_ptr &sdCardHal); + +private: +}; +#endif // !NETWORK_MANAGER_LIVE_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/CMakeLists.txt b/code/application/sifarsdk/component/Log/CMakeLists.txt new file mode 100644 index 000000000..3ec544cd6 --- /dev/null +++ b/code/application/sifarsdk/component/Log/CMakeLists.txt @@ -0,0 +1,24 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Log/src/easyloggingpp +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) +aux_source_directory(./src/easyloggingpp SRC_FILES) + +set(TARGET_NAME Log) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + + diff --git a/code/application/sifarsdk/component/Log/include/Log.h b/code/application/sifarsdk/component/Log/include/Log.h new file mode 100644 index 000000000..d10e68ef8 --- /dev/null +++ b/code/application/sifarsdk/component/Log/include/Log.h @@ -0,0 +1,112 @@ +/** + * @brief + * The only one header file for the other modules to use log module. + */ +#ifndef LOG_H +#define LOG_H +#define LogVerbose(...) Log(__FUNCTION__, __LINE__, LOG_TYPE_VERBOSE, __VA_ARGS__) +#define LogDebug(...) Log(__FUNCTION__, __LINE__, LOG_TYPE_DEBUG, __VA_ARGS__) +#define LogInfo(...) Log(__FUNCTION__, __LINE__, LOG_TYPE_INFORMATION, __VA_ARGS__) +#define LogWarning(...) Log(__FUNCTION__, __LINE__, LOG_TYPE_WARNING, __VA_ARGS__) +#define LogError(...) Log(__FUNCTION__, __LINE__, LOG_TYPE_ERROR, __VA_ARGS__) +#define LogTrace(...) Log(__FUNCTION__, __LINE__, LOG_TYPE_TRACE, __VA_ARGS__) +// For test code, never using in release version. +// #define LogTestTips(...) TestTips(LOG_TYPE_TEST_TIPS, __VA_ARGS__) + +// TODO: +#if 1 // For wifi log, should delete finally. +#define LOGD(...) + +#define LOGI(...) + +#define LOGW(...) + +#define LOGE(...) + +#define LOGF(...) +#endif + +/** + * @brief + * log type. + */ +enum LogType +{ + LOG_TYPE_VERBOSE = 0, + LOG_TYPE_DEBUG, + LOG_TYPE_INFORMATION, + LOG_TYPE_WARNING, + LOG_TYPE_ERROR, + LOG_TYPE_TRACE, + LOG_TYPE_TEST_TIPS, + LOG_TYPE_END +}; +/** + * @brief + * instance type of log module. + */ +enum LogInstanceType +{ + LOG_SERIAL_PRINT = 0, // for serial print. + LOG_EASYLOGGING, // for easylogging++. + LOG_CAPTURE_LOG, // capture log to other who need it + LOG_INSTANCE_TYPE_END + +}; +/** + * @brief + * Log setting + */ +typedef struct LogSetting +{ + const char *fileName; // File name of saving log. + const char *maxSize; // Max size of saving log. + const int (*callback)(const char *); // + + const int (*callback_InFo)(const char *); + const int (*callback_Warning)(const char *); + const int (*callback_Error)(const char *); + const int (*callback_Debug)(const char *); + const int (*callback_Trace)(const char *); +} LogSetting; +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" +{ +#endif + /** + * @brief + * Init what type of log to run, see LogInstanceType in this file. + * @param logInstanceType + * @param setting Setting of log module, See LogSetting. + * @return true + * @return false + */ + int InitLog(const int logInstanceType, const LogSetting *setting); + int UnInitLog(); + /** + * @brief + * Print log + * TODO: Crash will happen if print a string without '\0'. + * @param function + * @param line + * @param type + * @param format + * @param ... + * @return int + */ + int Log(const char *function, int line, int type, const char *format, ...); + /** + * @brief + * Only for test code. + * @param format + * @param ... + * @return const char* + */ + // const char *TestTips(int type, const char *format, ...); +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/ILog.cpp b/code/application/sifarsdk/component/Log/src/ILog.cpp new file mode 100644 index 000000000..a153496d8 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/ILog.cpp @@ -0,0 +1,32 @@ +#include "ILog.h" +#include +std::shared_ptr &ILog::GetInstance(std::shared_ptr *impl) +{ + static std::shared_ptr instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + // Don't use std::mutex for runing faster. + // Sleep for difference thread to release instance. + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + instance->Log("Instance change succeed.\n"); + instance->UnInit(); + (*impl)->Init(); + instance = *impl; + } + else + { + instance->Log("[ error ] instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static std::shared_ptr tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/ILog.h b/code/application/sifarsdk/component/Log/src/ILog.h new file mode 100644 index 000000000..f9102f3d7 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/ILog.h @@ -0,0 +1,48 @@ +#ifndef I_LOG_H +#define I_LOG_H +// #include "VReturnCode.h" +#include +#include +class ILog +{ +public: + /** + * @brief Get the Instance object + * Return reference for runing faster. Usage : ILog::GetInstance()->Init(); + * Don't use ILog like this: + * std::shared_ptr &log = ILog::GetInstance(); or std::shared_ptr log = ILog::GetInstance(); + * log->Log("Your log."); + * @param impl Change the instance. + * @return std::shared_ptr& + */ + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + ILog() = default; + virtual ~ILog() = default; + virtual bool Init() { return false; } + virtual bool UnInit() { return false; } + /** + * @brief + * If the Log module is working. + * @return true + * @return false + */ + virtual bool IsWorking() { return false; } + /** + * @brief + * Virtual log function. + * @param buff + * @return int + */ + virtual int Log(const char *buff) { return 0; } + + virtual int InFo(const char *buff) { return 0; } + + virtual int Warning(const char *buff) { return 0; } + + virtual int Error(const char *buff) { return 0; } + + virtual int Trace(const char *buff) { return 0; } + + virtual int Debug(const char *buff) { return 0; } +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/ILogMakePtr.cpp b/code/application/sifarsdk/component/Log/src/ILogMakePtr.cpp new file mode 100644 index 000000000..382917b16 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/ILogMakePtr.cpp @@ -0,0 +1,19 @@ +#include "ILogMakePtr.h" +#include "LogImpl.h" +#include "LogEasylogging.h" +#include "LogCapture.h" +std::shared_ptr ILogMakePtr::MakeLogImplPtr() +{ + std::shared_ptr logImpl = std::make_shared(); + return logImpl; +} +std::shared_ptr ILogMakePtr::MakeLogEasylogging(const LogSetting *setting) +{ + std::shared_ptr logImpl = std::make_shared(setting); + return logImpl; +} +std::shared_ptr ILogMakePtr::MakeLongCapture(const LogSetting *setting) +{ + std::shared_ptr logImpl = std::make_shared(*setting); + return logImpl; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/ILogMakePtr.h b/code/application/sifarsdk/component/Log/src/ILogMakePtr.h new file mode 100644 index 000000000..f6700427b --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/ILogMakePtr.h @@ -0,0 +1,25 @@ +#ifndef ILOG_MAKE_PTR_H +#define ILOG_MAKE_PTR_H +#include "ILog.h" +#include "Log.h" +#include +#include +class ILogMakePtr +{ +public: + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr) + { + static std::shared_ptr instance = std::make_shared(); + if (impl) + { + instance = *impl; + } + return instance; + } + ILogMakePtr() = default; + virtual ~ILogMakePtr() = default; + virtual std::shared_ptr MakeLogImplPtr(); + virtual std::shared_ptr MakeLogEasylogging(const LogSetting *setting); + virtual std::shared_ptr MakeLongCapture(const LogSetting *setting); +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/Log.cpp b/code/application/sifarsdk/component/Log/src/Log.cpp new file mode 100644 index 000000000..fa4f43662 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/Log.cpp @@ -0,0 +1,109 @@ +#include "Log.h" +#include "ILog.h" +#include "LogImpl.h" +#include "ILogMakePtr.h" +#include +#include +#include +#include +#include + +int InitLog(const int logInstanceType, const LogSetting *setting) +{ + switch (logInstanceType) + { + case LOG_SERIAL_PRINT: + { + std::shared_ptr logImpl = ILogMakePtr::GetInstance()->MakeLogImplPtr(); + ILog::GetInstance(&logImpl); + break; + } + case LOG_EASYLOGGING: + { + std::shared_ptr logImpl = ILogMakePtr::GetInstance()->MakeLogEasylogging(setting); + ILog::GetInstance(&logImpl); + break; + } + case LOG_CAPTURE_LOG: + { + std::shared_ptr logImpl = ILogMakePtr::GetInstance()->MakeLongCapture(setting); + ILog::GetInstance(&logImpl); + break; + } + + default: + { + LogError("Log module init error.\n"); + return -1; + } + } + return 0; +} +int UnInitLog() +{ + std::shared_ptr logImpl = std::make_shared(); + ILog::GetInstance(&logImpl); + return 0; +} +// static void LogTypeToString(const int type) +// { +// switch (type) +// { +// case LOG_TYPE_ERROR: +// { +// ILog::GetInstance()->Log("[ ERROR ]"); +// break; +// } +// case LOG_TYPE_TEST_TIPS: +// { +// ILog::GetInstance()->Log("[ FAILURE ]"); +// break; +// } +// default: +// break; +// } +// } +int Log(const char *function, int line, int type, const char *format, ...) +{ + if (!ILog::GetInstance()->IsWorking()) + { + return -1; + } + // TODO: + // LogTypeToString(type); + constexpr int SEND_TRACE_BUFF_SIZE = 2048; + char buff[SEND_TRACE_BUFF_SIZE] = {0}; + snprintf(buff, SEND_TRACE_BUFF_SIZE, "[%s][line:%d]:", function, line); + // ILog::GetInstance()->Log(buff); + const int headLen = strlen(buff); + va_list vargs; + va_start(vargs, format); + int len = vsnprintf(buff + headLen, SEND_TRACE_BUFF_SIZE - headLen, format, vargs); + va_end(vargs); + switch (type) + { + case LOG_TYPE_INFORMATION: + ILog::GetInstance()->InFo(buff); + break; + + case LOG_TYPE_WARNING: + ILog::GetInstance()->Warning(buff); + break; + + case LOG_TYPE_ERROR: + ILog::GetInstance()->Error(buff); + break; + + case LOG_TYPE_DEBUG: + ILog::GetInstance()->Debug(buff); + break; + + case LOG_TYPE_TRACE: + ILog::GetInstance()->Trace(buff); + break; + + default: + break; + } + return len; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/LogCapture.cpp b/code/application/sifarsdk/component/Log/src/LogCapture.cpp new file mode 100644 index 000000000..8c3be179a --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/LogCapture.cpp @@ -0,0 +1,81 @@ +#include "LogCapture.h" +#include +#include + +LogCapture::LogCapture(const LogSetting setting) : mLogCapture(setting.callback), + mLogCapture_InFo(setting.callback_InFo), mLogCapture_Warning(setting.callback_Warning), + mLogCapture_Error(setting.callback_Error), mLogCapture_Debug(setting.callback_Debug), + mLogCapture_Trace(setting.callback_Trace) +{ + if (!setting.callback) + { + return; + } +} + +bool LogCapture::Init() +{ + return true; +} +bool LogCapture::UnInit() +{ + return true; +} + +bool LogCapture::IsWorking() +{ + return true; +} +int LogCapture::Log(const char *buff) +{ + if (mLogCapture) + { + mLogCapture(buff); + } + return 0; +} + +int LogCapture::InFo(const char *buff) +{ + if (mLogCapture_InFo) + { + mLogCapture_InFo(buff); + } + return 0; +} + +int LogCapture::Warning(const char *buff) +{ + if (mLogCapture_Warning) + { + mLogCapture_Warning(buff); + } + return 0; +} + +int LogCapture::Error(const char *buff) +{ + if (mLogCapture_Error) + { + mLogCapture_Error(buff); + } + return 0; +} + +int LogCapture::Debug(const char *buff) +{ + if (mLogCapture_Debug) + { + mLogCapture_Debug(buff); + } + return 0; +} + +int LogCapture::Trace(const char *buff) +{ + if (mLogCapture_Trace) + { + mLogCapture_Trace(buff); + } + return 0; +} diff --git a/code/application/sifarsdk/component/Log/src/LogCapture.h b/code/application/sifarsdk/component/Log/src/LogCapture.h new file mode 100644 index 000000000..a0904ed26 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/LogCapture.h @@ -0,0 +1,31 @@ +#ifndef LOG_CAPTURE_H +#define LOG_CAPTURE_H +#include "ILog.h" +#include "Log.h" + +class LogCapture : public ILog +{ +public: + LogCapture(const LogSetting settings); // settings may it should add (*)? + virtual ~LogCapture() = default; + bool Init() override; + bool UnInit() override; + bool IsWorking() override; + int Log(const char *buff) override; + int InFo(const char *buff) override; + int Warning(const char *buff) override; + int Error(const char *buff) override; + int Trace(const char *buff) override; + int Debug(const char *buff) override; + +private: + std::string mFileName; // File name of saving log. + std::string mMaxSize; // Max size of saving log. + const int (*mLogCapture)(const char *buff); // For other modules to capture what to print. + const int (*mLogCapture_InFo)(const char *buff); + const int (*mLogCapture_Warning)(const char *buff); + const int (*mLogCapture_Error)(const char *buff); + const int (*mLogCapture_Debug)(const char *buff); + const int (*mLogCapture_Trace)(const char *buff); +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/LogEasylogging.cpp b/code/application/sifarsdk/component/Log/src/LogEasylogging.cpp new file mode 100644 index 000000000..15e2caac6 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/LogEasylogging.cpp @@ -0,0 +1,89 @@ +#include "LogEasylogging.h" +#include "easylogging++.h" +#include +// #define ELPP_UNICODE // Define for easylogging +INITIALIZE_EASYLOGGINGPP // Init easylogging + // static bool initFlag = false; // Only used for init easyloggingpp + bool test = false; +LogEasylogging::LogEasylogging(const LogSetting *setting) +{ + if (!setting) + { + return; + } + if (setting->fileName) + { + mFileName = setting->fileName; + } + if (setting->maxSize) + { + mMaxSize = setting->maxSize; + } +} +bool LogEasylogging::Init() +{ +#if 0 + el::Configurations conf("/home/xiaojiazhu/project/OS/OSThings/test/out/bin/default-logger.conf"); + el::Loggers::reconfigureAllLoggers(conf); +#endif + // Set the log path. + if (mFileName.size() > 0) + { + el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Filename, mFileName.c_str()); + } + + // Set the max size of log file. + // el::Loggers::reconfigureAllLoggers(el::ConfigurationType::MaxLogFileSize, "1048576"); + if (mMaxSize.size() > 0) + { + el::Loggers::reconfigureAllLoggers(el::ConfigurationType::MaxLogFileSize, mMaxSize.c_str()); + } + el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Enabled, "true"); + el::Loggers::reconfigureAllLoggers(el::ConfigurationType::ToFile, "true"); + return true; +} +bool LogEasylogging::UnInit() +{ + el::Loggers::reconfigureAllLoggers(el::ConfigurationType::ToFile, "false"); + el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Enabled, "false"); + return true; +} +bool LogEasylogging::IsWorking() +{ + return true; +} +int LogEasylogging::Log(const char *buff) +{ + // LOG(INFO) << buff; + return 0; +} + +int LogEasylogging::InFo(const char *buff) +{ + LOG(INFO) << buff; + return 0; +} + +int LogEasylogging::Warning(const char *buff) +{ + LOG(WARNING) << buff; + return 0; +} + +int LogEasylogging::Error(const char *buff) +{ + LOG(ERROR) << buff; + return 0; +} + +int LogEasylogging::Debug(const char *buff) +{ + LOG(DEBUG) << buff; + return 0; +} + +int LogEasylogging::Trace(const char *buff) +{ + LOG(TRACE) << buff; + return 0; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/LogEasylogging.h b/code/application/sifarsdk/component/Log/src/LogEasylogging.h new file mode 100644 index 000000000..4ca30af6b --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/LogEasylogging.h @@ -0,0 +1,24 @@ +#ifndef LOG_EASYLOGGING_H +#define LOG_EASYLOGGING_H +#include "ILog.h" +#include "Log.h" +class LogEasylogging : public ILog +{ +public: + LogEasylogging(const LogSetting *setting); + virtual ~LogEasylogging() = default; + bool Init() override; + bool UnInit() override; + bool IsWorking() override; + int Log(const char *buff) override; + int InFo(const char *buff) override; + int Warning(const char *buff) override; + int Error(const char *buff) override; + int Trace(const char *buff) override; + int Debug(const char *buff) override; + +private: + std::string mFileName; // File name of saving log. + std::string mMaxSize; // Max size of saving log. +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/LogImpl.cpp b/code/application/sifarsdk/component/Log/src/LogImpl.cpp new file mode 100644 index 000000000..b039eb115 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/LogImpl.cpp @@ -0,0 +1,9 @@ +#include "LogImpl.h" +bool LogImpl::IsWorking() +{ + return true; +} +int LogImpl::Log(const char *buff) +{ + return printf("%s", buff); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/LogImpl.h b/code/application/sifarsdk/component/Log/src/LogImpl.h new file mode 100644 index 000000000..ee1d59b08 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/LogImpl.h @@ -0,0 +1,12 @@ +#ifndef LOG_IMPL_H +#define LOG_IMPL_H +#include "ILog.h" +class LogImpl : public ILog +{ +public: + LogImpl() = default; + virtual ~LogImpl() = default; + bool IsWorking() override; + int Log(const char *buff) override; +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/Log/src/easyloggingpp/README.txt b/code/application/sifarsdk/component/Log/src/easyloggingpp/README.txt new file mode 100644 index 000000000..de33e5b79 --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/easyloggingpp/README.txt @@ -0,0 +1,9 @@ +这是一个开源库的源码。 +注意: +//1. 需要定义宏 +//#define ELPP_UNICODE // Define for easylogging +2. 初始化 +INITIALIZE_EASYLOGGINGPP // Init easylogging +//3. 支持多线程,在源码头文件"easyloggingpp.h"定义宏 +//#define ELPP_THREAD_SAFE // Working in threads. Added by xiaojiazhu +4. ELPP_NO_DEFAULT_LOG_FILE 此宏屏蔽生成默认的log文件 diff --git a/code/application/sifarsdk/component/Log/src/easyloggingpp/default-logger.conf b/code/application/sifarsdk/component/Log/src/easyloggingpp/default-logger.conf new file mode 100644 index 000000000..9e34afd2c --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/easyloggingpp/default-logger.conf @@ -0,0 +1,25 @@ +* GLOBAL: + FORMAT = "%datetime | %level | %logger | %msg" + FILENAME = "/tmp/logs/myeasylog-configuration.cpp.log" + ENABLED = true + TO_FILE = true + TO_STANDARD_OUTPUT = true + SUBSECOND_PRECISION = 3 + PERFORMANCE_TRACKING = false + MAX_LOG_FILE_SIZE = 2097152 ## Throw log files away after 2MB +* DEBUG: + FILENAME = "/tmp/logs/myeasylog-configuration.cpp-debug.log" + TO_STANDARD_OUTPUT = true + ENABLED = true ## We will set it to false after development completed +* WARNING: + FILENAME = "/tmp/logs/filename-with-time-%datetime{%H:%m}" +* TRACE: + TO_FILE = true ## Unnecessary configuration cuz its already true in GLOBAL but doing it anyway! +* VERBOSE: + FORMAT = "%datetime{%d/%M/%y} | %level-%vlevel | %msg" +## Error logs +* ERROR: + ENABLED = false + FILENAME = "/tmp/logs/myeasylog-configuration.cpp-error.log" +* FATAL: + ENABLED = false diff --git a/code/application/sifarsdk/component/Log/src/easyloggingpp/easylogging++.cc b/code/application/sifarsdk/component/Log/src/easyloggingpp/easylogging++.cc new file mode 100644 index 000000000..889e5c22a --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/easyloggingpp/easylogging++.cc @@ -0,0 +1,3122 @@ +// +// Bismillah ar-Rahmaan ar-Raheem +// +// Easylogging++ v9.96.7 +// Cross-platform logging library for C++ applications +// +// Copyright (c) 2012-2018 Amrayn Web Services +// Copyright (c) 2012-2018 @abumusamq +// +// This library is released under the MIT Licence. +// https://github.com/amrayn/easyloggingpp/blob/master/LICENSE +// +// https://amrayn.com +// http://muflihun.com +// + +#include "easylogging++.h" + +#define ELPP_NO_DEFAULT_LOG_FILE // Don't build the default log file. Added by xiaojiazhu + +#if defined(AUTO_INITIALIZE_EASYLOGGINGPP) +INITIALIZE_EASYLOGGINGPP +#endif + +namespace el { + +// el::base +namespace base { +// el::base::consts +namespace consts { + +// Level log values - These are values that are replaced in place of %level format specifier +// Extra spaces after format specifiers are only for readability purposes in log files +static const base::type::char_t* kInfoLevelLogValue = ELPP_LITERAL("INFO"); +static const base::type::char_t* kDebugLevelLogValue = ELPP_LITERAL("DEBUG"); +static const base::type::char_t* kWarningLevelLogValue = ELPP_LITERAL("WARNING"); +static const base::type::char_t* kErrorLevelLogValue = ELPP_LITERAL("ERROR"); +static const base::type::char_t* kFatalLevelLogValue = ELPP_LITERAL("FATAL"); +static const base::type::char_t* kVerboseLevelLogValue = + ELPP_LITERAL("VERBOSE"); // will become VERBOSE-x where x = verbose level +static const base::type::char_t* kTraceLevelLogValue = ELPP_LITERAL("TRACE"); +static const base::type::char_t* kInfoLevelShortLogValue = ELPP_LITERAL("I"); +static const base::type::char_t* kDebugLevelShortLogValue = ELPP_LITERAL("D"); +static const base::type::char_t* kWarningLevelShortLogValue = ELPP_LITERAL("W"); +static const base::type::char_t* kErrorLevelShortLogValue = ELPP_LITERAL("E"); +static const base::type::char_t* kFatalLevelShortLogValue = ELPP_LITERAL("F"); +static const base::type::char_t* kVerboseLevelShortLogValue = ELPP_LITERAL("V"); +static const base::type::char_t* kTraceLevelShortLogValue = ELPP_LITERAL("T"); +// Format specifiers - These are used to define log format +static const base::type::char_t* kAppNameFormatSpecifier = ELPP_LITERAL("%app"); +static const base::type::char_t* kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger"); +static const base::type::char_t* kThreadIdFormatSpecifier = ELPP_LITERAL("%thread"); +static const base::type::char_t* kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level"); +static const base::type::char_t* kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort"); +static const base::type::char_t* kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime"); +static const base::type::char_t* kLogFileFormatSpecifier = ELPP_LITERAL("%file"); +static const base::type::char_t* kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase"); +static const base::type::char_t* kLogLineFormatSpecifier = ELPP_LITERAL("%line"); +static const base::type::char_t* kLogLocationFormatSpecifier = ELPP_LITERAL("%loc"); +static const base::type::char_t* kLogFunctionFormatSpecifier = ELPP_LITERAL("%func"); +static const base::type::char_t* kCurrentUserFormatSpecifier = ELPP_LITERAL("%user"); +static const base::type::char_t* kCurrentHostFormatSpecifier = ELPP_LITERAL("%host"); +static const base::type::char_t* kMessageFormatSpecifier = ELPP_LITERAL("%msg"); +static const base::type::char_t* kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel"); +static const char* kDateTimeFormatSpecifierForFilename = "%datetime"; +// Date/time +static const char* kDays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; +static const char* kDaysAbbrev[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +static const char* kMonths[12] = { "January", "February", "March", "April", "May", "June", "July", "August", + "September", "October", "November", "December" + }; +static const char* kMonthsAbbrev[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +static const char* kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g"; +static const char* kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m"; +static const int kYearBase = 1900; +static const char* kAm = "AM"; +static const char* kPm = "PM"; +// Miscellaneous constants + +static const char* kNullPointer = "nullptr"; +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED +static const base::type::VerboseLevel kMaxVerboseLevel = 9; +static const char* kUnknownUser = "unknown-user"; +static const char* kUnknownHost = "unknown-host"; + + +//---------------- DEFAULT LOG FILE ----------------------- + +#if defined(ELPP_NO_DEFAULT_LOG_FILE) +# if ELPP_OS_UNIX +static const char* kDefaultLogFile = "/dev/null"; +# elif ELPP_OS_WINDOWS +static const char* kDefaultLogFile = "nul"; +# endif // ELPP_OS_UNIX +#elif defined(ELPP_DEFAULT_LOG_FILE) +static const char* kDefaultLogFile = ELPP_DEFAULT_LOG_FILE; +#else +static const char* kDefaultLogFile = "myeasylog.log"; +#endif // defined(ELPP_NO_DEFAULT_LOG_FILE) + + +#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +static const char* kDefaultLogFileParam = "--default-log-file"; +#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) +static const char* kLoggingFlagsParam = "--logging-flags"; +#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) +static const char* kValidLoggerIdSymbols = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; +static const char* kConfigurationComment = "##"; +static const char* kConfigurationLevel = "*"; +static const char* kConfigurationLoggerId = "--"; +} +// el::base::utils +namespace utils { + +/// @brief Aborts application due with user-defined status +static void abort(int status, const std::string& reason) { + // Both status and reason params are there for debugging with tools like gdb etc + ELPP_UNUSED(status); + ELPP_UNUSED(reason); +#if defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) + // Ignore msvc critical error dialog - break instead (on debug mode) + _asm int 3 +#else + ::abort(); +#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) +} + +} // namespace utils +} // namespace base + +// el + +// LevelHelper + +const char* LevelHelper::convertToString(Level level) { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (level == Level::Global) return "GLOBAL"; + if (level == Level::Debug) return "DEBUG"; + if (level == Level::Info) return "INFO"; + if (level == Level::Warning) return "WARNING"; + if (level == Level::Error) return "ERROR"; + if (level == Level::Fatal) return "FATAL"; + if (level == Level::Verbose) return "VERBOSE"; + if (level == Level::Trace) return "TRACE"; + return "UNKNOWN"; +} + +struct StringToLevelItem { + const char* levelString; + Level level; +}; + +static struct StringToLevelItem stringToLevelMap[] = { + { "global", Level::Global }, + { "debug", Level::Debug }, + { "info", Level::Info }, + { "warning", Level::Warning }, + { "error", Level::Error }, + { "fatal", Level::Fatal }, + { "verbose", Level::Verbose }, + { "trace", Level::Trace } +}; + +Level LevelHelper::convertFromString(const char* levelStr) { + for (auto& item : stringToLevelMap) { + if (base::utils::Str::cStringCaseEq(levelStr, item.levelString)) { + return item.level; + } + } + return Level::Unknown; +} + +void LevelHelper::forEachLevel(base::type::EnumType* startIndex, const std::function& fn) { + base::type::EnumType lIndexMax = LevelHelper::kMaxValid; + do { + if (fn()) { + break; + } + *startIndex = static_cast(*startIndex << 1); + } while (*startIndex <= lIndexMax); +} + +// ConfigurationTypeHelper + +const char* ConfigurationTypeHelper::convertToString(ConfigurationType configurationType) { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (configurationType == ConfigurationType::Enabled) return "ENABLED"; + if (configurationType == ConfigurationType::Filename) return "FILENAME"; + if (configurationType == ConfigurationType::Format) return "FORMAT"; + if (configurationType == ConfigurationType::ToFile) return "TO_FILE"; + if (configurationType == ConfigurationType::ToStandardOutput) return "TO_STANDARD_OUTPUT"; + if (configurationType == ConfigurationType::SubsecondPrecision) return "SUBSECOND_PRECISION"; + if (configurationType == ConfigurationType::PerformanceTracking) return "PERFORMANCE_TRACKING"; + if (configurationType == ConfigurationType::MaxLogFileSize) return "MAX_LOG_FILE_SIZE"; + if (configurationType == ConfigurationType::LogFlushThreshold) return "LOG_FLUSH_THRESHOLD"; + return "UNKNOWN"; +} + +struct ConfigurationStringToTypeItem { + const char* configString; + ConfigurationType configType; +}; + +static struct ConfigurationStringToTypeItem configStringToTypeMap[] = { + { "enabled", ConfigurationType::Enabled }, + { "to_file", ConfigurationType::ToFile }, + { "to_standard_output", ConfigurationType::ToStandardOutput }, + { "format", ConfigurationType::Format }, + { "filename", ConfigurationType::Filename }, + { "subsecond_precision", ConfigurationType::SubsecondPrecision }, + { "milliseconds_width", ConfigurationType::MillisecondsWidth }, + { "performance_tracking", ConfigurationType::PerformanceTracking }, + { "max_log_file_size", ConfigurationType::MaxLogFileSize }, + { "log_flush_threshold", ConfigurationType::LogFlushThreshold }, +}; + +ConfigurationType ConfigurationTypeHelper::convertFromString(const char* configStr) { + for (auto& item : configStringToTypeMap) { + if (base::utils::Str::cStringCaseEq(configStr, item.configString)) { + return item.configType; + } + } + return ConfigurationType::Unknown; +} + +void ConfigurationTypeHelper::forEachConfigType(base::type::EnumType* startIndex, const std::function& fn) { + base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid; + do { + if (fn()) { + break; + } + *startIndex = static_cast(*startIndex << 1); + } while (*startIndex <= cIndexMax); +} + +// Configuration + +Configuration::Configuration(const Configuration& c) : + m_level(c.m_level), + m_configurationType(c.m_configurationType), + m_value(c.m_value) { +} + +Configuration& Configuration::operator=(const Configuration& c) { + if (&c != this) { + m_level = c.m_level; + m_configurationType = c.m_configurationType; + m_value = c.m_value; + } + return *this; +} + +/// @brief Full constructor used to sets value of configuration +Configuration::Configuration(Level level, ConfigurationType configurationType, const std::string& value) : + m_level(level), + m_configurationType(configurationType), + m_value(value) { +} + +void Configuration::log(el::base::type::ostream_t& os) const { + os << LevelHelper::convertToString(m_level) + << ELPP_LITERAL(" ") << ConfigurationTypeHelper::convertToString(m_configurationType) + << ELPP_LITERAL(" = ") << m_value.c_str(); +} + +/// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. +Configuration::Predicate::Predicate(Level level, ConfigurationType configurationType) : + m_level(level), + m_configurationType(configurationType) { +} + +bool Configuration::Predicate::operator()(const Configuration* conf) const { + return ((conf != nullptr) && (conf->level() == m_level) && (conf->configurationType() == m_configurationType)); +} + +// Configurations + +Configurations::Configurations(void) : + m_configurationFile(std::string()), + m_isFromFile(false) { +} + +Configurations::Configurations(const std::string& configurationFile, bool useDefaultsForRemaining, + Configurations* base) : + m_configurationFile(configurationFile), + m_isFromFile(false) { + parseFromFile(configurationFile, base); + if (useDefaultsForRemaining) { + setRemainingToDefault(); + } +} + +bool Configurations::parseFromFile(const std::string& configurationFile, Configurations* base) { + // We initial assertion with true because if we have assertion disabled, we want to pass this + // check and if assertion is enabled we will have values re-assigned any way. + bool assertionPassed = true; + ELPP_ASSERT((assertionPassed = base::utils::File::pathExists(configurationFile.c_str(), true)) == true, + "Configuration file [" << configurationFile << "] does not exist!"); + if (!assertionPassed) { + return false; + } + bool success = Parser::parseFromFile(configurationFile, this, base); + m_isFromFile = success; + return success; +} + +bool Configurations::parseFromText(const std::string& configurationsString, Configurations* base) { + bool success = Parser::parseFromText(configurationsString, this, base); + if (success) { + m_isFromFile = false; + } + return success; +} + +void Configurations::setFromBase(Configurations* base) { + if (base == nullptr || base == this) { + return; + } + base::threading::ScopedLock scopedLock(base->lock()); + for (Configuration*& conf : base->list()) { + set(conf); + } +} + +bool Configurations::hasConfiguration(ConfigurationType configurationType) { + base::type::EnumType lIndex = LevelHelper::kMinValid; + bool result = false; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + if (hasConfiguration(LevelHelper::castFromInt(lIndex), configurationType)) { + result = true; + } + return result; + }); + return result; +} + +bool Configurations::hasConfiguration(Level level, ConfigurationType configurationType) { + base::threading::ScopedLock scopedLock(lock()); +#if ELPP_COMPILER_INTEL + // We cant specify template types here, Intel C++ throws compilation error + // "error: type name is not allowed" + return RegistryWithPred::get(level, configurationType) != nullptr; +#else + return RegistryWithPred::get(level, configurationType) != nullptr; +#endif // ELPP_COMPILER_INTEL +} + +void Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) { + base::threading::ScopedLock scopedLock(lock()); + unsafeSet(level, configurationType, value); // This is not unsafe anymore as we have locked mutex + if (level == Level::Global) { + unsafeSetGlobally(configurationType, value, false); // Again this is not unsafe either + } +} + +void Configurations::set(Configuration* conf) { + if (conf == nullptr) { + return; + } + set(conf->level(), conf->configurationType(), conf->value()); +} + +void Configurations::setToDefault(void) { + setGlobally(ConfigurationType::Enabled, std::string("true"), true); + setGlobally(ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile), true); +#if defined(ELPP_NO_LOG_TO_FILE) + setGlobally(ConfigurationType::ToFile, std::string("false"), true); +#else + setGlobally(ConfigurationType::ToFile, std::string("true"), true); +#endif // defined(ELPP_NO_LOG_TO_FILE) + setGlobally(ConfigurationType::ToStandardOutput, std::string("true"), true); + setGlobally(ConfigurationType::SubsecondPrecision, std::string("3"), true); + setGlobally(ConfigurationType::PerformanceTracking, std::string("true"), true); + setGlobally(ConfigurationType::MaxLogFileSize, std::string("0"), true); + setGlobally(ConfigurationType::LogFlushThreshold, std::string("0"), true); + + setGlobally(ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"), true); + set(Level::Debug, ConfigurationType::Format, + std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); + // INFO and WARNING are set to default by Level::Global + set(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + set(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + set(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); + set(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); +} + +void Configurations::setRemainingToDefault(void) { + base::threading::ScopedLock scopedLock(lock()); +#if defined(ELPP_NO_LOG_TO_FILE) + unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("false")); +#else + unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("true")); +#endif // defined(ELPP_NO_LOG_TO_FILE) + unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile)); + unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput, std::string("true")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::SubsecondPrecision, std::string("3")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking, std::string("true")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::MaxLogFileSize, std::string("0")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Debug, ConfigurationType::Format, + std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); + // INFO and WARNING are set to default by Level::Global + unsafeSetIfNotExist(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); + unsafeSetIfNotExist(Level::Trace, ConfigurationType::Format, + std::string("%datetime %level [%logger] [%func] [%loc] %msg")); +} + +bool Configurations::Parser::parseFromFile(const std::string& configurationFile, Configurations* sender, + Configurations* base) { + sender->setFromBase(base); + std::ifstream fileStream_(configurationFile.c_str(), std::ifstream::in); + ELPP_ASSERT(fileStream_.is_open(), "Unable to open configuration file [" << configurationFile << "] for parsing."); + bool parsedSuccessfully = false; + std::string line = std::string(); + Level currLevel = Level::Unknown; + std::string currConfigStr = std::string(); + std::string currLevelStr = std::string(); + while (fileStream_.good()) { + std::getline(fileStream_, line); + parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); + ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); + } + return parsedSuccessfully; +} + +bool Configurations::Parser::parseFromText(const std::string& configurationsString, Configurations* sender, + Configurations* base) { + sender->setFromBase(base); + bool parsedSuccessfully = false; + std::stringstream ss(configurationsString); + std::string line = std::string(); + Level currLevel = Level::Unknown; + std::string currConfigStr = std::string(); + std::string currLevelStr = std::string(); + while (std::getline(ss, line)) { + parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); + ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); + } + return parsedSuccessfully; +} + +void Configurations::Parser::ignoreComments(std::string* line) { + std::size_t foundAt = 0; + std::size_t quotesStart = line->find("\""); + std::size_t quotesEnd = std::string::npos; + if (quotesStart != std::string::npos) { + quotesEnd = line->find("\"", quotesStart + 1); + while (quotesEnd != std::string::npos && line->at(quotesEnd - 1) == '\\') { + // Do not erase slash yet - we will erase it in parseLine(..) while loop + quotesEnd = line->find("\"", quotesEnd + 2); + } + } + if ((foundAt = line->find(base::consts::kConfigurationComment)) != std::string::npos) { + if (foundAt < quotesEnd) { + foundAt = line->find(base::consts::kConfigurationComment, quotesEnd + 1); + } + *line = line->substr(0, foundAt); + } +} + +bool Configurations::Parser::isLevel(const std::string& line) { + return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLevel)); +} + +bool Configurations::Parser::isComment(const std::string& line) { + return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationComment)); +} + +bool Configurations::Parser::isConfig(const std::string& line) { + std::size_t assignment = line.find('='); + return line != "" && + ((line[0] >= 'A' && line[0] <= 'Z') || (line[0] >= 'a' && line[0] <= 'z')) && + (assignment != std::string::npos) && + (line.size() > assignment); +} + +bool Configurations::Parser::parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, + Level* currLevel, + Configurations* conf) { + ConfigurationType currConfig = ConfigurationType::Unknown; + std::string currValue = std::string(); + *line = base::utils::Str::trim(*line); + if (isComment(*line)) return true; + ignoreComments(line); + *line = base::utils::Str::trim(*line); + if (line->empty()) { + // Comment ignored + return true; + } + if (isLevel(*line)) { + if (line->size() <= 2) { + return true; + } + *currLevelStr = line->substr(1, line->size() - 2); + *currLevelStr = base::utils::Str::toUpper(*currLevelStr); + *currLevelStr = base::utils::Str::trim(*currLevelStr); + *currLevel = LevelHelper::convertFromString(currLevelStr->c_str()); + return true; + } + if (isConfig(*line)) { + std::size_t assignment = line->find('='); + *currConfigStr = line->substr(0, assignment); + *currConfigStr = base::utils::Str::toUpper(*currConfigStr); + *currConfigStr = base::utils::Str::trim(*currConfigStr); + currConfig = ConfigurationTypeHelper::convertFromString(currConfigStr->c_str()); + currValue = line->substr(assignment + 1); + currValue = base::utils::Str::trim(currValue); + std::size_t quotesStart = currValue.find("\"", 0); + std::size_t quotesEnd = std::string::npos; + if (quotesStart != std::string::npos) { + quotesEnd = currValue.find("\"", quotesStart + 1); + while (quotesEnd != std::string::npos && currValue.at(quotesEnd - 1) == '\\') { + currValue = currValue.erase(quotesEnd - 1, 1); + quotesEnd = currValue.find("\"", quotesEnd + 2); + } + } + if (quotesStart != std::string::npos && quotesEnd != std::string::npos) { + // Quote provided - check and strip if valid + ELPP_ASSERT((quotesStart < quotesEnd), "Configuration error - No ending quote found in [" + << currConfigStr << "]"); + ELPP_ASSERT((quotesStart + 1 != quotesEnd), "Empty configuration value for [" << currConfigStr << "]"); + if ((quotesStart != quotesEnd) && (quotesStart + 1 != quotesEnd)) { + // Explicit check in case if assertion is disabled + currValue = currValue.substr(quotesStart + 1, quotesEnd - 1); + } + } + } + ELPP_ASSERT(*currLevel != Level::Unknown, "Unrecognized severity level [" << *currLevelStr << "]"); + ELPP_ASSERT(currConfig != ConfigurationType::Unknown, "Unrecognized configuration [" << *currConfigStr << "]"); + if (*currLevel == Level::Unknown || currConfig == ConfigurationType::Unknown) { + return false; // unrecognizable level or config + } + conf->set(*currLevel, currConfig, currValue); + return true; +} + +void Configurations::unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value) { + Configuration* conf = RegistryWithPred::get(level, configurationType); + if (conf == nullptr) { + unsafeSet(level, configurationType, value); + } +} + +void Configurations::unsafeSet(Level level, ConfigurationType configurationType, const std::string& value) { + Configuration* conf = RegistryWithPred::get(level, configurationType); + if (conf == nullptr) { + registerNew(new Configuration(level, configurationType, value)); + } else { + conf->setValue(value); + } + if (level == Level::Global) { + unsafeSetGlobally(configurationType, value, false); + } +} + +void Configurations::setGlobally(ConfigurationType configurationType, const std::string& value, + bool includeGlobalLevel) { + if (includeGlobalLevel) { + set(Level::Global, configurationType, value); + } + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + set(LevelHelper::castFromInt(lIndex), configurationType, value); + return false; // Do not break lambda function yet as we need to set all levels regardless + }); +} + +void Configurations::unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, + bool includeGlobalLevel) { + if (includeGlobalLevel) { + unsafeSet(Level::Global, configurationType, value); + } + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + unsafeSet(LevelHelper::castFromInt(lIndex), configurationType, value); + return false; // Do not break lambda function yet as we need to set all levels regardless + }); +} + +// LogBuilder + +void LogBuilder::convertToColoredOutput(base::type::string_t* logLine, Level level) { + if (!m_termSupportsColor) return; + const base::type::char_t* resetColor = ELPP_LITERAL("\x1b[0m"); + if (level == Level::Error || level == Level::Fatal) + *logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor; + else if (level == Level::Warning) + *logLine = ELPP_LITERAL("\x1b[33m") + *logLine + resetColor; + else if (level == Level::Debug) + *logLine = ELPP_LITERAL("\x1b[32m") + *logLine + resetColor; + else if (level == Level::Info) + *logLine = ELPP_LITERAL("\x1b[36m") + *logLine + resetColor; + else if (level == Level::Trace) + *logLine = ELPP_LITERAL("\x1b[35m") + *logLine + resetColor; +} + +// Logger + +Logger::Logger(const std::string& id, base::LogStreamsReferenceMapPtr logStreamsReference) : + m_id(id), + m_typedConfigurations(nullptr), + m_parentApplicationName(std::string()), + m_isConfigured(false), + m_logStreamsReference(logStreamsReference) { + initUnflushedCount(); +} + +Logger::Logger(const std::string& id, const Configurations& configurations, + base::LogStreamsReferenceMapPtr logStreamsReference) : + m_id(id), + m_typedConfigurations(nullptr), + m_parentApplicationName(std::string()), + m_isConfigured(false), + m_logStreamsReference(logStreamsReference) { + initUnflushedCount(); + configure(configurations); +} + +Logger::Logger(const Logger& logger) { + base::utils::safeDelete(m_typedConfigurations); + m_id = logger.m_id; + m_typedConfigurations = logger.m_typedConfigurations; + m_parentApplicationName = logger.m_parentApplicationName; + m_isConfigured = logger.m_isConfigured; + m_configurations = logger.m_configurations; + m_unflushedCount = logger.m_unflushedCount; + m_logStreamsReference = logger.m_logStreamsReference; +} + +Logger& Logger::operator=(const Logger& logger) { + if (&logger != this) { + base::utils::safeDelete(m_typedConfigurations); + m_id = logger.m_id; + m_typedConfigurations = logger.m_typedConfigurations; + m_parentApplicationName = logger.m_parentApplicationName; + m_isConfigured = logger.m_isConfigured; + m_configurations = logger.m_configurations; + m_unflushedCount = logger.m_unflushedCount; + m_logStreamsReference = logger.m_logStreamsReference; + } + return *this; +} + +void Logger::configure(const Configurations& configurations) { + m_isConfigured = false; // we set it to false in case if we fail + initUnflushedCount(); + if (m_typedConfigurations != nullptr) { + Configurations* c = const_cast(m_typedConfigurations->configurations()); + if (c->hasConfiguration(Level::Global, ConfigurationType::Filename)) { + flush(); + } + } + base::threading::ScopedLock scopedLock(lock()); + if (m_configurations != configurations) { + m_configurations.setFromBase(const_cast(&configurations)); + } + base::utils::safeDelete(m_typedConfigurations); + m_typedConfigurations = new base::TypedConfigurations(&m_configurations, m_logStreamsReference); + resolveLoggerFormatSpec(); + m_isConfigured = true; +} + +void Logger::reconfigure(void) { + ELPP_INTERNAL_INFO(1, "Reconfiguring logger [" << m_id << "]"); + configure(m_configurations); +} + +bool Logger::isValidId(const std::string& id) { + for (std::string::const_iterator it = id.begin(); it != id.end(); ++it) { + if (!base::utils::Str::contains(base::consts::kValidLoggerIdSymbols, *it)) { + return false; + } + } + return true; +} + +void Logger::flush(void) { + ELPP_INTERNAL_INFO(3, "Flushing logger [" << m_id << "] all levels"); + base::threading::ScopedLock scopedLock(lock()); + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + flush(LevelHelper::castFromInt(lIndex), nullptr); + return false; + }); +} + +void Logger::flush(Level level, base::type::fstream_t* fs) { + if (fs == nullptr && m_typedConfigurations->toFile(level)) { + fs = m_typedConfigurations->fileStream(level); + } + if (fs != nullptr) { + fs->flush(); + std::unordered_map::iterator iter = m_unflushedCount.find(level); + if (iter != m_unflushedCount.end()) { + iter->second = 0; + } + Helpers::validateFileRolling(this, level); + } +} + +void Logger::initUnflushedCount(void) { + m_unflushedCount.clear(); + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + m_unflushedCount.insert(std::make_pair(LevelHelper::castFromInt(lIndex), 0)); + return false; + }); +} + +void Logger::resolveLoggerFormatSpec(void) const { + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + base::LogFormat* logFormat = + const_cast(&m_typedConfigurations->logFormat(LevelHelper::castFromInt(lIndex))); + base::utils::Str::replaceFirstWithEscape(logFormat->m_format, base::consts::kLoggerIdFormatSpecifier, m_id); + return false; + }); +} + +// el::base +namespace base { + +// el::base::utils +namespace utils { + +// File + +base::type::fstream_t* File::newFileStream(const std::string& filename) { + base::type::fstream_t *fs = new base::type::fstream_t(filename.c_str(), + base::type::fstream_t::out +#if !defined(ELPP_FRESH_LOG_FILE) + | base::type::fstream_t::app +#endif + ); +#if defined(ELPP_UNICODE) + std::locale elppUnicodeLocale(""); +# if ELPP_OS_WINDOWS + std::locale elppUnicodeLocaleWindows(elppUnicodeLocale, new std::codecvt_utf8_utf16); + elppUnicodeLocale = elppUnicodeLocaleWindows; +# endif // ELPP_OS_WINDOWS + fs->imbue(elppUnicodeLocale); +#endif // defined(ELPP_UNICODE) + if (fs->is_open()) { + fs->flush(); + } else { + base::utils::safeDelete(fs); + ELPP_INTERNAL_ERROR("Bad file [" << filename << "]", true); + } + return fs; +} + +std::size_t File::getSizeOfFile(base::type::fstream_t* fs) { + if (fs == nullptr) { + return 0; + } + // Since the file stream is appended to or truncated, the current + // offset is the file size. + std::size_t size = static_cast(fs->tellg()); + return size; +} + +bool File::pathExists(const char* path, bool considerFile) { + if (path == nullptr) { + return false; + } +#if ELPP_OS_UNIX + ELPP_UNUSED(considerFile); + struct stat st; + return (stat(path, &st) == 0); +#elif ELPP_OS_WINDOWS + DWORD fileType = GetFileAttributesA(path); + if (fileType == INVALID_FILE_ATTRIBUTES) { + return false; + } + return considerFile ? true : ((fileType & FILE_ATTRIBUTE_DIRECTORY) == 0 ? false : true); +#endif // ELPP_OS_UNIX +} + +bool File::createPath(const std::string& path) { + if (path.empty()) { + return false; + } + if (base::utils::File::pathExists(path.c_str())) { + return true; + } + int status = -1; + + char* currPath = const_cast(path.c_str()); + std::string builtPath = std::string(); +#if ELPP_OS_UNIX + if (path[0] == '/') { + builtPath = "/"; + } + currPath = STRTOK(currPath, base::consts::kFilePathSeparator, 0); +#elif ELPP_OS_WINDOWS + // Use secure functions API + char* nextTok_ = nullptr; + currPath = STRTOK(currPath, base::consts::kFilePathSeparator, &nextTok_); + ELPP_UNUSED(nextTok_); +#endif // ELPP_OS_UNIX + while (currPath != nullptr) { + builtPath.append(currPath); + builtPath.append(base::consts::kFilePathSeparator); +#if ELPP_OS_UNIX + status = mkdir(builtPath.c_str(), ELPP_LOG_PERMS); + currPath = STRTOK(nullptr, base::consts::kFilePathSeparator, 0); +#elif ELPP_OS_WINDOWS + status = _mkdir(builtPath.c_str()); + currPath = STRTOK(nullptr, base::consts::kFilePathSeparator, &nextTok_); +#endif // ELPP_OS_UNIX + } + if (status == -1) { + ELPP_INTERNAL_ERROR("Error while creating path [" << path << "]", true); + return false; + } + return true; +} + +std::string File::extractPathFromFilename(const std::string& fullPath, const char* separator) { + if ((fullPath == "") || (fullPath.find(separator) == std::string::npos)) { + return fullPath; + } + std::size_t lastSlashAt = fullPath.find_last_of(separator); + if (lastSlashAt == 0) { + return std::string(separator); + } + return fullPath.substr(0, lastSlashAt + 1); +} + +void File::buildStrippedFilename(const char* filename, char buff[], std::size_t limit) { + std::size_t sizeOfFilename = strlen(filename); + if (sizeOfFilename >= limit) { + filename += (sizeOfFilename - limit); + if (filename[0] != '.' && filename[1] != '.') { // prepend if not already + filename += 3; // 3 = '..' + STRCAT(buff, "..", limit); + } + } + STRCAT(buff, filename, limit); +} + +void File::buildBaseFilename(const std::string& fullPath, char buff[], std::size_t limit, const char* separator) { + const char *filename = fullPath.c_str(); + std::size_t lastSlashAt = fullPath.find_last_of(separator); + filename += lastSlashAt ? lastSlashAt+1 : 0; + std::size_t sizeOfFilename = strlen(filename); + if (sizeOfFilename >= limit) { + filename += (sizeOfFilename - limit); + if (filename[0] != '.' && filename[1] != '.') { // prepend if not already + filename += 3; // 3 = '..' + STRCAT(buff, "..", limit); + } + } + STRCAT(buff, filename, limit); +} + +// Str + +bool Str::wildCardMatch(const char* str, const char* pattern) { + while (*pattern) { + switch (*pattern) { + case '?': + if (!*str) + return false; + ++str; + ++pattern; + break; + case '*': + if (wildCardMatch(str, pattern + 1)) + return true; + if (*str && wildCardMatch(str + 1, pattern)) + return true; + return false; + default: + if (*str++ != *pattern++) + return false; + break; + } + } + return !*str && !*pattern; +} + +std::string& Str::ltrim(std::string& str) { + str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](char c) { + return !std::isspace(c); + } )); + return str; +} + +std::string& Str::rtrim(std::string& str) { + str.erase(std::find_if(str.rbegin(), str.rend(), [](char c) { + return !std::isspace(c); + }).base(), str.end()); + return str; +} + +std::string& Str::trim(std::string& str) { + return ltrim(rtrim(str)); +} + +bool Str::startsWith(const std::string& str, const std::string& start) { + return (str.length() >= start.length()) && (str.compare(0, start.length(), start) == 0); +} + +bool Str::endsWith(const std::string& str, const std::string& end) { + return (str.length() >= end.length()) && (str.compare(str.length() - end.length(), end.length(), end) == 0); +} + +std::string& Str::replaceAll(std::string& str, char replaceWhat, char replaceWith) { + std::replace(str.begin(), str.end(), replaceWhat, replaceWith); + return str; +} + +std::string& Str::replaceAll(std::string& str, const std::string& replaceWhat, + const std::string& replaceWith) { + if (replaceWhat == replaceWith) + return str; + std::size_t foundAt = std::string::npos; + while ((foundAt = str.find(replaceWhat, foundAt + 1)) != std::string::npos) { + str.replace(foundAt, replaceWhat.length(), replaceWith); + } + return str; +} + +void Str::replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, + const base::type::string_t& replaceWith) { + std::size_t foundAt = base::type::string_t::npos; + while ((foundAt = str.find(replaceWhat, foundAt + 1)) != base::type::string_t::npos) { + if (foundAt > 0 && str[foundAt - 1] == base::consts::kFormatSpecifierChar) { + str.erase(foundAt - 1, 1); + ++foundAt; + } else { + str.replace(foundAt, replaceWhat.length(), replaceWith); + return; + } + } +} +#if defined(ELPP_UNICODE) +void Str::replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, + const std::string& replaceWith) { + replaceFirstWithEscape(str, replaceWhat, base::type::string_t(replaceWith.begin(), replaceWith.end())); +} +#endif // defined(ELPP_UNICODE) + +std::string& Str::toUpper(std::string& str) { + std::transform(str.begin(), str.end(), str.begin(), + [](char c) { + return static_cast(::toupper(c)); + }); + return str; +} + +bool Str::cStringEq(const char* s1, const char* s2) { + if (s1 == nullptr && s2 == nullptr) return true; + if (s1 == nullptr || s2 == nullptr) return false; + return strcmp(s1, s2) == 0; +} + +bool Str::cStringCaseEq(const char* s1, const char* s2) { + if (s1 == nullptr && s2 == nullptr) return true; + if (s1 == nullptr || s2 == nullptr) return false; + + // With thanks to cygwin for this code + int d = 0; + + while (true) { + const int c1 = toupper(*s1++); + const int c2 = toupper(*s2++); + + if (((d = c1 - c2) != 0) || (c2 == '\0')) { + break; + } + } + + return d == 0; +} + +bool Str::contains(const char* str, char c) { + for (; *str; ++str) { + if (*str == c) + return true; + } + return false; +} + +char* Str::convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded) { + char localBuff[10] = ""; + char* p = localBuff + sizeof(localBuff) - 2; + if (n > 0) { + for (; n > 0 && p > localBuff && len > 0; n /= 10, --len) + *--p = static_cast(n % 10 + '0'); + } else { + *--p = '0'; + --len; + } + if (zeroPadded) + while (p > localBuff && len-- > 0) *--p = static_cast('0'); + return addToBuff(p, buf, bufLim); +} + +char* Str::addToBuff(const char* str, char* buf, const char* bufLim) { + while ((buf < bufLim) && ((*buf = *str++) != '\0')) + ++buf; + return buf; +} + +char* Str::clearBuff(char buff[], std::size_t lim) { + STRCPY(buff, "", lim); + ELPP_UNUSED(lim); // For *nix we dont have anything using lim in above STRCPY macro + return buff; +} + +/// @brief Converts wchar* to char* +/// NOTE: Need to free return value after use! +char* Str::wcharPtrToCharPtr(const wchar_t* line) { + std::size_t len_ = wcslen(line) + 1; + char* buff_ = static_cast(malloc(len_ + 1)); +# if ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) + std::wcstombs(buff_, line, len_); +# elif ELPP_OS_WINDOWS + std::size_t convCount_ = 0; + mbstate_t mbState_; + ::memset(static_cast(&mbState_), 0, sizeof(mbState_)); + wcsrtombs_s(&convCount_, buff_, len_, &line, len_, &mbState_); +# endif // ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) + return buff_; +} + +// OS + +#if ELPP_OS_WINDOWS +/// @brief Gets environment variables for Windows based OS. +/// We are not using getenv(const char*) because of CRT deprecation +/// @param varname Variable name to get environment variable value for +/// @return If variable exist the value of it otherwise nullptr +const char* OS::getWindowsEnvironmentVariable(const char* varname) { + const DWORD bufferLen = 50; + static char buffer[bufferLen]; + if (GetEnvironmentVariableA(varname, buffer, bufferLen)) { + return buffer; + } + return nullptr; +} +#endif // ELPP_OS_WINDOWS +#if ELPP_OS_ANDROID +std::string OS::getProperty(const char* prop) { + char propVal[PROP_VALUE_MAX + 1]; + int ret = __system_property_get(prop, propVal); + return ret == 0 ? std::string() : std::string(propVal); +} + +std::string OS::getDeviceName(void) { + std::stringstream ss; + std::string manufacturer = getProperty("ro.product.manufacturer"); + std::string model = getProperty("ro.product.model"); + if (manufacturer.empty() || model.empty()) { + return std::string(); + } + ss << manufacturer << "-" << model; + return ss.str(); +} +#endif // ELPP_OS_ANDROID + +const std::string OS::getBashOutput(const char* command) { +#if (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) + if (command == nullptr) { + return std::string(); + } + FILE* proc = nullptr; + if ((proc = popen(command, "r")) == nullptr) { + ELPP_INTERNAL_ERROR("\nUnable to run command [" << command << "]", true); + return std::string(); + } + char hBuff[4096]; + if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) { + pclose(proc); + const std::size_t buffLen = strlen(hBuff); + if (buffLen > 0 && hBuff[buffLen - 1] == '\n') { + hBuff[buffLen - 1] = '\0'; + } + return std::string(hBuff); + } else { + pclose(proc); + } + return std::string(); +#else + ELPP_UNUSED(command); + return std::string(); +#endif // (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) +} + +std::string OS::getEnvironmentVariable(const char* variableName, const char* defaultVal, + const char* alternativeBashCommand) { +#if ELPP_OS_UNIX + const char* val = getenv(variableName); +#elif ELPP_OS_WINDOWS + const char* val = getWindowsEnvironmentVariable(variableName); +#endif // ELPP_OS_UNIX + if ((val == nullptr) || ((strcmp(val, "") == 0))) { +#if ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) + // Try harder on unix-based systems + std::string valBash = base::utils::OS::getBashOutput(alternativeBashCommand); + if (valBash.empty()) { + return std::string(defaultVal); + } else { + return valBash; + } +#elif ELPP_OS_WINDOWS || ELPP_OS_UNIX + ELPP_UNUSED(alternativeBashCommand); + return std::string(defaultVal); +#endif // ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) + } + return std::string(val); +} + +std::string OS::currentUser(void) { +#if ELPP_OS_UNIX && !ELPP_OS_ANDROID + return getEnvironmentVariable("USER", base::consts::kUnknownUser, "whoami"); +#elif ELPP_OS_WINDOWS + return getEnvironmentVariable("USERNAME", base::consts::kUnknownUser); +#elif ELPP_OS_ANDROID + ELPP_UNUSED(base::consts::kUnknownUser); + return std::string("android"); +#else + return std::string(); +#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID +} + +std::string OS::currentHost(void) { +#if ELPP_OS_UNIX && !ELPP_OS_ANDROID + return getEnvironmentVariable("HOSTNAME", base::consts::kUnknownHost, "hostname"); +#elif ELPP_OS_WINDOWS + return getEnvironmentVariable("COMPUTERNAME", base::consts::kUnknownHost); +#elif ELPP_OS_ANDROID + ELPP_UNUSED(base::consts::kUnknownHost); + return getDeviceName(); +#else + return std::string(); +#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID +} + +bool OS::termSupportsColor(void) { + std::string term = getEnvironmentVariable("TERM", ""); + return term == "xterm" || term == "xterm-color" || term == "xterm-256color" + || term == "screen" || term == "linux" || term == "cygwin" + || term == "screen-256color"; +} + +// DateTime + +void DateTime::gettimeofday(struct timeval* tv) { +#if ELPP_OS_WINDOWS + if (tv != nullptr) { +# if ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) + const unsigned __int64 delta_ = 11644473600000000Ui64; +# else + const unsigned __int64 delta_ = 11644473600000000ULL; +# endif // ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) + const double secOffSet = 0.000001; + const unsigned long usecOffSet = 1000000; + FILETIME fileTime; + GetSystemTimeAsFileTime(&fileTime); + unsigned __int64 present = 0; + present |= fileTime.dwHighDateTime; + present = present << 32; + present |= fileTime.dwLowDateTime; + present /= 10; // mic-sec + // Subtract the difference + present -= delta_; + tv->tv_sec = static_cast(present * secOffSet); + tv->tv_usec = static_cast(present % usecOffSet); + } +#else + ::gettimeofday(tv, nullptr); +#endif // ELPP_OS_WINDOWS +} + +std::string DateTime::getDateTime(const char* format, const base::SubsecondPrecision* ssPrec) { + struct timeval currTime; + gettimeofday(&currTime); + return timevalToString(currTime, format, ssPrec); +} + +std::string DateTime::timevalToString(struct timeval tval, const char* format, + const el::base::SubsecondPrecision* ssPrec) { + struct ::tm timeInfo; + buildTimeInfo(&tval, &timeInfo); + const int kBuffSize = 30; + char buff_[kBuffSize] = ""; + parseFormat(buff_, kBuffSize, format, &timeInfo, static_cast(tval.tv_usec / ssPrec->m_offset), + ssPrec); + return std::string(buff_); +} + +base::type::string_t DateTime::formatTime(unsigned long long time, base::TimestampUnit timestampUnit) { + base::type::EnumType start = static_cast(timestampUnit); + const base::type::char_t* unit = base::consts::kTimeFormats[start].unit; + for (base::type::EnumType i = start; i < base::consts::kTimeFormatsCount - 1; ++i) { + if (time <= base::consts::kTimeFormats[i].value) { + break; + } + if (base::consts::kTimeFormats[i].value == 1000.0f && time / 1000.0f < 1.9f) { + break; + } + time /= static_cast(base::consts::kTimeFormats[i].value); + unit = base::consts::kTimeFormats[i + 1].unit; + } + base::type::stringstream_t ss; + ss << time << " " << unit; + return ss.str(); +} + +unsigned long long DateTime::getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, + base::TimestampUnit timestampUnit) { + if (timestampUnit == base::TimestampUnit::Microsecond) { + return static_cast(static_cast(1000000 * endTime.tv_sec + endTime.tv_usec) - + static_cast(1000000 * startTime.tv_sec + startTime.tv_usec)); + } + // milliseconds + auto conv = [](const struct timeval& tim) { + return static_cast((tim.tv_sec * 1000) + (tim.tv_usec / 1000)); + }; + return static_cast(conv(endTime) - conv(startTime)); +} + +struct ::tm* DateTime::buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo) { +#if ELPP_OS_UNIX + time_t rawTime = currTime->tv_sec; + ::elpptime_r(&rawTime, timeInfo); + return timeInfo; +#else +# if ELPP_COMPILER_MSVC + ELPP_UNUSED(currTime); + time_t t; +# if defined(_USE_32BIT_TIME_T) + _time32(&t); +# else + _time64(&t); +# endif + elpptime_s(timeInfo, &t); + return timeInfo; +# else + // For any other compilers that don't have CRT warnings issue e.g, MinGW or TDM GCC- we use different method + time_t rawTime = currTime->tv_sec; + struct tm* tmInf = elpptime(&rawTime); + *timeInfo = *tmInf; + return timeInfo; +# endif // ELPP_COMPILER_MSVC +#endif // ELPP_OS_UNIX +} + +char* DateTime::parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, + std::size_t msec, const base::SubsecondPrecision* ssPrec) { + const char* bufLim = buf + bufSz; + for (; *format; ++format) { + if (*format == base::consts::kFormatSpecifierChar) { + switch (*++format) { + case base::consts::kFormatSpecifierChar: // Escape + break; + case '\0': // End + --format; + break; + case 'd': // Day + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mday, 2, buf, bufLim); + continue; + case 'a': // Day of week (short) + buf = base::utils::Str::addToBuff(base::consts::kDaysAbbrev[tInfo->tm_wday], buf, bufLim); + continue; + case 'A': // Day of week (long) + buf = base::utils::Str::addToBuff(base::consts::kDays[tInfo->tm_wday], buf, bufLim); + continue; + case 'M': // month + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mon + 1, 2, buf, bufLim); + continue; + case 'b': // month (short) + buf = base::utils::Str::addToBuff(base::consts::kMonthsAbbrev[tInfo->tm_mon], buf, bufLim); + continue; + case 'B': // month (long) + buf = base::utils::Str::addToBuff(base::consts::kMonths[tInfo->tm_mon], buf, bufLim); + continue; + case 'y': // year (two digits) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 2, buf, bufLim); + continue; + case 'Y': // year (four digits) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 4, buf, bufLim); + continue; + case 'h': // hour (12-hour) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour % 12, 2, buf, bufLim); + continue; + case 'H': // hour (24-hour) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour, 2, buf, bufLim); + continue; + case 'm': // minute + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_min, 2, buf, bufLim); + continue; + case 's': // second + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_sec, 2, buf, bufLim); + continue; + case 'z': // subsecond part + case 'g': + buf = base::utils::Str::convertAndAddToBuff(msec, ssPrec->m_width, buf, bufLim); + continue; + case 'F': // AM/PM + buf = base::utils::Str::addToBuff((tInfo->tm_hour >= 12) ? base::consts::kPm : base::consts::kAm, buf, bufLim); + continue; + default: + continue; + } + } + if (buf == bufLim) break; + *buf++ = *format; + } + return buf; +} + +// CommandLineArgs + +void CommandLineArgs::setArgs(int argc, char** argv) { + m_params.clear(); + m_paramsWithValue.clear(); + if (argc == 0 || argv == nullptr) { + return; + } + m_argc = argc; + m_argv = argv; + for (int i = 1; i < m_argc; ++i) { + const char* v = (strstr(m_argv[i], "=")); + if (v != nullptr && strlen(v) > 0) { + std::string key = std::string(m_argv[i]); + key = key.substr(0, key.find_first_of('=')); + if (hasParamWithValue(key.c_str())) { + ELPP_INTERNAL_INFO(1, "Skipping [" << key << "] arg since it already has value [" + << getParamValue(key.c_str()) << "]"); + } else { + m_paramsWithValue.insert(std::make_pair(key, std::string(v + 1))); + } + } + if (v == nullptr) { + if (hasParam(m_argv[i])) { + ELPP_INTERNAL_INFO(1, "Skipping [" << m_argv[i] << "] arg since it already exists"); + } else { + m_params.push_back(std::string(m_argv[i])); + } + } + } +} + +bool CommandLineArgs::hasParamWithValue(const char* paramKey) const { + return m_paramsWithValue.find(std::string(paramKey)) != m_paramsWithValue.end(); +} + +const char* CommandLineArgs::getParamValue(const char* paramKey) const { + std::unordered_map::const_iterator iter = m_paramsWithValue.find(std::string(paramKey)); + return iter != m_paramsWithValue.end() ? iter->second.c_str() : ""; +} + +bool CommandLineArgs::hasParam(const char* paramKey) const { + return std::find(m_params.begin(), m_params.end(), std::string(paramKey)) != m_params.end(); +} + +bool CommandLineArgs::empty(void) const { + return m_params.empty() && m_paramsWithValue.empty(); +} + +std::size_t CommandLineArgs::size(void) const { + return m_params.size() + m_paramsWithValue.size(); +} + +base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c) { + for (int i = 1; i < c.m_argc; ++i) { + os << ELPP_LITERAL("[") << c.m_argv[i] << ELPP_LITERAL("]"); + if (i < c.m_argc - 1) { + os << ELPP_LITERAL(" "); + } + } + return os; +} + +} // namespace utils + +// el::base::threading +namespace threading { + +#if ELPP_THREADING_ENABLED +# if ELPP_USE_STD_THREADING +# if ELPP_ASYNC_LOGGING +static void msleep(int ms) { + // Only when async logging enabled - this is because async is strict on compiler +# if defined(ELPP_NO_SLEEP_FOR) + usleep(ms * 1000); +# else + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +# endif // defined(ELPP_NO_SLEEP_FOR) +} +# endif // ELPP_ASYNC_LOGGING +# endif // !ELPP_USE_STD_THREADING +#endif // ELPP_THREADING_ENABLED + +} // namespace threading + +// el::base + +// SubsecondPrecision + +void SubsecondPrecision::init(int width) { + if (width < 1 || width > 6) { + width = base::consts::kDefaultSubsecondPrecision; + } + m_width = width; + switch (m_width) { + case 3: + m_offset = 1000; + break; + case 4: + m_offset = 100; + break; + case 5: + m_offset = 10; + break; + case 6: + m_offset = 1; + break; + default: + m_offset = 1000; + break; + } +} + +// LogFormat + +LogFormat::LogFormat(void) : + m_level(Level::Unknown), + m_userFormat(base::type::string_t()), + m_format(base::type::string_t()), + m_dateTimeFormat(std::string()), + m_flags(0x0), + m_currentUser(base::utils::OS::currentUser()), + m_currentHost(base::utils::OS::currentHost()) { +} + +LogFormat::LogFormat(Level level, const base::type::string_t& format) + : m_level(level), m_userFormat(format), m_currentUser(base::utils::OS::currentUser()), + m_currentHost(base::utils::OS::currentHost()) { + parseFromFormat(m_userFormat); +} + +LogFormat::LogFormat(const LogFormat& logFormat): + m_level(logFormat.m_level), + m_userFormat(logFormat.m_userFormat), + m_format(logFormat.m_format), + m_dateTimeFormat(logFormat.m_dateTimeFormat), + m_flags(logFormat.m_flags), + m_currentUser(logFormat.m_currentUser), + m_currentHost(logFormat.m_currentHost) { +} + +LogFormat::LogFormat(LogFormat&& logFormat) { + m_level = std::move(logFormat.m_level); + m_userFormat = std::move(logFormat.m_userFormat); + m_format = std::move(logFormat.m_format); + m_dateTimeFormat = std::move(logFormat.m_dateTimeFormat); + m_flags = std::move(logFormat.m_flags); + m_currentUser = std::move(logFormat.m_currentUser); + m_currentHost = std::move(logFormat.m_currentHost); +} + +LogFormat& LogFormat::operator=(const LogFormat& logFormat) { + if (&logFormat != this) { + m_level = logFormat.m_level; + m_userFormat = logFormat.m_userFormat; + m_dateTimeFormat = logFormat.m_dateTimeFormat; + m_flags = logFormat.m_flags; + m_currentUser = logFormat.m_currentUser; + m_currentHost = logFormat.m_currentHost; + } + return *this; +} + +bool LogFormat::operator==(const LogFormat& other) { + return m_level == other.m_level && m_userFormat == other.m_userFormat && m_format == other.m_format && + m_dateTimeFormat == other.m_dateTimeFormat && m_flags == other.m_flags; +} + +/// @brief Updates format to be used while logging. +/// @param userFormat User provided format +void LogFormat::parseFromFormat(const base::type::string_t& userFormat) { + // We make copy because we will be changing the format + // i.e, removing user provided date format from original format + // and then storing it. + base::type::string_t formatCopy = userFormat; + m_flags = 0x0; + auto conditionalAddFlag = [&](const base::type::char_t* specifier, base::FormatFlags flag) { + std::size_t foundAt = base::type::string_t::npos; + while ((foundAt = formatCopy.find(specifier, foundAt + 1)) != base::type::string_t::npos) { + if (foundAt > 0 && formatCopy[foundAt - 1] == base::consts::kFormatSpecifierChar) { + if (hasFlag(flag)) { + // If we already have flag we remove the escape chars so that '%%' is turned to '%' + // even after specifier resolution - this is because we only replaceFirst specifier + formatCopy.erase(foundAt - 1, 1); + ++foundAt; + } + } else { + if (!hasFlag(flag)) addFlag(flag); + } + } + }; + conditionalAddFlag(base::consts::kAppNameFormatSpecifier, base::FormatFlags::AppName); + conditionalAddFlag(base::consts::kSeverityLevelFormatSpecifier, base::FormatFlags::Level); + conditionalAddFlag(base::consts::kSeverityLevelShortFormatSpecifier, base::FormatFlags::LevelShort); + conditionalAddFlag(base::consts::kLoggerIdFormatSpecifier, base::FormatFlags::LoggerId); + conditionalAddFlag(base::consts::kThreadIdFormatSpecifier, base::FormatFlags::ThreadId); + conditionalAddFlag(base::consts::kLogFileFormatSpecifier, base::FormatFlags::File); + conditionalAddFlag(base::consts::kLogFileBaseFormatSpecifier, base::FormatFlags::FileBase); + conditionalAddFlag(base::consts::kLogLineFormatSpecifier, base::FormatFlags::Line); + conditionalAddFlag(base::consts::kLogLocationFormatSpecifier, base::FormatFlags::Location); + conditionalAddFlag(base::consts::kLogFunctionFormatSpecifier, base::FormatFlags::Function); + conditionalAddFlag(base::consts::kCurrentUserFormatSpecifier, base::FormatFlags::User); + conditionalAddFlag(base::consts::kCurrentHostFormatSpecifier, base::FormatFlags::Host); + conditionalAddFlag(base::consts::kMessageFormatSpecifier, base::FormatFlags::LogMessage); + conditionalAddFlag(base::consts::kVerboseLevelFormatSpecifier, base::FormatFlags::VerboseLevel); + // For date/time we need to extract user's date format first + std::size_t dateIndex = std::string::npos; + if ((dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier)) != std::string::npos) { + while (dateIndex != std::string::npos && dateIndex > 0 && formatCopy[dateIndex - 1] == base::consts::kFormatSpecifierChar) { + dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier, dateIndex + 1); + } + if (dateIndex != std::string::npos) { + addFlag(base::FormatFlags::DateTime); + updateDateFormat(dateIndex, formatCopy); + } + } + m_format = formatCopy; + updateFormatSpec(); +} + +void LogFormat::updateDateFormat(std::size_t index, base::type::string_t& currFormat) { + if (hasFlag(base::FormatFlags::DateTime)) { + index += ELPP_STRLEN(base::consts::kDateTimeFormatSpecifier); + } + const base::type::char_t* ptr = currFormat.c_str() + index; + if ((currFormat.size() > index) && (ptr[0] == '{')) { + // User has provided format for date/time + ++ptr; + int count = 1; // Start by 1 in order to remove starting brace + std::stringstream ss; + for (; *ptr; ++ptr, ++count) { + if (*ptr == '}') { + ++count; // In order to remove ending brace + break; + } + ss << static_cast(*ptr); + } + currFormat.erase(index, count); + m_dateTimeFormat = ss.str(); + } else { + // No format provided, use default + if (hasFlag(base::FormatFlags::DateTime)) { + m_dateTimeFormat = std::string(base::consts::kDefaultDateTimeFormat); + } + } +} + +void LogFormat::updateFormatSpec(void) { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (m_level == Level::Debug) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kDebugLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kDebugLevelShortLogValue); + } else if (m_level == Level::Info) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kInfoLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kInfoLevelShortLogValue); + } else if (m_level == Level::Warning) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kWarningLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kWarningLevelShortLogValue); + } else if (m_level == Level::Error) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kErrorLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kErrorLevelShortLogValue); + } else if (m_level == Level::Fatal) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kFatalLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kFatalLevelShortLogValue); + } else if (m_level == Level::Verbose) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kVerboseLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kVerboseLevelShortLogValue); + } else if (m_level == Level::Trace) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kTraceLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kTraceLevelShortLogValue); + } + if (hasFlag(base::FormatFlags::User)) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentUserFormatSpecifier, + m_currentUser); + } + if (hasFlag(base::FormatFlags::Host)) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentHostFormatSpecifier, + m_currentHost); + } + // Ignore Level::Global and Level::Unknown +} + +// TypedConfigurations + +TypedConfigurations::TypedConfigurations(Configurations* configurations, + LogStreamsReferenceMapPtr logStreamsReference) { + m_configurations = configurations; + m_logStreamsReference = logStreamsReference; + build(m_configurations); +} + +TypedConfigurations::TypedConfigurations(const TypedConfigurations& other) { + this->m_configurations = other.m_configurations; + this->m_logStreamsReference = other.m_logStreamsReference; + build(m_configurations); +} + +bool TypedConfigurations::enabled(Level level) { + return getConfigByVal(level, &m_enabledMap, "enabled"); +} + +bool TypedConfigurations::toFile(Level level) { + return getConfigByVal(level, &m_toFileMap, "toFile"); +} + +const std::string& TypedConfigurations::filename(Level level) { + return getConfigByRef(level, &m_filenameMap, "filename"); +} + +bool TypedConfigurations::toStandardOutput(Level level) { + return getConfigByVal(level, &m_toStandardOutputMap, "toStandardOutput"); +} + +const base::LogFormat& TypedConfigurations::logFormat(Level level) { + return getConfigByRef(level, &m_logFormatMap, "logFormat"); +} + +const base::SubsecondPrecision& TypedConfigurations::subsecondPrecision(Level level) { + return getConfigByRef(level, &m_subsecondPrecisionMap, "subsecondPrecision"); +} + +const base::MillisecondsWidth& TypedConfigurations::millisecondsWidth(Level level) { + return getConfigByRef(level, &m_subsecondPrecisionMap, "millisecondsWidth"); +} + +bool TypedConfigurations::performanceTracking(Level level) { + return getConfigByVal(level, &m_performanceTrackingMap, "performanceTracking"); +} + +base::type::fstream_t* TypedConfigurations::fileStream(Level level) { + return getConfigByRef(level, &m_fileStreamMap, "fileStream").get(); +} + +std::size_t TypedConfigurations::maxLogFileSize(Level level) { + return getConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); +} + +std::size_t TypedConfigurations::logFlushThreshold(Level level) { + return getConfigByVal(level, &m_logFlushThresholdMap, "logFlushThreshold"); +} + +void TypedConfigurations::build(Configurations* configurations) { + base::threading::ScopedLock scopedLock(lock()); + auto getBool = [] (std::string boolStr) -> bool { // Pass by value for trimming + base::utils::Str::trim(boolStr); + return (boolStr == "TRUE" || boolStr == "true" || boolStr == "1"); + }; + std::vector withFileSizeLimit; + for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { + Configuration* conf = *it; + // We cannot use switch on strong enums because Intel C++ dont support them yet + if (conf->configurationType() == ConfigurationType::Enabled) { + setValue(conf->level(), getBool(conf->value()), &m_enabledMap); + } else if (conf->configurationType() == ConfigurationType::ToFile) { + setValue(conf->level(), getBool(conf->value()), &m_toFileMap); + } else if (conf->configurationType() == ConfigurationType::ToStandardOutput) { + setValue(conf->level(), getBool(conf->value()), &m_toStandardOutputMap); + } else if (conf->configurationType() == ConfigurationType::Filename) { + // We do not yet configure filename but we will configure in another + // loop. This is because if file cannot be created, we will force ToFile + // to be false. Because configuring logger is not necessarily performance + // sensitive operation, we can live with another loop; (by the way this loop + // is not very heavy either) + } else if (conf->configurationType() == ConfigurationType::Format) { + setValue(conf->level(), base::LogFormat(conf->level(), + base::type::string_t(conf->value().begin(), conf->value().end())), &m_logFormatMap); + } else if (conf->configurationType() == ConfigurationType::SubsecondPrecision) { + setValue(Level::Global, + base::SubsecondPrecision(static_cast(getULong(conf->value()))), &m_subsecondPrecisionMap); + } else if (conf->configurationType() == ConfigurationType::PerformanceTracking) { + setValue(Level::Global, getBool(conf->value()), &m_performanceTrackingMap); + } else if (conf->configurationType() == ConfigurationType::MaxLogFileSize) { + auto v = getULong(conf->value()); + setValue(conf->level(), static_cast(v), &m_maxLogFileSizeMap); + if (v != 0) { + withFileSizeLimit.push_back(conf); + } + } else if (conf->configurationType() == ConfigurationType::LogFlushThreshold) { + setValue(conf->level(), static_cast(getULong(conf->value())), &m_logFlushThresholdMap); + } + } + // As mentioned earlier, we will now set filename configuration in separate loop to deal with non-existent files + for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { + Configuration* conf = *it; + if (conf->configurationType() == ConfigurationType::Filename) { + insertFile(conf->level(), conf->value()); + } + } + for (std::vector::iterator conf = withFileSizeLimit.begin(); + conf != withFileSizeLimit.end(); ++conf) { + // This is not unsafe as mutex is locked in currect scope + unsafeValidateFileRolling((*conf)->level(), base::defaultPreRollOutCallback); + } +} + +unsigned long TypedConfigurations::getULong(std::string confVal) { + bool valid = true; + base::utils::Str::trim(confVal); + valid = !confVal.empty() && std::find_if(confVal.begin(), confVal.end(), + [](char c) { + return !base::utils::Str::isDigit(c); + }) == confVal.end(); + if (!valid) { + valid = false; + ELPP_ASSERT(valid, "Configuration value not a valid integer [" << confVal << "]"); + return 0; + } + return atol(confVal.c_str()); +} + +std::string TypedConfigurations::resolveFilename(const std::string& filename) { + std::string resultingFilename = filename; + std::size_t dateIndex = std::string::npos; + std::string dateTimeFormatSpecifierStr = std::string(base::consts::kDateTimeFormatSpecifierForFilename); + if ((dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str())) != std::string::npos) { + while (dateIndex > 0 && resultingFilename[dateIndex - 1] == base::consts::kFormatSpecifierChar) { + dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str(), dateIndex + 1); + } + if (dateIndex != std::string::npos) { + const char* ptr = resultingFilename.c_str() + dateIndex; + // Goto end of specifier + ptr += dateTimeFormatSpecifierStr.size(); + std::string fmt; + if ((resultingFilename.size() > dateIndex) && (ptr[0] == '{')) { + // User has provided format for date/time + ++ptr; + int count = 1; // Start by 1 in order to remove starting brace + std::stringstream ss; + for (; *ptr; ++ptr, ++count) { + if (*ptr == '}') { + ++count; // In order to remove ending brace + break; + } + ss << *ptr; + } + resultingFilename.erase(dateIndex + dateTimeFormatSpecifierStr.size(), count); + fmt = ss.str(); + } else { + fmt = std::string(base::consts::kDefaultDateTimeFormatInFilename); + } + base::SubsecondPrecision ssPrec(3); + std::string now = base::utils::DateTime::getDateTime(fmt.c_str(), &ssPrec); + base::utils::Str::replaceAll(now, '/', '-'); // Replace path element since we are dealing with filename + base::utils::Str::replaceAll(resultingFilename, dateTimeFormatSpecifierStr, now); + } + } + return resultingFilename; +} + +void TypedConfigurations::insertFile(Level level, const std::string& fullFilename) { + std::string resolvedFilename = resolveFilename(fullFilename); + if (resolvedFilename.empty()) { + std::cerr << "Could not load empty file for logging, please re-check your configurations for level [" + << LevelHelper::convertToString(level) << "]"; + } + std::string filePath = base::utils::File::extractPathFromFilename(resolvedFilename, base::consts::kFilePathSeparator); + if (filePath.size() < resolvedFilename.size()) { + base::utils::File::createPath(filePath); + } + auto create = [&](Level level) { + base::LogStreamsReferenceMap::iterator filestreamIter = m_logStreamsReference->find(resolvedFilename); + base::type::fstream_t* fs = nullptr; + if (filestreamIter == m_logStreamsReference->end()) { + // We need a completely new stream, nothing to share with + fs = base::utils::File::newFileStream(resolvedFilename); + m_filenameMap.insert(std::make_pair(level, resolvedFilename)); + m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(fs))); + m_logStreamsReference->insert(std::make_pair(resolvedFilename, base::FileStreamPtr(m_fileStreamMap.at(level)))); + } else { + // Woops! we have an existing one, share it! + m_filenameMap.insert(std::make_pair(level, filestreamIter->first)); + m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(filestreamIter->second))); + fs = filestreamIter->second.get(); + } + if (fs == nullptr) { + // We display bad file error from newFileStream() + ELPP_INTERNAL_ERROR("Setting [TO_FILE] of [" + << LevelHelper::convertToString(level) << "] to FALSE", false); + setValue(level, false, &m_toFileMap); + } + }; + // If we dont have file conf for any level, create it for Level::Global first + // otherwise create for specified level + create(m_filenameMap.empty() && m_fileStreamMap.empty() ? Level::Global : level); +} + +bool TypedConfigurations::unsafeValidateFileRolling(Level level, const PreRollOutCallback& preRollOutCallback) { + base::type::fstream_t* fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get(); + if (fs == nullptr) { + return true; + } + std::size_t maxLogFileSize = unsafeGetConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); + std::size_t currFileSize = base::utils::File::getSizeOfFile(fs); + if (maxLogFileSize != 0 && currFileSize >= maxLogFileSize) { + std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename"); + ELPP_INTERNAL_INFO(1, "Truncating log file [" << fname << "] as a result of configurations for level [" + << LevelHelper::convertToString(level) << "]"); + fs->close(); + preRollOutCallback(fname.c_str(), currFileSize); + fs->open(fname, std::fstream::out | std::fstream::trunc); + return true; + } + return false; +} + +// RegisteredHitCounters + +bool RegisteredHitCounters::validateEveryN(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + counter->validateHitCounts(n); + bool result = (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0); + return result; +} + +/// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one +/// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned +bool RegisteredHitCounters::validateAfterN(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + // Do not use validateHitCounts here since we do not want to reset counter here + // Note the >= instead of > because we are incrementing + // after this check + if (counter->hitCounts() >= n) + return true; + counter->increment(); + return false; +} + +/// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one +/// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned +bool RegisteredHitCounters::validateNTimes(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + counter->increment(); + // Do not use validateHitCounts here since we do not want to reset counter here + if (counter->hitCounts() <= n) + return true; + return false; +} + +// RegisteredLoggers + +RegisteredLoggers::RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder) : + m_defaultLogBuilder(defaultLogBuilder) { + m_defaultConfigurations.setToDefault(); + m_logStreamsReference = std::make_shared(); +} + +Logger* RegisteredLoggers::get(const std::string& id, bool forceCreation) { + base::threading::ScopedLock scopedLock(lock()); + Logger* logger_ = base::utils::Registry::get(id); + if (logger_ == nullptr && forceCreation) { + bool validId = Logger::isValidId(id); + if (!validId) { + ELPP_ASSERT(validId, "Invalid logger ID [" << id << "]. Not registering this logger."); + return nullptr; + } + logger_ = new Logger(id, m_defaultConfigurations, m_logStreamsReference); + logger_->m_logBuilder = m_defaultLogBuilder; + registerNew(id, logger_); + LoggerRegistrationCallback* callback = nullptr; + for (const std::pair& h + : m_loggerRegistrationCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + callback->handle(logger_); + } + } + } + return logger_; +} + +bool RegisteredLoggers::remove(const std::string& id) { + if (id == base::consts::kDefaultLoggerId) { + return false; + } + // get has internal lock + Logger* logger = base::utils::Registry::get(id); + if (logger != nullptr) { + // unregister has internal lock + unregister(logger); + } + return true; +} + +void RegisteredLoggers::unsafeFlushAll(void) { + ELPP_INTERNAL_INFO(1, "Flushing all log files"); + for (base::LogStreamsReferenceMap::iterator it = m_logStreamsReference->begin(); + it != m_logStreamsReference->end(); ++it) { + if (it->second.get() == nullptr) continue; + it->second->flush(); + } +} + +// VRegistry + +VRegistry::VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags) : m_level(level), m_pFlags(pFlags) { +} + +/// @brief Sets verbose level. Accepted range is 0-9 +void VRegistry::setLevel(base::type::VerboseLevel level) { + base::threading::ScopedLock scopedLock(lock()); + if (level > 9) + m_level = base::consts::kMaxVerboseLevel; + else + m_level = level; +} + +void VRegistry::setModules(const char* modules) { + base::threading::ScopedLock scopedLock(lock()); + auto addSuffix = [](std::stringstream& ss, const char* sfx, const char* prev) { + if (prev != nullptr && base::utils::Str::endsWith(ss.str(), std::string(prev))) { + std::string chr(ss.str().substr(0, ss.str().size() - strlen(prev))); + ss.str(std::string("")); + ss << chr; + } + if (base::utils::Str::endsWith(ss.str(), std::string(sfx))) { + std::string chr(ss.str().substr(0, ss.str().size() - strlen(sfx))); + ss.str(std::string("")); + ss << chr; + } + ss << sfx; + }; + auto insert = [&](std::stringstream& ss, base::type::VerboseLevel level) { + if (!base::utils::hasFlag(LoggingFlag::DisableVModulesExtensions, *m_pFlags)) { + addSuffix(ss, ".h", nullptr); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".c", ".h"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cpp", ".c"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cc", ".cpp"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cxx", ".cc"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".-inl.h", ".cxx"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hxx", ".-inl.h"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hpp", ".hxx"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hh", ".hpp"); + } + m_modules.insert(std::make_pair(ss.str(), level)); + }; + bool isMod = true; + bool isLevel = false; + std::stringstream ss; + int level = -1; + for (; *modules; ++modules) { + switch (*modules) { + case '=': + isLevel = true; + isMod = false; + break; + case ',': + isLevel = false; + isMod = true; + if (!ss.str().empty() && level != -1) { + insert(ss, static_cast(level)); + ss.str(std::string("")); + level = -1; + } + break; + default: + if (isMod) { + ss << *modules; + } else if (isLevel) { + if (isdigit(*modules)) { + level = static_cast(*modules) - 48; + } + } + break; + } + } + if (!ss.str().empty() && level != -1) { + insert(ss, static_cast(level)); + } +} + +bool VRegistry::allowed(base::type::VerboseLevel vlevel, const char* file) { + base::threading::ScopedLock scopedLock(lock()); + if (m_modules.empty() || file == nullptr) { + return vlevel <= m_level; + } else { + char baseFilename[base::consts::kSourceFilenameMaxLength] = ""; + base::utils::File::buildBaseFilename(file, baseFilename); + std::unordered_map::iterator it = m_modules.begin(); + for (; it != m_modules.end(); ++it) { + if (base::utils::Str::wildCardMatch(baseFilename, it->first.c_str())) { + return vlevel <= it->second; + } + } + if (base::utils::hasFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified, *m_pFlags)) { + return true; + } + return false; + } +} + +void VRegistry::setFromArgs(const base::utils::CommandLineArgs* commandLineArgs) { + if (commandLineArgs->hasParam("-v") || commandLineArgs->hasParam("--verbose") || + commandLineArgs->hasParam("-V") || commandLineArgs->hasParam("--VERBOSE")) { + setLevel(base::consts::kMaxVerboseLevel); + } else if (commandLineArgs->hasParamWithValue("--v")) { + setLevel(static_cast(atoi(commandLineArgs->getParamValue("--v")))); + } else if (commandLineArgs->hasParamWithValue("--V")) { + setLevel(static_cast(atoi(commandLineArgs->getParamValue("--V")))); + } else if ((commandLineArgs->hasParamWithValue("-vmodule")) && vModulesEnabled()) { + setModules(commandLineArgs->getParamValue("-vmodule")); + } else if (commandLineArgs->hasParamWithValue("-VMODULE") && vModulesEnabled()) { + setModules(commandLineArgs->getParamValue("-VMODULE")); + } +} + +#if !defined(ELPP_DEFAULT_LOGGING_FLAGS) +# define ELPP_DEFAULT_LOGGING_FLAGS 0x0 +#endif // !defined(ELPP_DEFAULT_LOGGING_FLAGS) +// Storage +#if ELPP_ASYNC_LOGGING +Storage::Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) : +#else +Storage::Storage(const LogBuilderPtr& defaultLogBuilder) : +#endif // ELPP_ASYNC_LOGGING + m_registeredHitCounters(new base::RegisteredHitCounters()), + m_registeredLoggers(new base::RegisteredLoggers(defaultLogBuilder)), + m_flags(ELPP_DEFAULT_LOGGING_FLAGS), + m_vRegistry(new base::VRegistry(0, &m_flags)), + +#if ELPP_ASYNC_LOGGING + m_asyncLogQueue(new base::AsyncLogQueue()), + m_asyncDispatchWorker(asyncDispatchWorker), +#endif // ELPP_ASYNC_LOGGING + + m_preRollOutCallback(base::defaultPreRollOutCallback) { + // Register default logger + m_registeredLoggers->get(std::string(base::consts::kDefaultLoggerId)); + // We register default logger anyway (worse case it's not going to register) just in case + m_registeredLoggers->get("default"); + +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + // Register performance logger and reconfigure format + Logger* performanceLogger = m_registeredLoggers->get(std::string(base::consts::kPerformanceLoggerId)); + m_registeredLoggers->get("performance"); + performanceLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%datetime %level %msg")); + performanceLogger->reconfigure(); +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + +#if defined(ELPP_SYSLOG) + // Register syslog logger and reconfigure format + Logger* sysLogLogger = m_registeredLoggers->get(std::string(base::consts::kSysLogLoggerId)); + sysLogLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%level: %msg")); + sysLogLogger->reconfigure(); +#endif // defined(ELPP_SYSLOG) + addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified); +#if ELPP_ASYNC_LOGGING + installLogDispatchCallback(std::string("AsyncLogDispatchCallback")); +#else + installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); +#endif // ELPP_ASYNC_LOGGING +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + installPerformanceTrackingCallback + (std::string("DefaultPerformanceTrackingCallback")); +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + ELPP_INTERNAL_INFO(1, "Easylogging++ has been initialized"); +#if ELPP_ASYNC_LOGGING + m_asyncDispatchWorker->start(); +#endif // ELPP_ASYNC_LOGGING +} + +Storage::~Storage(void) { + ELPP_INTERNAL_INFO(4, "Destroying storage"); +#if ELPP_ASYNC_LOGGING + ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous"); + uninstallLogDispatchCallback(std::string("AsyncLogDispatchCallback")); + installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); + ELPP_INTERNAL_INFO(5, "Destroying asyncDispatchWorker"); + base::utils::safeDelete(m_asyncDispatchWorker); + ELPP_INTERNAL_INFO(5, "Destroying asyncLogQueue"); + base::utils::safeDelete(m_asyncLogQueue); +#endif // ELPP_ASYNC_LOGGING + ELPP_INTERNAL_INFO(5, "Destroying registeredHitCounters"); + base::utils::safeDelete(m_registeredHitCounters); + ELPP_INTERNAL_INFO(5, "Destroying registeredLoggers"); + base::utils::safeDelete(m_registeredLoggers); + ELPP_INTERNAL_INFO(5, "Destroying vRegistry"); + base::utils::safeDelete(m_vRegistry); +} + +bool Storage::hasCustomFormatSpecifier(const char* formatSpecifier) { + base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); + return std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(), + formatSpecifier) != m_customFormatSpecifiers.end(); +} + +void Storage::installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { + if (hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier())) { + return; + } + base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); + m_customFormatSpecifiers.push_back(customFormatSpecifier); +} + +bool Storage::uninstallCustomFormatSpecifier(const char* formatSpecifier) { + base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); + std::vector::iterator it = std::find(m_customFormatSpecifiers.begin(), + m_customFormatSpecifiers.end(), formatSpecifier); + if (it != m_customFormatSpecifiers.end() && strcmp(formatSpecifier, it->formatSpecifier()) == 0) { + m_customFormatSpecifiers.erase(it); + return true; + } + return false; +} + +void Storage::setApplicationArguments(int argc, char** argv) { + m_commandLineArgs.setArgs(argc, argv); + m_vRegistry->setFromArgs(commandLineArgs()); + // default log file +#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) + if (m_commandLineArgs.hasParamWithValue(base::consts::kDefaultLogFileParam)) { + Configurations c; + c.setGlobally(ConfigurationType::Filename, + std::string(m_commandLineArgs.getParamValue(base::consts::kDefaultLogFileParam))); + registeredLoggers()->setDefaultConfigurations(c); + for (base::RegisteredLoggers::iterator it = registeredLoggers()->begin(); + it != registeredLoggers()->end(); ++it) { + it->second->configure(c); + } + } +#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) + if (m_commandLineArgs.hasParamWithValue(base::consts::kLoggingFlagsParam)) { + int userInput = atoi(m_commandLineArgs.getParamValue(base::consts::kLoggingFlagsParam)); + if (ELPP_DEFAULT_LOGGING_FLAGS == 0x0) { + m_flags = userInput; + } else { + base::utils::addFlag(userInput, &m_flags); + } + } +#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) +} + +} // namespace base + +// LogDispatchCallback +#if defined(ELPP_THREAD_SAFE) +void LogDispatchCallback::handle(const LogDispatchData* data) { + base::threading::ScopedLock scopedLock(m_fileLocksMapLock); + std::string filename = data->logMessage()->logger()->typedConfigurations()->filename(data->logMessage()->level()); + auto lock = m_fileLocks.find(filename); + if (lock == m_fileLocks.end()) { + m_fileLocks.emplace(std::make_pair(filename, std::unique_ptr(new base::threading::Mutex))); + } +} +#else +void LogDispatchCallback::handle(const LogDispatchData* /*data*/) {} +#endif + +base::threading::Mutex& LogDispatchCallback::fileHandle(const LogDispatchData* data) { + auto it = m_fileLocks.find(data->logMessage()->logger()->typedConfigurations()->filename(data->logMessage()->level())); + return *(it->second.get()); +} + +namespace base { +// DefaultLogDispatchCallback + +void DefaultLogDispatchCallback::handle(const LogDispatchData* data) { +#if defined(ELPP_THREAD_SAFE) + LogDispatchCallback::handle(data); + base::threading::ScopedLock scopedLock(fileHandle(data)); +#endif + m_data = data; + dispatch(m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(), + m_data->dispatchAction() == base::DispatchAction::NormalLog)); +} + +void DefaultLogDispatchCallback::dispatch(base::type::string_t&& logLine) { + if (m_data->dispatchAction() == base::DispatchAction::NormalLog) { + if (m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level())) { + base::type::fstream_t* fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream( + m_data->logMessage()->level()); + if (fs != nullptr) { + fs->write(logLine.c_str(), logLine.size()); + if (fs->fail()) { + ELPP_INTERNAL_ERROR("Unable to write log to file [" + << m_data->logMessage()->logger()->m_typedConfigurations->filename(m_data->logMessage()->level()) << "].\n" + << "Few possible reasons (could be something else):\n" << " * Permission denied\n" + << " * Disk full\n" << " * Disk is not writable", true); + } else { + if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) + || (m_data->logMessage()->logger()->isFlushNeeded(m_data->logMessage()->level()))) { + m_data->logMessage()->logger()->flush(m_data->logMessage()->level(), fs); + } + } + } else { + ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(m_data->logMessage()->level()) << "] " + << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " + << m_data->logMessage()->logger()->id() << "]", false); + } + } + if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) { + if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) + m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level()); + ELPP_COUT << ELPP_COUT_LINE(logLine); + } + } +#if defined(ELPP_SYSLOG) + else if (m_data->dispatchAction() == base::DispatchAction::SysLog) { + // Determine syslog priority + int sysLogPriority = 0; + if (m_data->logMessage()->level() == Level::Fatal) + sysLogPriority = LOG_EMERG; + else if (m_data->logMessage()->level() == Level::Error) + sysLogPriority = LOG_ERR; + else if (m_data->logMessage()->level() == Level::Warning) + sysLogPriority = LOG_WARNING; + else if (m_data->logMessage()->level() == Level::Info) + sysLogPriority = LOG_INFO; + else if (m_data->logMessage()->level() == Level::Debug) + sysLogPriority = LOG_DEBUG; + else + sysLogPriority = LOG_NOTICE; +# if defined(ELPP_UNICODE) + char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); + syslog(sysLogPriority, "%s", line); + free(line); +# else + syslog(sysLogPriority, "%s", logLine.c_str()); +# endif + } +#endif // defined(ELPP_SYSLOG) +} + +#if ELPP_ASYNC_LOGGING + +// AsyncLogDispatchCallback + +void AsyncLogDispatchCallback::handle(const LogDispatchData* data) { + base::type::string_t logLine = data->logMessage()->logger()->logBuilder()->build(data->logMessage(), + data->dispatchAction() == base::DispatchAction::NormalLog); + if (data->dispatchAction() == base::DispatchAction::NormalLog + && data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level())) { + if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) + data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level()); + ELPP_COUT << ELPP_COUT_LINE(logLine); + } + // Save resources and only queue if we want to write to file otherwise just ignore handler + if (data->logMessage()->logger()->typedConfigurations()->toFile(data->logMessage()->level())) { + ELPP->asyncLogQueue()->push(AsyncLogItem(*(data->logMessage()), *data, logLine)); + } +} + +// AsyncDispatchWorker +AsyncDispatchWorker::AsyncDispatchWorker() { + setContinueRunning(false); +} + +AsyncDispatchWorker::~AsyncDispatchWorker() { + setContinueRunning(false); + ELPP_INTERNAL_INFO(6, "Stopping dispatch worker - Cleaning log queue"); + clean(); + ELPP_INTERNAL_INFO(6, "Log queue cleaned"); +} + +bool AsyncDispatchWorker::clean(void) { + std::mutex m; + std::unique_lock lk(m); + cv.wait(lk, [] { return !ELPP->asyncLogQueue()->empty(); }); + emptyQueue(); + lk.unlock(); + cv.notify_one(); + return ELPP->asyncLogQueue()->empty(); +} + +void AsyncDispatchWorker::emptyQueue(void) { + while (!ELPP->asyncLogQueue()->empty()) { + AsyncLogItem data = ELPP->asyncLogQueue()->next(); + handle(&data); + base::threading::msleep(100); + } +} + +void AsyncDispatchWorker::start(void) { + base::threading::msleep(5000); // 5s (why?) + setContinueRunning(true); + std::thread t1(&AsyncDispatchWorker::run, this); + t1.join(); +} + +void AsyncDispatchWorker::handle(AsyncLogItem* logItem) { + LogDispatchData* data = logItem->data(); + LogMessage* logMessage = logItem->logMessage(); + Logger* logger = logMessage->logger(); + base::TypedConfigurations* conf = logger->typedConfigurations(); + base::type::string_t logLine = logItem->logLine(); + if (data->dispatchAction() == base::DispatchAction::NormalLog) { + if (conf->toFile(logMessage->level())) { + base::type::fstream_t* fs = conf->fileStream(logMessage->level()); + if (fs != nullptr) { + fs->write(logLine.c_str(), logLine.size()); + if (fs->fail()) { + ELPP_INTERNAL_ERROR("Unable to write log to file [" + << conf->filename(logMessage->level()) << "].\n" + << "Few possible reasons (could be something else):\n" << " * Permission denied\n" + << " * Disk full\n" << " * Disk is not writable", true); + } else { + if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (logger->isFlushNeeded(logMessage->level()))) { + logger->flush(logMessage->level(), fs); + } + } + } else { + ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(logMessage->level()) << "] " + << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " << logger->id() << "]", false); + } + } + } +# if defined(ELPP_SYSLOG) + else if (data->dispatchAction() == base::DispatchAction::SysLog) { + // Determine syslog priority + int sysLogPriority = 0; + if (logMessage->level() == Level::Fatal) + sysLogPriority = LOG_EMERG; + else if (logMessage->level() == Level::Error) + sysLogPriority = LOG_ERR; + else if (logMessage->level() == Level::Warning) + sysLogPriority = LOG_WARNING; + else if (logMessage->level() == Level::Info) + sysLogPriority = LOG_INFO; + else if (logMessage->level() == Level::Debug) + sysLogPriority = LOG_DEBUG; + else + sysLogPriority = LOG_NOTICE; +# if defined(ELPP_UNICODE) + char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); + syslog(sysLogPriority, "%s", line); + free(line); +# else + syslog(sysLogPriority, "%s", logLine.c_str()); +# endif + } +# endif // defined(ELPP_SYSLOG) +} + +void AsyncDispatchWorker::run(void) { + while (continueRunning()) { + emptyQueue(); + base::threading::msleep(10); // 10ms + } +} +#endif // ELPP_ASYNC_LOGGING + +// DefaultLogBuilder + +base::type::string_t DefaultLogBuilder::build(const LogMessage* logMessage, bool appendNewLine) const { + base::TypedConfigurations* tc = logMessage->logger()->typedConfigurations(); + const base::LogFormat* logFormat = &tc->logFormat(logMessage->level()); + base::type::string_t logLine = logFormat->format(); + char buff[base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength] = ""; + const char* bufLim = buff + sizeof(buff); + if (logFormat->hasFlag(base::FormatFlags::AppName)) { + // App name + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kAppNameFormatSpecifier, + logMessage->logger()->parentApplicationName()); + } + if (logFormat->hasFlag(base::FormatFlags::ThreadId)) { + // Thread ID + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kThreadIdFormatSpecifier, + ELPP->getThreadName(base::threading::getCurrentThreadId())); + } + if (logFormat->hasFlag(base::FormatFlags::DateTime)) { + // DateTime + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kDateTimeFormatSpecifier, + base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), + &tc->subsecondPrecision(logMessage->level()))); + } + if (logFormat->hasFlag(base::FormatFlags::Function)) { + // Function + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFunctionFormatSpecifier, logMessage->func()); + } + if (logFormat->hasFlag(base::FormatFlags::File)) { + // File + base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); + base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::FileBase)) { + // FileBase + base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); + base::utils::File::buildBaseFilename(logMessage->file(), buff); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileBaseFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::Line)) { + // Line + char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceLineMaxLength); + buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), base::consts::kSourceLineMaxLength, buf, bufLim, false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLineFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::Location)) { + // Location + char* buf = base::utils::Str::clearBuff(buff, + base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength); + base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); + buf = base::utils::Str::addToBuff(buff, buf, bufLim); + buf = base::utils::Str::addToBuff(":", buf, bufLim); + buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), base::consts::kSourceLineMaxLength, buf, bufLim, + false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLocationFormatSpecifier, std::string(buff)); + } + if (logMessage->level() == Level::Verbose && logFormat->hasFlag(base::FormatFlags::VerboseLevel)) { + // Verbose level + char* buf = base::utils::Str::clearBuff(buff, 1); + buf = base::utils::Str::convertAndAddToBuff(logMessage->verboseLevel(), 1, buf, bufLim, false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kVerboseLevelFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::LogMessage)) { + // Log message + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kMessageFormatSpecifier, logMessage->message()); + } +#if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) + el::base::threading::ScopedLock lock_(ELPP->customFormatSpecifiersLock()); + ELPP_UNUSED(lock_); + for (std::vector::const_iterator it = ELPP->customFormatSpecifiers()->begin(); + it != ELPP->customFormatSpecifiers()->end(); ++it) { + std::string fs(it->formatSpecifier()); + base::type::string_t wcsFormatSpecifier(fs.begin(), fs.end()); + base::utils::Str::replaceFirstWithEscape(logLine, wcsFormatSpecifier, it->resolver()(logMessage)); + } +#endif // !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) + if (appendNewLine) logLine += ELPP_LITERAL("\n"); + return logLine; +} + +// LogDispatcher + +void LogDispatcher::dispatch(void) { + if (m_proceed && m_dispatchAction == base::DispatchAction::None) { + m_proceed = false; + } + if (!m_proceed) { + return; + } +#ifndef ELPP_NO_GLOBAL_LOCK + // see https://github.com/muflihun/easyloggingpp/issues/580 + // global lock is turned on by default unless + // ELPP_NO_GLOBAL_LOCK is defined + base::threading::ScopedLock scopedLock(ELPP->lock()); +#endif + base::TypedConfigurations* tc = m_logMessage->logger()->m_typedConfigurations; + if (ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck)) { + tc->validateFileRolling(m_logMessage->level(), ELPP->preRollOutCallback()); + } + LogDispatchCallback* callback = nullptr; + LogDispatchData data; + for (const std::pair& h + : ELPP->m_logDispatchCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + data.setLogMessage(m_logMessage); + data.setDispatchAction(m_dispatchAction); + callback->handle(&data); + } + } +} + +// MessageBuilder + +void MessageBuilder::initialize(Logger* logger) { + m_logger = logger; + m_containerLogSeparator = ELPP->hasFlag(LoggingFlag::NewLineForContainer) ? + ELPP_LITERAL("\n ") : ELPP_LITERAL(", "); +} + +MessageBuilder& MessageBuilder::operator<<(const wchar_t* msg) { + if (msg == nullptr) { + m_logger->stream() << base::consts::kNullPointer; + return *this; + } +# if defined(ELPP_UNICODE) + m_logger->stream() << msg; +# else + char* buff_ = base::utils::Str::wcharPtrToCharPtr(msg); + m_logger->stream() << buff_; + free(buff_); +# endif + if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { + m_logger->stream() << " "; + } + return *this; +} + +// Writer + +Writer& Writer::construct(Logger* logger, bool needLock) { + m_logger = logger; + initializeLogger(logger->id(), false, needLock); + m_messageBuilder.initialize(m_logger); + return *this; +} + +Writer& Writer::construct(int count, const char* loggerIds, ...) { + if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { + va_list loggersList; + va_start(loggersList, loggerIds); + const char* id = loggerIds; + m_loggerIds.reserve(count); + for (int i = 0; i < count; ++i) { + m_loggerIds.push_back(std::string(id)); + id = va_arg(loggersList, const char*); + } + va_end(loggersList); + initializeLogger(m_loggerIds.at(0)); + } else { + initializeLogger(std::string(loggerIds)); + } + m_messageBuilder.initialize(m_logger); + return *this; +} + +void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool needLock) { + if (lookup) { + m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)); + } + if (m_logger == nullptr) { + { + if (!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId))) { + // Somehow default logger has been unregistered. Not good! Register again + ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId)); + } + } + Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) + << "Logger [" << loggerId << "] is not registered yet!"; + m_proceed = false; + } else { + if (needLock) { + m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because + // m_proceed can be changed by lines below + } + if (ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) { + m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) : + LevelHelper::castToInt(m_level) >= LevelHelper::castToInt(ELPP->m_loggingLevel); + } else { + m_proceed = m_logger->enabled(m_level); + } + } +} + +void Writer::processDispatch() { +#if ELPP_LOGGING_ENABLED + if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { + bool firstDispatched = false; + base::type::string_t logMessage; + std::size_t i = 0; + do { + if (m_proceed) { + if (firstDispatched) { + m_logger->stream() << logMessage; + } else { + firstDispatched = true; + if (m_loggerIds.size() > 1) { + logMessage = m_logger->stream().str(); + } + } + triggerDispatch(); + } else if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + if (i + 1 < m_loggerIds.size()) { + initializeLogger(m_loggerIds.at(i + 1)); + } + } while (++i < m_loggerIds.size()); + } else { + if (m_proceed) { + triggerDispatch(); + } else if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + } +#else + if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } +#endif // ELPP_LOGGING_ENABLED +} + +void Writer::triggerDispatch(void) { + try { + if (m_proceed) { + if (m_msg == nullptr) { + LogMessage msg(m_level, m_file, m_line, m_func, m_verboseLevel, + m_logger); + base::LogDispatcher(m_proceed, &msg, m_dispatchAction).dispatch(); + } else { + base::LogDispatcher(m_proceed, m_msg, m_dispatchAction).dispatch(); + } + } + if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + if (m_proceed && m_level == Level::Fatal + && !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) { + base::Writer(Level::Warning, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) + << "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]"; + std::stringstream reasonStream; + reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]" + << " If you wish to disable 'abort on fatal log' please use " + << "el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)"; + base::utils::abort(1, reasonStream.str()); + } + m_proceed = false; + } + catch(std::exception & ex){ + // Extremely low memory situation; don't let exception be unhandled. + } +} + +// PErrorWriter + +PErrorWriter::~PErrorWriter(void) { + if (m_proceed) { +#if ELPP_COMPILER_MSVC + char buff[256]; + strerror_s(buff, 256, errno); + m_logger->stream() << ": " << buff << " [" << errno << "]"; +#else + m_logger->stream() << ": " << strerror(errno) << " [" << errno << "]"; +#endif + } +} + +// PerformanceTracker + +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + +PerformanceTracker::PerformanceTracker(const std::string& blockName, + base::TimestampUnit timestampUnit, + const std::string& loggerId, + bool scopedLog, Level level) : + m_blockName(blockName), m_timestampUnit(timestampUnit), m_loggerId(loggerId), m_scopedLog(scopedLog), + m_level(level), m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false) { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + // We store it locally so that if user happen to change configuration by the end of scope + // or before calling checkpoint, we still depend on state of configuration at time of construction + el::Logger* loggerPtr = ELPP->registeredLoggers()->get(loggerId, false); + m_enabled = loggerPtr != nullptr && loggerPtr->m_typedConfigurations->performanceTracking(m_level); + if (m_enabled) { + base::utils::DateTime::gettimeofday(&m_startTime); + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED +} + +PerformanceTracker::~PerformanceTracker(void) { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + if (m_enabled) { + base::threading::ScopedLock scopedLock(lock()); + if (m_scopedLog) { + base::utils::DateTime::gettimeofday(&m_endTime); + base::type::string_t formattedTime = getFormattedTimeTaken(); + PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete); + data.init(this); + data.m_formattedTimeTaken = formattedTime; + PerformanceTrackingCallback* callback = nullptr; + for (const std::pair& h + : ELPP->m_performanceTrackingCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + callback->handle(&data); + } + } + } + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) +} + +void PerformanceTracker::checkpoint(const std::string& id, const char* file, base::type::LineNumber line, + const char* func) { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + if (m_enabled) { + base::threading::ScopedLock scopedLock(lock()); + base::utils::DateTime::gettimeofday(&m_endTime); + base::type::string_t formattedTime = m_hasChecked ? getFormattedTimeTaken(m_lastCheckpointTime) : ELPP_LITERAL(""); + PerformanceTrackingData data(PerformanceTrackingData::DataType::Checkpoint); + data.init(this); + data.m_checkpointId = id; + data.m_file = file; + data.m_line = line; + data.m_func = func; + data.m_formattedTimeTaken = formattedTime; + PerformanceTrackingCallback* callback = nullptr; + for (const std::pair& h + : ELPP->m_performanceTrackingCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + callback->handle(&data); + } + } + base::utils::DateTime::gettimeofday(&m_lastCheckpointTime); + m_hasChecked = true; + m_lastCheckpointId = id; + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + ELPP_UNUSED(id); + ELPP_UNUSED(file); + ELPP_UNUSED(line); + ELPP_UNUSED(func); +} + +const base::type::string_t PerformanceTracker::getFormattedTimeTaken(struct timeval startTime) const { + if (ELPP->hasFlag(LoggingFlag::FixedTimeFormat)) { + base::type::stringstream_t ss; + ss << base::utils::DateTime::getTimeDifference(m_endTime, + startTime, m_timestampUnit) << " " << base::consts::kTimeFormats[static_cast + (m_timestampUnit)].unit; + return ss.str(); + } + return base::utils::DateTime::formatTime(base::utils::DateTime::getTimeDifference(m_endTime, + startTime, m_timestampUnit), m_timestampUnit); +} + +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + +namespace debug { +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) + +// StackTrace + +StackTrace::StackTraceEntry::StackTraceEntry(std::size_t index, const std::string& loc, const std::string& demang, + const std::string& hex, + const std::string& addr) : + m_index(index), + m_location(loc), + m_demangled(demang), + m_hex(hex), + m_addr(addr) { +} + +std::ostream& operator<<(std::ostream& ss, const StackTrace::StackTraceEntry& si) { + ss << "[" << si.m_index << "] " << si.m_location << (si.m_hex.empty() ? "" : "+") << si.m_hex << " " << si.m_addr << + (si.m_demangled.empty() ? "" : ":") << si.m_demangled; + return ss; +} + +std::ostream& operator<<(std::ostream& os, const StackTrace& st) { + std::vector::const_iterator it = st.m_stack.begin(); + while (it != st.m_stack.end()) { + os << " " << *it++ << "\n"; + } + return os; +} + +void StackTrace::generateNew(void) { +#ifdef HAVE_EXECINFO + m_stack.clear(); + void* stack[kMaxStack]; + unsigned int size = backtrace(stack, kMaxStack); + char** strings = backtrace_symbols(stack, size); + if (size > kStackStart) { // Skip StackTrace c'tor and generateNew + for (std::size_t i = kStackStart; i < size; ++i) { + std::string mangName; + std::string location; + std::string hex; + std::string addr; + + // entry: 2 crash.cpp.bin 0x0000000101552be5 _ZN2el4base5debug10StackTraceC1Ev + 21 + const std::string line(strings[i]); + auto p = line.find("_"); + if (p != std::string::npos) { + mangName = line.substr(p); + mangName = mangName.substr(0, mangName.find(" +")); + } + p = line.find("0x"); + if (p != std::string::npos) { + addr = line.substr(p); + addr = addr.substr(0, addr.find("_")); + } + // Perform demangling if parsed properly + if (!mangName.empty()) { + int status = 0; + char* demangName = abi::__cxa_demangle(mangName.data(), 0, 0, &status); + // if demangling is successful, output the demangled function name + if (status == 0) { + // Success (see http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html) + StackTraceEntry entry(i - 1, location, demangName, hex, addr); + m_stack.push_back(entry); + } else { + // Not successful - we will use mangled name + StackTraceEntry entry(i - 1, location, mangName, hex, addr); + m_stack.push_back(entry); + } + free(demangName); + } else { + StackTraceEntry entry(i - 1, line); + m_stack.push_back(entry); + } + } + } + free(strings); +#else + ELPP_INTERNAL_INFO(1, "Stacktrace generation not supported for selected compiler"); +#endif // ELPP_STACKTRACE +} + +// Static helper functions + +static std::string crashReason(int sig) { + std::stringstream ss; + bool foundReason = false; + for (int i = 0; i < base::consts::kCrashSignalsCount; ++i) { + if (base::consts::kCrashSignals[i].numb == sig) { + ss << "Application has crashed due to [" << base::consts::kCrashSignals[i].name << "] signal"; + if (ELPP->hasFlag(el::LoggingFlag::LogDetailedCrashReason)) { + ss << std::endl << + " " << base::consts::kCrashSignals[i].brief << std::endl << + " " << base::consts::kCrashSignals[i].detail; + } + foundReason = true; + } + } + if (!foundReason) { + ss << "Application has crashed due to unknown signal [" << sig << "]"; + } + return ss.str(); +} +/// @brief Logs reason of crash from sig +static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger) { + if (sig == SIGINT && ELPP->hasFlag(el::LoggingFlag::IgnoreSigInt)) { + return; + } + std::stringstream ss; + ss << "CRASH HANDLED; "; + ss << crashReason(sig); +#if ELPP_STACKTRACE + if (stackTraceIfAvailable) { + ss << std::endl << " ======= Backtrace: =========" << std::endl << base::debug::StackTrace(); + } +#else + ELPP_UNUSED(stackTraceIfAvailable); +#endif // ELPP_STACKTRACE + ELPP_WRITE_LOG(el::base::Writer, level, base::DispatchAction::NormalLog, logger) << ss.str(); +} + +static inline void crashAbort(int sig) { + base::utils::abort(sig, std::string()); +} + +/// @brief Default application crash handler +/// +/// @detail This function writes log using 'default' logger, prints stack trace for GCC based compilers and aborts program. +static inline void defaultCrashHandler(int sig) { + base::debug::logCrashReason(sig, true, Level::Fatal, base::consts::kDefaultLoggerId); + base::debug::crashAbort(sig); +} + +// CrashHandler + +CrashHandler::CrashHandler(bool useDefault) { + if (useDefault) { + setHandler(defaultCrashHandler); + } +} + +void CrashHandler::setHandler(const Handler& cHandler) { + m_handler = cHandler; +#if defined(ELPP_HANDLE_SIGABRT) + int i = 0; // SIGABRT is at base::consts::kCrashSignals[0] +#else + int i = 1; +#endif // defined(ELPP_HANDLE_SIGABRT) + for (; i < base::consts::kCrashSignalsCount; ++i) { + m_handler = signal(base::consts::kCrashSignals[i].numb, cHandler); + } +} + +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) +} // namespace debug +} // namespace base + +// el + +// Helpers + +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) + +void Helpers::crashAbort(int sig, const char* sourceFile, unsigned int long line) { + std::stringstream ss; + ss << base::debug::crashReason(sig).c_str(); + ss << " - [Called el::Helpers::crashAbort(" << sig << ")]"; + if (sourceFile != nullptr && strlen(sourceFile) > 0) { + ss << " - Source: " << sourceFile; + if (line > 0) + ss << ":" << line; + else + ss << " (line number not specified)"; + } + base::utils::abort(sig, ss.str()); +} + +void Helpers::logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger) { + el::base::debug::logCrashReason(sig, stackTraceIfAvailable, level, logger); +} + +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) + +// Loggers + +Logger* Loggers::getLogger(const std::string& identity, bool registerIfNotAvailable) { + return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable); +} + +void Loggers::setDefaultLogBuilder(el::LogBuilderPtr& logBuilderPtr) { + ELPP->registeredLoggers()->setDefaultLogBuilder(logBuilderPtr); +} + +bool Loggers::unregisterLogger(const std::string& identity) { + return ELPP->registeredLoggers()->remove(identity); +} + +bool Loggers::hasLogger(const std::string& identity) { + return ELPP->registeredLoggers()->has(identity); +} + +Logger* Loggers::reconfigureLogger(Logger* logger, const Configurations& configurations) { + if (!logger) return nullptr; + logger->configure(configurations); + return logger; +} + +Logger* Loggers::reconfigureLogger(const std::string& identity, const Configurations& configurations) { + return Loggers::reconfigureLogger(Loggers::getLogger(identity), configurations); +} + +Logger* Loggers::reconfigureLogger(const std::string& identity, ConfigurationType configurationType, + const std::string& value) { + Logger* logger = Loggers::getLogger(identity); + if (logger == nullptr) { + return nullptr; + } + logger->configurations()->set(Level::Global, configurationType, value); + logger->reconfigure(); + return logger; +} + +void Loggers::reconfigureAllLoggers(const Configurations& configurations) { + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); + it != ELPP->registeredLoggers()->end(); ++it) { + Loggers::reconfigureLogger(it->second, configurations); + } +} + +void Loggers::reconfigureAllLoggers(Level level, ConfigurationType configurationType, + const std::string& value) { + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); + it != ELPP->registeredLoggers()->end(); ++it) { + Logger* logger = it->second; + logger->configurations()->set(level, configurationType, value); + logger->reconfigure(); + } +} + +void Loggers::setDefaultConfigurations(const Configurations& configurations, bool reconfigureExistingLoggers) { + ELPP->registeredLoggers()->setDefaultConfigurations(configurations); + if (reconfigureExistingLoggers) { + Loggers::reconfigureAllLoggers(configurations); + } +} + +const Configurations* Loggers::defaultConfigurations(void) { + return ELPP->registeredLoggers()->defaultConfigurations(); +} + +const base::LogStreamsReferenceMapPtr Loggers::logStreamsReference(void) { + return ELPP->registeredLoggers()->logStreamsReference(); +} + +base::TypedConfigurations Loggers::defaultTypedConfigurations(void) { + return base::TypedConfigurations( + ELPP->registeredLoggers()->defaultConfigurations(), + ELPP->registeredLoggers()->logStreamsReference()); +} + +std::vector* Loggers::populateAllLoggerIds(std::vector* targetList) { + targetList->clear(); + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->list().begin(); + it != ELPP->registeredLoggers()->list().end(); ++it) { + targetList->push_back(it->first); + } + return targetList; +} + +void Loggers::configureFromGlobal(const char* globalConfigurationFilePath) { + std::ifstream gcfStream(globalConfigurationFilePath, std::ifstream::in); + ELPP_ASSERT(gcfStream.is_open(), "Unable to open global configuration file [" << globalConfigurationFilePath + << "] for parsing."); + std::string line = std::string(); + std::stringstream ss; + Logger* logger = nullptr; + auto configure = [&](void) { + ELPP_INTERNAL_INFO(8, "Configuring logger: '" << logger->id() << "' with configurations \n" << ss.str() + << "\n--------------"); + Configurations c; + c.parseFromText(ss.str()); + logger->configure(c); + }; + while (gcfStream.good()) { + std::getline(gcfStream, line); + ELPP_INTERNAL_INFO(1, "Parsing line: " << line); + base::utils::Str::trim(line); + if (Configurations::Parser::isComment(line)) continue; + Configurations::Parser::ignoreComments(&line); + base::utils::Str::trim(line); + if (line.size() > 2 && base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLoggerId))) { + if (!ss.str().empty() && logger != nullptr) { + configure(); + } + ss.str(std::string("")); + line = line.substr(2); + base::utils::Str::trim(line); + if (line.size() > 1) { + ELPP_INTERNAL_INFO(1, "Getting logger: '" << line << "'"); + logger = getLogger(line); + } + } else { + ss << line << "\n"; + } + } + if (!ss.str().empty() && logger != nullptr) { + configure(); + } +} + +bool Loggers::configureFromArg(const char* argKey) { +#if defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) + ELPP_UNUSED(argKey); +#else + if (!Helpers::commandLineArgs()->hasParamWithValue(argKey)) { + return false; + } + configureFromGlobal(Helpers::commandLineArgs()->getParamValue(argKey)); +#endif // defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) + return true; +} + +void Loggers::flushAll(void) { + ELPP->registeredLoggers()->flushAll(); +} + +void Loggers::setVerboseLevel(base::type::VerboseLevel level) { + ELPP->vRegistry()->setLevel(level); +} + +base::type::VerboseLevel Loggers::verboseLevel(void) { + return ELPP->vRegistry()->level(); +} + +void Loggers::setVModules(const char* modules) { + if (ELPP->vRegistry()->vModulesEnabled()) { + ELPP->vRegistry()->setModules(modules); + } +} + +void Loggers::clearVModules(void) { + ELPP->vRegistry()->clearModules(); +} + +// VersionInfo + +const std::string VersionInfo::version(void) { + return std::string("9.96.7"); +} +/// @brief Release date of current version +const std::string VersionInfo::releaseDate(void) { + return std::string("24-11-2018 0728hrs"); +} + +} // namespace el diff --git a/code/application/sifarsdk/component/Log/src/easyloggingpp/easylogging++.h b/code/application/sifarsdk/component/Log/src/easyloggingpp/easylogging++.h new file mode 100644 index 000000000..04ea9da2b --- /dev/null +++ b/code/application/sifarsdk/component/Log/src/easyloggingpp/easylogging++.h @@ -0,0 +1,4580 @@ +// +// Bismillah ar-Rahmaan ar-Raheem +// +// Easylogging++ v9.96.7 +// Single-header only, cross-platform logging library for C++ applications +// +// Copyright (c) 2012-2018 Amrayn Web Services +// Copyright (c) 2012-2018 @abumusamq +// +// This library is released under the MIT Licence. +// https://github.com/amrayn/easyloggingpp/blob/master/LICENSE +// +// https://amrayn.com +// http://muflihun.com +// + +#ifndef EASYLOGGINGPP_H +#define EASYLOGGINGPP_H + +#define ELPP_THREAD_SAFE // Working in threads. Added by xiaojiazhu +// #define ELPP_STL_LOGGING + +// Compilers and C++0x/C++11 Evaluation +#if __cplusplus >= 201103L +# define ELPP_CXX11 1 +#endif // __cplusplus >= 201103L +#if (defined(__GNUC__)) +# define ELPP_COMPILER_GCC 1 +#else +# define ELPP_COMPILER_GCC 0 +#endif +#if ELPP_COMPILER_GCC +# define ELPP_GCC_VERSION (__GNUC__ * 10000 \ ++ __GNUC_MINOR__ * 100 \ ++ __GNUC_PATCHLEVEL__) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define ELPP_CXX0X 1 +# endif +#endif +// Visual C++ +#if defined(_MSC_VER) +# define ELPP_COMPILER_MSVC 1 +#else +# define ELPP_COMPILER_MSVC 0 +#endif +#define ELPP_CRT_DBG_WARNINGS ELPP_COMPILER_MSVC +#if ELPP_COMPILER_MSVC +# if (_MSC_VER == 1600) +# define ELPP_CXX0X 1 +# elif(_MSC_VER >= 1700) +# define ELPP_CXX11 1 +# endif +#endif +// Clang++ +#if (defined(__clang__) && (__clang__ == 1)) +# define ELPP_COMPILER_CLANG 1 +#else +# define ELPP_COMPILER_CLANG 0 +#endif +#if ELPP_COMPILER_CLANG +# if __has_include() +# include // Make __GLIBCXX__ defined when using libstdc++ +# if !defined(__GLIBCXX__) || __GLIBCXX__ >= 20150426 +# define ELPP_CLANG_SUPPORTS_THREAD +# endif // !defined(__GLIBCXX__) || __GLIBCXX__ >= 20150426 +# endif // __has_include() +#endif +#if (defined(__MINGW32__) || defined(__MINGW64__)) +# define ELPP_MINGW 1 +#else +# define ELPP_MINGW 0 +#endif +#if (defined(__CYGWIN__) && (__CYGWIN__ == 1)) +# define ELPP_CYGWIN 1 +#else +# define ELPP_CYGWIN 0 +#endif +#if (defined(__INTEL_COMPILER)) +# define ELPP_COMPILER_INTEL 1 +#else +# define ELPP_COMPILER_INTEL 0 +#endif +// Operating System Evaluation +// Windows +#if (defined(_WIN32) || defined(_WIN64)) +# define ELPP_OS_WINDOWS 1 +#else +# define ELPP_OS_WINDOWS 0 +#endif +// Linux +#if (defined(__linux) || defined(__linux__)) +# define ELPP_OS_LINUX 1 +#else +# define ELPP_OS_LINUX 0 +#endif +#if (defined(__APPLE__)) +# define ELPP_OS_MAC 1 +#else +# define ELPP_OS_MAC 0 +#endif +#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) +# define ELPP_OS_FREEBSD 1 +#else +# define ELPP_OS_FREEBSD 0 +#endif +#if (defined(__sun)) +# define ELPP_OS_SOLARIS 1 +#else +# define ELPP_OS_SOLARIS 0 +#endif +#if (defined(_AIX)) +# define ELPP_OS_AIX 1 +#else +# define ELPP_OS_AIX 0 +#endif +#if (defined(__NetBSD__)) +# define ELPP_OS_NETBSD 1 +#else +# define ELPP_OS_NETBSD 0 +#endif +#if defined(__EMSCRIPTEN__) +# define ELPP_OS_EMSCRIPTEN 1 +#else +# define ELPP_OS_EMSCRIPTEN 0 +#endif +#if (defined(__QNX__) || defined(__QNXNTO__)) +# define ELPP_OS_QNX 1 +#else +# define ELPP_OS_QNX 0 +#endif +// Unix +#if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_NETBSD || ELPP_OS_SOLARIS || ELPP_OS_AIX || ELPP_OS_EMSCRIPTEN || ELPP_OS_QNX) && (!ELPP_OS_WINDOWS)) +# define ELPP_OS_UNIX 1 +#else +# define ELPP_OS_UNIX 0 +#endif +#if (defined(__ANDROID__)) +# define ELPP_OS_ANDROID 1 +#else +# define ELPP_OS_ANDROID 0 +#endif +// Evaluating Cygwin as *nix OS +#if !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN +# undef ELPP_OS_UNIX +# undef ELPP_OS_LINUX +# define ELPP_OS_UNIX 1 +# define ELPP_OS_LINUX 1 +#endif // !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN +#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_INFO) +# define ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_ERROR) +# define ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_ENDL) +# define ELPP_INTERNAL_DEBUGGING_ENDL std::endl +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_MSG) +# define ELPP_INTERNAL_DEBUGGING_MSG(msg) msg +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +// Internal Assertions and errors +#if !defined(ELPP_DISABLE_ASSERT) +# if (defined(ELPP_DEBUG_ASSERT_FAILURE)) +# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ +std::stringstream internalInfoStream; internalInfoStream << msg; \ +ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ +<< "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \ +<< ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << ELPP_INTERNAL_DEBUGGING_ENDL; base::utils::abort(1, \ +"ELPP Assertion failure, please define ELPP_DEBUG_ASSERT_FAILURE"); } +# else +# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ +std::stringstream internalInfoStream; internalInfoStream << msg; \ +ELPP_INTERNAL_DEBUGGING_OUT_ERROR\ +<< "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \ +<< __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \ +<< ELPP_INTERNAL_DEBUGGING_ENDL; } +# endif // (defined(ELPP_DEBUG_ASSERT_FAILURE)) +#else +# define ELPP_ASSERT(x, y) +#endif //(!defined(ELPP_DISABLE_ASSERT) +#if ELPP_COMPILER_MSVC +# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ +{ char buff[256]; strerror_s(buff, 256, errno); \ +ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]";} (void)0 +#else +# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ +ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; (void)0 +#endif // ELPP_COMPILER_MSVC +#if defined(ELPP_DEBUG_ERRORS) +# if !defined(ELPP_INTERNAL_ERROR) +# define ELPP_INTERNAL_ERROR(msg, pe) { \ +std::stringstream internalInfoStream; internalInfoStream << " " << msg; \ +ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ +<< "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \ +<< ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << ELPP_INTERNAL_DEBUGGING_ENDL; \ +if (pe) { ELPP_INTERNAL_DEBUGGING_OUT_ERROR << " "; ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; }} (void)0 +# endif +#else +# undef ELPP_INTERNAL_INFO +# define ELPP_INTERNAL_ERROR(msg, pe) +#endif // defined(ELPP_DEBUG_ERRORS) +#if (defined(ELPP_DEBUG_INFO)) +# if !(defined(ELPP_INTERNAL_INFO_LEVEL)) +# define ELPP_INTERNAL_INFO_LEVEL 9 +# endif // !(defined(ELPP_INTERNAL_INFO_LEVEL)) +# if !defined(ELPP_INTERNAL_INFO) +# define ELPP_INTERNAL_INFO(lvl, msg) { if (lvl <= ELPP_INTERNAL_INFO_LEVEL) { \ +std::stringstream internalInfoStream; internalInfoStream << " " << msg; \ +ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \ +<< ELPP_INTERNAL_DEBUGGING_ENDL; }} +# endif +#else +# undef ELPP_INTERNAL_INFO +# define ELPP_INTERNAL_INFO(lvl, msg) +#endif // (defined(ELPP_DEBUG_INFO)) +#if (defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) +# if (ELPP_COMPILER_GCC && !ELPP_MINGW && !ELPP_CYGWIN && !ELPP_OS_ANDROID && !ELPP_OS_EMSCRIPTEN && !ELPP_OS_QNX) +# define ELPP_STACKTRACE 1 +# else +# if ELPP_COMPILER_MSVC +# pragma message("Stack trace not available for this compiler") +# else +# warning "Stack trace not available for this compiler"; +# endif // ELPP_COMPILER_MSVC +# define ELPP_STACKTRACE 0 +# endif // ELPP_COMPILER_GCC +#else +# define ELPP_STACKTRACE 0 +#endif // (defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) +// Miscellaneous macros +#define ELPP_UNUSED(x) (void)x +#if ELPP_OS_UNIX +// Log file permissions for unix-based systems +# define ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH +#endif // ELPP_OS_UNIX +#if defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC +# if defined(ELPP_EXPORT_SYMBOLS) +# define ELPP_EXPORT __declspec(dllexport) +# else +# define ELPP_EXPORT __declspec(dllimport) +# endif // defined(ELPP_EXPORT_SYMBOLS) +#else +# define ELPP_EXPORT +#endif // defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC +// Some special functions that are VC++ specific +#undef STRTOK +#undef STRERROR +#undef STRCAT +#undef STRCPY +#if ELPP_CRT_DBG_WARNINGS +# define STRTOK(a, b, c) strtok_s(a, b, c) +# define STRERROR(a, b, c) strerror_s(a, b, c) +# define STRCAT(a, b, len) strcat_s(a, len, b) +# define STRCPY(a, b, len) strcpy_s(a, len, b) +#else +# define STRTOK(a, b, c) strtok(a, b) +# define STRERROR(a, b, c) strerror(c) +# define STRCAT(a, b, len) strcat(a, b) +# define STRCPY(a, b, len) strcpy(a, b) +#endif +// Compiler specific support evaluations +#if (ELPP_MINGW && !defined(ELPP_FORCE_USE_STD_THREAD)) +# define ELPP_USE_STD_THREADING 0 +#else +# if ((ELPP_COMPILER_CLANG && defined(ELPP_CLANG_SUPPORTS_THREAD)) || \ + (!ELPP_COMPILER_CLANG && defined(ELPP_CXX11)) || \ + defined(ELPP_FORCE_USE_STD_THREAD)) +# define ELPP_USE_STD_THREADING 1 +# else +# define ELPP_USE_STD_THREADING 0 +# endif +#endif +#undef ELPP_FINAL +#if ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) +# define ELPP_FINAL +#else +# define ELPP_FINAL final +#endif // ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) +#if defined(ELPP_EXPERIMENTAL_ASYNC) +# define ELPP_ASYNC_LOGGING 1 +#else +# define ELPP_ASYNC_LOGGING 0 +#endif // defined(ELPP_EXPERIMENTAL_ASYNC) +#if defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING +# define ELPP_THREADING_ENABLED 1 +#else +# define ELPP_THREADING_ENABLED 0 +#endif // defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING +// Function macro ELPP_FUNC +#undef ELPP_FUNC +#if ELPP_COMPILER_MSVC // Visual C++ +# define ELPP_FUNC __FUNCSIG__ +#elif ELPP_COMPILER_GCC // GCC +# define ELPP_FUNC __PRETTY_FUNCTION__ +#elif ELPP_COMPILER_INTEL // Intel C++ +# define ELPP_FUNC __PRETTY_FUNCTION__ +#elif ELPP_COMPILER_CLANG // Clang++ +# define ELPP_FUNC __PRETTY_FUNCTION__ +#else +# if defined(__func__) +# define ELPP_FUNC __func__ +# else +# define ELPP_FUNC "" +# endif // defined(__func__) +#endif // defined(_MSC_VER) +#undef ELPP_VARIADIC_TEMPLATES_SUPPORTED +// Keep following line commented until features are fixed +#define ELPP_VARIADIC_TEMPLATES_SUPPORTED \ +(ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800)) +// Logging Enable/Disable macros +#if defined(ELPP_DISABLE_LOGS) +#define ELPP_LOGGING_ENABLED 0 +#else +#define ELPP_LOGGING_ENABLED 1 +#endif +#if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_DEBUG_LOG 1 +#else +# define ELPP_DEBUG_LOG 0 +#endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_INFO_LOG 1 +#else +# define ELPP_INFO_LOG 0 +#endif // (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_WARNING_LOG 1 +#else +# define ELPP_WARNING_LOG 0 +#endif // (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_ERROR_LOG 1 +#else +# define ELPP_ERROR_LOG 0 +#endif // (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_FATAL_LOG 1 +#else +# define ELPP_FATAL_LOG 0 +#endif // (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_TRACE_LOG 1 +#else +# define ELPP_TRACE_LOG 0 +#endif // (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_VERBOSE_LOG 1 +#else +# define ELPP_VERBOSE_LOG 0 +#endif // (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!(ELPP_CXX0X || ELPP_CXX11)) +# error "C++0x (or higher) support not detected! (Is `-std=c++11' missing?)" +#endif // (!(ELPP_CXX0X || ELPP_CXX11)) +// Headers +#if defined(ELPP_SYSLOG) +# include +#endif // defined(ELPP_SYSLOG) +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(ELPP_UNICODE) +# include +# if ELPP_OS_WINDOWS +# include +# endif // ELPP_OS_WINDOWS +#endif // defined(ELPP_UNICODE) +#ifdef HAVE_EXECINFO +# include +# include +#endif // ENABLE_EXECINFO +#if ELPP_OS_ANDROID +# include +#endif // ELPP_OS_ANDROID +#if ELPP_OS_UNIX +# include +# include +#elif ELPP_OS_WINDOWS +# include +# include +# if defined(WIN32_LEAN_AND_MEAN) +# if defined(ELPP_WINSOCK2) +# include +# else +# include +# endif // defined(ELPP_WINSOCK2) +# endif // defined(WIN32_LEAN_AND_MEAN) +#endif // ELPP_OS_UNIX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if ELPP_THREADING_ENABLED +# if ELPP_USE_STD_THREADING +# include +# include +# else +# if ELPP_OS_UNIX +# include +# endif // ELPP_OS_UNIX +# endif // ELPP_USE_STD_THREADING +#endif // ELPP_THREADING_ENABLED +#if ELPP_ASYNC_LOGGING +# if defined(ELPP_NO_SLEEP_FOR) +# include +# endif // defined(ELPP_NO_SLEEP_FOR) +# include +# include +# include +#endif // ELPP_ASYNC_LOGGING +#if defined(ELPP_STL_LOGGING) +// For logging STL based templates +# include +# include +# include +# include +# include +# include +# if defined(ELPP_LOG_STD_ARRAY) +# include +# endif // defined(ELPP_LOG_STD_ARRAY) +# if defined(ELPP_LOG_UNORDERED_SET) +# include +# endif // defined(ELPP_UNORDERED_SET) +#endif // defined(ELPP_STL_LOGGING) +#if defined(ELPP_QT_LOGGING) +// For logging Qt based classes & templates +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif // defined(ELPP_QT_LOGGING) +#if defined(ELPP_BOOST_LOGGING) +// For logging boost based classes & templates +# include +# include +# include +# include +# include +# include +# include +# include +#endif // defined(ELPP_BOOST_LOGGING) +#if defined(ELPP_WXWIDGETS_LOGGING) +// For logging wxWidgets based classes & templates +# include +#endif // defined(ELPP_WXWIDGETS_LOGGING) +#if defined(ELPP_UTC_DATETIME) +# define elpptime_r gmtime_r +# define elpptime_s gmtime_s +# define elpptime gmtime +#else +# define elpptime_r localtime_r +# define elpptime_s localtime_s +# define elpptime localtime +#endif // defined(ELPP_UTC_DATETIME) +// Forward declarations +namespace el { +class Logger; +class LogMessage; +class PerformanceTrackingData; +class Loggers; +class Helpers; +template class Callback; +class LogDispatchCallback; +class PerformanceTrackingCallback; +class LoggerRegistrationCallback; +class LogDispatchData; +namespace base { +class Storage; +class RegisteredLoggers; +class PerformanceTracker; +class MessageBuilder; +class Writer; +class PErrorWriter; +class LogDispatcher; +class DefaultLogBuilder; +class DefaultLogDispatchCallback; +#if ELPP_ASYNC_LOGGING +class AsyncLogDispatchCallback; +class AsyncDispatchWorker; +#endif // ELPP_ASYNC_LOGGING +class DefaultPerformanceTrackingCallback; +} // namespace base +} // namespace el +/// @brief Easylogging++ entry namespace +namespace el { +/// @brief Namespace containing base/internal functionality used by Easylogging++ +namespace base { +/// @brief Data types used by Easylogging++ +namespace type { +#undef ELPP_LITERAL +#undef ELPP_STRLEN +#undef ELPP_COUT +#if defined(ELPP_UNICODE) +# define ELPP_LITERAL(txt) L##txt +# define ELPP_STRLEN wcslen +# if defined ELPP_CUSTOM_COUT +# define ELPP_COUT ELPP_CUSTOM_COUT +# else +# define ELPP_COUT std::wcout +# endif // defined ELPP_CUSTOM_COUT +typedef wchar_t char_t; +typedef std::wstring string_t; +typedef std::wstringstream stringstream_t; +typedef std::wfstream fstream_t; +typedef std::wostream ostream_t; +#else +# define ELPP_LITERAL(txt) txt +# define ELPP_STRLEN strlen +# if defined ELPP_CUSTOM_COUT +# define ELPP_COUT ELPP_CUSTOM_COUT +# else +# define ELPP_COUT std::cout +# endif // defined ELPP_CUSTOM_COUT +typedef char char_t; +typedef std::string string_t; +typedef std::stringstream stringstream_t; +typedef std::fstream fstream_t; +typedef std::ostream ostream_t; +#endif // defined(ELPP_UNICODE) +#if defined(ELPP_CUSTOM_COUT_LINE) +# define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine) +#else +# define ELPP_COUT_LINE(logLine) logLine << std::flush +#endif // defined(ELPP_CUSTOM_COUT_LINE) +typedef unsigned int EnumType; +typedef unsigned short VerboseLevel; +typedef unsigned long int LineNumber; +typedef std::shared_ptr StoragePointer; +typedef std::shared_ptr LogDispatchCallbackPtr; +typedef std::shared_ptr PerformanceTrackingCallbackPtr; +typedef std::shared_ptr LoggerRegistrationCallbackPtr; +typedef std::unique_ptr PerformanceTrackerPtr; +} // namespace type +/// @brief Internal helper class that prevent copy constructor for class +/// +/// @detail When using this class simply inherit it privately +class NoCopy { + protected: + NoCopy(void) {} + private: + NoCopy(const NoCopy&); + NoCopy& operator=(const NoCopy&); +}; +/// @brief Internal helper class that makes all default constructors private. +/// +/// @detail This prevents initializing class making it static unless an explicit constructor is declared. +/// When using this class simply inherit it privately +class StaticClass { + private: + StaticClass(void); + StaticClass(const StaticClass&); + StaticClass& operator=(const StaticClass&); +}; +} // namespace base +/// @brief Represents enumeration for severity level used to determine level of logging +/// +/// @detail With Easylogging++, developers may disable or enable any level regardless of +/// what the severity is. Or they can choose to log using hierarchical logging flag +enum class Level : base::type::EnumType { + /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels + Global = 1, + /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs. + Trace = 2, + /// @brief Informational events most useful for developers to debug application + Debug = 4, + /// @brief Severe error information that will presumably abort application + Fatal = 8, + /// @brief Information representing errors in application but application will keep running + Error = 16, + /// @brief Useful when application has potentially harmful situations + Warning = 32, + /// @brief Information that can be highly useful and vary with verbose logging level. + Verbose = 64, + /// @brief Mainly useful to represent current progress of application + Info = 128, + /// @brief Represents unknown level + Unknown = 1010 +}; +} // namespace el +namespace std { +template<> struct hash { + public: + std::size_t operator()(const el::Level& l) const { + return hash {}(static_cast(l)); + } +}; +} +namespace el { +/// @brief Static class that contains helper functions for el::Level +class LevelHelper : base::StaticClass { + public: + /// @brief Represents minimum valid level. Useful when iterating through enum. + static const base::type::EnumType kMinValid = static_cast(Level::Trace); + /// @brief Represents maximum valid level. This is used internally and you should not need it. + static const base::type::EnumType kMaxValid = static_cast(Level::Info); + /// @brief Casts level to int, useful for iterating through enum. + static base::type::EnumType castToInt(Level level) { + return static_cast(level); + } + /// @brief Casts int(ushort) to level, useful for iterating through enum. + static Level castFromInt(base::type::EnumType l) { + return static_cast(l); + } + /// @brief Converts level to associated const char* + /// @return Upper case string based level. + static const char* convertToString(Level level); + /// @brief Converts from levelStr to Level + /// @param levelStr Upper case string based level. + /// Lower case is also valid but providing upper case is recommended. + static Level convertFromString(const char* levelStr); + /// @brief Applies specified function to each level starting from startIndex + /// @param startIndex initial value to start the iteration from. This is passed as pointer and + /// is left-shifted so this can be used inside function (fn) to represent current level. + /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels. + static void forEachLevel(base::type::EnumType* startIndex, const std::function& fn); +}; +/// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect +/// of logging +enum class ConfigurationType : base::type::EnumType { + /// @brief Determines whether or not corresponding level and logger of logging is enabled + /// You may disable all logs by using el::Level::Global + Enabled = 1, + /// @brief Whether or not to write corresponding log to log file + ToFile = 2, + /// @brief Whether or not to write corresponding level and logger log to standard output. + /// By standard output meaning termnal, command prompt etc + ToStandardOutput = 4, + /// @brief Determines format of logging corresponding level and logger. + Format = 8, + /// @brief Determines log file (full path) to write logs to for corresponding level and logger + Filename = 16, + /// @brief Specifies precision of the subsecond part. It should be within range (1-6). + SubsecondPrecision = 32, + /// @brief Alias of SubsecondPrecision (for backward compatibility) + MillisecondsWidth = SubsecondPrecision, + /// @brief Determines whether or not performance tracking is enabled. + /// + /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger + PerformanceTracking = 64, + /// @brief Specifies log file max size. + /// + /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will + /// be truncated and re-initiated. + MaxLogFileSize = 128, + /// @brief Specifies number of log entries to hold until we flush pending log data + LogFlushThreshold = 256, + /// @brief Represents unknown configuration + Unknown = 1010 +}; +/// @brief Static class that contains helper functions for el::ConfigurationType +class ConfigurationTypeHelper : base::StaticClass { + public: + /// @brief Represents minimum valid configuration type. Useful when iterating through enum. + static const base::type::EnumType kMinValid = static_cast(ConfigurationType::Enabled); + /// @brief Represents maximum valid configuration type. This is used internally and you should not need it. + static const base::type::EnumType kMaxValid = static_cast(ConfigurationType::MaxLogFileSize); + /// @brief Casts configuration type to int, useful for iterating through enum. + static base::type::EnumType castToInt(ConfigurationType configurationType) { + return static_cast(configurationType); + } + /// @brief Casts int(ushort) to configuration type, useful for iterating through enum. + static ConfigurationType castFromInt(base::type::EnumType c) { + return static_cast(c); + } + /// @brief Converts configuration type to associated const char* + /// @returns Upper case string based configuration type. + static const char* convertToString(ConfigurationType configurationType); + /// @brief Converts from configStr to ConfigurationType + /// @param configStr Upper case string based configuration type. + /// Lower case is also valid but providing upper case is recommended. + static ConfigurationType convertFromString(const char* configStr); + /// @brief Applies specified function to each configuration type starting from startIndex + /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted + /// so this can be used inside function (fn) to represent current configuration type. + /// @param fn function to apply with each configuration type. + /// This bool represent whether or not to stop iterating through configurations. + static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function& fn); +}; +/// @brief Flags used while writing logs. This flags are set by user +enum class LoggingFlag : base::type::EnumType { + /// @brief Makes sure we have new line for each container log entry + NewLineForContainer = 1, + /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose + /// logging is allowed via that module. + AllowVerboseIfModuleNotSpecified = 2, + /// @brief When handling crashes by default, detailed crash reason will be logged as well + LogDetailedCrashReason = 4, + /// @brief Allows to disable application abortion when logged using FATAL level + DisableApplicationAbortOnFatalLog = 8, + /// @brief Flushes log with every log-entry (performance sensitive) - Disabled by default + ImmediateFlush = 16, + /// @brief Enables strict file rolling + StrictLogFileSizeCheck = 32, + /// @brief Make terminal output colorful for supported terminals + ColoredTerminalOutput = 64, + /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network") + MultiLoggerSupport = 128, + /// @brief Disables comparing performance tracker's checkpoints + DisablePerformanceTrackingCheckpointComparison = 256, + /// @brief Disable VModules + DisableVModules = 512, + /// @brief Disable VModules extensions + DisableVModulesExtensions = 1024, + /// @brief Enables hierarchical logging + HierarchicalLogging = 2048, + /// @brief Creates logger automatically when not available + CreateLoggerAutomatically = 4096, + /// @brief Adds spaces b/w logs that separated by left-shift operator + AutoSpacing = 8192, + /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only) + FixedTimeFormat = 16384, + // @brief Ignore SIGINT or crash + IgnoreSigInt = 32768, +}; +namespace base { +/// @brief Namespace containing constants used internally. +namespace consts { +static const char kFormatSpecifierCharValue = 'v'; +static const char kFormatSpecifierChar = '%'; +static const unsigned int kMaxLogPerCounter = 100000; +static const unsigned int kMaxLogPerContainer = 100; +static const unsigned int kDefaultSubsecondPrecision = 3; + +#ifdef ELPP_DEFAULT_LOGGER +static const char* kDefaultLoggerId = ELPP_DEFAULT_LOGGER; +#else +static const char* kDefaultLoggerId = "default"; +#endif + +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) +#ifdef ELPP_DEFAULT_PERFORMANCE_LOGGER +static const char* kPerformanceLoggerId = ELPP_DEFAULT_PERFORMANCE_LOGGER; +#else +static const char* kPerformanceLoggerId = "performance"; +#endif // ELPP_DEFAULT_PERFORMANCE_LOGGER +#endif + +#if defined(ELPP_SYSLOG) +static const char* kSysLogLoggerId = "syslog"; +#endif // defined(ELPP_SYSLOG) + +#if ELPP_OS_WINDOWS +static const char* kFilePathSeparator = "\\"; +#else +static const char* kFilePathSeparator = "/"; +#endif // ELPP_OS_WINDOWS + +static const std::size_t kSourceFilenameMaxLength = 100; +static const std::size_t kSourceLineMaxLength = 10; +static const Level kPerformanceTrackerDefaultLevel = Level::Info; +const struct { + double value; + const base::type::char_t* unit; +} kTimeFormats[] = { + { 1000.0f, ELPP_LITERAL("us") }, + { 1000.0f, ELPP_LITERAL("ms") }, + { 60.0f, ELPP_LITERAL("seconds") }, + { 60.0f, ELPP_LITERAL("minutes") }, + { 24.0f, ELPP_LITERAL("hours") }, + { 7.0f, ELPP_LITERAL("days") } +}; +static const int kTimeFormatsCount = sizeof(kTimeFormats) / sizeof(kTimeFormats[0]); +const struct { + int numb; + const char* name; + const char* brief; + const char* detail; +} kCrashSignals[] = { + // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..) + { + SIGABRT, "SIGABRT", "Abnormal termination", + "Program was abnormally terminated." + }, + { + SIGFPE, "SIGFPE", "Erroneous arithmetic operation", + "Arithmetic operation issue such as division by zero or operation resulting in overflow." + }, + { + SIGILL, "SIGILL", "Illegal instruction", + "Generally due to a corruption in the code or to an attempt to execute data." + }, + { + SIGSEGV, "SIGSEGV", "Invalid access to memory", + "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory." + }, + { + SIGINT, "SIGINT", "Interactive attention signal", + "Interruption generated (generally) by user or operating system." + }, +}; +static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]); +} // namespace consts +} // namespace base +typedef std::function PreRollOutCallback; +namespace base { +static inline void defaultPreRollOutCallback(const char*, std::size_t) {} +/// @brief Enum to represent timestamp unit +enum class TimestampUnit : base::type::EnumType { + Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, Day = 5 +}; +/// @brief Format flags used to determine specifiers that are active for performance improvements. +enum class FormatFlags : base::type::EnumType { + DateTime = 1 << 1, + LoggerId = 1 << 2, + File = 1 << 3, + Line = 1 << 4, + Location = 1 << 5, + Function = 1 << 6, + User = 1 << 7, + Host = 1 << 8, + LogMessage = 1 << 9, + VerboseLevel = 1 << 10, + AppName = 1 << 11, + ThreadId = 1 << 12, + Level = 1 << 13, + FileBase = 1 << 14, + LevelShort = 1 << 15 +}; +/// @brief A subsecond precision class containing actual width and offset of the subsecond part +class SubsecondPrecision { + public: + SubsecondPrecision(void) { + init(base::consts::kDefaultSubsecondPrecision); + } + explicit SubsecondPrecision(int width) { + init(width); + } + bool operator==(const SubsecondPrecision& ssPrec) { + return m_width == ssPrec.m_width && m_offset == ssPrec.m_offset; + } + int m_width; + unsigned int m_offset; + private: + void init(int width); +}; +/// @brief Type alias of SubsecondPrecision +typedef SubsecondPrecision MillisecondsWidth; +/// @brief Namespace containing utility functions/static classes used internally +namespace utils { +/// @brief Deletes memory safely and points to null +template +static +typename std::enable_if::value, void>::type +safeDelete(T*& pointer) { + if (pointer == nullptr) + return; + delete pointer; + pointer = nullptr; +} +/// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation +/// Use these function as
flag = bitwise::Or(MyEnum::val1, flag);
+namespace bitwise { +template +static inline base::type::EnumType And(Enum e, base::type::EnumType flag) { + return static_cast(flag) & static_cast(e); +} +template +static inline base::type::EnumType Not(Enum e, base::type::EnumType flag) { + return static_cast(flag) & ~(static_cast(e)); +} +template +static inline base::type::EnumType Or(Enum e, base::type::EnumType flag) { + return static_cast(flag) | static_cast(e); +} +} // namespace bitwise +template +static inline void addFlag(Enum e, base::type::EnumType* flag) { + *flag = base::utils::bitwise::Or(e, *flag); +} +template +static inline void removeFlag(Enum e, base::type::EnumType* flag) { + *flag = base::utils::bitwise::Not(e, *flag); +} +template +static inline bool hasFlag(Enum e, base::type::EnumType flag) { + return base::utils::bitwise::And(e, flag) > 0x0; +} +} // namespace utils +namespace threading { +#if ELPP_THREADING_ENABLED +# if !ELPP_USE_STD_THREADING +namespace internal { +/// @brief A mutex wrapper for compiler that dont yet support std::recursive_mutex +class Mutex : base::NoCopy { + public: + Mutex(void) { +# if ELPP_OS_UNIX + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_underlyingMutex, &attr); + pthread_mutexattr_destroy(&attr); +# elif ELPP_OS_WINDOWS + InitializeCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + virtual ~Mutex(void) { +# if ELPP_OS_UNIX + pthread_mutex_destroy(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + DeleteCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline void lock(void) { +# if ELPP_OS_UNIX + pthread_mutex_lock(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + EnterCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline bool try_lock(void) { +# if ELPP_OS_UNIX + return (pthread_mutex_trylock(&m_underlyingMutex) == 0); +# elif ELPP_OS_WINDOWS + return TryEnterCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline void unlock(void) { +# if ELPP_OS_UNIX + pthread_mutex_unlock(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + LeaveCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + private: +# if ELPP_OS_UNIX + pthread_mutex_t m_underlyingMutex; +# elif ELPP_OS_WINDOWS + CRITICAL_SECTION m_underlyingMutex; +# endif // ELPP_OS_UNIX +}; +/// @brief Scoped lock for compiler that dont yet support std::lock_guard +template +class ScopedLock : base::NoCopy { + public: + explicit ScopedLock(M& mutex) { + m_mutex = &mutex; + m_mutex->lock(); + } + + virtual ~ScopedLock(void) { + m_mutex->unlock(); + } + private: + M* m_mutex; + ScopedLock(void); +}; +} // namespace internal +typedef base::threading::internal::Mutex Mutex; +typedef base::threading::internal::ScopedLock ScopedLock; +# else +typedef std::recursive_mutex Mutex; +typedef std::lock_guard ScopedLock; +# endif // !ELPP_USE_STD_THREADING +#else +namespace internal { +/// @brief Mutex wrapper used when multi-threading is disabled. +class NoMutex : base::NoCopy { + public: + NoMutex(void) {} + inline void lock(void) {} + inline bool try_lock(void) { + return true; + } + inline void unlock(void) {} +}; +/// @brief Lock guard wrapper used when multi-threading is disabled. +template +class NoScopedLock : base::NoCopy { + public: + explicit NoScopedLock(Mutex&) { + } + virtual ~NoScopedLock(void) { + } + private: + NoScopedLock(void); +}; +} // namespace internal +typedef base::threading::internal::NoMutex Mutex; +typedef base::threading::internal::NoScopedLock ScopedLock; +#endif // ELPP_THREADING_ENABLED +/// @brief Base of thread safe class, this class is inheritable-only +class ThreadSafe { + public: + virtual inline void acquireLock(void) ELPP_FINAL { m_mutex.lock(); } + virtual inline void releaseLock(void) ELPP_FINAL { m_mutex.unlock(); } + virtual inline base::threading::Mutex& lock(void) ELPP_FINAL { return m_mutex; } + protected: + ThreadSafe(void) {} + virtual ~ThreadSafe(void) {} + private: + base::threading::Mutex m_mutex; +}; + +#if ELPP_THREADING_ENABLED +# if !ELPP_USE_STD_THREADING +/// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned. +static std::string getCurrentThreadId(void) { + std::stringstream ss; +# if (ELPP_OS_WINDOWS) + ss << GetCurrentThreadId(); +# endif // (ELPP_OS_WINDOWS) + return ss.str(); +} +# else +/// @brief Gets ID of currently running threading using std::this_thread::get_id() +static std::string getCurrentThreadId(void) { + std::stringstream ss; + ss << std::this_thread::get_id(); + return ss.str(); +} +# endif // !ELPP_USE_STD_THREADING +#else +static inline std::string getCurrentThreadId(void) { + return std::string(); +} +#endif // ELPP_THREADING_ENABLED +} // namespace threading +namespace utils { +class File : base::StaticClass { + public: + /// @brief Creates new out file stream for specified filename. + /// @return Pointer to newly created fstream or nullptr + static base::type::fstream_t* newFileStream(const std::string& filename); + + /// @brief Gets size of file provided in stream + static std::size_t getSizeOfFile(base::type::fstream_t* fs); + + /// @brief Determines whether or not provided path exist in current file system + static bool pathExists(const char* path, bool considerFile = false); + + /// @brief Creates specified path on file system + /// @param path Path to create. + static bool createPath(const std::string& path); + /// @brief Extracts path of filename with leading slash + static std::string extractPathFromFilename(const std::string& fullPath, + const char* separator = base::consts::kFilePathSeparator); + /// @brief builds stripped filename and puts it in buff + static void buildStrippedFilename(const char* filename, char buff[], + std::size_t limit = base::consts::kSourceFilenameMaxLength); + /// @brief builds base filename and puts it in buff + static void buildBaseFilename(const std::string& fullPath, char buff[], + std::size_t limit = base::consts::kSourceFilenameMaxLength, + const char* separator = base::consts::kFilePathSeparator); +}; +/// @brief String utilities helper class used internally. You should not use it. +class Str : base::StaticClass { + public: + /// @brief Checks if character is digit. Dont use libc implementation of it to prevent locale issues. + static inline bool isDigit(char c) { + return c >= '0' && c <= '9'; + } + + /// @brief Matches wildcards, '*' and '?' only supported. + static bool wildCardMatch(const char* str, const char* pattern); + + static std::string& ltrim(std::string& str); + static std::string& rtrim(std::string& str); + static std::string& trim(std::string& str); + + /// @brief Determines whether or not str starts with specified string + /// @param str String to check + /// @param start String to check against + /// @return Returns true if starts with specified string, false otherwise + static bool startsWith(const std::string& str, const std::string& start); + + /// @brief Determines whether or not str ends with specified string + /// @param str String to check + /// @param end String to check against + /// @return Returns true if ends with specified string, false otherwise + static bool endsWith(const std::string& str, const std::string& end); + + /// @brief Replaces all instances of replaceWhat with 'replaceWith'. Original variable is changed for performance. + /// @param [in,out] str String to replace from + /// @param replaceWhat Character to replace + /// @param replaceWith Character to replace with + /// @return Modified version of str + static std::string& replaceAll(std::string& str, char replaceWhat, char replaceWith); + + /// @brief Replaces all instances of 'replaceWhat' with 'replaceWith'. (String version) Replaces in place + /// @param str String to replace from + /// @param replaceWhat Character to replace + /// @param replaceWith Character to replace with + /// @return Modified (original) str + static std::string& replaceAll(std::string& str, const std::string& replaceWhat, + const std::string& replaceWith); + + static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, + const base::type::string_t& replaceWith); +#if defined(ELPP_UNICODE) + static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, + const std::string& replaceWith); +#endif // defined(ELPP_UNICODE) + /// @brief Converts string to uppercase + /// @param str String to convert + /// @return Uppercase string + static std::string& toUpper(std::string& str); + + /// @brief Compares cstring equality - uses strcmp + static bool cStringEq(const char* s1, const char* s2); + + /// @brief Compares cstring equality (case-insensitive) - uses toupper(char) + /// Dont use strcasecmp because of CRT (VC++) + static bool cStringCaseEq(const char* s1, const char* s2); + + /// @brief Returns true if c exist in str + static bool contains(const char* str, char c); + + static char* convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded = true); + static char* addToBuff(const char* str, char* buf, const char* bufLim); + static char* clearBuff(char buff[], std::size_t lim); + + /// @brief Converts wchar* to char* + /// NOTE: Need to free return value after use! + static char* wcharPtrToCharPtr(const wchar_t* line); +}; +/// @brief Operating System helper static class used internally. You should not use it. +class OS : base::StaticClass { + public: +#if ELPP_OS_WINDOWS + /// @brief Gets environment variables for Windows based OS. + /// We are not using getenv(const char*) because of CRT deprecation + /// @param varname Variable name to get environment variable value for + /// @return If variable exist the value of it otherwise nullptr + static const char* getWindowsEnvironmentVariable(const char* varname); +#endif // ELPP_OS_WINDOWS +#if ELPP_OS_ANDROID + /// @brief Reads android property value + static std::string getProperty(const char* prop); + + /// @brief Reads android device name + static std::string getDeviceName(void); +#endif // ELPP_OS_ANDROID + + /// @brief Runs command on terminal and returns the output. + /// + /// @detail This is applicable only on unix based systems, for all other OS, an empty string is returned. + /// @param command Bash command + /// @return Result of bash output or empty string if no result found. + static const std::string getBashOutput(const char* command); + + /// @brief Gets environment variable. This is cross-platform and CRT safe (for VC++) + /// @param variableName Environment variable name + /// @param defaultVal If no environment variable or value found the value to return by default + /// @param alternativeBashCommand If environment variable not found what would be alternative bash command + /// in order to look for value user is looking for. E.g, for 'user' alternative command will 'whoami' + static std::string getEnvironmentVariable(const char* variableName, const char* defaultVal, + const char* alternativeBashCommand = nullptr); + /// @brief Gets current username. + static std::string currentUser(void); + + /// @brief Gets current host name or computer name. + /// + /// @detail For android systems this is device name with its manufacturer and model separated by hyphen + static std::string currentHost(void); + /// @brief Whether or not terminal supports colors + static bool termSupportsColor(void); +}; +/// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str +class DateTime : base::StaticClass { + public: + /// @brief Cross platform gettimeofday for Windows and unix platform. This can be used to determine current microsecond. + /// + /// @detail For unix system it uses gettimeofday(timeval*, timezone*) and for Windows, a separate implementation is provided + /// @param [in,out] tv Pointer that gets updated + static void gettimeofday(struct timeval* tv); + + /// @brief Gets current date and time with a subsecond part. + /// @param format User provided date/time format + /// @param ssPrec A pointer to base::SubsecondPrecision from configuration (non-null) + /// @returns string based date time in specified format. + static std::string getDateTime(const char* format, const base::SubsecondPrecision* ssPrec); + + /// @brief Converts timeval (struct from ctime) to string using specified format and subsecond precision + static std::string timevalToString(struct timeval tval, const char* format, + const el::base::SubsecondPrecision* ssPrec); + + /// @brief Formats time to get unit accordingly, units like second if > 1000 or minutes if > 60000 etc + static base::type::string_t formatTime(unsigned long long time, base::TimestampUnit timestampUnit); + + /// @brief Gets time difference in milli/micro second depending on timestampUnit + static unsigned long long getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, + base::TimestampUnit timestampUnit); + + + static struct ::tm* buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo); + private: + static char* parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, + std::size_t msec, const base::SubsecondPrecision* ssPrec); +}; +/// @brief Command line arguments for application if specified using el::Helpers::setArgs(..) or START_EASYLOGGINGPP(..) +class CommandLineArgs { + public: + CommandLineArgs(void) { + setArgs(0, static_cast(nullptr)); + } + CommandLineArgs(int argc, const char** argv) { + setArgs(argc, argv); + } + CommandLineArgs(int argc, char** argv) { + setArgs(argc, argv); + } + virtual ~CommandLineArgs(void) {} + /// @brief Sets arguments and parses them + inline void setArgs(int argc, const char** argv) { + setArgs(argc, const_cast(argv)); + } + /// @brief Sets arguments and parses them + void setArgs(int argc, char** argv); + /// @brief Returns true if arguments contain paramKey with a value (separated by '=') + bool hasParamWithValue(const char* paramKey) const; + /// @brief Returns value of arguments + /// @see hasParamWithValue(const char*) + const char* getParamValue(const char* paramKey) const; + /// @brief Return true if arguments has a param (not having a value) i,e without '=' + bool hasParam(const char* paramKey) const; + /// @brief Returns true if no params available. This exclude argv[0] + bool empty(void) const; + /// @brief Returns total number of arguments. This exclude argv[0] + std::size_t size(void) const; + friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c); + + private: + int m_argc; + char** m_argv; + std::unordered_map m_paramsWithValue; + std::vector m_params; +}; +/// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type. +/// +/// @detail Most of the functions are virtual final methods but anything implementing this abstract class should implement +/// unregisterAll() and deepCopy(const AbstractRegistry&) and write registerNew() method according to container +/// and few more methods; get() to find element, unregister() to unregister single entry. +/// Please note that this is thread-unsafe and should also implement thread-safety mechanisms in implementation. +template +class AbstractRegistry : public base::threading::ThreadSafe { + public: + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + + /// @brief Default constructor + AbstractRegistry(void) {} + + /// @brief Move constructor that is useful for base classes + AbstractRegistry(AbstractRegistry&& sr) { + if (this == &sr) { + return; + } + unregisterAll(); + m_list = std::move(sr.m_list); + } + + bool operator==(const AbstractRegistry& other) { + if (size() != other.size()) { + return false; + } + for (std::size_t i = 0; i < m_list.size(); ++i) { + if (m_list.at(i) != other.m_list.at(i)) { + return false; + } + } + return true; + } + + bool operator!=(const AbstractRegistry& other) { + if (size() != other.size()) { + return true; + } + for (std::size_t i = 0; i < m_list.size(); ++i) { + if (m_list.at(i) != other.m_list.at(i)) { + return true; + } + } + return false; + } + + /// @brief Assignment move operator + AbstractRegistry& operator=(AbstractRegistry&& sr) { + if (this == &sr) { + return *this; + } + unregisterAll(); + m_list = std::move(sr.m_list); + return *this; + } + + virtual ~AbstractRegistry(void) { + } + + /// @return Iterator pointer from start of repository + virtual inline iterator begin(void) ELPP_FINAL { + return m_list.begin(); + } + + /// @return Iterator pointer from end of repository + virtual inline iterator end(void) ELPP_FINAL { + return m_list.end(); + } + + + /// @return Constant iterator pointer from start of repository + virtual inline const_iterator cbegin(void) const ELPP_FINAL { + return m_list.cbegin(); + } + + /// @return End of repository + virtual inline const_iterator cend(void) const ELPP_FINAL { + return m_list.cend(); + } + + /// @return Whether or not repository is empty + virtual inline bool empty(void) const ELPP_FINAL { + return m_list.empty(); + } + + /// @return Size of repository + virtual inline std::size_t size(void) const ELPP_FINAL { + return m_list.size(); + } + + /// @brief Returns underlying container by reference + virtual inline Container& list(void) ELPP_FINAL { + return m_list; + } + + /// @brief Returns underlying container by constant reference. + virtual inline const Container& list(void) const ELPP_FINAL { + return m_list; + } + + /// @brief Unregisters all the pointers from current repository. + virtual void unregisterAll(void) = 0; + + protected: + virtual void deepCopy(const AbstractRegistry&) = 0; + void reinitDeepCopy(const AbstractRegistry& sr) { + unregisterAll(); + deepCopy(sr); + } + + private: + Container m_list; +}; + +/// @brief A pointer registry mechanism to manage memory and provide search functionalities. (non-predicate version) +/// +/// @detail NOTE: This is thread-unsafe implementation (although it contains lock function, it does not use these functions) +/// of AbstractRegistry. Any implementation of this class should be +/// explicitly (by using lock functions) +template +class Registry : public AbstractRegistry> { + public: + typedef typename Registry::iterator iterator; + typedef typename Registry::const_iterator const_iterator; + + Registry(void) {} + + /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. + Registry(const Registry& sr) : AbstractRegistry>() { + if (this == &sr) { + return; + } + this->reinitDeepCopy(sr); + } + + /// @brief Assignment operator that unregisters all the existing registries and deeply copies each of repo element + /// @see unregisterAll() + /// @see deepCopy(const AbstractRegistry&) + Registry& operator=(const Registry& sr) { + if (this == &sr) { + return *this; + } + this->reinitDeepCopy(sr); + return *this; + } + + virtual ~Registry(void) { + unregisterAll(); + } + + protected: + virtual void unregisterAll(void) ELPP_FINAL { + if (!this->empty()) { + for (auto&& curr : this->list()) { + base::utils::safeDelete(curr.second); + } + this->list().clear(); + } + } + +/// @brief Registers new registry to repository. + virtual void registerNew(const T_Key& uniqKey, T_Ptr* ptr) ELPP_FINAL { + unregister(uniqKey); + this->list().insert(std::make_pair(uniqKey, ptr)); + } + +/// @brief Unregisters single entry mapped to specified unique key + void unregister(const T_Key& uniqKey) { + T_Ptr* existing = get(uniqKey); + if (existing != nullptr) { + this->list().erase(uniqKey); + base::utils::safeDelete(existing); + } + } + +/// @brief Gets pointer from repository. If none found, nullptr is returned. + T_Ptr* get(const T_Key& uniqKey) { + iterator it = this->list().find(uniqKey); + return it == this->list().end() + ? nullptr + : it->second; + } + + private: + virtual void deepCopy(const AbstractRegistry>& sr) ELPP_FINAL { + for (const_iterator it = sr.cbegin(); it != sr.cend(); ++it) { + registerNew(it->first, new T_Ptr(*it->second)); + } + } +}; + +/// @brief A pointer registry mechanism to manage memory and provide search functionalities. (predicate version) +/// +/// @detail NOTE: This is thread-unsafe implementation of AbstractRegistry. Any implementation of this class +/// should be made thread-safe explicitly +template +class RegistryWithPred : public AbstractRegistry> { + public: + typedef typename RegistryWithPred::iterator iterator; + typedef typename RegistryWithPred::const_iterator const_iterator; + + RegistryWithPred(void) { + } + + virtual ~RegistryWithPred(void) { + unregisterAll(); + } + + /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. + RegistryWithPred(const RegistryWithPred& sr) : AbstractRegistry>() { + if (this == &sr) { + return; + } + this->reinitDeepCopy(sr); + } + + /// @brief Assignment operator that unregisters all the existing registries and deeply copies each of repo element + /// @see unregisterAll() + /// @see deepCopy(const AbstractRegistry&) + RegistryWithPred& operator=(const RegistryWithPred& sr) { + if (this == &sr) { + return *this; + } + this->reinitDeepCopy(sr); + return *this; + } + + friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const RegistryWithPred& sr) { + for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { + os << ELPP_LITERAL(" ") << **it << ELPP_LITERAL("\n"); + } + return os; + } + + protected: + virtual void unregisterAll(void) ELPP_FINAL { + if (!this->empty()) { + for (auto&& curr : this->list()) { + base::utils::safeDelete(curr); + } + this->list().clear(); + } + } + + virtual void unregister(T_Ptr*& ptr) ELPP_FINAL { + if (ptr) { + iterator iter = this->begin(); + for (; iter != this->end(); ++iter) { + if (ptr == *iter) { + break; + } + } + if (iter != this->end() && *iter != nullptr) { + this->list().erase(iter); + base::utils::safeDelete(*iter); + } + } + } + + virtual inline void registerNew(T_Ptr* ptr) ELPP_FINAL { + this->list().push_back(ptr); + } + +/// @brief Gets pointer from repository with specified arguments. Arguments are passed to predicate +/// in order to validate pointer. + template + T_Ptr* get(const T& arg1, const T2 arg2) { + iterator iter = std::find_if(this->list().begin(), this->list().end(), Pred(arg1, arg2)); + if (iter != this->list().end() && *iter != nullptr) { + return *iter; + } + return nullptr; + } + + private: + virtual void deepCopy(const AbstractRegistry>& sr) { + for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { + registerNew(new T_Ptr(**it)); + } + } +}; +class Utils { + public: + template + static bool installCallback(const std::string& id, std::unordered_map* mapT) { + if (mapT->find(id) == mapT->end()) { + mapT->insert(std::make_pair(id, TPtr(new T()))); + return true; + } + return false; + } + + template + static void uninstallCallback(const std::string& id, std::unordered_map* mapT) { + if (mapT->find(id) != mapT->end()) { + mapT->erase(id); + } + } + + template + static T* callback(const std::string& id, std::unordered_map* mapT) { + typename std::unordered_map::iterator iter = mapT->find(id); + if (iter != mapT->end()) { + return static_cast(iter->second.get()); + } + return nullptr; + } +}; +} // namespace utils +} // namespace base +/// @brief Base of Easylogging++ friendly class +/// +/// @detail After inheriting this class publicly, implement pure-virtual function `void log(std::ostream&) const` +class Loggable { + public: + virtual ~Loggable(void) {} + virtual void log(el::base::type::ostream_t&) const = 0; + private: + friend inline el::base::type::ostream_t& operator<<(el::base::type::ostream_t& os, const Loggable& loggable) { + loggable.log(os); + return os; + } +}; +namespace base { +/// @brief Represents log format containing flags and date format. This is used internally to start initial log +class LogFormat : public Loggable { + public: + LogFormat(void); + LogFormat(Level level, const base::type::string_t& format); + LogFormat(const LogFormat& logFormat); + LogFormat(LogFormat&& logFormat); + LogFormat& operator=(const LogFormat& logFormat); + virtual ~LogFormat(void) {} + bool operator==(const LogFormat& other); + + /// @brief Updates format to be used while logging. + /// @param userFormat User provided format + void parseFromFormat(const base::type::string_t& userFormat); + + inline Level level(void) const { + return m_level; + } + + inline const base::type::string_t& userFormat(void) const { + return m_userFormat; + } + + inline const base::type::string_t& format(void) const { + return m_format; + } + + inline const std::string& dateTimeFormat(void) const { + return m_dateTimeFormat; + } + + inline base::type::EnumType flags(void) const { + return m_flags; + } + + inline bool hasFlag(base::FormatFlags flag) const { + return base::utils::hasFlag(flag, m_flags); + } + + virtual void log(el::base::type::ostream_t& os) const { + os << m_format; + } + + protected: + /// @brief Updates date time format if available in currFormat. + /// @param index Index where %datetime, %date or %time was found + /// @param [in,out] currFormat current format that is being used to format + virtual void updateDateFormat(std::size_t index, base::type::string_t& currFormat) ELPP_FINAL; + + /// @brief Updates %level from format. This is so that we dont have to do it at log-writing-time. It uses m_format and m_level + virtual void updateFormatSpec(void) ELPP_FINAL; + + inline void addFlag(base::FormatFlags flag) { + base::utils::addFlag(flag, &m_flags); + } + + private: + Level m_level; + base::type::string_t m_userFormat; + base::type::string_t m_format; + std::string m_dateTimeFormat; + base::type::EnumType m_flags; + std::string m_currentUser; + std::string m_currentHost; + friend class el::Logger; // To resolve loggerId format specifier easily +}; +} // namespace base +/// @brief Resolving function for format specifier +typedef std::function FormatSpecifierValueResolver; +/// @brief User-provided custom format specifier +/// @see el::Helpers::installCustomFormatSpecifier +/// @see FormatSpecifierValueResolver +class CustomFormatSpecifier { + public: + CustomFormatSpecifier(const char* formatSpecifier, const FormatSpecifierValueResolver& resolver) : + m_formatSpecifier(formatSpecifier), m_resolver(resolver) {} + inline const char* formatSpecifier(void) const { + return m_formatSpecifier; + } + inline const FormatSpecifierValueResolver& resolver(void) const { + return m_resolver; + } + inline bool operator==(const char* formatSpecifier) { + return strcmp(m_formatSpecifier, formatSpecifier) == 0; + } + + private: + const char* m_formatSpecifier; + FormatSpecifierValueResolver m_resolver; +}; +/// @brief Represents single configuration that has representing level, configuration type and a string based value. +/// +/// @detail String based value means any value either its boolean, integer or string itself, it will be embedded inside quotes +/// and will be parsed later. +/// +/// Consider some examples below: +/// * el::Configuration confEnabledInfo(el::Level::Info, el::ConfigurationType::Enabled, "true"); +/// * el::Configuration confMaxLogFileSizeInfo(el::Level::Info, el::ConfigurationType::MaxLogFileSize, "2048"); +/// * el::Configuration confFilenameInfo(el::Level::Info, el::ConfigurationType::Filename, "/var/log/my.log"); +class Configuration : public Loggable { + public: + Configuration(const Configuration& c); + Configuration& operator=(const Configuration& c); + + virtual ~Configuration(void) { + } + + /// @brief Full constructor used to sets value of configuration + Configuration(Level level, ConfigurationType configurationType, const std::string& value); + + /// @brief Gets level of current configuration + inline Level level(void) const { + return m_level; + } + + /// @brief Gets configuration type of current configuration + inline ConfigurationType configurationType(void) const { + return m_configurationType; + } + + /// @brief Gets string based configuration value + inline const std::string& value(void) const { + return m_value; + } + + /// @brief Set string based configuration value + /// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values + /// use them in quotes. They will be parsed when configuring + inline void setValue(const std::string& value) { + m_value = value; + } + + virtual void log(el::base::type::ostream_t& os) const; + + /// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. + class Predicate { + public: + Predicate(Level level, ConfigurationType configurationType); + + bool operator()(const Configuration* conf) const; + + private: + Level m_level; + ConfigurationType m_configurationType; + }; + + private: + Level m_level; + ConfigurationType m_configurationType; + std::string m_value; +}; + +/// @brief Thread-safe Configuration repository +/// +/// @detail This repository represents configurations for all the levels and configuration type mapped to a value. +class Configurations : public base::utils::RegistryWithPred { + public: + /// @brief Default constructor with empty repository + Configurations(void); + + /// @brief Constructor used to set configurations using configuration file. + /// @param configurationFile Full path to configuration file + /// @param useDefaultsForRemaining Lets you set the remaining configurations to default. + /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to. + /// @see parseFromFile(const std::string&, Configurations* base) + /// @see setRemainingToDefault() + Configurations(const std::string& configurationFile, bool useDefaultsForRemaining = true, + Configurations* base = nullptr); + + virtual ~Configurations(void) { + } + + /// @brief Parses configuration from file. + /// @param configurationFile Full path to configuration file + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration file. + /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you + /// do not proceed without successful parse. + bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr); + + /// @brief Parse configurations from configuration string. + /// + /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary + /// new line characters are provided. + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration text. + /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you + /// do not proceed without successful parse. + bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr); + + /// @brief Sets configuration based-off an existing configurations. + /// @param base Pointer to existing configurations. + void setFromBase(Configurations* base); + + /// @brief Determines whether or not specified configuration type exists in the repository. + /// + /// @detail Returns as soon as first level is found. + /// @param configurationType Type of configuration to check existence for. + bool hasConfiguration(ConfigurationType configurationType); + + /// @brief Determines whether or not specified configuration type exists for specified level + /// @param level Level to check + /// @param configurationType Type of configuration to check existence for. + bool hasConfiguration(Level level, ConfigurationType configurationType); + + /// @brief Sets value of configuration for specified level. + /// + /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types + /// ConfigurationType::SubsecondPrecision and ConfigurationType::PerformanceTracking will be ignored if not set for + /// Level::Global because these configurations are not dependant on level. + /// @param level Level to set configuration for (el::Level). + /// @param configurationType Type of configuration (el::ConfigurationType) + /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string + /// from users' point of view. This is then parsed later to be used internally. + /// @see Configuration::setValue(const std::string& value) + /// @see el::Level + /// @see el::ConfigurationType + void set(Level level, ConfigurationType configurationType, const std::string& value); + + /// @brief Sets single configuration based on other single configuration. + /// @see set(Level level, ConfigurationType configurationType, const std::string& value) + void set(Configuration* conf); + + inline Configuration* get(Level level, ConfigurationType configurationType) { + base::threading::ScopedLock scopedLock(lock()); + return RegistryWithPred::get(level, configurationType); + } + + /// @brief Sets configuration for all levels. + /// @param configurationType Type of configuration + /// @param value String based value + /// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) + inline void setGlobally(ConfigurationType configurationType, const std::string& value) { + setGlobally(configurationType, value, false); + } + + /// @brief Clears repository so that all the configurations are unset + inline void clear(void) { + base::threading::ScopedLock scopedLock(lock()); + unregisterAll(); + } + + /// @brief Gets configuration file used in parsing this configurations. + /// + /// @detail If this repository was set manually or by text this returns empty string. + inline const std::string& configurationFile(void) const { + return m_configurationFile; + } + + /// @brief Sets configurations to "factory based" configurations. + void setToDefault(void); + + /// @brief Lets you set the remaining configurations to default. + /// + /// @detail By remaining, it means that the level/type a configuration does not exist for. + /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets + /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e, + /// true. If you dont do this explicitly (either by calling this function or by using second param in Constructor + /// and try to access a value, an error is thrown + void setRemainingToDefault(void); + + /// @brief Parser used internally to parse configurations from file or text. + /// + /// @detail This class makes use of base::utils::Str. + /// You should not need this unless you are working on some tool for Easylogging++ + class Parser : base::StaticClass { + public: + /// @brief Parses configuration from file. + /// @param configurationFile Full path to configuration file + /// @param sender Sender configurations pointer. Usually 'this' is used from calling class + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration file. + /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you + /// do not proceed without successful parse. + static bool parseFromFile(const std::string& configurationFile, Configurations* sender, + Configurations* base = nullptr); + + /// @brief Parse configurations from configuration string. + /// + /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary + /// new line characters are provided. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you + /// do not proceed without successful parse (This is recommended) + /// @param configurationsString the configuration in plain text format + /// @param sender Sender configurations pointer. Usually 'this' is used from calling class + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration text. + /// @return True if successfully parsed, false otherwise. + static bool parseFromText(const std::string& configurationsString, Configurations* sender, + Configurations* base = nullptr); + + private: + friend class el::Loggers; + static void ignoreComments(std::string* line); + static bool isLevel(const std::string& line); + static bool isComment(const std::string& line); + static inline bool isConfig(const std::string& line); + static bool parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, Level* currLevel, + Configurations* conf); + }; + + private: + std::string m_configurationFile; + bool m_isFromFile; + friend class el::Loggers; + + /// @brief Unsafely sets configuration if does not already exist + void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value); + + /// @brief Thread unsafe set + void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value); + + /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true + /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) + void setGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel); + + /// @brief Sets configurations (Unsafely) for all levels including Level::Global if includeGlobalLevel is true + /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) + void unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel); +}; + +namespace base { +typedef std::shared_ptr FileStreamPtr; +typedef std::unordered_map LogStreamsReferenceMap; +typedef std::shared_ptr LogStreamsReferenceMapPtr; +/// @brief Configurations with data types. +/// +/// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations. +/// This is to perform faster while writing logs using correct configurations. +/// +/// This is thread safe and final class containing non-virtual destructor (means nothing should inherit this class) +class TypedConfigurations : public base::threading::ThreadSafe { + public: + /// @brief Constructor to initialize (construct) the object off el::Configurations + /// @param configurations Configurations pointer/reference to base this typed configurations off. + /// @param logStreamsReference Use ELPP->registeredLoggers()->logStreamsReference() + TypedConfigurations(Configurations* configurations, LogStreamsReferenceMapPtr logStreamsReference); + + TypedConfigurations(const TypedConfigurations& other); + + virtual ~TypedConfigurations(void) { + } + + const Configurations* configurations(void) const { + return m_configurations; + } + + bool enabled(Level level); + bool toFile(Level level); + const std::string& filename(Level level); + bool toStandardOutput(Level level); + const base::LogFormat& logFormat(Level level); + const base::SubsecondPrecision& subsecondPrecision(Level level = Level::Global); + const base::MillisecondsWidth& millisecondsWidth(Level level = Level::Global); + bool performanceTracking(Level level = Level::Global); + base::type::fstream_t* fileStream(Level level); + std::size_t maxLogFileSize(Level level); + std::size_t logFlushThreshold(Level level); + + private: + Configurations* m_configurations; + std::unordered_map m_enabledMap; + std::unordered_map m_toFileMap; + std::unordered_map m_filenameMap; + std::unordered_map m_toStandardOutputMap; + std::unordered_map m_logFormatMap; + std::unordered_map m_subsecondPrecisionMap; + std::unordered_map m_performanceTrackingMap; + std::unordered_map m_fileStreamMap; + std::unordered_map m_maxLogFileSizeMap; + std::unordered_map m_logFlushThresholdMap; + LogStreamsReferenceMapPtr m_logStreamsReference = nullptr; + + friend class el::Helpers; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::DefaultLogDispatchCallback; + friend class el::base::LogDispatcher; + + template + inline Conf_T getConfigByVal(Level level, const std::unordered_map* confMap, const char* confName) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope + } + + template + inline Conf_T& getConfigByRef(Level level, std::unordered_map* confMap, const char* confName) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope + } + + template + Conf_T unsafeGetConfigByVal(Level level, const std::unordered_map* confMap, const char* confName) { + ELPP_UNUSED(confName); + typename std::unordered_map::const_iterator it = confMap->find(level); + if (it == confMap->end()) { + try { + return confMap->at(Level::Global); + } catch (...) { + ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" + << LevelHelper::convertToString(level) << "]" + << std::endl << "Please ensure you have properly configured logger.", false); + return Conf_T(); + } + } + return it->second; + } + + template + Conf_T& unsafeGetConfigByRef(Level level, std::unordered_map* confMap, const char* confName) { + ELPP_UNUSED(confName); + typename std::unordered_map::iterator it = confMap->find(level); + if (it == confMap->end()) { + try { + return confMap->at(Level::Global); + } catch (...) { + ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" + << LevelHelper::convertToString(level) << "]" + << std::endl << "Please ensure you have properly configured logger.", false); + } + } + return it->second; + } + + template + void setValue(Level level, const Conf_T& value, std::unordered_map* confMap, + bool includeGlobalLevel = true) { + // If map is empty and we are allowed to add into generic level (Level::Global), do it! + if (confMap->empty() && includeGlobalLevel) { + confMap->insert(std::make_pair(Level::Global, value)); + return; + } + // If same value exist in generic level already, dont add it to explicit level + typename std::unordered_map::iterator it = confMap->find(Level::Global); + if (it != confMap->end() && it->second == value) { + return; + } + // Now make sure we dont double up values if we really need to add it to explicit level + it = confMap->find(level); + if (it == confMap->end()) { + // Value not found for level, add new + confMap->insert(std::make_pair(level, value)); + } else { + // Value found, just update value + confMap->at(level) = value; + } + } + + void build(Configurations* configurations); + unsigned long getULong(std::string confVal); + std::string resolveFilename(const std::string& filename); + void insertFile(Level level, const std::string& fullFilename); + bool unsafeValidateFileRolling(Level level, const PreRollOutCallback& preRollOutCallback); + + inline bool validateFileRolling(Level level, const PreRollOutCallback& preRollOutCallback) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeValidateFileRolling(level, preRollOutCallback); + } +}; +/// @brief Class that keeps record of current line hit for occasional logging +class HitCounter { + public: + HitCounter(void) : + m_filename(""), + m_lineNumber(0), + m_hitCounts(0) { + } + + HitCounter(const char* filename, base::type::LineNumber lineNumber) : + m_filename(filename), + m_lineNumber(lineNumber), + m_hitCounts(0) { + } + + HitCounter(const HitCounter& hitCounter) : + m_filename(hitCounter.m_filename), + m_lineNumber(hitCounter.m_lineNumber), + m_hitCounts(hitCounter.m_hitCounts) { + } + + HitCounter& operator=(const HitCounter& hitCounter) { + if (&hitCounter != this) { + m_filename = hitCounter.m_filename; + m_lineNumber = hitCounter.m_lineNumber; + m_hitCounts = hitCounter.m_hitCounts; + } + return *this; + } + + virtual ~HitCounter(void) { + } + + /// @brief Resets location of current hit counter + inline void resetLocation(const char* filename, base::type::LineNumber lineNumber) { + m_filename = filename; + m_lineNumber = lineNumber; + } + + /// @brief Validates hit counts and resets it if necessary + inline void validateHitCounts(std::size_t n) { + if (m_hitCounts >= base::consts::kMaxLogPerCounter) { + m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0); + } + ++m_hitCounts; + } + + inline const char* filename(void) const { + return m_filename; + } + + inline base::type::LineNumber lineNumber(void) const { + return m_lineNumber; + } + + inline std::size_t hitCounts(void) const { + return m_hitCounts; + } + + inline void increment(void) { + ++m_hitCounts; + } + + class Predicate { + public: + Predicate(const char* filename, base::type::LineNumber lineNumber) + : m_filename(filename), + m_lineNumber(lineNumber) { + } + inline bool operator()(const HitCounter* counter) { + return ((counter != nullptr) && + (strcmp(counter->m_filename, m_filename) == 0) && + (counter->m_lineNumber == m_lineNumber)); + } + + private: + const char* m_filename; + base::type::LineNumber m_lineNumber; + }; + + private: + const char* m_filename; + base::type::LineNumber m_lineNumber; + std::size_t m_hitCounts; +}; +/// @brief Repository for hit counters used across the application +class RegisteredHitCounters : public base::utils::RegistryWithPred { + public: + /// @brief Validates counter for every N, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateEveryN(const char* filename, base::type::LineNumber lineNumber, std::size_t n); + + /// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateAfterN(const char* filename, base::type::LineNumber lineNumber, std::size_t n); + + /// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateNTimes(const char* filename, base::type::LineNumber lineNumber, std::size_t n); + + /// @brief Gets hit counter registered at specified position + inline const base::HitCounter* getCounter(const char* filename, base::type::LineNumber lineNumber) { + base::threading::ScopedLock scopedLock(lock()); + return get(filename, lineNumber); + } +}; +/// @brief Action to be taken for dispatching +enum class DispatchAction : base::type::EnumType { + None = 1, NormalLog = 2, SysLog = 4 +}; +} // namespace base +template +class Callback : protected base::threading::ThreadSafe { + public: + Callback(void) : m_enabled(true) {} + inline bool enabled(void) const { + return m_enabled; + } + inline void setEnabled(bool enabled) { + base::threading::ScopedLock scopedLock(lock()); + m_enabled = enabled; + } + protected: + virtual void handle(const T* handlePtr) = 0; + private: + bool m_enabled; +}; +class LogDispatchData { + public: + LogDispatchData() : m_logMessage(nullptr), m_dispatchAction(base::DispatchAction::None) {} + inline const LogMessage* logMessage(void) const { + return m_logMessage; + } + inline base::DispatchAction dispatchAction(void) const { + return m_dispatchAction; + } + inline void setLogMessage(LogMessage* logMessage) { + m_logMessage = logMessage; + } + inline void setDispatchAction(base::DispatchAction dispatchAction) { + m_dispatchAction = dispatchAction; + } + private: + LogMessage* m_logMessage; + base::DispatchAction m_dispatchAction; + friend class base::LogDispatcher; + +}; +class LogDispatchCallback : public Callback { + protected: + virtual void handle(const LogDispatchData* data); + base::threading::Mutex& fileHandle(const LogDispatchData* data); + private: + friend class base::LogDispatcher; + std::unordered_map> m_fileLocks; + base::threading::Mutex m_fileLocksMapLock; +}; +class PerformanceTrackingCallback : public Callback { + private: + friend class base::PerformanceTracker; +}; +class LoggerRegistrationCallback : public Callback { + private: + friend class base::RegisteredLoggers; +}; +class LogBuilder : base::NoCopy { + public: + LogBuilder() : m_termSupportsColor(base::utils::OS::termSupportsColor()) {} + virtual ~LogBuilder(void) { + ELPP_INTERNAL_INFO(3, "Destroying log builder...") + } + virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0; + void convertToColoredOutput(base::type::string_t* logLine, Level level); + private: + bool m_termSupportsColor; + friend class el::base::DefaultLogDispatchCallback; +}; +typedef std::shared_ptr LogBuilderPtr; +/// @brief Represents a logger holding ID and configurations we need to write logs +/// +/// @detail This class does not write logs itself instead its used by writer to read configurations from. +class Logger : public base::threading::ThreadSafe, public Loggable { + public: + Logger(const std::string& id, base::LogStreamsReferenceMapPtr logStreamsReference); + Logger(const std::string& id, const Configurations& configurations, base::LogStreamsReferenceMapPtr logStreamsReference); + Logger(const Logger& logger); + Logger& operator=(const Logger& logger); + + virtual ~Logger(void) { + base::utils::safeDelete(m_typedConfigurations); + } + + virtual inline void log(el::base::type::ostream_t& os) const { + os << m_id.c_str(); + } + + /// @brief Configures the logger using specified configurations. + void configure(const Configurations& configurations); + + /// @brief Reconfigures logger using existing configurations + void reconfigure(void); + + inline const std::string& id(void) const { + return m_id; + } + + inline const std::string& parentApplicationName(void) const { + return m_parentApplicationName; + } + + inline void setParentApplicationName(const std::string& parentApplicationName) { + m_parentApplicationName = parentApplicationName; + } + + inline Configurations* configurations(void) { + return &m_configurations; + } + + inline base::TypedConfigurations* typedConfigurations(void) { + return m_typedConfigurations; + } + + static bool isValidId(const std::string& id); + + /// @brief Flushes logger to sync all log files for all levels + void flush(void); + + void flush(Level level, base::type::fstream_t* fs); + + inline bool isFlushNeeded(Level level) { + return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level); + } + + inline LogBuilder* logBuilder(void) const { + return m_logBuilder.get(); + } + + inline void setLogBuilder(const LogBuilderPtr& logBuilder) { + m_logBuilder = logBuilder; + } + + inline bool enabled(Level level) const { + return m_typedConfigurations->enabled(level); + } + +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED +# define LOGGER_LEVEL_WRITERS_SIGNATURES(FUNCTION_NAME)\ +template \ +inline void FUNCTION_NAME(const char*, const T&, const Args&...);\ +template \ +inline void FUNCTION_NAME(const T&); + + template + inline void verbose(int, const char*, const T&, const Args&...); + + template + inline void verbose(int, const T&); + + LOGGER_LEVEL_WRITERS_SIGNATURES(info) + LOGGER_LEVEL_WRITERS_SIGNATURES(debug) + LOGGER_LEVEL_WRITERS_SIGNATURES(warn) + LOGGER_LEVEL_WRITERS_SIGNATURES(error) + LOGGER_LEVEL_WRITERS_SIGNATURES(fatal) + LOGGER_LEVEL_WRITERS_SIGNATURES(trace) +# undef LOGGER_LEVEL_WRITERS_SIGNATURES +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED + private: + std::string m_id; + base::TypedConfigurations* m_typedConfigurations; + base::type::stringstream_t m_stream; + std::string m_parentApplicationName; + bool m_isConfigured; + Configurations m_configurations; + std::unordered_map m_unflushedCount; + base::LogStreamsReferenceMapPtr m_logStreamsReference = nullptr; + LogBuilderPtr m_logBuilder; + + friend class el::LogMessage; + friend class el::Loggers; + friend class el::Helpers; + friend class el::base::RegisteredLoggers; + friend class el::base::DefaultLogDispatchCallback; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::PErrorWriter; + friend class el::base::Storage; + friend class el::base::PerformanceTracker; + friend class el::base::LogDispatcher; + + Logger(void); + +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED + template + void log_(Level, int, const char*, const T&, const Args&...); + + template + inline void log_(Level, int, const T&); + + template + void log(Level, const char*, const T&, const Args&...); + + template + inline void log(Level, const T&); +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED + + void initUnflushedCount(void); + + inline base::type::stringstream_t& stream(void) { + return m_stream; + } + + void resolveLoggerFormatSpec(void) const; +}; +namespace base { +/// @brief Loggers repository +class RegisteredLoggers : public base::utils::Registry { + public: + explicit RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder); + + virtual ~RegisteredLoggers(void) { + unsafeFlushAll(); + } + + inline void setDefaultConfigurations(const Configurations& configurations) { + base::threading::ScopedLock scopedLock(lock()); + m_defaultConfigurations.setFromBase(const_cast(&configurations)); + } + + inline Configurations* defaultConfigurations(void) { + return &m_defaultConfigurations; + } + + Logger* get(const std::string& id, bool forceCreation = true); + + template + inline bool installLoggerRegistrationCallback(const std::string& id) { + return base::utils::Utils::installCallback(id, + &m_loggerRegistrationCallbacks); + } + + template + inline void uninstallLoggerRegistrationCallback(const std::string& id) { + base::utils::Utils::uninstallCallback(id, &m_loggerRegistrationCallbacks); + } + + template + inline T* loggerRegistrationCallback(const std::string& id) { + return base::utils::Utils::callback(id, &m_loggerRegistrationCallbacks); + } + + bool remove(const std::string& id); + + inline bool has(const std::string& id) { + return get(id, false) != nullptr; + } + + inline void unregister(Logger*& logger) { + base::threading::ScopedLock scopedLock(lock()); + base::utils::Registry::unregister(logger->id()); + } + + inline LogStreamsReferenceMapPtr logStreamsReference(void) { + return m_logStreamsReference; + } + + inline void flushAll(void) { + base::threading::ScopedLock scopedLock(lock()); + unsafeFlushAll(); + } + + inline void setDefaultLogBuilder(LogBuilderPtr& logBuilderPtr) { + base::threading::ScopedLock scopedLock(lock()); + m_defaultLogBuilder = logBuilderPtr; + } + + private: + LogBuilderPtr m_defaultLogBuilder; + Configurations m_defaultConfigurations; + base::LogStreamsReferenceMapPtr m_logStreamsReference = nullptr; + std::unordered_map m_loggerRegistrationCallbacks; + friend class el::base::Storage; + + void unsafeFlushAll(void); +}; +/// @brief Represents registries for verbose logging +class VRegistry : base::NoCopy, public base::threading::ThreadSafe { + public: + explicit VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags); + + /// @brief Sets verbose level. Accepted range is 0-9 + void setLevel(base::type::VerboseLevel level); + + inline base::type::VerboseLevel level(void) const { + return m_level; + } + + inline void clearModules(void) { + base::threading::ScopedLock scopedLock(lock()); + m_modules.clear(); + } + + void setModules(const char* modules); + + bool allowed(base::type::VerboseLevel vlevel, const char* file); + + inline const std::unordered_map& modules(void) const { + return m_modules; + } + + void setFromArgs(const base::utils::CommandLineArgs* commandLineArgs); + + /// @brief Whether or not vModules enabled + inline bool vModulesEnabled(void) { + return !base::utils::hasFlag(LoggingFlag::DisableVModules, *m_pFlags); + } + + private: + base::type::VerboseLevel m_level; + base::type::EnumType* m_pFlags; + std::unordered_map m_modules; +}; +} // namespace base +class LogMessage { + public: + LogMessage(Level level, const std::string& file, base::type::LineNumber line, const std::string& func, + base::type::VerboseLevel verboseLevel, Logger* logger) : + m_level(level), m_file(file), m_line(line), m_func(func), + m_verboseLevel(verboseLevel), m_logger(logger), m_message(logger->stream().str()) { + } + inline Level level(void) const { + return m_level; + } + inline const std::string& file(void) const { + return m_file; + } + inline base::type::LineNumber line(void) const { + return m_line; + } + inline const std::string& func(void) const { + return m_func; + } + inline base::type::VerboseLevel verboseLevel(void) const { + return m_verboseLevel; + } + inline Logger* logger(void) const { + return m_logger; + } + inline const base::type::string_t& message(void) const { + return m_message; + } + private: + Level m_level; + std::string m_file; + base::type::LineNumber m_line; + std::string m_func; + base::type::VerboseLevel m_verboseLevel; + Logger* m_logger; + base::type::string_t m_message; +}; +namespace base { +#if ELPP_ASYNC_LOGGING +class AsyncLogItem { + public: + explicit AsyncLogItem(const LogMessage& logMessage, const LogDispatchData& data, const base::type::string_t& logLine) + : m_logMessage(logMessage), m_dispatchData(data), m_logLine(logLine) {} + virtual ~AsyncLogItem() {} + inline LogMessage* logMessage(void) { + return &m_logMessage; + } + inline LogDispatchData* data(void) { + return &m_dispatchData; + } + inline base::type::string_t logLine(void) { + return m_logLine; + } + private: + LogMessage m_logMessage; + LogDispatchData m_dispatchData; + base::type::string_t m_logLine; +}; +class AsyncLogQueue : public base::threading::ThreadSafe { + public: + virtual ~AsyncLogQueue() { + ELPP_INTERNAL_INFO(6, "~AsyncLogQueue"); + } + + inline AsyncLogItem next(void) { + base::threading::ScopedLock scopedLock(lock()); + AsyncLogItem result = m_queue.front(); + m_queue.pop(); + return result; + } + + inline void push(const AsyncLogItem& item) { + base::threading::ScopedLock scopedLock(lock()); + m_queue.push(item); + } + inline void pop(void) { + base::threading::ScopedLock scopedLock(lock()); + m_queue.pop(); + } + inline AsyncLogItem front(void) { + base::threading::ScopedLock scopedLock(lock()); + return m_queue.front(); + } + inline bool empty(void) { + base::threading::ScopedLock scopedLock(lock()); + return m_queue.empty(); + } + private: + std::queue m_queue; +}; +class IWorker { + public: + virtual ~IWorker() {} + virtual void start() = 0; +}; +#endif // ELPP_ASYNC_LOGGING +/// @brief Easylogging++ management storage +class Storage : base::NoCopy, public base::threading::ThreadSafe { + public: +#if ELPP_ASYNC_LOGGING + Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker); +#else + explicit Storage(const LogBuilderPtr& defaultLogBuilder); +#endif // ELPP_ASYNC_LOGGING + + virtual ~Storage(void); + + inline bool validateEveryNCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t occasion) { + return hitCounters()->validateEveryN(filename, lineNumber, occasion); + } + + inline bool validateAfterNCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { + return hitCounters()->validateAfterN(filename, lineNumber, n); + } + + inline bool validateNTimesCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { + return hitCounters()->validateNTimes(filename, lineNumber, n); + } + + inline base::RegisteredHitCounters* hitCounters(void) const { + return m_registeredHitCounters; + } + + inline base::RegisteredLoggers* registeredLoggers(void) const { + return m_registeredLoggers; + } + + inline base::VRegistry* vRegistry(void) const { + return m_vRegistry; + } + +#if ELPP_ASYNC_LOGGING + inline base::AsyncLogQueue* asyncLogQueue(void) const { + return m_asyncLogQueue; + } +#endif // ELPP_ASYNC_LOGGING + + inline const base::utils::CommandLineArgs* commandLineArgs(void) const { + return &m_commandLineArgs; + } + + inline void addFlag(LoggingFlag flag) { + base::utils::addFlag(flag, &m_flags); + } + + inline void removeFlag(LoggingFlag flag) { + base::utils::removeFlag(flag, &m_flags); + } + + inline bool hasFlag(LoggingFlag flag) const { + return base::utils::hasFlag(flag, m_flags); + } + + inline base::type::EnumType flags(void) const { + return m_flags; + } + + inline void setFlags(base::type::EnumType flags) { + m_flags = flags; + } + + inline void setPreRollOutCallback(const PreRollOutCallback& callback) { + m_preRollOutCallback = callback; + } + + inline void unsetPreRollOutCallback(void) { + m_preRollOutCallback = base::defaultPreRollOutCallback; + } + + inline PreRollOutCallback& preRollOutCallback(void) { + return m_preRollOutCallback; + } + + bool hasCustomFormatSpecifier(const char* formatSpecifier); + void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier); + bool uninstallCustomFormatSpecifier(const char* formatSpecifier); + + const std::vector* customFormatSpecifiers(void) const { + return &m_customFormatSpecifiers; + } + + base::threading::Mutex& customFormatSpecifiersLock() { + return m_customFormatSpecifiersLock; + } + + inline void setLoggingLevel(Level level) { + m_loggingLevel = level; + } + + template + inline bool installLogDispatchCallback(const std::string& id) { + return base::utils::Utils::installCallback(id, &m_logDispatchCallbacks); + } + + template + inline void uninstallLogDispatchCallback(const std::string& id) { + base::utils::Utils::uninstallCallback(id, &m_logDispatchCallbacks); + } + template + inline T* logDispatchCallback(const std::string& id) { + return base::utils::Utils::callback(id, &m_logDispatchCallbacks); + } + +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + template + inline bool installPerformanceTrackingCallback(const std::string& id) { + return base::utils::Utils::installCallback(id, + &m_performanceTrackingCallbacks); + } + + template + inline void uninstallPerformanceTrackingCallback(const std::string& id) { + base::utils::Utils::uninstallCallback(id, + &m_performanceTrackingCallbacks); + } + + template + inline T* performanceTrackingCallback(const std::string& id) { + return base::utils::Utils::callback(id, &m_performanceTrackingCallbacks); + } +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + + /// @brief Sets thread name for current thread. Requires std::thread + inline void setThreadName(const std::string& name) { + if (name.empty()) return; + base::threading::ScopedLock scopedLock(m_threadNamesLock); + m_threadNames[base::threading::getCurrentThreadId()] = name; + } + + inline std::string getThreadName(const std::string& threadId) { + base::threading::ScopedLock scopedLock(m_threadNamesLock); + std::unordered_map::const_iterator it = m_threadNames.find(threadId); + if (it == m_threadNames.end()) { + return threadId; + } + return it->second; + } + private: + base::RegisteredHitCounters* m_registeredHitCounters; + base::RegisteredLoggers* m_registeredLoggers; + base::type::EnumType m_flags; + base::VRegistry* m_vRegistry; +#if ELPP_ASYNC_LOGGING + base::AsyncLogQueue* m_asyncLogQueue; + base::IWorker* m_asyncDispatchWorker; +#endif // ELPP_ASYNC_LOGGING + base::utils::CommandLineArgs m_commandLineArgs; + PreRollOutCallback m_preRollOutCallback; + std::unordered_map m_logDispatchCallbacks; + std::unordered_map m_performanceTrackingCallbacks; + std::unordered_map m_threadNames; + std::vector m_customFormatSpecifiers; + base::threading::Mutex m_customFormatSpecifiersLock; + base::threading::Mutex m_threadNamesLock; + Level m_loggingLevel; + + friend class el::Helpers; + friend class el::base::DefaultLogDispatchCallback; + friend class el::LogBuilder; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::PerformanceTracker; + friend class el::base::LogDispatcher; + + void setApplicationArguments(int argc, char** argv); + + inline void setApplicationArguments(int argc, const char** argv) { + setApplicationArguments(argc, const_cast(argv)); + } +}; +extern ELPP_EXPORT base::type::StoragePointer elStorage; +#define ELPP el::base::elStorage +class DefaultLogDispatchCallback : public LogDispatchCallback { + protected: + void handle(const LogDispatchData* data); + private: + const LogDispatchData* m_data; + void dispatch(base::type::string_t&& logLine); +}; +#if ELPP_ASYNC_LOGGING +class AsyncLogDispatchCallback : public LogDispatchCallback { + protected: + void handle(const LogDispatchData* data); +}; +class AsyncDispatchWorker : public base::IWorker, public base::threading::ThreadSafe { + public: + AsyncDispatchWorker(); + virtual ~AsyncDispatchWorker(); + + bool clean(void); + void emptyQueue(void); + virtual void start(void); + void handle(AsyncLogItem* logItem); + void run(void); + + void setContinueRunning(bool value) { + base::threading::ScopedLock scopedLock(m_continueRunningLock); + m_continueRunning = value; + } + + bool continueRunning(void) const { + return m_continueRunning; + } + private: + std::condition_variable cv; + bool m_continueRunning; + base::threading::Mutex m_continueRunningLock; +}; +#endif // ELPP_ASYNC_LOGGING +} // namespace base +namespace base { +class DefaultLogBuilder : public LogBuilder { + public: + base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const; +}; +/// @brief Dispatches log messages +class LogDispatcher : base::NoCopy { + public: + LogDispatcher(bool proceed, LogMessage* logMessage, base::DispatchAction dispatchAction) : + m_proceed(proceed), + m_logMessage(logMessage), + m_dispatchAction(std::move(dispatchAction)) { + } + + void dispatch(void); + + private: + bool m_proceed; + LogMessage* m_logMessage; + base::DispatchAction m_dispatchAction; +}; +#if defined(ELPP_STL_LOGGING) +/// @brief Workarounds to write some STL logs +/// +/// @detail There is workaround needed to loop through some stl containers. In order to do that, we need iterable containers +/// of same type and provide iterator interface and pass it on to writeIterator(). +/// Remember, this is passed by value in constructor so that we dont change original containers. +/// This operation is as expensive as Big-O(std::min(class_.size(), base::consts::kMaxLogPerContainer)) +namespace workarounds { +/// @brief Abstract IterableContainer template that provides interface for iterable classes of type T +template +class IterableContainer { + public: + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + IterableContainer(void) {} + virtual ~IterableContainer(void) {} + iterator begin(void) { + return getContainer().begin(); + } + iterator end(void) { + return getContainer().end(); + } + private: + virtual Container& getContainer(void) = 0; +}; +/// @brief Implements IterableContainer and provides iterable std::priority_queue class +template, typename Comparator = std::less> +class IterablePriorityQueue : public IterableContainer, + public std::priority_queue { + public: + IterablePriorityQueue(std::priority_queue queue_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { + this->push(queue_.top()); + queue_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } +}; +/// @brief Implements IterableContainer and provides iterable std::queue class +template> +class IterableQueue : public IterableContainer, public std::queue { + public: + IterableQueue(std::queue queue_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { + this->push(queue_.front()); + queue_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } +}; +/// @brief Implements IterableContainer and provides iterable std::stack class +template> +class IterableStack : public IterableContainer, public std::stack { + public: + IterableStack(std::stack stack_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !stack_.empty()) { + this->push(stack_.top()); + stack_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } +}; +} // namespace workarounds +#endif // defined(ELPP_STL_LOGGING) +// Log message builder +class MessageBuilder { + public: + MessageBuilder(void) : m_logger(nullptr), m_containerLogSeparator(ELPP_LITERAL("")) {} + void initialize(Logger* logger); + +# define ELPP_SIMPLE_LOG(LOG_TYPE)\ +MessageBuilder& operator<<(LOG_TYPE msg) {\ +m_logger->stream() << msg;\ +if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) {\ +m_logger->stream() << " ";\ +}\ +return *this;\ +} + + inline MessageBuilder& operator<<(const std::string& msg) { + return operator<<(msg.c_str()); + } + ELPP_SIMPLE_LOG(char) + ELPP_SIMPLE_LOG(bool) + ELPP_SIMPLE_LOG(signed short) + ELPP_SIMPLE_LOG(unsigned short) + ELPP_SIMPLE_LOG(signed int) + ELPP_SIMPLE_LOG(unsigned int) + ELPP_SIMPLE_LOG(signed long) + ELPP_SIMPLE_LOG(unsigned long) + ELPP_SIMPLE_LOG(float) + ELPP_SIMPLE_LOG(double) + ELPP_SIMPLE_LOG(char*) + ELPP_SIMPLE_LOG(const char*) + ELPP_SIMPLE_LOG(const void*) + ELPP_SIMPLE_LOG(long double) + inline MessageBuilder& operator<<(const std::wstring& msg) { + return operator<<(msg.c_str()); + } + MessageBuilder& operator<<(const wchar_t* msg); + // ostream manipulators + inline MessageBuilder& operator<<(std::ostream& (*OStreamMani)(std::ostream&)) { + m_logger->stream() << OStreamMani; + return *this; + } +#define ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(temp) \ +template \ +inline MessageBuilder& operator<<(const temp& template_inst) { \ +return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ +} +#define ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(temp) \ +template \ +inline MessageBuilder& operator<<(const temp& template_inst) { \ +return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ +} +#define ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(temp) \ +template \ +inline MessageBuilder& operator<<(const temp& template_inst) { \ +return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ +} +#define ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(temp) \ +template \ +inline MessageBuilder& operator<<(const temp& template_inst) { \ +return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ +} +#define ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(temp) \ +template \ +inline MessageBuilder& operator<<(const temp& template_inst) { \ +return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ +} + +#if defined(ELPP_STL_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::list) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::deque) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::set) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::multiset) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::map) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::multimap) + template + inline MessageBuilder& operator<<(const std::queue& queue_) { + base::workarounds::IterableQueue iterableQueue_ = + static_cast >(queue_); + return writeIterator(iterableQueue_.begin(), iterableQueue_.end(), iterableQueue_.size()); + } + template + inline MessageBuilder& operator<<(const std::stack& stack_) { + base::workarounds::IterableStack iterableStack_ = + static_cast >(stack_); + return writeIterator(iterableStack_.begin(), iterableStack_.end(), iterableStack_.size()); + } + template + inline MessageBuilder& operator<<(const std::priority_queue& priorityQueue_) { + base::workarounds::IterablePriorityQueue iterablePriorityQueue_ = + static_cast >(priorityQueue_); + return writeIterator(iterablePriorityQueue_.begin(), iterablePriorityQueue_.end(), iterablePriorityQueue_.size()); + } + template + MessageBuilder& operator<<(const std::pair& pair_) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast(pair_.first)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast(pair_.second)); + m_logger->stream() << ELPP_LITERAL(")"); + return *this; + } + template + MessageBuilder& operator<<(const std::bitset& bitset_) { + m_logger->stream() << ELPP_LITERAL("["); + operator << (bitset_.to_string()); + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } +# if defined(ELPP_LOG_STD_ARRAY) + template + inline MessageBuilder& operator<<(const std::array& array) { + return writeIterator(array.begin(), array.end(), array.size()); + } +# endif // defined(ELPP_LOG_STD_ARRAY) +# if defined(ELPP_LOG_UNORDERED_MAP) + ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_map) + ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_multimap) +# endif // defined(ELPP_LOG_UNORDERED_MAP) +# if defined(ELPP_LOG_UNORDERED_SET) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_set) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_multiset) +# endif // defined(ELPP_LOG_UNORDERED_SET) +#endif // defined(ELPP_STL_LOGGING) +#if defined(ELPP_QT_LOGGING) + inline MessageBuilder& operator<<(const QString& msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << msg.toStdWString(); +# else + m_logger->stream() << msg.toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(const QByteArray& msg) { + return operator << (QString(msg)); + } + inline MessageBuilder& operator<<(const QStringRef& msg) { + return operator<<(msg.toString()); + } + inline MessageBuilder& operator<<(qint64 msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << QString::number(msg).toStdWString(); +# else + m_logger->stream() << QString::number(msg).toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(quint64 msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << QString::number(msg).toStdWString(); +# else + m_logger->stream() << QString::number(msg).toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(QChar msg) { + m_logger->stream() << msg.toLatin1(); + return *this; + } + inline MessageBuilder& operator<<(const QLatin1String& msg) { + m_logger->stream() << msg.latin1(); + return *this; + } + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QList) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QVector) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QQueue) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QSet) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QLinkedList) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QStack) + template + MessageBuilder& operator<<(const QPair& pair_) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast(pair_.first)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast(pair_.second)); + m_logger->stream() << ELPP_LITERAL(")"); + return *this; + } + template + MessageBuilder& operator<<(const QMap& map_) { + m_logger->stream() << ELPP_LITERAL("["); + QList keys = map_.keys(); + typename QList::const_iterator begin = keys.begin(); + typename QList::const_iterator end = keys.end(); + int max_ = static_cast(base::consts::kMaxLogPerContainer); // to prevent warning + for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast(*begin)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast(map_.value(*begin))); + m_logger->stream() << ELPP_LITERAL(")"); + m_logger->stream() << ((index_ < keys.size() -1) ? m_containerLogSeparator : ELPP_LITERAL("")); + } + if (begin != end) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } + template + inline MessageBuilder& operator<<(const QMultiMap& map_) { + operator << (static_cast>(map_)); + return *this; + } + template + MessageBuilder& operator<<(const QHash& hash_) { + m_logger->stream() << ELPP_LITERAL("["); + QList keys = hash_.keys(); + typename QList::const_iterator begin = keys.begin(); + typename QList::const_iterator end = keys.end(); + int max_ = static_cast(base::consts::kMaxLogPerContainer); // prevent type warning + for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast(*begin)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast(hash_.value(*begin))); + m_logger->stream() << ELPP_LITERAL(")"); + m_logger->stream() << ((index_ < keys.size() -1) ? m_containerLogSeparator : ELPP_LITERAL("")); + } + if (begin != end) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } + template + inline MessageBuilder& operator<<(const QMultiHash& multiHash_) { + operator << (static_cast>(multiHash_)); + return *this; + } +#endif // defined(ELPP_QT_LOGGING) +#if defined(ELPP_BOOST_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::stable_vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::list) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::deque) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::map) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::flat_map) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::set) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::flat_set) +#endif // defined(ELPP_BOOST_LOGGING) + + /// @brief Macro used internally that can be used externally to make containers easylogging++ friendly + /// + /// @detail This macro expands to write an ostream& operator<< for container. This container is expected to + /// have begin() and end() methods that return respective iterators + /// @param ContainerType Type of container e.g, MyList from WX_DECLARE_LIST(int, MyList); in wxwidgets + /// @param SizeMethod Method used to get size of container. + /// @param ElementInstance Instance of element to be fed out. Instance name is "elem". See WXELPP_ENABLED macro + /// for an example usage +#define MAKE_CONTAINERELPP_FRIENDLY(ContainerType, SizeMethod, ElementInstance) \ +el::base::type::ostream_t& operator<<(el::base::type::ostream_t& ss, const ContainerType& container) {\ +const el::base::type::char_t* sep = ELPP->hasFlag(el::LoggingFlag::NewLineForContainer) ? \ +ELPP_LITERAL("\n ") : ELPP_LITERAL(", ");\ +ContainerType::const_iterator elem = container.begin();\ +ContainerType::const_iterator endElem = container.end();\ +std::size_t size_ = container.SizeMethod; \ +ss << ELPP_LITERAL("[");\ +for (std::size_t i = 0; elem != endElem && i < el::base::consts::kMaxLogPerContainer; ++i, ++elem) { \ +ss << ElementInstance;\ +ss << ((i < size_ - 1) ? sep : ELPP_LITERAL(""));\ +}\ +if (elem != endElem) {\ +ss << ELPP_LITERAL("...");\ +}\ +ss << ELPP_LITERAL("]");\ +return ss;\ +} +#if defined(ELPP_WXWIDGETS_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(wxVector) +# define ELPP_WX_PTR_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), *(*elem)) +# define ELPP_WX_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), (*elem)) +# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), \ +ELPP_LITERAL("(") << elem->first << ELPP_LITERAL(", ") << elem->second << ELPP_LITERAL(")") +#else +# define ELPP_WX_PTR_ENABLED(ContainerType) +# define ELPP_WX_ENABLED(ContainerType) +# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) +#endif // defined(ELPP_WXWIDGETS_LOGGING) + // Other classes + template + ELPP_SIMPLE_LOG(const Class&) +#undef ELPP_SIMPLE_LOG +#undef ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG + private: + Logger* m_logger; + const base::type::char_t* m_containerLogSeparator; + + template + MessageBuilder& writeIterator(Iterator begin_, Iterator end_, std::size_t size_) { + m_logger->stream() << ELPP_LITERAL("["); + for (std::size_t i = 0; begin_ != end_ && i < base::consts::kMaxLogPerContainer; ++i, ++begin_) { + operator << (*begin_); + m_logger->stream() << ((i < size_ - 1) ? m_containerLogSeparator : ELPP_LITERAL("")); + } + if (begin_ != end_) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { + m_logger->stream() << " "; + } + return *this; + } +}; +/// @brief Writes nothing - Used when certain log is disabled +class NullWriter : base::NoCopy { + public: + NullWriter(void) {} + + // Null manipulator + inline NullWriter& operator<<(std::ostream& (*)(std::ostream&)) { + return *this; + } + + template + inline NullWriter& operator<<(const T&) { + return *this; + } + + inline operator bool() { + return true; + } +}; +/// @brief Main entry point of each logging +class Writer : base::NoCopy { + public: + Writer(Level level, const char* file, base::type::LineNumber line, + const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, + base::type::VerboseLevel verboseLevel = 0) : + m_msg(nullptr), m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), + m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) { + } + + Writer(LogMessage* msg, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog) : + m_msg(msg), m_level(msg != nullptr ? msg->level() : Level::Unknown), + m_line(0), m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) { + } + + virtual ~Writer(void) { + processDispatch(); + } + + template + inline Writer& operator<<(const T& log) { +#if ELPP_LOGGING_ENABLED + if (m_proceed) { + m_messageBuilder << log; + } +#endif // ELPP_LOGGING_ENABLED + return *this; + } + + inline Writer& operator<<(std::ostream& (*log)(std::ostream&)) { +#if ELPP_LOGGING_ENABLED + if (m_proceed) { + m_messageBuilder << log; + } +#endif // ELPP_LOGGING_ENABLED + return *this; + } + + inline operator bool() { + return true; + } + + Writer& construct(Logger* logger, bool needLock = true); + Writer& construct(int count, const char* loggerIds, ...); + protected: + LogMessage* m_msg; + Level m_level; + const char* m_file; + const base::type::LineNumber m_line; + const char* m_func; + base::type::VerboseLevel m_verboseLevel; + Logger* m_logger; + bool m_proceed; + base::MessageBuilder m_messageBuilder; + base::DispatchAction m_dispatchAction; + std::vector m_loggerIds; + friend class el::Helpers; + + void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true); + void processDispatch(); + void triggerDispatch(void); +}; +class PErrorWriter : public base::Writer { + public: + PErrorWriter(Level level, const char* file, base::type::LineNumber line, + const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, + base::type::VerboseLevel verboseLevel = 0) : + base::Writer(level, file, line, func, dispatchAction, verboseLevel) { + } + + virtual ~PErrorWriter(void); +}; +} // namespace base +// Logging from Logger class. Why this is here? Because we have Storage and Writer class available +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED +template +void Logger::log_(Level level, int vlevel, const char* s, const T& value, const Args&... args) { + base::MessageBuilder b; + b.initialize(this); + while (*s) { + if (*s == base::consts::kFormatSpecifierChar) { + if (*(s + 1) == base::consts::kFormatSpecifierChar) { + ++s; + } else { + if (*(s + 1) == base::consts::kFormatSpecifierCharValue) { + ++s; + b << value; + log_(level, vlevel, ++s, args...); + return; + } + } + } + b << *s++; + } + ELPP_INTERNAL_ERROR("Too many arguments provided. Unable to handle. Please provide more format specifiers", false); +} +template +void Logger::log_(Level level, int vlevel, const T& log) { + if (level == Level::Verbose) { + if (ELPP->vRegistry()->allowed(vlevel, __FILE__)) { + base::Writer(Level::Verbose, "FILE", 0, "FUNCTION", + base::DispatchAction::NormalLog, vlevel).construct(this, false) << log; + } else { + stream().str(ELPP_LITERAL("")); + releaseLock(); + } + } else { + base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log; + } +} +template +inline void Logger::log(Level level, const char* s, const T& value, const Args&... args) { + acquireLock(); // released in Writer! + log_(level, 0, s, value, args...); +} +template +inline void Logger::log(Level level, const T& log) { + acquireLock(); // released in Writer! + log_(level, 0, log); +} +# if ELPP_VERBOSE_LOG +template +inline void Logger::verbose(int vlevel, const char* s, const T& value, const Args&... args) { + acquireLock(); // released in Writer! + log_(el::Level::Verbose, vlevel, s, value, args...); +} +template +inline void Logger::verbose(int vlevel, const T& log) { + acquireLock(); // released in Writer! + log_(el::Level::Verbose, vlevel, log); +} +# else +template +inline void Logger::verbose(int, const char*, const T&, const Args&...) { + return; +} +template +inline void Logger::verbose(int, const T&) { + return; +} +# endif // ELPP_VERBOSE_LOG +# define LOGGER_LEVEL_WRITERS(FUNCTION_NAME, LOG_LEVEL)\ +template \ +inline void Logger::FUNCTION_NAME(const char* s, const T& value, const Args&... args) {\ +log(LOG_LEVEL, s, value, args...);\ +}\ +template \ +inline void Logger::FUNCTION_NAME(const T& value) {\ +log(LOG_LEVEL, value);\ +} +# define LOGGER_LEVEL_WRITERS_DISABLED(FUNCTION_NAME, LOG_LEVEL)\ +template \ +inline void Logger::FUNCTION_NAME(const char*, const T&, const Args&...) {\ +return;\ +}\ +template \ +inline void Logger::FUNCTION_NAME(const T&) {\ +return;\ +} + +# if ELPP_INFO_LOG +LOGGER_LEVEL_WRITERS(info, Level::Info) +# else +LOGGER_LEVEL_WRITERS_DISABLED(info, Level::Info) +# endif // ELPP_INFO_LOG +# if ELPP_DEBUG_LOG +LOGGER_LEVEL_WRITERS(debug, Level::Debug) +# else +LOGGER_LEVEL_WRITERS_DISABLED(debug, Level::Debug) +# endif // ELPP_DEBUG_LOG +# if ELPP_WARNING_LOG +LOGGER_LEVEL_WRITERS(warn, Level::Warning) +# else +LOGGER_LEVEL_WRITERS_DISABLED(warn, Level::Warning) +# endif // ELPP_WARNING_LOG +# if ELPP_ERROR_LOG +LOGGER_LEVEL_WRITERS(error, Level::Error) +# else +LOGGER_LEVEL_WRITERS_DISABLED(error, Level::Error) +# endif // ELPP_ERROR_LOG +# if ELPP_FATAL_LOG +LOGGER_LEVEL_WRITERS(fatal, Level::Fatal) +# else +LOGGER_LEVEL_WRITERS_DISABLED(fatal, Level::Fatal) +# endif // ELPP_FATAL_LOG +# if ELPP_TRACE_LOG +LOGGER_LEVEL_WRITERS(trace, Level::Trace) +# else +LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace) +# endif // ELPP_TRACE_LOG +# undef LOGGER_LEVEL_WRITERS +# undef LOGGER_LEVEL_WRITERS_DISABLED +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED +#if ELPP_COMPILER_MSVC +# define ELPP_VARIADIC_FUNC_MSVC(variadicFunction, variadicArgs) variadicFunction variadicArgs +# define ELPP_VARIADIC_FUNC_MSVC_RUN(variadicFunction, ...) ELPP_VARIADIC_FUNC_MSVC(variadicFunction, (__VA_ARGS__)) +# define el_getVALength(...) ELPP_VARIADIC_FUNC_MSVC_RUN(el_resolveVALength, 0, ## __VA_ARGS__,\ +10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +#else +# if ELPP_COMPILER_CLANG +# define el_getVALength(...) el_resolveVALength(0, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +# else +# define el_getVALength(...) el_resolveVALength(0, ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +# endif // ELPP_COMPILER_CLANG +#endif // ELPP_COMPILER_MSVC +#define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N +#define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \ +writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \ +writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \ +ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion) && \ +writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \ +ELPP->validateAfterNCounter(__FILE__, __LINE__, n) && \ +writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \ +ELPP->validateNTimesCounter(__FILE__, __LINE__, n) && \ +writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) +class PerformanceTrackingData { + public: + enum class DataType : base::type::EnumType { + Checkpoint = 1, Complete = 2 + }; + // Do not use constructor, will run into multiple definition error, use init(PerformanceTracker*) + explicit PerformanceTrackingData(DataType dataType) : m_performanceTracker(nullptr), + m_dataType(dataType), m_firstCheckpoint(false), m_file(""), m_line(0), m_func("") {} + inline const std::string* blockName(void) const; + inline const struct timeval* startTime(void) const; + inline const struct timeval* endTime(void) const; + inline const struct timeval* lastCheckpointTime(void) const; + inline const base::PerformanceTracker* performanceTracker(void) const { + return m_performanceTracker; + } + inline PerformanceTrackingData::DataType dataType(void) const { + return m_dataType; + } + inline bool firstCheckpoint(void) const { + return m_firstCheckpoint; + } + inline std::string checkpointId(void) const { + return m_checkpointId; + } + inline const char* file(void) const { + return m_file; + } + inline base::type::LineNumber line(void) const { + return m_line; + } + inline const char* func(void) const { + return m_func; + } + inline const base::type::string_t* formattedTimeTaken() const { + return &m_formattedTimeTaken; + } + inline const std::string& loggerId(void) const; + private: + base::PerformanceTracker* m_performanceTracker; + base::type::string_t m_formattedTimeTaken; + PerformanceTrackingData::DataType m_dataType; + bool m_firstCheckpoint; + std::string m_checkpointId; + const char* m_file; + base::type::LineNumber m_line; + const char* m_func; + inline void init(base::PerformanceTracker* performanceTracker, bool firstCheckpoint = false) { + m_performanceTracker = performanceTracker; + m_firstCheckpoint = firstCheckpoint; + } + + friend class el::base::PerformanceTracker; +}; +namespace base { +/// @brief Represents performanceTracker block of code that conditionally adds performance status to log +/// either when goes outside the scope of when checkpoint() is called +class PerformanceTracker : public base::threading::ThreadSafe, public Loggable { + public: + PerformanceTracker(const std::string& blockName, + base::TimestampUnit timestampUnit = base::TimestampUnit::Millisecond, + const std::string& loggerId = std::string(el::base::consts::kPerformanceLoggerId), + bool scopedLog = true, Level level = base::consts::kPerformanceTrackerDefaultLevel); + /// @brief Copy constructor + PerformanceTracker(const PerformanceTracker& t) : + m_blockName(t.m_blockName), m_timestampUnit(t.m_timestampUnit), m_loggerId(t.m_loggerId), m_scopedLog(t.m_scopedLog), + m_level(t.m_level), m_hasChecked(t.m_hasChecked), m_lastCheckpointId(t.m_lastCheckpointId), m_enabled(t.m_enabled), + m_startTime(t.m_startTime), m_endTime(t.m_endTime), m_lastCheckpointTime(t.m_lastCheckpointTime) { + } + virtual ~PerformanceTracker(void); + /// @brief A checkpoint for current performanceTracker block. + void checkpoint(const std::string& id = std::string(), const char* file = __FILE__, + base::type::LineNumber line = __LINE__, + const char* func = ""); + inline Level level(void) const { + return m_level; + } + private: + std::string m_blockName; + base::TimestampUnit m_timestampUnit; + std::string m_loggerId; + bool m_scopedLog; + Level m_level; + bool m_hasChecked; + std::string m_lastCheckpointId; + bool m_enabled; + struct timeval m_startTime, m_endTime, m_lastCheckpointTime; + + PerformanceTracker(void); + + friend class el::PerformanceTrackingData; + friend class base::DefaultPerformanceTrackingCallback; + + const inline base::type::string_t getFormattedTimeTaken() const { + return getFormattedTimeTaken(m_startTime); + } + + const base::type::string_t getFormattedTimeTaken(struct timeval startTime) const; + + virtual inline void log(el::base::type::ostream_t& os) const { + os << getFormattedTimeTaken(); + } +}; +class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback { + protected: + void handle(const PerformanceTrackingData* data) { + m_data = data; + base::type::stringstream_t ss; + if (m_data->dataType() == PerformanceTrackingData::DataType::Complete) { + ss << ELPP_LITERAL("Executed [") << m_data->blockName()->c_str() << ELPP_LITERAL("] in [") << + *m_data->formattedTimeTaken() << ELPP_LITERAL("]"); + } else { + ss << ELPP_LITERAL("Performance checkpoint"); + if (!m_data->checkpointId().empty()) { + ss << ELPP_LITERAL(" [") << m_data->checkpointId().c_str() << ELPP_LITERAL("]"); + } + ss << ELPP_LITERAL(" for block [") << m_data->blockName()->c_str() << ELPP_LITERAL("] : [") << + *m_data->performanceTracker(); + if (!ELPP->hasFlag(LoggingFlag::DisablePerformanceTrackingCheckpointComparison) + && m_data->performanceTracker()->m_hasChecked) { + ss << ELPP_LITERAL(" ([") << *m_data->formattedTimeTaken() << ELPP_LITERAL("] from "); + if (m_data->performanceTracker()->m_lastCheckpointId.empty()) { + ss << ELPP_LITERAL("last checkpoint"); + } else { + ss << ELPP_LITERAL("checkpoint '") << m_data->performanceTracker()->m_lastCheckpointId.c_str() << ELPP_LITERAL("'"); + } + ss << ELPP_LITERAL(")]"); + } else { + ss << ELPP_LITERAL("]"); + } + } + el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1, + m_data->loggerId().c_str()) << ss.str(); + } + private: + const PerformanceTrackingData* m_data; +}; +} // namespace base +inline const std::string* PerformanceTrackingData::blockName() const { + return const_cast(&m_performanceTracker->m_blockName); +} +inline const struct timeval* PerformanceTrackingData::startTime() const { + return const_cast(&m_performanceTracker->m_startTime); +} +inline const struct timeval* PerformanceTrackingData::endTime() const { + return const_cast(&m_performanceTracker->m_endTime); +} +inline const struct timeval* PerformanceTrackingData::lastCheckpointTime() const { + return const_cast(&m_performanceTracker->m_lastCheckpointTime); +} +inline const std::string& PerformanceTrackingData::loggerId(void) const { + return m_performanceTracker->m_loggerId; +} +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) +namespace base { +/// @brief Contains some internal debugging tools like crash handler and stack tracer +namespace debug { +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) +class StackTrace : base::NoCopy { + public: + static const unsigned int kMaxStack = 64; + static const unsigned int kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew() + class StackTraceEntry { + public: + StackTraceEntry(std::size_t index, const std::string& loc, const std::string& demang, const std::string& hex, + const std::string& addr); + StackTraceEntry(std::size_t index, const std::string& loc) : + m_index(index), + m_location(loc) { + } + std::size_t m_index; + std::string m_location; + std::string m_demangled; + std::string m_hex; + std::string m_addr; + friend std::ostream& operator<<(std::ostream& ss, const StackTraceEntry& si); + + private: + StackTraceEntry(void); + }; + + StackTrace(void) { + generateNew(); + } + + virtual ~StackTrace(void) { + } + + inline std::vector& getLatestStack(void) { + return m_stack; + } + + friend std::ostream& operator<<(std::ostream& os, const StackTrace& st); + + private: + std::vector m_stack; + + void generateNew(void); +}; +/// @brief Handles unexpected crashes +class CrashHandler : base::NoCopy { + public: + typedef void (*Handler)(int); + + explicit CrashHandler(bool useDefault); + explicit CrashHandler(const Handler& cHandler) { + setHandler(cHandler); + } + void setHandler(const Handler& cHandler); + + private: + Handler m_handler; +}; +#else +class CrashHandler { + public: + explicit CrashHandler(bool) {} +}; +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) +} // namespace debug +} // namespace base +extern base::debug::CrashHandler elCrashHandler; +#define MAKE_LOGGABLE(ClassType, ClassInstance, OutputStreamInstance) \ +el::base::type::ostream_t& operator<<(el::base::type::ostream_t& OutputStreamInstance, const ClassType& ClassInstance) +/// @brief Initializes syslog with process ID, options and facility. calls closelog() on d'tor +class SysLogInitializer { + public: + SysLogInitializer(const char* processIdent, int options = 0, int facility = 0) { +#if defined(ELPP_SYSLOG) + (void)base::consts::kSysLogLoggerId; + openlog(processIdent, options, facility); +#else + ELPP_UNUSED(processIdent); + ELPP_UNUSED(options); + ELPP_UNUSED(facility); +#endif // defined(ELPP_SYSLOG) + } + virtual ~SysLogInitializer(void) { +#if defined(ELPP_SYSLOG) + closelog(); +#endif // defined(ELPP_SYSLOG) + } +}; +#define ELPP_INITIALIZE_SYSLOG(id, opt, fac) el::SysLogInitializer elSyslogInit(id, opt, fac) +/// @brief Static helpers for developers +class Helpers : base::StaticClass { + public: + /// @brief Shares logging repository (base::Storage) + static inline void setStorage(base::type::StoragePointer storage) { + ELPP = storage; + } + /// @return Main storage repository + static inline base::type::StoragePointer storage() { + return ELPP; + } + /// @brief Sets application arguments and figures out whats active for logging and whats not. + static inline void setArgs(int argc, char** argv) { + ELPP->setApplicationArguments(argc, argv); + } + /// @copydoc setArgs(int argc, char** argv) + static inline void setArgs(int argc, const char** argv) { + ELPP->setApplicationArguments(argc, const_cast(argv)); + } + /// @brief Sets thread name for current thread. Requires std::thread + static inline void setThreadName(const std::string& name) { + ELPP->setThreadName(name); + } + static inline std::string getThreadName() { + return ELPP->getThreadName(base::threading::getCurrentThreadId()); + } +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) + /// @brief Overrides default crash handler and installs custom handler. + /// @param crashHandler A functor with no return type that takes single int argument. + /// Handler is a typedef with specification: void (*Handler)(int) + static inline void setCrashHandler(const el::base::debug::CrashHandler::Handler& crashHandler) { + el::elCrashHandler.setHandler(crashHandler); + } + /// @brief Abort due to crash with signal in parameter + /// @param sig Crash signal + static void crashAbort(int sig, const char* sourceFile = "", unsigned int long line = 0); + /// @brief Logs reason of crash as per sig + /// @param sig Crash signal + /// @param stackTraceIfAvailable Includes stack trace if available + /// @param level Logging level + /// @param logger Logger to use for logging + static void logCrashReason(int sig, bool stackTraceIfAvailable = false, + Level level = Level::Fatal, const char* logger = base::consts::kDefaultLoggerId); +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) + /// @brief Installs pre rollout callback, this callback is triggered when log file is about to be rolled out + /// (can be useful for backing up) + static inline void installPreRollOutCallback(const PreRollOutCallback& callback) { + ELPP->setPreRollOutCallback(callback); + } + /// @brief Uninstalls pre rollout callback + static inline void uninstallPreRollOutCallback(void) { + ELPP->unsetPreRollOutCallback(); + } + /// @brief Installs post log dispatch callback, this callback is triggered when log is dispatched + template + static inline bool installLogDispatchCallback(const std::string& id) { + return ELPP->installLogDispatchCallback(id); + } + /// @brief Uninstalls log dispatch callback + template + static inline void uninstallLogDispatchCallback(const std::string& id) { + ELPP->uninstallLogDispatchCallback(id); + } + template + static inline T* logDispatchCallback(const std::string& id) { + return ELPP->logDispatchCallback(id); + } +#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + /// @brief Installs post performance tracking callback, this callback is triggered when performance tracking is finished + template + static inline bool installPerformanceTrackingCallback(const std::string& id) { + return ELPP->installPerformanceTrackingCallback(id); + } + /// @brief Uninstalls post performance tracking handler + template + static inline void uninstallPerformanceTrackingCallback(const std::string& id) { + ELPP->uninstallPerformanceTrackingCallback(id); + } + template + static inline T* performanceTrackingCallback(const std::string& id) { + return ELPP->performanceTrackingCallback(id); + } +#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) + /// @brief Converts template to std::string - useful for loggable classes to log containers within log(std::ostream&) const + template + static std::string convertTemplateToStdString(const T& templ) { + el::Logger* logger = + ELPP->registeredLoggers()->get(el::base::consts::kDefaultLoggerId); + if (logger == nullptr) { + return std::string(); + } + base::MessageBuilder b; + b.initialize(logger); + logger->acquireLock(); + b << templ; +#if defined(ELPP_UNICODE) + std::string s = std::string(logger->stream().str().begin(), logger->stream().str().end()); +#else + std::string s = logger->stream().str(); +#endif // defined(ELPP_UNICODE) + logger->stream().str(ELPP_LITERAL("")); + logger->releaseLock(); + return s; + } + /// @brief Returns command line arguments (pointer) provided to easylogging++ + static inline const el::base::utils::CommandLineArgs* commandLineArgs(void) { + return ELPP->commandLineArgs(); + } + /// @brief Reserve space for custom format specifiers for performance + /// @see std::vector::reserve + static inline void reserveCustomFormatSpecifiers(std::size_t size) { + ELPP->m_customFormatSpecifiers.reserve(size); + } + /// @brief Installs user defined format specifier and handler + static inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { + ELPP->installCustomFormatSpecifier(customFormatSpecifier); + } + /// @brief Uninstalls user defined format specifier and handler + static inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { + return ELPP->uninstallCustomFormatSpecifier(formatSpecifier); + } + /// @brief Returns true if custom format specifier is installed + static inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { + return ELPP->hasCustomFormatSpecifier(formatSpecifier); + } + static inline void validateFileRolling(Logger* logger, Level level) { + if (ELPP == nullptr || logger == nullptr) return; + logger->m_typedConfigurations->validateFileRolling(level, ELPP->preRollOutCallback()); + } +}; +/// @brief Static helpers to deal with loggers and their configurations +class Loggers : base::StaticClass { + public: + /// @brief Gets existing or registers new logger + static Logger* getLogger(const std::string& identity, bool registerIfNotAvailable = true); + /// @brief Changes default log builder for future loggers + static void setDefaultLogBuilder(el::LogBuilderPtr& logBuilderPtr); + /// @brief Installs logger registration callback, this callback is triggered when new logger is registered + template + static inline bool installLoggerRegistrationCallback(const std::string& id) { + return ELPP->registeredLoggers()->installLoggerRegistrationCallback(id); + } + /// @brief Uninstalls log dispatch callback + template + static inline void uninstallLoggerRegistrationCallback(const std::string& id) { + ELPP->registeredLoggers()->uninstallLoggerRegistrationCallback(id); + } + template + static inline T* loggerRegistrationCallback(const std::string& id) { + return ELPP->registeredLoggers()->loggerRegistrationCallback(id); + } + /// @brief Unregisters logger - use it only when you know what you are doing, you may unregister + /// loggers initialized / used by third-party libs. + static bool unregisterLogger(const std::string& identity); + /// @brief Whether or not logger with id is registered + static bool hasLogger(const std::string& identity); + /// @brief Reconfigures specified logger with new configurations + static Logger* reconfigureLogger(Logger* logger, const Configurations& configurations); + /// @brief Reconfigures logger with new configurations after looking it up using identity + static Logger* reconfigureLogger(const std::string& identity, const Configurations& configurations); + /// @brief Reconfigures logger's single configuration + static Logger* reconfigureLogger(const std::string& identity, ConfigurationType configurationType, + const std::string& value); + /// @brief Reconfigures all the existing loggers with new configurations + static void reconfigureAllLoggers(const Configurations& configurations); + /// @brief Reconfigures single configuration for all the loggers + static inline void reconfigureAllLoggers(ConfigurationType configurationType, const std::string& value) { + reconfigureAllLoggers(Level::Global, configurationType, value); + } + /// @brief Reconfigures single configuration for all the loggers for specified level + static void reconfigureAllLoggers(Level level, ConfigurationType configurationType, + const std::string& value); + /// @brief Sets default configurations. This configuration is used for future (and conditionally for existing) loggers + static void setDefaultConfigurations(const Configurations& configurations, + bool reconfigureExistingLoggers = false); + /// @brief Returns current default + static const Configurations* defaultConfigurations(void); + /// @brief Returns log stream reference pointer if needed by user + static const base::LogStreamsReferenceMapPtr logStreamsReference(void); + /// @brief Default typed configuration based on existing defaultConf + static base::TypedConfigurations defaultTypedConfigurations(void); + /// @brief Populates all logger IDs in current repository. + /// @param [out] targetList List of fill up. + static std::vector* populateAllLoggerIds(std::vector* targetList); + /// @brief Sets configurations from global configuration file. + static void configureFromGlobal(const char* globalConfigurationFilePath); + /// @brief Configures loggers using command line arg. Ensure you have already set command line args, + /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger. + /// If true is returned that does not mean it has been configured successfully, it only means that it + /// has attempted to configure logger using configuration file provided in argument + static bool configureFromArg(const char* argKey); + /// @brief Flushes all loggers for all levels - Be careful if you dont know how many loggers are registered + static void flushAll(void); + /// @brief Adds logging flag used internally. + static inline void addFlag(LoggingFlag flag) { + ELPP->addFlag(flag); + } + /// @brief Removes logging flag used internally. + static inline void removeFlag(LoggingFlag flag) { + ELPP->removeFlag(flag); + } + /// @brief Determines whether or not certain flag is active + static inline bool hasFlag(LoggingFlag flag) { + return ELPP->hasFlag(flag); + } + /// @brief Adds flag and removes it when scope goes out + class ScopedAddFlag { + public: + ScopedAddFlag(LoggingFlag flag) : m_flag(flag) { + Loggers::addFlag(m_flag); + } + ~ScopedAddFlag(void) { + Loggers::removeFlag(m_flag); + } + private: + LoggingFlag m_flag; + }; + /// @brief Removes flag and add it when scope goes out + class ScopedRemoveFlag { + public: + ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) { + Loggers::removeFlag(m_flag); + } + ~ScopedRemoveFlag(void) { + Loggers::addFlag(m_flag); + } + private: + LoggingFlag m_flag; + }; + /// @brief Sets hierarchy for logging. Needs to enable logging flag (HierarchicalLogging) + static void setLoggingLevel(Level level) { + ELPP->setLoggingLevel(level); + } + /// @brief Sets verbose level on the fly + static void setVerboseLevel(base::type::VerboseLevel level); + /// @brief Gets current verbose level + static base::type::VerboseLevel verboseLevel(void); + /// @brief Sets vmodules as specified (on the fly) + static void setVModules(const char* modules); + /// @brief Clears vmodules + static void clearVModules(void); +}; +class VersionInfo : base::StaticClass { + public: + /// @brief Current version number + static const std::string version(void); + + /// @brief Release date of current version + static const std::string releaseDate(void); +}; +} // namespace el +#undef VLOG_IS_ON +/// @brief Determines whether verbose logging is on for specified level current file. +#define VLOG_IS_ON(verboseLevel) (ELPP->vRegistry()->allowed(verboseLevel, __FILE__)) +#undef TIMED_BLOCK +#undef TIMED_SCOPE +#undef TIMED_SCOPE_IF +#undef TIMED_FUNC +#undef TIMED_FUNC_IF +#undef ELPP_MIN_UNIT +#if defined(ELPP_PERFORMANCE_MICROSECONDS) +# define ELPP_MIN_UNIT el::base::TimestampUnit::Microsecond +#else +# define ELPP_MIN_UNIT el::base::TimestampUnit::Millisecond +#endif // (defined(ELPP_PERFORMANCE_MICROSECONDS)) +/// @brief Performance tracked scope. Performance gets written when goes out of scope using +/// 'performance' logger. +/// +/// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint(); +/// @see el::base::PerformanceTracker +/// @see el::base::PerformanceTracker::checkpoint +// Note: Do not surround this definition with null macro because of obj instance +#define TIMED_SCOPE_IF(obj, blockname, condition) el::base::type::PerformanceTrackerPtr obj( condition ? \ + new el::base::PerformanceTracker(blockname, ELPP_MIN_UNIT) : nullptr ) +#define TIMED_SCOPE(obj, blockname) TIMED_SCOPE_IF(obj, blockname, true) +#define TIMED_BLOCK(obj, blockName) for (struct { int i; el::base::type::PerformanceTrackerPtr timer; } obj = { 0, \ + el::base::type::PerformanceTrackerPtr(new el::base::PerformanceTracker(blockName, ELPP_MIN_UNIT)) }; obj.i < 1; ++obj.i) +/// @brief Performance tracked function. Performance gets written when goes out of scope using +/// 'performance' logger. +/// +/// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint(); +/// @see el::base::PerformanceTracker +/// @see el::base::PerformanceTracker::checkpoint +#define TIMED_FUNC_IF(obj,condition) TIMED_SCOPE_IF(obj, ELPP_FUNC, condition) +#define TIMED_FUNC(obj) TIMED_SCOPE(obj, ELPP_FUNC) +#undef PERFORMANCE_CHECKPOINT +#undef PERFORMANCE_CHECKPOINT_WITH_ID +#define PERFORMANCE_CHECKPOINT(obj) obj->checkpoint(std::string(), __FILE__, __LINE__, ELPP_FUNC) +#define PERFORMANCE_CHECKPOINT_WITH_ID(obj, id) obj->checkpoint(id, __FILE__, __LINE__, ELPP_FUNC) +#undef ELPP_COUNTER +#undef ELPP_COUNTER_POS +/// @brief Gets hit counter for file/line +#define ELPP_COUNTER (ELPP->hitCounters()->getCounter(__FILE__, __LINE__)) +/// @brief Gets hit counter position for file/line, -1 if not registered yet +#define ELPP_COUNTER_POS (ELPP_COUNTER == nullptr ? -1 : ELPP_COUNTER->hitCounts()) +// Undef levels to support LOG(LEVEL) +#undef INFO +#undef WARNING +#undef DEBUG +#undef ERROR +#undef FATAL +#undef TRACE +#undef VERBOSE +// Undef existing +#undef CINFO +#undef CWARNING +#undef CDEBUG +#undef CFATAL +#undef CERROR +#undef CTRACE +#undef CVERBOSE +#undef CINFO_IF +#undef CWARNING_IF +#undef CDEBUG_IF +#undef CERROR_IF +#undef CFATAL_IF +#undef CTRACE_IF +#undef CVERBOSE_IF +#undef CINFO_EVERY_N +#undef CWARNING_EVERY_N +#undef CDEBUG_EVERY_N +#undef CERROR_EVERY_N +#undef CFATAL_EVERY_N +#undef CTRACE_EVERY_N +#undef CVERBOSE_EVERY_N +#undef CINFO_AFTER_N +#undef CWARNING_AFTER_N +#undef CDEBUG_AFTER_N +#undef CERROR_AFTER_N +#undef CFATAL_AFTER_N +#undef CTRACE_AFTER_N +#undef CVERBOSE_AFTER_N +#undef CINFO_N_TIMES +#undef CWARNING_N_TIMES +#undef CDEBUG_N_TIMES +#undef CERROR_N_TIMES +#undef CFATAL_N_TIMES +#undef CTRACE_N_TIMES +#undef CVERBOSE_N_TIMES +// Normal logs +#if ELPP_INFO_LOG +# define CINFO(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE(writer, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel)) writer(\ +el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#else +# define CVERBOSE(writer, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG +// Conditional logs +#if ELPP_INFO_LOG +# define CINFO_IF(writer, condition_, dispatchAction, ...) \ +ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_IF(writer, condition_, dispatchAction, ...)\ +ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_IF(writer, condition_, dispatchAction, ...)\ +ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_IF(writer, condition_, dispatchAction, ...)\ +ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_IF(writer, condition_, dispatchAction, ...)\ +ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_IF(writer, condition_, dispatchAction, ...)\ +ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel) && (condition_)) writer( \ +el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#else +# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG +// Occasional logs +#if ELPP_INFO_LOG +# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...)\ +ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...)\ +ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...)\ +ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...)\ +ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...)\ +ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...)\ +ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...)\ +CVERBOSE_IF(writer, ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG +// After N logs +#if ELPP_INFO_LOG +# define CINFO_AFTER_N(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_AFTER_N(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_AFTER_N(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_AFTER_N(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_AFTER_N(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...)\ +CVERBOSE_IF(writer, ELPP->validateAfterNCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG +// N Times logs +#if ELPP_INFO_LOG +# define CINFO_N_TIMES(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_N_TIMES(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_N_TIMES(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_N_TIMES(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_N_TIMES(writer, n, dispatchAction, ...)\ +ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...)\ +CVERBOSE_IF(writer, ELPP->validateNTimesCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG +// +// Custom Loggers - Requires (level, dispatchAction, loggerId/s) +// +// undef existing +#undef CLOG +#undef CLOG_VERBOSE +#undef CVLOG +#undef CLOG_IF +#undef CLOG_VERBOSE_IF +#undef CVLOG_IF +#undef CLOG_EVERY_N +#undef CVLOG_EVERY_N +#undef CLOG_AFTER_N +#undef CVLOG_AFTER_N +#undef CLOG_N_TIMES +#undef CVLOG_N_TIMES +// Normal logs +#define CLOG(LEVEL, ...)\ +C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG(vlevel, ...) CVERBOSE(el::base::Writer, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +// Conditional logs +#define CLOG_IF(condition, LEVEL, ...)\ +C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_IF(condition, vlevel, ...)\ +CVERBOSE_IF(el::base::Writer, condition, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +// Hit counts based logs +#define CLOG_EVERY_N(n, LEVEL, ...)\ +C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_EVERY_N(n, vlevel, ...)\ +CVERBOSE_EVERY_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CLOG_AFTER_N(n, LEVEL, ...)\ +C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_AFTER_N(n, vlevel, ...)\ +CVERBOSE_AFTER_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CLOG_N_TIMES(n, LEVEL, ...)\ +C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_N_TIMES(n, vlevel, ...)\ +CVERBOSE_N_TIMES(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +// +// Default Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros +// +// undef existing +#undef LOG +#undef VLOG +#undef LOG_IF +#undef VLOG_IF +#undef LOG_EVERY_N +#undef VLOG_EVERY_N +#undef LOG_AFTER_N +#undef VLOG_AFTER_N +#undef LOG_N_TIMES +#undef VLOG_N_TIMES +#undef ELPP_CURR_FILE_LOGGER_ID +#if defined(ELPP_DEFAULT_LOGGER) +# define ELPP_CURR_FILE_LOGGER_ID ELPP_DEFAULT_LOGGER +#else +# define ELPP_CURR_FILE_LOGGER_ID el::base::consts::kDefaultLoggerId +#endif +#undef ELPP_TRACE +#define ELPP_TRACE CLOG(TRACE, ELPP_CURR_FILE_LOGGER_ID) +// Normal logs +#define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG(vlevel) CVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) +// Conditional logs +#define LOG_IF(condition, LEVEL) CLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_IF(condition, vlevel) CVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) +// Hit counts based logs +#define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_EVERY_N(n, vlevel) CVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_AFTER_N(n, vlevel) CVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_N_TIMES(n, vlevel) CVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +// Generic PLOG() +#undef CPLOG +#undef CPLOG_IF +#undef PLOG +#undef PLOG_IF +#undef DCPLOG +#undef DCPLOG_IF +#undef DPLOG +#undef DPLOG_IF +#define CPLOG(LEVEL, ...)\ +C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CPLOG_IF(condition, LEVEL, ...)\ +C##LEVEL##_IF(el::base::PErrorWriter, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define DCPLOG(LEVEL, ...)\ +if (ELPP_DEBUG_LOG) C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define DCPLOG_IF(condition, LEVEL, ...)\ +C##LEVEL##_IF(el::base::PErrorWriter, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define PLOG(LEVEL) CPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define PLOG_IF(condition, LEVEL) CPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DPLOG(LEVEL) DCPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DPLOG_IF(condition, LEVEL) DCPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +// Generic SYSLOG() +#undef CSYSLOG +#undef CSYSLOG_IF +#undef CSYSLOG_EVERY_N +#undef CSYSLOG_AFTER_N +#undef CSYSLOG_N_TIMES +#undef SYSLOG +#undef SYSLOG_IF +#undef SYSLOG_EVERY_N +#undef SYSLOG_AFTER_N +#undef SYSLOG_N_TIMES +#undef DCSYSLOG +#undef DCSYSLOG_IF +#undef DCSYSLOG_EVERY_N +#undef DCSYSLOG_AFTER_N +#undef DCSYSLOG_N_TIMES +#undef DSYSLOG +#undef DSYSLOG_IF +#undef DSYSLOG_EVERY_N +#undef DSYSLOG_AFTER_N +#undef DSYSLOG_N_TIMES +#if defined(ELPP_SYSLOG) +# define CSYSLOG(LEVEL, ...)\ +C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_IF(condition, LEVEL, ...)\ +C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define SYSLOG(LEVEL) CSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_IF(condition, LEVEL) CSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DCSYSLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_IF(condition, LEVEL, ...)\ +C##LEVEL##_IF(el::base::Writer, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_EVERY_N(n, LEVEL, ...)\ +if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_AFTER_N(n, LEVEL, ...)\ +if (ELPP_DEBUG_LOG) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_N_TIMES(n, LEVEL, ...)\ +if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DSYSLOG(LEVEL) DCSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_IF(condition, LEVEL) DCSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_EVERY_N(n, LEVEL) DCSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_AFTER_N(n, LEVEL) DCSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_N_TIMES(n, LEVEL) DCSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) +#else +# define CSYSLOG(LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() +# define SYSLOG(LEVEL) el::base::NullWriter() +# define SYSLOG_IF(condition, LEVEL) el::base::NullWriter() +# define SYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() +# define SYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() +# define SYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() +# define DCSYSLOG(LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() +# define DSYSLOG(LEVEL) el::base::NullWriter() +# define DSYSLOG_IF(condition, LEVEL) el::base::NullWriter() +# define DSYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() +# define DSYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() +# define DSYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() +#endif // defined(ELPP_SYSLOG) +// +// Custom Debug Only Loggers - Requires (level, loggerId/s) +// +// undef existing +#undef DCLOG +#undef DCVLOG +#undef DCLOG_IF +#undef DCVLOG_IF +#undef DCLOG_EVERY_N +#undef DCVLOG_EVERY_N +#undef DCLOG_AFTER_N +#undef DCVLOG_AFTER_N +#undef DCLOG_N_TIMES +#undef DCVLOG_N_TIMES +// Normal logs +#define DCLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG(LEVEL, __VA_ARGS__) +#define DCLOG_VERBOSE(vlevel, ...) if (ELPP_DEBUG_LOG) CLOG_VERBOSE(vlevel, __VA_ARGS__) +#define DCVLOG(vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG(vlevel, __VA_ARGS__) +// Conditional logs +#define DCLOG_IF(condition, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_IF(condition, LEVEL, __VA_ARGS__) +#define DCVLOG_IF(condition, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_IF(condition, vlevel, __VA_ARGS__) +// Hit counts based logs +#define DCLOG_EVERY_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_EVERY_N(n, LEVEL, __VA_ARGS__) +#define DCVLOG_EVERY_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_EVERY_N(n, vlevel, __VA_ARGS__) +#define DCLOG_AFTER_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_AFTER_N(n, LEVEL, __VA_ARGS__) +#define DCVLOG_AFTER_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_AFTER_N(n, vlevel, __VA_ARGS__) +#define DCLOG_N_TIMES(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_N_TIMES(n, LEVEL, __VA_ARGS__) +#define DCVLOG_N_TIMES(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_N_TIMES(n, vlevel, __VA_ARGS__) +// +// Default Debug Only Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros +// +#if !defined(ELPP_NO_DEBUG_MACROS) +// undef existing +#undef DLOG +#undef DVLOG +#undef DLOG_IF +#undef DVLOG_IF +#undef DLOG_EVERY_N +#undef DVLOG_EVERY_N +#undef DLOG_AFTER_N +#undef DVLOG_AFTER_N +#undef DLOG_N_TIMES +#undef DVLOG_N_TIMES +// Normal logs +#define DLOG(LEVEL) DCLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG(vlevel) DCVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) +// Conditional logs +#define DLOG_IF(condition, LEVEL) DCLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_IF(condition, vlevel) DCVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) +// Hit counts based logs +#define DLOG_EVERY_N(n, LEVEL) DCLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_EVERY_N(n, vlevel) DCVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define DLOG_AFTER_N(n, LEVEL) DCLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_AFTER_N(n, vlevel) DCVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define DLOG_N_TIMES(n, LEVEL) DCLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_N_TIMES(n, vlevel) DCVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#endif // defined(ELPP_NO_DEBUG_MACROS) +#if !defined(ELPP_NO_CHECK_MACROS) +// Check macros +#undef CCHECK +#undef CPCHECK +#undef CCHECK_EQ +#undef CCHECK_NE +#undef CCHECK_LT +#undef CCHECK_GT +#undef CCHECK_LE +#undef CCHECK_GE +#undef CCHECK_BOUNDS +#undef CCHECK_NOTNULL +#undef CCHECK_STRCASEEQ +#undef CCHECK_STRCASENE +#undef CHECK +#undef PCHECK +#undef CHECK_EQ +#undef CHECK_NE +#undef CHECK_LT +#undef CHECK_GT +#undef CHECK_LE +#undef CHECK_GE +#undef CHECK_BOUNDS +#undef CHECK_NOTNULL +#undef CHECK_STRCASEEQ +#undef CHECK_STRCASENE +#define CCHECK(condition, ...) CLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " +#define CPCHECK(condition, ...) CPLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " +#define CHECK(condition) CCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define PCHECK(condition) CPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define CCHECK_EQ(a, b, ...) CCHECK(a == b, __VA_ARGS__) +#define CCHECK_NE(a, b, ...) CCHECK(a != b, __VA_ARGS__) +#define CCHECK_LT(a, b, ...) CCHECK(a < b, __VA_ARGS__) +#define CCHECK_GT(a, b, ...) CCHECK(a > b, __VA_ARGS__) +#define CCHECK_LE(a, b, ...) CCHECK(a <= b, __VA_ARGS__) +#define CCHECK_GE(a, b, ...) CCHECK(a >= b, __VA_ARGS__) +#define CCHECK_BOUNDS(val, min, max, ...) CCHECK(val >= min && val <= max, __VA_ARGS__) +#define CHECK_EQ(a, b) CCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_NE(a, b) CCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_LT(a, b) CCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_GT(a, b) CCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_LE(a, b) CCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_GE(a, b) CCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_BOUNDS(val, min, max) CCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) +#define CCHECK_NOTNULL(ptr, ...) CCHECK((ptr) != nullptr, __VA_ARGS__) +#define CCHECK_STREQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ +<< "Check failed: [" << #str1 << " == " << #str2 << "] " +#define CCHECK_STRNE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ +<< "Check failed: [" << #str1 << " != " << #str2 << "] " +#define CCHECK_STRCASEEQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ +<< "Check failed: [" << #str1 << " == " << #str2 << "] " +#define CCHECK_STRCASENE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ +<< "Check failed: [" << #str1 << " != " << #str2 << "] " +#define CHECK_NOTNULL(ptr) CCHECK_NOTNULL((ptr), ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STREQ(str1, str2) CCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRNE(str1, str2) CCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRCASEEQ(str1, str2) CCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRCASENE(str1, str2) CCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#undef DCCHECK +#undef DCCHECK_EQ +#undef DCCHECK_NE +#undef DCCHECK_LT +#undef DCCHECK_GT +#undef DCCHECK_LE +#undef DCCHECK_GE +#undef DCCHECK_BOUNDS +#undef DCCHECK_NOTNULL +#undef DCCHECK_STRCASEEQ +#undef DCCHECK_STRCASENE +#undef DCPCHECK +#undef DCHECK +#undef DCHECK_EQ +#undef DCHECK_NE +#undef DCHECK_LT +#undef DCHECK_GT +#undef DCHECK_LE +#undef DCHECK_GE +#undef DCHECK_BOUNDS_ +#undef DCHECK_NOTNULL +#undef DCHECK_STRCASEEQ +#undef DCHECK_STRCASENE +#undef DPCHECK +#define DCCHECK(condition, ...) if (ELPP_DEBUG_LOG) CCHECK(condition, __VA_ARGS__) +#define DCCHECK_EQ(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_EQ(a, b, __VA_ARGS__) +#define DCCHECK_NE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_NE(a, b, __VA_ARGS__) +#define DCCHECK_LT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LT(a, b, __VA_ARGS__) +#define DCCHECK_GT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GT(a, b, __VA_ARGS__) +#define DCCHECK_LE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LE(a, b, __VA_ARGS__) +#define DCCHECK_GE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GE(a, b, __VA_ARGS__) +#define DCCHECK_BOUNDS(val, min, max, ...) if (ELPP_DEBUG_LOG) CCHECK_BOUNDS(val, min, max, __VA_ARGS__) +#define DCCHECK_NOTNULL(ptr, ...) if (ELPP_DEBUG_LOG) CCHECK_NOTNULL((ptr), __VA_ARGS__) +#define DCCHECK_STREQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STREQ(str1, str2, __VA_ARGS__) +#define DCCHECK_STRNE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRNE(str1, str2, __VA_ARGS__) +#define DCCHECK_STRCASEEQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASEEQ(str1, str2, __VA_ARGS__) +#define DCCHECK_STRCASENE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASENE(str1, str2, __VA_ARGS__) +#define DCPCHECK(condition, ...) if (ELPP_DEBUG_LOG) CPCHECK(condition, __VA_ARGS__) +#define DCHECK(condition) DCCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_EQ(a, b) DCCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_NE(a, b) DCCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_LT(a, b) DCCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_GT(a, b) DCCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_LE(a, b) DCCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_GE(a, b) DCCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_BOUNDS(val, min, max) DCCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_NOTNULL(ptr) DCCHECK_NOTNULL((ptr), ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STREQ(str1, str2) DCCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRNE(str1, str2) DCCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRCASEEQ(str1, str2) DCCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRCASENE(str1, str2) DCCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DPCHECK(condition) DCPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#endif // defined(ELPP_NO_CHECK_MACROS) +#if defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) +# define ELPP_USE_DEF_CRASH_HANDLER false +#else +# define ELPP_USE_DEF_CRASH_HANDLER true +#endif // defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) +#define ELPP_CRASH_HANDLER_INIT +#define ELPP_INIT_EASYLOGGINGPP(val) \ +namespace el { \ +namespace base { \ +el::base::type::StoragePointer elStorage(val); \ +} \ +el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER); \ +} + +#if ELPP_ASYNC_LOGGING +# define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()),\ +new el::base::AsyncDispatchWorker())) +#else +# define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))) +#endif // ELPP_ASYNC_LOGGING +#define INITIALIZE_NULL_EASYLOGGINGPP \ +namespace el {\ +namespace base {\ +el::base::type::StoragePointer elStorage;\ +}\ +el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ +} +#define SHARE_EASYLOGGINGPP(initializedStorage)\ +namespace el {\ +namespace base {\ +el::base::type::StoragePointer elStorage(initializedStorage);\ +}\ +el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ +} + +#if defined(ELPP_UNICODE) +# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv); std::locale::global(std::locale("")) +#else +# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv) +#endif // defined(ELPP_UNICODE) +#endif // EASYLOGGINGPP_H diff --git a/code/application/sifarsdk/component/McuManager/CMakeLists.txt b/code/application/sifarsdk/component/McuManager/CMakeLists.txt new file mode 100644 index 000000000..f0be0c811 --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/CMakeLists.txt @@ -0,0 +1,29 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Config/include + ${COMPONENT_SOURCE_PATH}/SystemTime/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${COMPONENT_SOURCE_PATH}/utils/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME McuManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} Log) \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/include/IMcuManager.h b/code/application/sifarsdk/component/McuManager/include/IMcuManager.h new file mode 100644 index 000000000..f9daa9d87 --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/include/IMcuManager.h @@ -0,0 +1,107 @@ +#ifndef I_MCU_MANAGER_H +#define I_MCU_MANAGER_H +#include "VReturnCode.h" +#include +enum class McuEvent +{ + STARTUP_MODE_CHANGED = 0, + END +}; +class McuMessageBase +{ +public: + McuMessageBase(const McuEvent &event) : mEvent(event) + { + } + virtual ~McuMessageBase() = default; + +public: + const McuEvent mEvent; +}; +template +class McuMessage +{ +public: + McuMessage(const McuEvent &event, T value) : mData(value) + { + } + virtual ~McuMessage() = default; + +public: + /** + * @brief + * 数据 + */ + T mData; +}; +class VMcuMonitor +{ +public: + VMcuMonitor() = default; + virtual ~VMcuMonitor() = default; + virtual RETURN_CODE McuEventHapped(const std::shared_ptr &message) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +class VMcuTask +{ +public: + VMcuTask() = default; + virtual ~VMcuTask() = default; + virtual const char *GetBuf(void) { return nullptr; } + virtual const unsigned int GetBufLength(void) { return 0; } + virtual void Response(const char *buf, const unsigned int &length) {} +}; +typedef enum +{ + SF_MCU_STARTMODE = 0, + SF_MCU_POWERON, + SF_MCU_POWEROFF, + SF_MCU_CTRL_MODULE_PIR, + SF_MCU_PARA, + SF_MCU_RESET_MODULE, + SF_MCU_SOFT_UPDATE, + SF_MCU_POWER_RESTART, + SF_MCU_PIR_RESTART, + SF_MCU_TEST_PIR, + SF_MCU_PARAM_MAX +} MCUParam_t; +class EnvironmentData +{ +public: + EnvironmentData(const bool &isNight, const unsigned short &lightValue) + : mIsNight(isNight), mLightValue(lightValue) + { + } + ~EnvironmentData() = default; + const bool mIsNight; + const unsigned short mLightValue; +}; +class VMcuDevice +{ +public: + VMcuDevice() = default; + virtual ~VMcuDevice() = default; + virtual RETURN_CODE SetMonitor(const std::shared_ptr &monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual unsigned int Write(const std::shared_ptr &task) { return 0; } + virtual RETURN_CODE SetWatchDogMinute(const unsigned int &min) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetWatchDogSecond(const unsigned int &sec) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual unsigned char GetStartupMode(void) { return -1; } + virtual unsigned char sf_mcu_reg_set(MCUParam_t attrId, unsigned char val) { return 0; } + virtual bool IsNightMode(void) { return false; } + virtual const EnvironmentData GetEnvironmentData(void) + { + EnvironmentData data(false, 0); + return data; + } +}; +class IMcuManager +{ +public: + IMcuManager() = default; + virtual ~IMcuManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetMcuDevice(std::shared_ptr &mcu) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreateMcuManager(void); +#endif // !I_MCU_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/IMcuManager.cpp b/code/application/sifarsdk/component/McuManager/src/IMcuManager.cpp new file mode 100644 index 000000000..469658d50 --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/IMcuManager.cpp @@ -0,0 +1,29 @@ +#include "IMcuManager.h" +#include "Log.h" +#include +std::shared_ptr &IMcuManager::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/McuDevice.cpp b/code/application/sifarsdk/component/McuManager/src/McuDevice.cpp new file mode 100644 index 000000000..50d6302dc --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/McuDevice.cpp @@ -0,0 +1,982 @@ +#include "McuDevice.h" +#include "Log.h" +#include "IConfig.h" +#include "ISystemTime.h" // TODO:解耦合 +#include "IPeripheralManager.h" // TODO:解耦合 +#include +static const unsigned short Crc16Table[256] = + { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040}; +McuDevice::McuDevice() +{ + mcu_buf_len = 0; + memset(mcu_buf, 0, MUC_BUF_LENGTH); + mcu_upgrade_buf_len = 0; + memset(mcu_upgrade_buf, 0, MUC_BUF_LENGTH); + mMcuReading = false; + SMAP_waitAck = 0; + smap_buf.index = 0; + memset(smap_buf.buf, 0, MUC_BUF_LENGTH); + mMonitor = std::make_shared(); + IRSHTTER = 0; +} +void McuDevice::Init(void) +{ + McuDeviceInformation info = IHal::GetInstance()->GetMcuDeviceInformation(); + int fd = sf_commu_mcu_interface_init(info.mDevice, info.mSpeed, info.mFlow_ctrl, info.mDatabits, info.mStopbits, info.mParity); + if (fd >= 0) + { + auto readingThread = [](std::shared_ptr mcu) + { + LogInfo("Mcu reading started.\n"); + mcu->ReadingThread(); + }; + mMcuReading = true; + mReading = std::thread(readingThread, shared_from_this()); + } +} +void McuDevice::UnInit(void) +{ + mMcuReading = false; + if (mReading.joinable()) + { + mReading.join(); + } + sf_commu_mcu_interface_uninit(); + if (mMonitor) + { + mMonitor.reset(); + } +} +void McuDevice::ReadingThread(void) +{ + unsigned char buffer[MUC_BUF_LENGTH] = {0}; + int i = 0; + int readLen = 0; + int lenAlreadyRead = 0; + short start = -1; + short end = -1; + unsigned char temp_start1 = 0; + unsigned char temp_start2 = 0; + unsigned char temp_end1 = 0; + unsigned char temp_end2 = 0; + unsigned char copy_size = 0; + while (mMcuReading) + { + readLen = sf_commu_read(buffer + lenAlreadyRead, MUC_BUF_LENGTH - lenAlreadyRead); + + if (readLen > 0) + { + lenAlreadyRead += readLen; + } + + while (i < lenAlreadyRead) + { + + while (i < lenAlreadyRead && start < 0) + { + if (buffer[i] == 0x55) + { + temp_start1 = i; + } + if (buffer[i] == 0xAA) + { + temp_start2 = i; + } + if ((temp_start2 - temp_start1) == 1) + { + start = temp_start1; + temp_start1 = 0; + temp_start2 = 0; + break; + } + i++; + } + + if (start >= 0) + { + while (i < lenAlreadyRead) + { + if (buffer[i] == 0xFF) + { + temp_end1 = i; + } + if (buffer[i] == 0xEE) + { + temp_end2 = i; + } + if ((temp_end2 - temp_end1) == 1) + { + end = temp_end2; + temp_end1 = 0; + temp_end2 = 0; + break; + } + i++; + } + } + + if (start >= 0 && end > 0) + { + copy_size = end - start + 1; + if (buffer[start + 2] != 0xff) + { + if (buffer[start + 2] != 0x05 && buffer[start + 2] != 0x06 && buffer[start + 2] != 0xff) + { + if (buffer[start + 2] == 0xee || buffer[start + 2] == 0xef || buffer[start + 2] == 0xec) + { + memcpy(mcu_upgrade_buf, &buffer[start], copy_size); + mcu_upgrade_buf_len = copy_size; + } + else + { + memcpy(smap_buf.buf + smap_buf.index, &buffer[start], copy_size); + smap_buf.index += copy_size; // index从0开始 + SMAP_waitAck = 1; + } + } + else + { + memcpy(mcu_buf, &buffer[start], copy_size); + mcu_buf_len = copy_size; + sf_commu_parse_mcu_data(mcu_buf, mcu_buf_len); + mcubuf_reset(); + } + start = -1; + end = -1; + lenAlreadyRead = 0; + i = 0; + } + else + { + start = -1; + end = -1; + lenAlreadyRead = 0; + i = 0; + } + } + } + + // usleep(10000); // 10ms + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } +} +RETURN_CODE McuDevice::SetWatchDogSecond(const unsigned int &sec) +{ + constexpr int MAX_SECOND = 155; + if (sec <= MAX_SECOND) + { + SetWatchDog(sec + WATCH_DOG_MINUTE_MAX); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); +} +unsigned char McuDevice::GetStartupMode(void) +{ + LogInfo("GetStartupMode.\n"); + unsigned char mode = 0; + mode = sf_commu_get_mcu(START_MODE); + mode = mode & 0x1F; + return mode; +} +RETURN_CODE McuDevice::SetMonitor(const std::shared_ptr &monitor) +{ + mMonitor = monitor; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE McuDevice::SetWatchDogMinute(const unsigned int &min) +{ + if (min <= WATCH_DOG_MINUTE_MAX) + { + SetWatchDog(min); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); +} +void McuDevice::SetWatchDog(const unsigned int &value) +{ + unsigned char i = 0; + unsigned char regsize = 0; + unsigned char mcuReg[2] = {0}; + unsigned char mcuPara[2] = {0}; + + mcuReg[i] = WDT_TIME; + mcuPara[i++] = value; + + mcuReg[i] = DSP_WRITE_FLG; + mcuPara[i++] = 1; + + regsize = i; + + for (i = 0; i < regsize; i++) + { + LogInfo("[sf_mcu_watchdog_set],add[%d]---value:%x\n", mcuReg[i], mcuPara[i]); + } + + for (i = 0; i < regsize; i++) + { + sf_commu_set_mcu(mcuReg[i], mcuPara[i]); + } +} +void McuDevice::MonitorEventHapped(const std::shared_ptr &message) +{ + mMonitor->McuEventHapped(message); +} +unsigned char McuDevice::sf_commu_parse_mcu_data(unsigned char *src, unsigned int len) +{ + unsigned char *copyBuf = src; + unsigned int copyLen = len; + int ret = -1; + unsigned char reg[3] = {0}; + unsigned char val[3] = {0}; + switch (copyBuf[2]) + { + case 0x05: + ret = sf_getRegFromMcu_depack(copyBuf, copyLen, ®[0], &val[0]); + if (ret > 0) + { + LogInfo("MCU send 0x05, reg_value[%d,%d]\n\n", reg[0], val[0]); + sf_getRegFromMcu_ack(reg[0], val[0]); + // SF_MESSAGE_BUF_S stMessageBuf = {0}; // TODO: + // stMessageBuf.cmdId = CMD_KEY; + // stMessageBuf.arg1 = SF_EVENT_KEY_SHORT_CLICK; + // stMessageBuf.arg2 = SF_KEY_PIN_DATAREADY; + // sf_com_message_send_to_app(&stMessageBuf); + std::shared_ptr message = std::make_shared(McuEvent::STARTUP_MODE_CHANGED); + MonitorEventHapped(message); + ret = 0x05; + } + else + { + LogInfo("0x05 error\r\n"); + } + break; + /* + case 0x06: + LogInfo("SMAP_parse_data 0x06\r\n"); + ret = SMAP_getMultiRegFromMcu_depack(copyBuf, copyLen, ®Cnt, reg, val); + if (ret > 0) + { + SMAP_getMultiRegFromMcu_ack(regCnt, reg, val); + ret = 0x06; + } + else + { + LogInfo("0x06 error\r\n"); + } + break; + */ + default: + // ret = 0x00; + break; + } + return ret; +} +int McuDevice::sf_getRegFromMcu_depack(unsigned char *dataToParse, unsigned int datalen, unsigned char *regAddr, unsigned char *regVal) +{ + unsigned short crc1 = 0; + unsigned short crc2 = 0; + unsigned char crc_start = 0; + unsigned char crc_end = 0; + + crc_start = 2; + crc_end = datalen - 4 - 1; + crc1 = (((unsigned short)dataToParse[datalen - 1 - 3] << 8) & 0xff00) | dataToParse[datalen - 1 - 2]; + crc2 = sf_crc16_check(&dataToParse[crc_start], crc_end - crc_start + 1); + + if (crc1 != crc2) + { + LogInfo("0x05 crc error\r\n"); + return -1; + } + else + { + *regVal = dataToParse[4]; + *regAddr = dataToParse[3]; + return dataToParse[2]; + } +} +int McuDevice::sf_getRegFromMcu_ack(unsigned char regAddr, unsigned char regVal) +{ + unsigned char sndBuf[MUC_BUF_LENGTH] = {0}; + unsigned short index = 0; + unsigned short crc = 0; + unsigned short crc_start = 0; + unsigned short crc_end = 0; + memset(sndBuf, 0x00, sizeof(sndBuf)); + + sndBuf[index] = 0x55; + index++; + sndBuf[index] = 0xAA; + index++; + crc_start = index; + sndBuf[index] = 0x05; + index++; + sndBuf[index] = regAddr; + index++; + sndBuf[index] = regVal; + index++; + crc_end = index; + crc = sf_crc16_check(&sndBuf[crc_start], crc_end - crc_start); + sndBuf[index] = (crc & 0xff00) >> 8; + index++; + sndBuf[index] = crc & 0x00ff; + index++; + sndBuf[index] = 0xFF; + index++; + sndBuf[index] = 0xEE; + + sf_commu_write(sndBuf, index + 1); + + return 0x05; +} +unsigned short McuDevice::sf_crc16_check(unsigned char *dataIn, int length) +{ + unsigned short result = 0; + unsigned short tableNo = 0; + + for (int i = 0; i < length; i++) + { + tableNo = ((result & 0xff) ^ (dataIn[i] & 0xff)); + result = ((result >> 8) & 0xff) ^ Crc16Table[tableNo]; + } + + return result; +} +void McuDevice::mcubuf_reset(void) +{ + mcu_buf_len = 0; + memset(mcu_buf, 0x00, sizeof(mcu_buf)); +} +int McuDevice::sf_commu_set_mcu(unsigned char reg, unsigned char val) +{ + int ret = -1; + unsigned int address = 0; + unsigned int value = 0; + LogInfo("Reg_Data[%02d,0x%02x]\n", reg, val); + sf_commu_reset(); + sf_set_mcu_reg(reg, val); + ret = sf_commu_wait(0x03); + if (ret < 0) + { + LogInfo("sf_commu_set_mcu time out\r\n"); + sf_commu_reset(); + return -1; + } + ret = sf_set_mcu_reg_ack_depack(&address, &value); + + if (ret < 0 || address != reg || value != val) + { + LogInfo("sf_commu_set_mcu error address %d, value %d\r\n", address, value); + ret = -1; + } + else + { + ret = 0; + } + return ret; +} +void McuDevice::sf_commu_reset(void) +{ + smap_buf.index = 0; + SMAP_waitAck = 0; + memset(smap_buf.buf, 0x00, MUC_BUF_LENGTH); +} +int McuDevice::sf_set_mcu_reg(unsigned char reg, unsigned char val) +{ + unsigned char sndBuf[MUC_BUF_LENGTH] = {0}; + unsigned short index = 0; + unsigned short crc = 0; + unsigned short crc_start = 0; + unsigned short crc_end = 0; + memset(sndBuf, 0x00, sizeof(sndBuf)); + // uint8_t i = 0; + sndBuf[index] = 0x55; + index++; + sndBuf[index] = 0xAA; + index++; + crc_start = index; + sndBuf[index] = 0x03; + index++; + sndBuf[index] = reg; + index++; + sndBuf[index] = val; + index++; + crc_end = index; + crc = sf_crc16_check(&sndBuf[crc_start], crc_end - crc_start); + sndBuf[index] = (crc & 0xff00) >> 8; + index++; + sndBuf[index] = crc & 0x00ff; + index++; + sndBuf[index] = 0xFF; + index++; + sndBuf[index] = 0xEE; + sf_commu_write(sndBuf, index + 1); + + return 0x03; +} +int McuDevice::sf_commu_wait(unsigned char cmd) +{ + volatile char trytimes = 0; + while ((smap_buf.buf[2] != cmd || SMAP_waitAck == 0) && trytimes <= 100) + { + trytimes++; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + if (trytimes > 100) + { + sf_commu_reset(); + return -1; + } + return 0; +} +unsigned int McuDevice::sf_set_mcu_reg_ack_depack(unsigned int *address, unsigned int *value) +{ + unsigned short crc1 = (((unsigned short)smap_buf.buf[smap_buf.index - 4]) << 8) | smap_buf.buf[smap_buf.index - 3]; + unsigned short crc2 = 0; + + crc2 = sf_crc16_check(&smap_buf.buf[2], smap_buf.index - 6); + + if (crc2 != crc1) + { + LogInfo("crc error crc1 %d, crc2 %d, function %s\r\n", crc1, crc2, __FUNCTION__); + return -1; + } + + *address = smap_buf.buf[3]; + *value = smap_buf.buf[4]; + + if (smap_buf.buf[2] == 0xFF) /* error command 0xff */ + { + LogInfo("sf_set_mcu_reg_ack_depack command error\r\n"); + return -1; + } + + return (unsigned int)smap_buf.buf[2]; +} +int McuDevice::sf_commu_get_mcu(unsigned char reg) +{ + int ret = 0; + unsigned int address = 0; + unsigned int value = 0; + + sf_commu_reset(); + + sf_get_mcu_reg(reg); + LogInfo("reg %d\r\n", reg); + ret = sf_commu_wait(0x01); + if (ret < 0) + { + LogWarning("sf_commu_get_mcu time out\r\n"); + sf_commu_reset(); + return -1; + } + ret = sf_get_mcu_reg_ack_depack(&address, &value); + if (ret < 0 || address != reg) + { + LogError("sf_commu_get_mcu error\r\n"); + ret = -1; + } + else + { + ret = (int)value; + } + + return ret; +} +int McuDevice::sf_get_mcu_reg(unsigned char reg) +{ + unsigned char sndBuf[MUC_BUF_LENGTH] = {0}; + unsigned short index = 0; + unsigned short crc = 0; + unsigned short crc_start = 0; + unsigned short crc_end = 0; + // uint8_t i = 0; + memset(sndBuf, 0x00, sizeof(sndBuf)); + sndBuf[index] = 0x55; + index++; + sndBuf[index] = 0xAA; + index++; + crc_start = index; + sndBuf[index] = 0x01; + index++; + sndBuf[index] = reg; + index++; + crc_end = index; + crc = sf_crc16_check(&sndBuf[crc_start], crc_end - crc_start); + sndBuf[index] = (crc & 0xff00) >> 8; + index++; + sndBuf[index] = crc & 0x00ff; + index++; + sndBuf[index] = 0xFF; + index++; + sndBuf[index] = 0xEE; + + sf_commu_write(sndBuf, index + 1); + + return 0x01; +} +unsigned int McuDevice::sf_get_mcu_reg_ack_depack(unsigned int *address, unsigned int *value) +{ + unsigned short crc1 = (((unsigned short)smap_buf.buf[smap_buf.index - 4] << 8) & 0xff00) | smap_buf.buf[smap_buf.index - 3]; + unsigned short crc2 = 0; + + crc2 = sf_crc16_check(&smap_buf.buf[2], smap_buf.index - 6); + + if (crc2 != crc1) + { + LogError("crc error crc1 %d, crc2 %d, function %s, file %s, line %d\r\n", crc1, crc2, __FUNCTION__, + __FILE__, __LINE__); + return -1; + } + + *address = smap_buf.buf[3]; + *value = smap_buf.buf[4]; + + if (smap_buf.buf[2] == 0xFF) /* error command 0xff */ + { + LogError("SMAP_getRegisterAck_depack command error\r\n"); + return -1; + } + + return (unsigned int)smap_buf.buf[2]; +} +unsigned char McuDevice::sf_mcu_reg_set(MCUParam_t attrId, unsigned char val) +{ + unsigned char mcuReg[70] = {0}; + unsigned char mcuData[70] = {0}; + unsigned char regsize = 0; + unsigned char i = 0; + unsigned char temp = 0; + unsigned char paraSyncFlag = 0; + unsigned char DigPirPulseCount = 0; + unsigned char DigPirWindowTime = 0; + // SF_PDT_PARAM_CFG_S *puiPara = sf_customer_param_get(); + Param GPSEnterResetModeFlag = GetParam(PARAM_GPS_ENTER_RESET_MODE_FLAG); + Param PirSwitch = GetParam(PARAM_PIR_SWITCH); + Param GprsMode = GetParam(PARAM_GPRS_MODE); + Param TimelapseSwitch = GetParam(PARAM_TIMELAPSE_SWITCH); + Param PirDelaySwitch = GetParam(PARAM_PIR_DELAY_SWITCH); + Param PirSensitivity = GetParam(PARAM_PIR_SENSITIVITY); + Param GprsSwitch = GetParam(PARAM_GPRS_SWITCH); + Param DigitPirSensitivity = GetParam(PARAM_DIGIT_PIR_SENSITIVITY); + Param TimelapseTime = GetParam(PARAM_TIMELAPSE_TIME); + Param PirDelayTime = GetParam(PARAM_PIR_DELAY_TIME); + Param GPSWaitRestartFlag = GetParam(PARAM_GPS_WAIT_RESTART_FLAG); + Param DailyReportTime = GetParam(PARAM_DAILY_REPORT_TIME); + Param WorkMode = GetParam(PARAM_WORK_MODE); + Param TimeSend1 = GetParam(PARAM_TIME_SEND_1); + Param WorkTime1Switch = GetParam(PARAM_WORK_TIME_1_SWITCH); + Param WorkTime2Switch = GetParam(PARAM_WORK_TIME_2_SWITCH); + Param WorkTime = GetParam(PARAM_WORK_TIME); + SF_STORE_ATTR_S storeattrs = {0}; + std::shared_ptr sdCard = std::make_shared(); + IPeripheralManager::GetInstance()->GetSDCardHandle(sdCard); + sdCard->GetInfo(storeattrs); + SF_SD_STATUS_E sdState = sdCard->GetStatus(); + SystemTime date = {0}; + + if (attrId > SF_MCU_PARAM_MAX) + { + LogError("attrId ERROR!\n"); + return -1; + } + + if (attrId == SF_MCU_POWEROFF) + { + LogInfo("GPSEnterResetModeFlag = %d\n", GPSEnterResetModeFlag.numberUInt); + if (GPSEnterResetModeFlag.numberUInt == 1) + { + paraSyncFlag = 1; + } + + // sf_sys_rtc_time_get(&date); + date = GetSystemTime(); + LogInfo("%04d/%02d/%02d %02d:%02d:%02d\n", + date.Year, date.Mon, date.Day, date.Hour, date.Min, date.Sec); + mcuReg[i] = RTC_YEAR; + mcuData[i++] = date.Year - 2000; + mcuReg[i] = RTC_MONTH; + mcuData[i++] = date.Mon; + mcuReg[i] = RTC_DAY; + mcuData[i++] = date.Day; + mcuReg[i] = RTC_HOUR; + mcuData[i++] = date.Hour; + mcuReg[i] = RTC_MINUTE; + mcuData[i++] = date.Min; + mcuReg[i] = RTC_SEC; + mcuData[i++] = date.Sec; + + if (PirSwitch.numberUInt) + temp = 0x01; + else + temp = 0x00; + + if (GprsMode.numberUInt == 0) + temp |= 0x20; + + if (TimelapseSwitch.numberUInt) + temp |= 0x02; + + if (PirDelaySwitch.numberUInt) + temp |= 0x04; + if (paraSyncFlag) + temp |= 0x08; + + temp |= 0x10; + + mcuReg[i] = FUNCTION_SWTICH0; + mcuData[i++] = temp; + + temp = 0; + + if (paraSyncFlag) + { + mcuReg[i] = GPS_POWER_TIMER_CLEAR; + mcuData[i++] = 1; + mcuReg[i] = GPS_POWER_CTRL; + mcuData[i++] = 1; + } + else + { + mcuReg[i] = GPS_POWER_CTRL; + mcuData[i++] = 0; + } + + LogInfo("PirSensitivity=%d\n", PirSensitivity.numberUInt); + mcuReg[i] = ANALOG_PIR_SENSITIVITY; + temp = PirSensitivity.numberUInt; + LogInfo("GprsMode:%d\n", GprsMode.numberUInt); + + if ((GprsMode.numberUInt < 10)) + { + if ((GprsMode.numberUInt == 1)) + temp |= 0x40; // bit 6-bit5: 2 instant, 1 hybird, 0: daily + else + temp |= 0x20; // bit 6-bit5: 2 instant, 1 hybird, 0: daily + } + if ((GprsSwitch.numberUInt)) + temp |= 0x80; + if ((val == SF_POWEROFF_SYNC_PARAM)) + temp &= 0x9F; + + mcuData[i++] = temp; + +#if 1 // DIGITAL_PIR + LogInfo("DigitPirSensitivity=%d\n", DigitPirSensitivity.numberUInt); + DigPirPulseCount = sf_set_digit_pir_pulse_cnt(DigitPirSensitivity.numberUInt); + DigPirWindowTime = 0; + + mcuReg[i] = DIGITAL_PIR_SENSITIVITY; + + mcuData[i++] = sf_set_digit_pir_level(DigitPirSensitivity.numberUInt); + mcuReg[i] = DIGITAL_PIR_CFG; + mcuData[i++] = DigPirWindowTime << 4 | DigPirPulseCount; + +#endif + + // DSP busy/idle + + mcuReg[i] = DSP_BUSY_STATUS; + mcuData[i++] = 0; + + temp = 1; + if (val == SF_POWEROFF_SD_FULL || sdState == SF_SD_FULL) + temp |= 0x02; + if (val == SF_POWEROFF_NO_SD) + temp &= ~0x01; + + mcuReg[i] = SYS_STATUS; + mcuData[i++] = temp; + + temp = 0; + if ((val == SF_POWEROFF_KEYON) || (val == SF_POWEROFF_SYNC_PARAM)) + temp |= 0x01; // bit0-3:1, reboot in A + else if (val == SF_POWEROFF_AUTO) + temp |= 0x81; // bit7:1 auto power when 3min no operation + else if (val == SF_POWEROFF_LOW_BAT) + temp |= 0x40; + + mcuReg[i] = POWEROFF_TYPE; + mcuData[i++] = temp; + + // battery recovery + mcuReg[i] = VBAT_RECOVER_VAL; + mcuData[i++] = 72; // SF_BATT_RECOVERY; + + if (TimelapseSwitch.numberUInt) + { + mcuReg[i] = TIMELAPSE_HOUR; + mcuData[i++] = TimelapseTime.time.Hour; + mcuReg[i] = TIMELAPSE_MINUTE; + mcuData[i++] = TimelapseTime.time.Min; + mcuReg[i] = TIMELAPSE_SEC; + + if ((TimelapseSwitch.numberUInt) && (TimelapseTime.time.Hour == 0) && (TimelapseTime.time.Min == 0) && (TimelapseTime.time.Sec == 0)) + mcuData[i++] = 5; + else + mcuData[i++] = TimelapseTime.time.Sec; + } + else + { + mcuReg[i] = TIMELAPSE_HOUR; + mcuData[i++] = 0; + mcuReg[i] = TIMELAPSE_MINUTE; + mcuData[i++] = 0; + mcuReg[i] = TIMELAPSE_SEC; + mcuData[i++] = 0; + } + + if (PirDelaySwitch.numberUInt) + { + mcuReg[i] = PIR_DELAY_HOUR; + mcuData[i++] = PirDelayTime.time.Hour; + mcuReg[i] = PIR_DELAY_MINUTE; + mcuData[i++] = PirDelayTime.time.Min; + mcuReg[i] = PIR_DELAY_SEC; + mcuData[i++] = PirDelayTime.time.Sec; + } + else + { + mcuReg[i] = PIR_DELAY_HOUR; + mcuData[i++] = 0; + mcuReg[i] = PIR_DELAY_MINUTE; + mcuData[i++] = 0; + mcuReg[i] = PIR_DELAY_SEC; + mcuData[i++] = 0; + } + + if (paraSyncFlag) + { + mcuReg[i] = TIME_SYNC_HOUR; + mcuData[i++] = 0; + mcuReg[i] = TIME_SYNC_MINUTE; + mcuData[i++] = 1; + mcuReg[i] = TIME_SYNC_SEC; + mcuData[i++] = 30; + } + LogInfo("GPSWaitRestartFlag = %d\n", GPSWaitRestartFlag.numberUInt); + + if (GprsMode.numberUInt == 1) + { + mcuReg[i] = DAILY_REPORT_HOUR; + mcuData[i++] = (date.Hour + 2) % 24; + mcuReg[i] = DAILY_REPORT_MINUTE; + mcuData[i++] = date.Min; + } + else + { + if (GPSWaitRestartFlag.numberUInt == 2) + { + DailyReportTime.time.Hour = 0; + DailyReportTime.time.Min = 1; + } + + if (GprsMode.numberUInt != 2 && GPSWaitRestartFlag.numberUInt == 1) + { + + mcuReg[i] = DAILY_REPORT_HOUR; + mcuData[i++] = (date.Hour + 1) % 24; + mcuReg[i] = DAILY_REPORT_MINUTE; + mcuData[i++] = (date.Min) % 60; + GPSWaitRestartFlag.numberUInt = 0; // TODO: set + } + else + { + GPSWaitRestartFlag.numberUInt = 0; + if ((date.Min + DailyReportTime.time.Min) > 59) + { + mcuReg[i] = DAILY_REPORT_HOUR; + mcuData[i++] = (date.Hour + DailyReportTime.time.Hour + 1) % 24; + } + else + { + mcuReg[i] = DAILY_REPORT_HOUR; + mcuData[i++] = (date.Hour + DailyReportTime.time.Hour) % 24; + } + + mcuReg[i] = DAILY_REPORT_MINUTE; + LogInfo("now time =[%02d:%02d:%02d],DailyReportTimer = [%02d:%02d:00]\n", date.Hour, date.Min, date.Sec, DailyReportTime.time.Hour, DailyReportTime.time.Min); + + if (DailyReportTime.time.Hour == 24) + mcuData[i++] = (date.Min + DailyReportTime.time.Min - 1) % 60; + else + mcuData[i++] = (date.Min + DailyReportTime.time.Min) % 60; + } + } + +#if 1 // no use + if (WorkMode.numberUInt == 1) + { + + mcuReg[i] = DAILY_SEND1_HOUR; + mcuData[i++] = TimeSend1.time.Hour; + mcuReg[i] = DAILY_SEND1_MINUTE; + mcuData[i++] = TimeSend1.time.Min; + } +#endif + + if (WorkTime1Switch.numberUInt) + { + mcuReg[i] = WORKTIME1_SWITCH; + + if (WorkTime.workTime[0].StartTime.Day > 0) + { + mcuData[i++] = WorkTime.workTime[0].StartTime.Day; + } + else + { + mcuData[i++] = 0xFF; + } + + mcuReg[i] = WORKTIME1_START_HOUR; + mcuData[i++] = WorkTime.workTime[0].StartTime.Hour; + mcuReg[i] = WORKTIME1_START_MINUTE; + mcuData[i++] = WorkTime.workTime[0].StartTime.Min; + + mcuReg[i] = WORKTIME1_STOP_HOUR; + mcuData[i++] = WorkTime.workTime[0].StopTime.Hour; + + mcuReg[i] = WORKTIME1_STOP_MINUTE; + mcuData[i++] = WorkTime.workTime[0].StopTime.Min; + } + else + { + mcuReg[i] = WORKTIME1_SWITCH; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME1_START_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME1_START_MINUTE; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME1_STOP_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME1_STOP_MINUTE; + mcuData[i++] = 0; + } + + if (WorkTime2Switch.numberUInt) + { + mcuReg[i] = WORKTIME2_SWITCH; + if (WorkTime.workTime[1].StartTime.Day > 0) + { + mcuData[i++] = WorkTime.workTime[1].StartTime.Day; + } + else + { + mcuData[i++] = 0xFF; + } + + mcuReg[i] = WORKTIME2_START_HOUR; + mcuData[i++] = WorkTime.workTime[1].StartTime.Hour; + mcuReg[i] = WORKTIME2_START_MINUTE; + mcuData[i++] = WorkTime.workTime[1].StartTime.Min; + + mcuReg[i] = WORKTIME2_STOP_HOUR; + mcuData[i++] = WorkTime.workTime[1].StopTime.Hour; + mcuReg[i] = WORKTIME2_STOP_MINUTE; + mcuData[i++] = WorkTime.workTime[1].StopTime.Min; + } + else + { + mcuReg[i] = WORKTIME2_SWITCH; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME2_START_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME2_START_MINUTE; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME2_STOP_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME2_STOP_MINUTE; + mcuData[i++] = 0; + } + } + + mcuReg[i] = DSP_WRITE_FLG; // MCU set end + mcuData[i++] = 1; + + regsize = i; + + for (i = 0; i < regsize; i++) + { + sf_commu_set_mcu(mcuReg[i], mcuData[i]); + } + return 0; +} +bool McuDevice::IsNightMode(void) +{ + unsigned char dataTemp1 = 0; + unsigned char dataTemp2 = 0; + unsigned short lightval = 0; + dataTemp1 = sf_commu_get_mcu(LUMINANCE_L); + dataTemp2 = sf_commu_get_mcu(LUMINANCE_H); + lightval = (dataTemp2 << 8) | dataTemp1; + IRSHTTER = lightval; + LogInfo("[sf_is_night_mode]IRSHTTER = %d\n", lightval); + if (lightval < SF_MCU_NIGHT_MODE_LUMINANCE) + { + return true; + } + else + { + return false; + } +} +const EnvironmentData McuDevice::GetEnvironmentData(void) +{ + bool isNight = IRSHTTER < SF_MCU_NIGHT_MODE_LUMINANCE ? true : false; + EnvironmentData data(isNight, IRSHTTER); + return data; +} +UINT8 McuDevice::sf_set_digit_pir_pulse_cnt(UINT8 pirs) +{ + UINT8 digPirPulseCnt[10] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1}; + + if (pirs > 9) + pirs = 9; + + return digPirPulseCnt[pirs]; +} +UINT8 McuDevice::sf_set_digit_pir_level(UINT8 pirs) +{ + UINT8 digPirLevel[10] = {200, 38, 30, 24, 18, 16, 10, 9, 8, 7}; + + if (pirs > 9) + pirs = 9; + + return digPirLevel[pirs]; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/McuDevice.h b/code/application/sifarsdk/component/McuManager/src/McuDevice.h new file mode 100644 index 000000000..c021df829 --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/McuDevice.h @@ -0,0 +1,183 @@ +#ifndef MCU_DEVICE_H +#define MCU_DEVICE_H +#include "Serial.h" +#include "IMcuManager.h" +#include "IHal.h" +#include "SfTypeDefine.h" +#include +constexpr int MUC_BUF_LENGTH = 32; +constexpr int WATCH_DOG_MINUTE_MAX = 100; +constexpr int SF_MCU_NIGHT_MODE_LUMINANCE = 380; +typedef enum +{ + MCU_SUB_VER = 0, + MCU_VER_L = 1, + MCU_VER_H = 2, + MCU_PRODUCT_INFO = 3, + START_MODE = 4, + LUMINANCE_L = 5, + LUMINANCE_H = 6, + RESERVER1 = 7, + + RTC_YEAR = 8, + RTC_MONTH = 9, + RTC_DAY = 10, + RTC_HOUR = 11, + RTC_MINUTE = 12, + RTC_SEC = 13, + RTC_WEEK = 14, + FUNCTION_SWTICH0 = 15, + FUNCTION_SWTICH1 = 16, + FUNCTION_SWTICH2 = 17, + RESERVER2 = 18, + + GPS_POWER_TIMER_CLEAR = 19, + GPS_POWER_CTRL = 20, + ANALOG_PIR_SENSITIVITY = 21, + DIGITAL_PIR_SENSITIVITY = 22, + DIGITAL_PIR_CFG = 23, + DSP_BUSY_STATUS = 24, + SYS_STATUS = 25, + RESERVER3 = 26, + + POWEROFF_TYPE = 27, + WDT_TIME = 28, + VBAT_LOW_WARN_VAL = 29, + VBAT_RECOVER_VAL = 30, + RESERVER4 = 31, + + TIMELAPSE_HOUR = 32, + TIMELAPSE_MINUTE = 33, + TIMELAPSE_SEC = 34, + PIR_DELAY_HOUR = 35, + PIR_DELAY_MINUTE = 36, + PIR_DELAY_SEC = 37, + TIME_SYNC_HOUR = 38, + TIME_SYNC_MINUTE = 39, + TIME_SYNC_SEC = 40, + DAILY_REPORT_HOUR = 41, + DAILY_REPORT_MINUTE = 42, + DAILY_SEND1_HOUR = 43, + DAILY_SEND1_MINUTE = 44, + DAILY_SEND2_HOUR = 45, + DAILY_SEND2_MINUTE = 46, + DAILY_SEND3_HOUR = 47, + DAILY_SEND3_MINUTE = 48, + DAILY_SEND4_HOUR = 49, + DAILY_SEND4_MINUTE = 50, + RESERVER5 = 51, + RESERVER6 = 52, + RESERVER7 = 53, + + WORKTIME1_SWITCH = 54, + WORKTIME1_START_HOUR = 55, + WORKTIME1_START_MINUTE = 56, + WORKTIME1_STOP_HOUR = 57, + WORKTIME1_STOP_MINUTE = 58, + + WORKTIME2_SWITCH = 59, + WORKTIME2_START_HOUR = 60, + WORKTIME2_START_MINUTE = 61, + WORKTIME2_STOP_HOUR = 62, + WORKTIME2_STOP_MINUTE = 63, + + WORKTIME3_SWITCH = 64, + WORKTIME3_START_HOUR = 65, + WORKTIME3_START_MINUTE = 66, + WORKTIME3_STOP_HOUR = 67, + WORKTIME3_STOP_MINUTE = 68, + + WORKTIME4_SWITCH = 69, + WORKTIME4_START_HOUR = 70, + WORKTIME4_START_MINUTE = 71, + WORKTIME4_STOP_HOUR = 72, + WORKTIME4_STOP_MINUTE = 73, + + WORKTIME5_SWITCH = 74, + WORKTIME5_START_HOUR = 75, + WORKTIME5_START_MINUTE = 76, + WORKTIME5_STOP_HOUR = 77, + WORKTIME5_STOP_MINUTE = 78, + + WORKTIME6_SWITCH = 79, + WORKTIME6_START_HOUR = 80, + WORKTIME6_START_MINUTE = 81, + WORKTIME6_STOP_HOUR = 82, + WORKTIME6_STOP_MINUTE = 83, + + DSP_WRITE_FLG = 84, + + RESERVER8 = 85, + RESERVER9 = 86, + RESERVER10 = 87, + RESERVER11 = 88, + RESERVER12 = 89, + RESERVER13 = 90, +} PARA_REG; +typedef struct +{ + unsigned char buf[MUC_BUF_LENGTH]; + unsigned int index; +} SMAPBUF_t; +typedef enum sfPOWEROFF_TYPE_E +{ + SF_POWEROFF_NOT = 0x00, + SF_POWEROFF_AUTO = 0x01, /*auto power when 3min no operation*/ + SF_POWEROFF_REBOOT = 0x02, /*poweroff to reboot*/ + SF_POWEROFF_KEYON = 0x03, + SF_POWEROFF_KEYOFF = 0x04, + SF_POWEROFF_SYNC_PARAM = 0x05, + SF_POWEROFF_GPS_DP = 0x06, + SF_POWEROFF_SD_FULL = 0x07, + SF_POWEROFF_LOW_BAT = 0x08, + SF_POWEROFF_NO_SD = 0x09, + SF_POWEROFF_BUTT, +} SF_POWEROFF_TYPE_E; +class McuDevice : public VMcuDevice, public Serial, public std::enable_shared_from_this +{ +public: + McuDevice(); + virtual ~McuDevice() = default; + void Init(void); + void UnInit(void); + void ReadingThread(void); + RETURN_CODE SetWatchDogMinute(const unsigned int &min) override; + RETURN_CODE SetWatchDogSecond(const unsigned int &sec) override; + unsigned char GetStartupMode(void) override; + RETURN_CODE SetMonitor(const std::shared_ptr &monitor) override; + unsigned char sf_mcu_reg_set(MCUParam_t attrId, unsigned char val) override; + bool IsNightMode(void) override; + const EnvironmentData GetEnvironmentData(void) override; + +private: + void SetWatchDog(const unsigned int &value); + void MonitorEventHapped(const std::shared_ptr &message); + unsigned char sf_commu_parse_mcu_data(unsigned char *src, unsigned int len); + int sf_getRegFromMcu_depack(unsigned char *dataToParse, unsigned int datalen, unsigned char *regAddr, unsigned char *regVal); + int sf_getRegFromMcu_ack(unsigned char regAddr, unsigned char regVal); + unsigned short sf_crc16_check(unsigned char *dataIn, int length); + void mcubuf_reset(void); + int sf_commu_set_mcu(unsigned char reg, unsigned char val); + void sf_commu_reset(void); + int sf_set_mcu_reg(unsigned char reg, unsigned char val); + int sf_commu_wait(unsigned char cmd); + unsigned int sf_set_mcu_reg_ack_depack(unsigned int *address, unsigned int *value); + int sf_commu_get_mcu(unsigned char reg); + int sf_get_mcu_reg(unsigned char reg); + unsigned int sf_get_mcu_reg_ack_depack(unsigned int *address, unsigned int *value); + UINT8 sf_set_digit_pir_pulse_cnt(UINT8 pirs); + UINT8 sf_set_digit_pir_level(UINT8 pirs); + +private: + std::shared_ptr mMonitor; + unsigned char mcu_buf[MUC_BUF_LENGTH]; + unsigned int mcu_buf_len; + bool mMcuReading; + std::thread mReading; + unsigned char mcu_upgrade_buf[MUC_BUF_LENGTH]; + unsigned char mcu_upgrade_buf_len; + int SMAP_waitAck; + SMAPBUF_t smap_buf; + unsigned short IRSHTTER; +}; +#endif // !MCU_DEVICE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/McuManager.cpp b/code/application/sifarsdk/component/McuManager/src/McuManager.cpp new file mode 100644 index 000000000..00a1a9e15 --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/McuManager.cpp @@ -0,0 +1,28 @@ +#include "McuManager.h" +#include "McuDevice.h" +#include "McuManagerMakePtr.h" +McuManager::McuManager() +{ + mMcuDevice = std::make_shared(); +} +RETURN_CODE McuManager::Init(void) +{ + mMcuDevice = std::make_shared(); + McuManagerMakePtr::GetInstance()->CreateMcuDevice(mMcuDevice); + std::dynamic_pointer_cast(mMcuDevice)->Init(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE McuManager::UnInit(void) +{ + if (mMcuDevice) + { + std::dynamic_pointer_cast(mMcuDevice)->UnInit(); + mMcuDevice.reset(); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE McuManager::GetMcuDevice(std::shared_ptr &mcu) +{ + mcu = mMcuDevice; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/McuManager.h b/code/application/sifarsdk/component/McuManager/src/McuManager.h new file mode 100644 index 000000000..0ef2f2c81 --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/McuManager.h @@ -0,0 +1,16 @@ +#ifndef MCU_MANAGER_H +#define MCU_MANAGER_H +#include "IMcuManager.h" +class McuManager : public IMcuManager +{ +public: + McuManager(); + ~McuManager() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + RETURN_CODE GetMcuDevice(std::shared_ptr &mcu) override; + +private: + std::shared_ptr mMcuDevice; +}; +#endif // !MCU_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/McuManagerMakePtr.cpp b/code/application/sifarsdk/component/McuManager/src/McuManagerMakePtr.cpp new file mode 100644 index 000000000..77b64ba2c --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/McuManagerMakePtr.cpp @@ -0,0 +1,40 @@ +#include "McuManagerMakePtr.h" +#include "Log.h" +#include "McuDevice.h" +bool CreateMcuManager(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = McuManagerMakePtr::GetInstance()->CreateMcuManager(instance); + if (code->IsCodeOK()) + { + LogInfo("Dual core manager instance is ok.\n"); + IMcuManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &McuManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + /** + * @brief + * The non-thread-safe changing is only for gtest. + */ + instance = *impl; + } + return instance; +} +RETURN_CODE McuManagerMakePtr::CreateMcuManager(std::shared_ptr &impl) +{ + auto tmp = std::make_shared(); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE McuManagerMakePtr::CreateMcuDevice(std::shared_ptr &impl) +{ + auto tmp = std::make_shared(); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/McuManagerMakePtr.h b/code/application/sifarsdk/component/McuManager/src/McuManagerMakePtr.h new file mode 100644 index 000000000..ddf90befe --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/McuManagerMakePtr.h @@ -0,0 +1,14 @@ +#ifndef MCU_MANAGER_MAKE_PTR_H +#define MCU_MANAGER_MAKE_PTR_H +#include "McuManager.h" +#include +class McuManagerMakePtr +{ +public: + McuManagerMakePtr() = default; + virtual ~McuManagerMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE CreateMcuManager(std::shared_ptr &impl); + virtual RETURN_CODE CreateMcuDevice(std::shared_ptr &impl); +}; +#endif // !MCU_MANAGER_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/Serial.cpp b/code/application/sifarsdk/component/McuManager/src/Serial.cpp new file mode 100644 index 000000000..ab22a39a3 --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/Serial.cpp @@ -0,0 +1,281 @@ + +#include "Serial.h" +#include "Log.h" +#include "linux_api.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +Serial::Serial() +{ + gsfd = -1; +} +int Serial::sf_commu_mcu_interface_init(const char *device, int speed, char flow_ctrl, int databits, int stopbits, char parity) +{ + + int i; + int speed_arr[] = {B115200, B460800}; + int name_arr[] = {115200, 460800}; + struct termios options; + int fd = -1; + int ret = -1; + fd = linux_open(device, O_RDWR | O_NONBLOCK); + if (fd < 0) + { + LogError("Open %s error! fd = %d\n", device, fd); + ret = -1; + return ret; + } + else + { + LogInfo("Open %s success!\n", device); + } + + if (tcgetattr(fd, &options) != 0) + { + LogInfo("SetupSerial 1"); + close(fd); + return -1; + } + + // cfmakeraw(&options); + + for (i = 0; i < (2); i++) + { + if (speed == name_arr[i]) + { + cfsetispeed(&options, speed_arr[i]); + cfsetospeed(&options, speed_arr[i]); + } + } + // options.c_cflag |= CLOCAL; + // options.c_cflag |= CREAD; + + switch (flow_ctrl) + { + case 'n': + case 'N': // 不使用流控制 + options.c_cflag &= ~(600); // CRTSCTS; + break; + + case 'h': + case 'H': // 使用硬件流控制 + options.c_cflag |= 600; // CRTSCTS; + break; + + case 'S': + case 's': // 使用软件流控制 + options.c_cflag |= IXON | IXOFF | IXANY; + break; + } + + // 设置数据位 + options.c_cflag &= ~CSIZE; // 屏蔽其他标志位 + + switch (databits) + { + case 5: + options.c_cflag |= CS5; + break; + + case 6: + options.c_cflag |= CS6; + break; + + case 7: + options.c_cflag |= CS7; + break; + + case 8: + options.c_cflag |= CS8; + break; + + default: + LogInfo("Unsupported data size/n"); + close(fd); + return -1; + } + + // 设置校验位 + switch (parity) + { + case 'n': + case 'N': // 无奇偶校验位 + options.c_cflag &= ~PARENB; + options.c_iflag &= ~INPCK; + break; + + case 'o': + case 'O': // 设置为奇校验 + options.c_cflag |= (PARODD | PARENB); + options.c_iflag |= INPCK; + break; + + case 'e': + case 'E': // 设置为偶校验 + options.c_cflag |= PARENB; + options.c_cflag &= ~PARODD; + options.c_iflag |= INPCK; + break; + + case 's': + case 'S': // 设置为空格 + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + break; + + default: + LogInfo("Unsupported parity/n"); + close(fd); + return -1; + } + + // 设置停止位 + switch (stopbits) + { + case 1: + options.c_cflag &= ~CSTOPB; + break; + + case 2: + options.c_cflag |= CSTOPB; + break; + + default: + LogInfo("Unsupported stop bits/n"); + close(fd); + return -1; + } + + // 修改输出模式,原始数据输出 + options.c_oflag &= ~OPOST; + + // 激活配置 (将修改后的termios数据设置到串口中) + if (tcsetattr(fd, TCSANOW, &options) != 0) + { + LogInfo("com set error!/n"); + close(fd); + return -1; + } + + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + + // 设置等待时间和最小接收字符 + options.c_cc[VTIME] = 0; + options.c_cc[VMIN] = 1; + + // 如果发生数据溢出,接收数据,但是不再读取 + tcflush(fd, TCIFLUSH); + + // 激活配置 (将修改后的termios数据设置到串口中) + if (tcsetattr(fd, TCSANOW, &options) != 0) + { + LogInfo("com set error!/n"); + close(fd); + return -1; + } + LogInfo("Open serial succeed.\n"); + gsfd = fd; + return gsfd; +} +int Serial::sf_commu_mcu_interface_uninit(void) +{ + if (gsfd >= 0) + { + linux_close(gsfd); + gsfd = -1; + } + return 0; +} +int Serial::sf_commu_read(unsigned char *buf, int len) +{ + int ret = 0; + constexpr int TIME_OUT_MS = 1000; + // 参数检查 + if (buf == NULL || len <= 0 || TIME_OUT_MS < 0) + { + LogInfo("Invalid parameters for sf_mcu_dev_read.\n"); + return -EINVAL; + } + + struct timeval timeout; + fd_set read_fds; + + // 设置超时时间 + timeout.tv_sec = TIME_OUT_MS / 1000; + timeout.tv_usec = (TIME_OUT_MS % 1000) * 1000; + + // 初始化文件描述符集 + FD_ZERO(&read_fds); + FD_SET(gsfd, &read_fds); + + // 使用 select 检查文件描述符是否可读 + ret = select(gsfd + 1, &read_fds, NULL, NULL, &timeout); + if (ret < 0) + { + // LogInfo("%s select error: %s\n", MCU_SERIAL_DEVICE, strerror(errno)); + LogError("mcu select failed.\n"); + return -errno; + } + else if (ret == 0) + { + // 超时,没有数据可读 + return 0; + } + + if (FD_ISSET(gsfd, &read_fds)) + { + ret = linux_read(gsfd, buf, len); + if (ret < 0) + { + // LogInfo("%s read error: %s\n", MCU_SERIAL_DEVICE, strerror(errno)); + LogError("mcu read failed.\n"); + return -errno; + } + else + { +#if 1 // For test. + printf("============ read.\n"); + for (int i = 0; i < ret; i++) + { + printf("0x%02x,", buf[i]); + } + printf("\n"); +#endif + // 返回实际读取的字节数 + return ret; + } + } + + return -1; // 不可达的代码,但为了保持一致性,这里也返回-1 +} +int Serial::sf_commu_write(unsigned char *buf, int len) +{ + int ret = 0; +#if 1 // For test. + printf("============ write.\n"); + for (int i = 0; i < len; i++) + { + printf("0x%02x,", buf[i]); + } + printf("\n"); +#endif + ret = linux_write(gsfd, buf, len); + if (ret < 0) + { + LogError("%s write error!\n"); + close(gsfd); + gsfd = -1; + } + LogInfo("========================= write end.\n"); + return ret; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/McuManager/src/Serial.h b/code/application/sifarsdk/component/McuManager/src/Serial.h new file mode 100644 index 000000000..17a010789 --- /dev/null +++ b/code/application/sifarsdk/component/McuManager/src/Serial.h @@ -0,0 +1,16 @@ +#ifndef SERIAL_H +#define SERIAL_H +class Serial +{ +public: + Serial(); + virtual ~Serial() = default; + int sf_commu_mcu_interface_init(const char *device, int speed, char flow_ctrl, int databits, int stopbits, char parity); + int sf_commu_read(unsigned char *buf, int len); + int sf_commu_write(unsigned char *buf, int len); + int sf_commu_mcu_interface_uninit(void); + +private: + int gsfd; +}; +#endif // !SERIAL_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/CMakeLists.txt b/code/application/sifarsdk/component/PeripheralManager/CMakeLists.txt new file mode 100644 index 000000000..d23623159 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/CMakeLists.txt @@ -0,0 +1,37 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/FileManager/include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/AtCommand/include + ${HAL_SOURCE_PATH}/include + ${AT_COMMAND_PATH} +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) +# At command src code. +string(COMPARE EQUAL "${AT_COMMAND_PATH}" "" value) +message("The at-command src code path is ${AT_COMMAND_PATH}.") +if (value EQUAL 0) #变量被设置了 +message("build at-command src code.") +# include(${AT_COMMAND_PATH}/at-command.cmake) +endif() + +set(TARGET_NAME PeripheralManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} FileManager AtCommand Hal ReturnCode Log) + diff --git a/code/application/sifarsdk/component/PeripheralManager/include/IPeripheralManager.h b/code/application/sifarsdk/component/PeripheralManager/include/IPeripheralManager.h new file mode 100644 index 000000000..330f60e3a --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/include/IPeripheralManager.h @@ -0,0 +1,273 @@ +#ifndef I_PERIPHERAL_MANAGER_H +#define I_PERIPHERAL_MANAGER_H +#include "VReturnCode.h" +#include "IHalCommon.h" +#include +#include +#include +enum class NetGeneration +{ + NET_2G = 0, + NET_3G, + NET_4G, + END +}; +enum class SimInitResult +{ + SIM_INIT_OK = 0, + SIM_INIT_INSERTED, + SIM_INIT_NOT_INSERTED, + SIM_INIT_NOT_SUPPORT_MOBILE_NETWORK, + SIM_INIT_END +}; +enum class RegisterNetworkResult +{ + SUCCEED = 0, + FAILED, + ERROR_REG_NET, + FAILED_NOT_SUPPORT, + FAILED_NO_SIGNAL, + END +}; +enum class NetApnConfigResult +{ + SUCCEED = 0, + FAILED, + END +}; +typedef enum sf_SIM_TYPE_E +{ + SF_SIM_MEGA = 0, // normal mega sim, use in abroad + SF_SIM_MEGA_IOT, // special mega sim, only use in T110 + SF_SIM_OTHER, // other sim + SF_SIM_BUTT +} SF_SIM_TYPE_E; +class SimInitDataOut +{ +public: + SimInitDataOut() + { + mResult = SimInitResult::SIM_INIT_END; + mType = SF_SIM_BUTT; + } + ~SimInitDataOut() + { + } + SimInitResult mResult; + std::string mIMEI; + std::string mModuleSubVersion; + std::string mIccid; + SF_SIM_TYPE_E mType; +}; +enum class SignalLevel +{ + LEVEL_0 = 0, + LEVEL_1 = 2, + LEVEL_2 = 3, + LEVEL_3 = 4, + END +}; +class RegisterNetworkDataOut +{ +public: + RegisterNetworkDataOut() + { + result = RegisterNetworkResult::END; + mGeneration = NetGeneration::END; + mSimSignal = 0; + mSignalLevel = SignalLevel::END; + } + ~RegisterNetworkDataOut() + { + } + RegisterNetworkResult result; + NetGeneration mGeneration; + std::string mServiceProvider; + unsigned char mSimSignal; + SignalLevel mSignalLevel; +}; +class NetApnConfigDataOut +{ +public: + NetApnConfigDataOut() + { + result = NetApnConfigResult::END; + } + ~NetApnConfigDataOut() + { + } + NetApnConfigResult result; +}; +enum class SfKeyAction +{ + SF_KEY_ACTION_SHORT_CLICK = 0, + SF_KEY_ACTION_LONG_CLICK, + SF_KEY_ACTION_HOLD_DOWN, + SF_KEY_ACTION_HOLD_UP, + SF_KEY_ACTION_GROUP, + SF_KEY_ACTION_BUTT, + SF_KEY_ACTION_END +}; +// class KeysState +// { +// public: +// KeysState() +// { +// mAction = SfKeyAction::SF_KEY_ACTION_END; +// mHoldTimeMs = 0; +// } +// ~KeysState() +// { +// } +// SfKeyAction mAction; +// long int mHoldTimeMs; +// }; +constexpr int TIME_MEANS_KEY_NOT_HOLD = 0; +class KeysState +{ +public: + KeysState(const SfKeyAction &action, const long int &holdTimeMs) + : mAction(action), mHoldTimeMs(holdTimeMs) + { + } + ~KeysState() + { + } + const SfKeyAction mAction; + const long int mHoldTimeMs; +}; +class VKeyMonitor +{ +public: + VKeyMonitor() = default; + virtual ~VKeyMonitor() = default; + virtual RETURN_CODE KeyActionHappened(const SfKeyDefine &key, const SfKeyAction &event, const unsigned int holdTimeMs = 0) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +enum class GpioDevice +{ + PIR = 0, + USB, + END +}; +enum class DeviceInput +{ + VALID = 0, + INVALID, + END +}; +class VGpioMonitor +{ +public: + VGpioMonitor() = default; + virtual ~VGpioMonitor() = default; + virtual RETURN_CODE InputTransform(const GpioDevice &gpio, const DeviceInput &input) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +constexpr unsigned int LED_NOT_BLINK = 0; +constexpr unsigned int BLINKING_FAST_MS = 500; +constexpr unsigned int BLINKING_SLOW_MS = 1000; +constexpr long int KEEP_ALIVE_FOREVER = 0; +constexpr unsigned int DELETED_LED_STATE = -1; +constexpr unsigned int DO_NOT_KEEP_ALIVE = -2; +class VLedState +{ +public: + VLedState() = default; + virtual ~VLedState() = default; + virtual RETURN_CODE GetLedState(SfLedState &state) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual unsigned int GetKeepAliveTimeMs(void) { return KEEP_ALIVE_FOREVER; } + virtual unsigned int GetBlinkTimeMs(void) { return LED_NOT_BLINK; } +}; +using SimInitCallback = void (*)(const SimInitDataOut &); +using RegisterNetworkCallback = void (*)(const RegisterNetworkDataOut &); +using NetApnConfigCallback = void (*)(const NetApnConfigDataOut &); +class VNetworkHardwareHandle +{ +public: + VNetworkHardwareHandle() = default; + virtual ~VNetworkHardwareHandle() = default; + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual bool IsModuleWorking(void) { return false; } + virtual RETURN_CODE SimInit(SimInitCallback func) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE RegisterNetworkManual(RegisterNetworkCallback func) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE RegisterNetworkAuto(RegisterNetworkCallback func) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE NetApnConfig(NetApnConfigCallback func) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE KeepAliveForLive(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +class VRtcTime +{ +public: + VRtcTime() = default; + virtual ~VRtcTime() = default; + virtual int Set(const struct rtc_time &rtctm) { return -1; } + virtual int Get(struct rtc_time &rtctm) { return -1; } + virtual bool Check(const struct rtc_time &rtctm) { return false; } + virtual int Reset(void) { return -1; } +}; +typedef enum +{ + SF_SD_FORMAT_SUCUSS = 0, + SF_SD_FORMAT_NO_CARD = 1, + SF_SD_FORMAT_NOT_SUPPORT_FAT = 2, + SF_SD_FORMAT_MAX = 3, +} SF_SD_FORMAT_RESULT_e; +typedef enum sfSD_STATUS_E +{ + SF_SD_UNPLUGED = 0x00, + SD_MOUNT_FAILURE, + SD_MOUNT_SUCCESS, + SF_SD_FULL, + SF_SD_ERROR, + SF_SD_PLUGED, + SF_SD_BUTT, +} SF_SD_STATUS_E; +typedef struct sf_STORE_ATTR_S +{ + unsigned int SDStatus; + unsigned int SDFree; + unsigned int SDTotalSize; +} SF_STORE_ATTR_S; +constexpr int SDLOOP_REMAIN_SPACE = 300; /*300MB*/ +class VSDCardMonitor +{ +public: + VSDCardMonitor() = default; + virtual ~VSDCardMonitor() = default; + virtual void ReportSDCardStatus(const SF_SD_STATUS_E &status) {} +}; +class VSDCardHandle +{ +public: + VSDCardHandle() = default; + virtual ~VSDCardHandle() = default; + virtual void GetInfo(SF_STORE_ATTR_S &pstoreattrs) {} + virtual void RemoveFile(const char *path, const signed int &threshold) {} + virtual void LoopRemove(const char *path) {} + virtual void IsFull(signed int &Isfull) {} + virtual SF_SD_STATUS_E GetStatus(void) { return SF_SD_BUTT; } + virtual void SetStatus(SF_SD_STATUS_E enStatus) {} + virtual void SetMonitor(const std::shared_ptr &monitor) {} + virtual RETURN_CODE Format(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE USBInsert(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +class IPeripheralManager +{ +public: + IPeripheralManager() = default; + virtual ~IPeripheralManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetKeyMonitor(std::shared_ptr monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetAllKeysState(std::map &state) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetGpioMonitor(std::shared_ptr monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetLedState(const SfLedIndex &led, std::shared_ptr &state) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + // virtual RETURN_CODE LuckLed(const SfLedIndex &led, std::shared_ptr monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + // virtual RETURN_CODE UnLuckLed(const SfLedIndex &led, std::shared_ptr monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetLongClickPeriod(unsigned int period) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetNetworkModuleHandle(std::shared_ptr &module) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetRtcTimeHandle(std::shared_ptr &rtc) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetSDCardHandle(std::shared_ptr &sdCard) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreatePeripheralManager(void); +#endif // !I_PERIPHERAL_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/GpioInputDevice.cpp b/code/application/sifarsdk/component/PeripheralManager/src/GpioInputDevice.cpp new file mode 100644 index 000000000..403faa0d1 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/GpioInputDevice.cpp @@ -0,0 +1,20 @@ +#include "GpioInputDevice.h" +#include "Log.h" +GpioInputDevice::GpioInputDevice(std::shared_ptr &gpioHandle, GpioInputCallback gpioInputEvent) + : mGpioHandle(gpioHandle), mGpioInputEvent(gpioInputEvent) +{ +} +void GpioInputDevice::InputTransform(const GpioPin &device, const GpioInputValue &value, void *context) +{ + if (mGpioInputEvent) + { + mGpioInputEvent(device, value, context); + } +} +void GpioInputDevice::Init(void) +{ + mGpioHandle->SetInputMonitor(shared_from_this(), nullptr); +} +void GpioInputDevice::UnInit(void) +{ +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/GpioInputDevice.h b/code/application/sifarsdk/component/PeripheralManager/src/GpioInputDevice.h new file mode 100644 index 000000000..2ab23a763 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/GpioInputDevice.h @@ -0,0 +1,18 @@ +#ifndef GPIO_INPUT_DEVICE_H +#define GPIO_INPUT_DEVICE_H +#include "IHal.h" +using GpioInputCallback = std::function; +class GpioInputDevice : public VGpioInputMonitor, public std::enable_shared_from_this +{ +public: + GpioInputDevice(std::shared_ptr &gpioHandle, GpioInputCallback gpioInputEvent); + ~GpioInputDevice() = default; + void InputTransform(const GpioPin &device, const GpioInputValue &value, void *context) override; + void Init(void); + void UnInit(void); + +private: + std::shared_ptr mGpioHandle; + GpioInputCallback mGpioInputEvent; +}; +#endif // !GPIO_INPUT_DEVICE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/IPeripheralManager.cpp b/code/application/sifarsdk/component/PeripheralManager/src/IPeripheralManager.cpp new file mode 100644 index 000000000..55e58abe2 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/IPeripheralManager.cpp @@ -0,0 +1,31 @@ +#include "IPeripheralManager.h" +#include "Log.h" +#include +std::shared_ptr &IPeripheralManager::GetInstance(std::shared_ptr *impl) +{ + static std::shared_ptr instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Don't sleep and make sure that start fast. + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + // instance->UnInit(); + // (*impl)->Init(); // TODO: Don't need to Init is better? + instance = *impl; + } + else + { + LogError("[ error ] instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static std::shared_ptr tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/KeyManager.cpp b/code/application/sifarsdk/component/PeripheralManager/src/KeyManager.cpp new file mode 100644 index 000000000..08cce2507 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/KeyManager.cpp @@ -0,0 +1,112 @@ +#include "KeyManager.h" +#include "Log.h" +constexpr long int KEY_PRESSING = 0; +constexpr unsigned int NOT_A_HOLD_KEY_ACTION = 0; +KeyManager::KeyManager() +{ + mKeyContrl = nullptr; + mKeyActionEvent = nullptr; + mPressedTime = KEY_NOT_PRESSING; + mKeyState = SfKeyEvent::KEY_EVENT_UN_PRESSED; + mLongClickTime = 0; +} +KeyManager::KeyManager(std::shared_ptr &keyContrl, const KeyActionCallback &keyAction, const long int &longClickTime) + : mKeyContrl(keyContrl), mKeyActionEvent(keyAction), mLongClickTime(longClickTime) +{ + mPressedTime = KEY_NOT_PRESSING; + mKeyState = SfKeyEvent::KEY_EVENT_UN_PRESSED; +} +KeyManager::~KeyManager() +{ +} +void KeyManager::HalKeyEventHappened(const SfKeyDefine &key, const SfKeyEvent &event, void *context) +{ + std::lock_guard locker(mMutex); + KeyEventCallback(key, event, context); +} +void KeyManager::TimerKeyEventHappened(const SfKeyDefine &key, const SfKeyEvent &event, void *context) +{ + std::lock_guard locker(mMutex); + if (IsKeyPressing()) + { + KeyEventCallback(key, event, context); + } +} +long int KeyManager::GetHoldPressingTimeMs(void) +{ + return mPressedTime; +} +bool KeyManager::IsKeyPressing(void) +{ + return mPressedTime >= KEY_PRESSING ? true : false; +} +void KeyManager::Init(void) +{ + mKeyContrl->SetKeyEventMonitor(shared_from_this(), nullptr); +} +void KeyManager::UnInit(void) +{ +} +void KeyManager::KeyEventCallback(const SfKeyDefine &key, const SfKeyEvent &keyEvent, void *context) +{ + if (KEY_PRESSING <= mPressedTime) + { + mPressedTime += PERIPHERAL_CHECK_PERIOD_MS; + // LogInfo("Pressing time = %ld\n", mPressedTime); + } + switch (keyEvent) + { + case SfKeyEvent::KEY_EVENT_PRESSED: + KeyPressedHandle(key); + break; + case SfKeyEvent::KEY_EVENT_UN_PRESSED: + KeyUnPressedHandle(key); + break; + + default: + break; + } +} +void KeyManager::SetLongClickPeriod(unsigned int period) +{ + mLongClickTime = period; +} +void KeyManager::KeyPressedHandle(const SfKeyDefine &key) +{ + if (mLongClickTime <= mPressedTime) // long click + { + if (mKeyActionEvent) + { + // mKeyActionEvent(key, SfKeyAction::SF_KEY_ACTION_LONG_CLICK, NOT_A_HOLD_KEY_ACTION, nullptr); + } + } + if (mPressedTime != KEY_NOT_PRESSING && mPressedTime % KEY_ACTION_HOLD_DWON == 0) + { + if (mKeyActionEvent) + { + mKeyActionEvent(key, SfKeyAction::SF_KEY_ACTION_HOLD_DOWN, mPressedTime, nullptr); + } + } + if (KEY_NOT_PRESSING == mPressedTime) + { + mPressedTime = KEY_PRESSING; + } +} +void KeyManager::KeyUnPressedHandle(const SfKeyDefine &key) +{ + if (KEY_ACTION_SHORT_CLICK <= mPressedTime && mPressedTime < KEY_ACTION_HOLD_DWON) + { + if (mKeyActionEvent) + { + mKeyActionEvent(key, SfKeyAction::SF_KEY_ACTION_SHORT_CLICK, NOT_A_HOLD_KEY_ACTION, nullptr); + } + } + if (KEY_ACTION_HOLD_DWON <= mPressedTime) + { + if (mKeyActionEvent) + { + mKeyActionEvent(key, SfKeyAction::SF_KEY_ACTION_HOLD_UP, mPressedTime, nullptr); + } + } + mPressedTime = KEY_NOT_PRESSING; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/KeyManager.h b/code/application/sifarsdk/component/PeripheralManager/src/KeyManager.h new file mode 100644 index 000000000..285b7efd3 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/KeyManager.h @@ -0,0 +1,38 @@ +#ifndef KEY_MANAGER_H +#define KEY_MANAGER_H +#include "IHal.h" +#include "IPeripheralManager.h" +#include +using KeyActionCallback = std::function; +constexpr int KEY_ACTION_LONG_CLICK = 1000 * 5; // 3s means long click. +constexpr int KEY_ACTION_SHORT_CLICK = 200; // 300 ms means short click. +constexpr int KEY_ACTION_HOLD_DWON = 500; // 500 ms meand key was hold. +constexpr long int KEY_NOT_PRESSING = -1; +class KeyManager : public VKeyEventMonitor, public std::enable_shared_from_this +{ +public: + KeyManager(); + KeyManager(std::shared_ptr &keyContrl, const KeyActionCallback &keyAction, const long int &longClickTime = KEY_ACTION_LONG_CLICK); + ~KeyManager(); + void HalKeyEventHappened(const SfKeyDefine &key, const SfKeyEvent &event, void *context) override; + void TimerKeyEventHappened(const SfKeyDefine &key, const SfKeyEvent &event, void *context) override; + long int GetHoldPressingTimeMs(void) override; + void Init(void); + void UnInit(void); + void KeyEventCallback(const SfKeyDefine &key, const SfKeyEvent &keyEvent, void *context); + +private: + void KeyPressedHandle(const SfKeyDefine &key); + void KeyUnPressedHandle(const SfKeyDefine &key); + bool IsKeyPressing(void); + void SetLongClickPeriod(unsigned int period); + +private: + std::mutex mMutex; + std::shared_ptr mKeyContrl; + KeyActionCallback mKeyActionEvent; + long int mPressedTime; + long int mLongClickTime; + SfKeyEvent mKeyState; +}; +#endif // !KEY_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/KeyTimer.cpp b/code/application/sifarsdk/component/PeripheralManager/src/KeyTimer.cpp new file mode 100644 index 000000000..dd244c28a --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/KeyTimer.cpp @@ -0,0 +1,76 @@ +#include "KeyTimer.h" +#include "Log.h" +#include "KeyManager.h" +KeyTimer::KeyTimer() +{ + mTimerRuning = false; +} +std::shared_ptr &KeyTimer::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + // if (impl) + // { + // instance = *impl; + // } + return instance; +} +void KeyTimer::StartTimer(void) +{ + for (int i = 0; i < static_cast(SfKeyDefine::KEY_PIN_END); i++) + { + std::map>::iterator iter; + iter = mKeyManagers.find(static_cast(i)); + if (iter == mKeyManagers.end()) + { + LogError("Key timer start failed."); + return; + } + } + auto timerThread = [](std::shared_ptr timer) + { + LogInfo("Key timer started.\n"); + timer->Timer(); + }; + mTimer = std::thread(timerThread, shared_from_this()); +} +void KeyTimer::StopTimer(void) +{ + mTimerRuning = false; + if (mTimer.joinable()) + { + mTimer.join(); + } +} +void KeyTimer::AddKey(const SfKeyDefine &key, std::shared_ptr &keyManager) +{ + mKeyManagers[key] = keyManager; +} +void KeyTimer::Timer(void) +{ + mTimerRuning = true; + while (mTimerRuning) + { + for (int i = 0; i < static_cast(SfKeyDefine::KEY_PIN_END); i++) + { + mKeyManagers[static_cast(i)]->TimerKeyEventHappened(static_cast(i), SfKeyEvent::KEY_EVENT_PRESSED, nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(PERIPHERAL_CHECK_PERIOD_MS)); + } +} +void KeyTimer::GetAllKeysState(std::map &state) +{ + for (int i = 0; i < static_cast(SfKeyDefine::KEY_PIN_END); i++) + { + long int holdTime = mKeyManagers[static_cast(i)]->GetHoldPressingTimeMs(); + if (KEY_NOT_PRESSING == holdTime) + { + continue; + } + // KeysState keyState; + // keyState.mAction = SfKeyAction::SF_KEY_ACTION_HOLD_DOWN; + // keyState.mHoldTimeMs = holdTime; + // state[static_cast(i)] = keyState; + KeysState keyState(SfKeyAction::SF_KEY_ACTION_HOLD_DOWN, holdTime); + state.insert(std::make_pair(static_cast(i), keyState)); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/KeyTimer.h b/code/application/sifarsdk/component/PeripheralManager/src/KeyTimer.h new file mode 100644 index 000000000..f41dfa211 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/KeyTimer.h @@ -0,0 +1,29 @@ +#ifndef KEY_TIMER_H +#define KEY_TIMER_H +#include "IHalCommon.h" +#include "IHal.h" +#include "IPeripheralManager.h" +#include +#include +#include +#include +// TODO: 这个类要优化去适配随意添加定制的按键 +class KeyTimer : public std::enable_shared_from_this +{ +public: + KeyTimer(); + ~KeyTimer() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + void StartTimer(void); + void StopTimer(void); + void AddKey(const SfKeyDefine &key, std::shared_ptr &keyManager); + void Timer(void); + void GetAllKeysState(std::map &state); + +private: + std::mutex mMutex; + std::map> mKeyManagers; + bool mTimerRuning; + std::thread mTimer; +}; +#endif // !KEY_TIMER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/LedHandle.cpp b/code/application/sifarsdk/component/PeripheralManager/src/LedHandle.cpp new file mode 100644 index 000000000..8fd85c1ef --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/LedHandle.cpp @@ -0,0 +1,109 @@ +#include "LedHandle.h" +#include "Log.h" +LedHandle::LedHandle(std::shared_ptr ledContrl) : mLedContrl(ledContrl) +{ + NewLedStateStart(); +} +void LedHandle::AddLedState(std::shared_ptr &state) +{ + LogInfo("Add led state.\n"); + NewLedStateStart(); + SfLedState ledState = SfLedState::SF_LED_STATE_END; + state->GetLedState(ledState); + mLedContrl->SetLedState(ledState); + mCurrentState = ledState; + if (DO_NOT_KEEP_ALIVE == state->GetKeepAliveTimeMs()) + { + return; + } + mStates.push_back(state); +} +void LedHandle::CheckState(const unsigned int &period) +{ + const int TOP_STATE_SHOW = mStates.size() - 1; + mStateAliveTime += period; + mBlinkPeriod += period; + if (TOP_STATE_SHOW >= 0) + { + // LogInfo("TOP_STATE_SHOW = %d.\n", TOP_STATE_SHOW); + std::shared_ptr state = mStates[TOP_STATE_SHOW]; + SfLedState ledState = SfLedState::SF_LED_STATE_END; + if (state->GetKeepAliveTimeMs() == DELETED_LED_STATE || (state->GetKeepAliveTimeMs() != KEEP_ALIVE_FOREVER && state->GetKeepAliveTimeMs() <= mStateAliveTime)) + { + DeleteTopLedState(); + return; + } + state->GetLedState(ledState); + if (mCurrentState != ledState && LED_NOT_BLINK == state->GetBlinkTimeMs()) + { + mLedContrl->SetLedState(ledState); + mCurrentState = ledState; + } + else if (mCurrentState == ledState && state->GetBlinkTimeMs() != LED_NOT_BLINK) + { + BlinkOff(state); + } + else if (mCurrentState == SfLedState::SF_LED_STATE_OFF && state->GetBlinkTimeMs() != LED_NOT_BLINK) + { + BlinkOn(state, ledState); + } + } +} +bool LedHandle::SetLedState(const SfLedState &state) +{ + return mLedContrl->SetLedState(state); +} +void LedHandle::NewLedStateStart(void) +{ + mCurrentState = SfLedState::SF_LED_STATE_END; + mStateAliveTime = NEW_TOP_LED_STATE; + mBlinkPeriod = 0; +} +void LedHandle::DeleteTopLedState(void) +{ + const int TOP_STATE_SHOW = mStates.size() - 1; + if (TOP_STATE_SHOW < 0) + { + return; + } + // if (TOP_STATE_SHOW >= 0) + // { + LogInfo("Delete led state.\n"); + NewLedStateStart(); + mStates.erase(mStates.begin() + TOP_STATE_SHOW); + // } + const int NEXT_LED_STATE = mStates.size() - 1; + if (NEXT_LED_STATE < 0) + { + return; + } + // if (NEXT_LED_STATE >= 0) + // { + LogInfo("Top next led state.\n"); + std::shared_ptr state = mStates[NEXT_LED_STATE]; + SfLedState ledState = SfLedState::SF_LED_STATE_END; + state->GetLedState(ledState); + mLedContrl->SetLedState(ledState); + mCurrentState = ledState; + // } +} +void LedHandle::BlinkOff(std::shared_ptr &state) +{ + if (state->GetBlinkTimeMs() < mBlinkPeriod) + { + // LogInfo("blink off.\n"); + mLedContrl->SetLedState(SfLedState::SF_LED_STATE_OFF); + mCurrentState = SfLedState::SF_LED_STATE_OFF; + mBlinkPeriod = 0; + } +} +void LedHandle::BlinkOn(std::shared_ptr &state, const SfLedState &onState) +{ + if (state->GetBlinkTimeMs() < mBlinkPeriod) + { + // LogInfo("blink on.\n"); + mLedContrl->SetLedState(onState); + mCurrentState = onState; + mBlinkPeriod = 0; + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/LedHandle.h b/code/application/sifarsdk/component/PeripheralManager/src/LedHandle.h new file mode 100644 index 000000000..2fa1d819c --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/LedHandle.h @@ -0,0 +1,30 @@ +#ifndef LED_HANDLE_H +#define LED_HANDLE_H +#include "IHal.h" +#include "IPeripheralManager.h" +#include +constexpr unsigned int NEW_TOP_LED_STATE = 0; +class LedHandle +{ +public: + LedHandle() = default; + LedHandle(std::shared_ptr ledContrl); + virtual ~LedHandle() = default; + void AddLedState(std::shared_ptr &state); + void CheckState(const unsigned int &period); + +private: + bool SetLedState(const SfLedState &state); + void NewLedStateStart(void); + void DeleteTopLedState(void); + void BlinkOff(std::shared_ptr &state); + void BlinkOn(std::shared_ptr &state, const SfLedState &onState); + +private: + std::shared_ptr mLedContrl; + std::vector> mStates; + SfLedState mCurrentState; + unsigned int mStateAliveTime; + unsigned int mBlinkPeriod; +}; +#endif // !LED_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/LedTimer.cpp b/code/application/sifarsdk/component/PeripheralManager/src/LedTimer.cpp new file mode 100644 index 000000000..3bab31473 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/LedTimer.cpp @@ -0,0 +1,78 @@ +#include "LedTimer.h" +#include "Log.h" +LedTimer::LedTimer() +{ + mTimerRuning = false; +} +std::shared_ptr &LedTimer::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + // if (impl) + // { + // instance = *impl; + // } + return instance; +} +void LedTimer::Init(void) +{ + for (int i = 0; i < static_cast(SfLedIndex::SF_LED_END); i++) + { + auto ledHandle = std::make_shared(); + IHal::GetInstance()->GetLedContrlHandle(static_cast(i), ledHandle); + LedHandle handle(ledHandle); + mLeds[static_cast(i)] = handle; + } + StartTimer(); +} +void LedTimer::UnInit(void) +{ + StopTimer(); + std::shared_ptr ledState = std::make_shared(); + for (int i = 0; i < static_cast(SfLedIndex::SF_LED_END); i++) + { + // mLeds[static_cast(i)].AddLedState(ledState); + std::map::iterator iter; + iter = mLeds.find(static_cast(i)); + if (iter != mLeds.end()) + { + mLeds[static_cast(i)].AddLedState(ledState); + } + } + mLeds.clear(); +} +void LedTimer::StartTimer(void) +{ + auto timerThread = [](std::shared_ptr timer) + { + LogInfo("Led timer started.\n"); + timer->Timer(); + }; + mTimer = std::thread(timerThread, shared_from_this()); +} +void LedTimer::StopTimer(void) +{ + mTimerRuning = false; + if (mTimer.joinable()) + { + mTimer.join(); + } +} +void LedTimer::Timer(void) +{ + mTimerRuning = true; + while (mTimerRuning) + { + mMutex.lock(); + for (int i = 0; i < static_cast(SfLedIndex::SF_LED_END); i++) + { + mLeds[static_cast(i)].CheckState(LED_STATE_CHECK_PERIOD_MS); + } + mMutex.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(LED_STATE_CHECK_PERIOD_MS)); + } +} +void LedTimer::SetLedState(const SfLedIndex &led, std::shared_ptr &state) +{ + std::lock_guard locker(mMutex); + mLeds[led].AddLedState(state); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/LedTimer.h b/code/application/sifarsdk/component/PeripheralManager/src/LedTimer.h new file mode 100644 index 000000000..1d8b43951 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/LedTimer.h @@ -0,0 +1,44 @@ +#ifndef LED_TIMER_H +#define LED_TIMER_H +#include "IHalCommon.h" +#include "IHal.h" +#include "LedHandle.h" +#include +#include +#include +#include +constexpr int LED_STATE_CHECK_PERIOD_MS = 100; +class TurnOffLed : public VLedState +{ +public: + TurnOffLed() = default; + virtual ~TurnOffLed() = default; + RETURN_CODE GetLedState(SfLedState &state) + { + state = SfLedState::SF_LED_STATE_OFF; + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + unsigned int GetKeepAliveTimeMs(void) { return DO_NOT_KEEP_ALIVE; } +}; +class LedTimer : public std::enable_shared_from_this +{ +public: + LedTimer(); + ~LedTimer() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + void Init(void); + void UnInit(void); + void Timer(void); + void SetLedState(const SfLedIndex &led, std::shared_ptr &state); + +private: + void StartTimer(void); + void StopTimer(void); + +private: + std::mutex mMutex; + std::map mLeds; + bool mTimerRuning; + std::thread mTimer; +}; +#endif // !LED_TIMER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/MobileHardwareHandleV2.cpp b/code/application/sifarsdk/component/PeripheralManager/src/MobileHardwareHandleV2.cpp new file mode 100644 index 000000000..020285815 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/MobileHardwareHandleV2.cpp @@ -0,0 +1,117 @@ +#include "MobileHardwareHandleV2.h" +#include "Log.h" +#include "IAtCommand.h" +MobileHardwareHandleV2::MobileHardwareHandleV2() +{ + mModule = std::make_shared(); + mSimInitCallback = nullptr; + mRegisterNetworkCallback = nullptr; + mNetApnConfigCallback = nullptr; + // memset(&mSimInfo, 0, sizeof(SIM_INFO_S)); +} +RETURN_CODE MobileHardwareHandleV2::Init(void) +{ + LogInfo("MobileHardwareHandleV2::Init\n"); + IHal::GetInstance()->GetNetworkHardware(mModule); + std::shared_ptr atOwner = shared_from_this(); + IAtCommand::GetInstance()->SetOwner(atOwner); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE MobileHardwareHandleV2::UnInit(void) +{ + // AtSimInit::UnInit(); // TODO: + mModule->UnInit(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +bool MobileHardwareHandleV2::IsModuleWorking(void) +{ + return mModule->IsModuleWorking(); +} +RETURN_CODE MobileHardwareHandleV2::SimInit(SimInitCallback func) +{ + LogInfo("MobileHardwareHandleV2::SimInit.\n"); + mSimInitCallback = func; + IAtCommand::GetInstance()->SimInit(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE MobileHardwareHandleV2::RegisterNetworkManual(RegisterNetworkCallback func) +{ + mRegisterNetworkCallback = func; + IAtCommand::GetInstance()->AtRegisterNetworkManual(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE MobileHardwareHandleV2::NetApnConfig(NetApnConfigCallback func) +{ + mNetApnConfigCallback = func; + IAtCommand::GetInstance()->AtNetApnConfig(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE MobileHardwareHandleV2::KeepAliveForLive(void) +{ + IAtCommand::GetInstance()->MqttKeepAlive(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void MobileHardwareHandleV2::WriteAtCommand(const std::shared_ptr &task) +{ + std::shared_ptr networkTask = std::dynamic_pointer_cast(task); + if (networkTask) + { + mModule->NetworkWrite(networkTask); + } + else + { + LogError("Network task write failed.\n"); + } +} +void MobileHardwareHandleV2::AtFinishInitSimCard(const AtSimInitData &data) +{ + mSimInitData.mResult = static_cast(data.mResult); + mSimInitData.mType = static_cast(data.mType); + mSimInitData.mIMEI = data.mIMEI; + mSimInitData.mModuleSubVersion = data.mModuleSubVersion; + mSimInitData.mIccid = data.mIccid; + if (mSimInitCallback) + { + LogInfo("Sim init result %d\n", static_cast(mSimInitData.mResult)); + mSimInitCallback(mSimInitData); + } +} +void MobileHardwareHandleV2::AtFinishRegisterNetwork(const NetworkRegisterResult &data) +{ + // std::map resultConvert; + // resultConvert[AtRegisterNetworkResult::SUCCEED] = RegisterNetworkResult::SUCCEED; + // resultConvert[AtRegisterNetworkResult::FAILED] = RegisterNetworkResult::FAILED; + // resultConvert[AtRegisterNetworkResult::ERROR_REG_NET] = RegisterNetworkResult::ERROR_REG_NET; + // resultConvert[AtRegisterNetworkResult::FAILED_NOT_SUPPORT] = RegisterNetworkResult::FAILED_NOT_SUPPORT; + // resultConvert[AtRegisterNetworkResult::FAILED_NO_SIGNAL] = RegisterNetworkResult::FAILED_NO_SIGNAL; + // mRegisterNetworkData.result = resultConvert[data.result]; + mRegisterNetworkData.result = static_cast(data.result); + mRegisterNetworkData.mGeneration = static_cast(data.mGeneration); + mRegisterNetworkData.mSignalLevel = static_cast(data.mSignalLevel); + mRegisterNetworkData.mServiceProvider = data.mServiceProvider; + mRegisterNetworkData.mSimSignal = data.mSimSignal; + if (mRegisterNetworkCallback) + { + LogInfo("MobileHardwareHandleV2::AtFinishRegisterNetwork %d\n", static_cast(mRegisterNetworkData.result)); + mRegisterNetworkCallback(mRegisterNetworkData); + } +} +void MobileHardwareHandleV2::AtFinishNetApnConfig(const AtNetApnConfigData &data) +{ + NetApnConfigDataOut result; + result.result = static_cast(data.mResult); + if (NetApnConfigResult::SUCCEED == result.result) + { + LogInfo("Net driver load.\n"); + mModule->NetDriverLoad(); + } + if (mNetApnConfigCallback) + { + LogInfo("MobileHardwareHandle::AtNetApnConfigResult %d\n", static_cast(result.result)); + mNetApnConfigCallback(result); + } +} +void MobileHardwareHandleV2::GetDeviceMessage(AtDeviceMessage &message) +{ + message.mPdp = mModule->GetPdpIndex(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/MobileHardwareHandleV2.h b/code/application/sifarsdk/component/PeripheralManager/src/MobileHardwareHandleV2.h new file mode 100644 index 000000000..791508127 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/MobileHardwareHandleV2.h @@ -0,0 +1,35 @@ +#ifndef MOBILE_HARDWARE_HANDLE_V2_H +#define MOBILE_HARDWARE_HANDLE_V2_H +#include "IPeripheralManager.h" +#include "IAtCommand.h" +#include "IHal.h" +class MobileHardwareHandleV2 : public VNetworkHardwareHandle, public VAtOwner, public std::enable_shared_from_this +{ +public: + MobileHardwareHandleV2(); + ~MobileHardwareHandleV2() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + bool IsModuleWorking(void) override; + RETURN_CODE SimInit(SimInitCallback func) override; + RETURN_CODE RegisterNetworkManual(RegisterNetworkCallback func) override; + RETURN_CODE NetApnConfig(NetApnConfigCallback func) override; + RETURN_CODE KeepAliveForLive(void) override; + +private: + void WriteAtCommand(const std::shared_ptr &task) override; + void AtFinishInitSimCard(const AtSimInitData &data) override; + void AtFinishRegisterNetwork(const NetworkRegisterResult &data) override; + void AtFinishNetApnConfig(const AtNetApnConfigData &data) override; + void GetDeviceMessage(AtDeviceMessage &message) override; + +private: + std::shared_ptr mModule; + SimInitCallback mSimInitCallback; + RegisterNetworkCallback mRegisterNetworkCallback; + NetApnConfigCallback mNetApnConfigCallback; + SimInitDataOut mSimInitData; + RegisterNetworkDataOut mRegisterNetworkData; + // SIM_INFO_S mSimInfo; +}; +#endif // !MOBILE_HARDWARE_HANDLE_V2_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManager.cpp b/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManager.cpp new file mode 100644 index 000000000..d7ed8dc5a --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManager.cpp @@ -0,0 +1,126 @@ +#include "PeripheralManager.h" +#include "KeyManager.h" +#include "IHal.h" +#include "Log.h" +#include "PeripheralManagerMakePtr.h" +#include "SDCardHandle.h" +#include "KeyTimer.h" +#include "LedTimer.h" +PeripheralManager::PeripheralManager() +{ + mKeyMonitor = std::make_shared(); + mGpioMonitor = std::make_shared(); + mNetworkModuleHandle = std::make_shared(); + mSdCardHandle = std::make_shared(); + mGpioMap[GpioPin::PIR] = GpioDevice::PIR; + mInputMap[GpioInputValue::INVALID] = DeviceInput::INVALID; + mInputMap[GpioInputValue::VALID] = DeviceInput::VALID; +} +RETURN_CODE PeripheralManager::Init(void) +{ + LogInfo("PeripheralManager::Init\n"); + for (int i = 0; i < static_cast(SfKeyDefine::KEY_PIN_END); i++) + { + auto keyContrl = std::make_shared(); + auto func = std::bind(&PeripheralManager::KeyActionCallback, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); + IHal::GetInstance()->GetKeyContrlHandle(static_cast(i), keyContrl); + auto manager = std::make_shared(keyContrl, func); + manager->Init(); + std::shared_ptr monitor = manager; + KeyTimer::GetInstance()->AddKey(static_cast(i), monitor); + mKeys[static_cast(i)] = manager; + } + for (int i = 0; i < static_cast(GpioPin::END); i++) + { + auto gpioInput = std::make_shared(); + auto func = std::bind(&PeripheralManager::GpioInputCallback, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + IHal::GetInstance()->GetGpioInputHandle(static_cast(i), gpioInput); + auto device = std::make_shared(gpioInput, func); + device->Init(); + mGpios[static_cast(i)] = device; + } + KeyTimer::GetInstance()->StartTimer(); + LedTimer::GetInstance()->Init(); + PeripheralManagerMakePtr::GetInstance()->CreateNetworkModuleHandle(mNetworkModuleHandle); + mNetworkModuleHandle->Init(); + PeripheralManagerMakePtr::GetInstance()->CreateSDCardHandle(mSdCardHandle); + std::dynamic_pointer_cast(mSdCardHandle)->Init(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManager::UnInit(void) +{ + if (mNetworkModuleHandle) + { + mNetworkModuleHandle->UnInit(); + mNetworkModuleHandle.reset(); + } + KeyTimer::GetInstance()->StopTimer(); + for (int i = 0; i < static_cast(SfKeyDefine::KEY_PIN_END); i++) + { + std::map>::iterator iter; + iter = mKeys.find(static_cast(i)); + if (iter != mKeys.end()) + { + mKeys[static_cast(i)]->UnInit(); + mKeys[static_cast(i)].reset(); + } + } + mKeys.clear(); + mKeyMonitor.reset(); + mGpioMonitor.reset(); + LedTimer::GetInstance()->UnInit(); + if (mSdCardHandle) + { + std::dynamic_pointer_cast(mSdCardHandle)->UnInit(); + mSdCardHandle.reset(); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManager::SetKeyMonitor(std::shared_ptr monitor) +{ + LogInfo("PeripheralManager::SetKeyMonitor.\n"); + mKeyMonitor = monitor; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManager::GetAllKeysState(std::map &state) +{ + KeyTimer::GetInstance()->GetAllKeysState(state); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManager::SetGpioMonitor(std::shared_ptr monitor) +{ + LogInfo("PeripheralManager::SetGpioMonitor.\n"); + mGpioMonitor = monitor; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManager::SetLedState(const SfLedIndex &led, std::shared_ptr &state) +{ + LedTimer::GetInstance()->SetLedState(led, state); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManager::GetNetworkModuleHandle(std::shared_ptr &module) +{ + LogInfo("GetNetworkModuleHandle.\n"); + module = mNetworkModuleHandle; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManager::GetRtcTimeHandle(std::shared_ptr &rtc) +{ + PeripheralManagerMakePtr::GetInstance()->CreateRtcHandle(rtc); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManager::GetSDCardHandle(std::shared_ptr &sdCard) +{ + sdCard = mSdCardHandle; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +void PeripheralManager::KeyActionCallback(const SfKeyDefine &key, const SfKeyAction &action, const unsigned int holdTimeMs, void *context) +{ + mKeyMonitor->KeyActionHappened(key, action, holdTimeMs); +} +void PeripheralManager::GpioInputCallback(const GpioPin &gpio, const GpioInputValue &input, void *context) +{ + mGpioMonitor->InputTransform(mGpioMap[gpio], mInputMap[input]); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManager.h b/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManager.h new file mode 100644 index 000000000..fedd9414c --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManager.h @@ -0,0 +1,37 @@ +#ifndef PERIPHERAL_MANAGER_H +#define PERIPHERAL_MANAGER_H +#include "IPeripheralManager.h" +#include "VReturnCode.h" +#include "KeyManager.h" +#include "LedHandle.h" +#include "GpioInputDevice.h" +#include +#include +class PeripheralManager : public IPeripheralManager +{ +public: + PeripheralManager(); + virtual ~PeripheralManager() = default; + RETURN_CODE Init(void) override; + RETURN_CODE UnInit(void) override; + RETURN_CODE SetKeyMonitor(std::shared_ptr monitor) override; + RETURN_CODE GetAllKeysState(std::map &state) override; + RETURN_CODE SetGpioMonitor(std::shared_ptr monitor) override; + RETURN_CODE SetLedState(const SfLedIndex &led, std::shared_ptr &state) override; + RETURN_CODE GetNetworkModuleHandle(std::shared_ptr &module) override; + RETURN_CODE GetRtcTimeHandle(std::shared_ptr &rtc) override; + RETURN_CODE GetSDCardHandle(std::shared_ptr &sdCard) override; + void KeyActionCallback(const SfKeyDefine &key, const SfKeyAction &action, const unsigned int holdTimeMs, void *context); + void GpioInputCallback(const GpioPin &gpio, const GpioInputValue &input, void *context); + +private: + std::shared_ptr mKeyMonitor; + std::shared_ptr mGpioMonitor; + std::map> mKeys; + std::map> mGpios; + std::shared_ptr mNetworkModuleHandle; + std::shared_ptr mSdCardHandle; + std::map mGpioMap; + std::map mInputMap; +}; +#endif // !PERIPHERAL_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManagerMakePtr.cpp b/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManagerMakePtr.cpp new file mode 100644 index 000000000..444e83c05 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManagerMakePtr.cpp @@ -0,0 +1,55 @@ +#include "PeripheralManagerMakePtr.h" +#include "Log.h" +#include "MobileHardwareHandleV2.h" +#include "RtcTime.h" +#include "SDCardHandle.h" +#include "IHal.h" +#include "VReturnCode.h" +#include + +bool CreatePeripheralManager(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = PeripheralManagerMakePtr::GetInstance()->CreatePeripheralManager(instance); + if (code->IsCodeOK()) + { + LogInfo("Peripheral manager instance is ok.\n"); + IPeripheralManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &PeripheralManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + instance = *impl; + } + return instance; +} +RETURN_CODE PeripheralManagerMakePtr::CreatePeripheralManager(std::shared_ptr &impl) +{ + impl = std::make_shared(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManagerMakePtr::CreateNetworkModuleHandle(std::shared_ptr &impl) +{ + impl = std::make_shared(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE PeripheralManagerMakePtr::CreateRtcHandle(std::shared_ptr &impl) +{ + const RtcDevice &rtc = IHal::GetInstance()->GetRtcDevice(); + if (RtcDeviceSupport::SUPPORT == rtc.mSupport) + { + impl = std::make_shared(rtc.mRtcDevice); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); +} +RETURN_CODE PeripheralManagerMakePtr::CreateSDCardHandle(std::shared_ptr &impl) +{ + impl = std::make_shared(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManagerMakePtr.h b/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManagerMakePtr.h new file mode 100644 index 000000000..e4e2298f7 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/PeripheralManagerMakePtr.h @@ -0,0 +1,19 @@ +#ifndef PERIPHERAL_MANAGER_MAKE_PTR_H +#define PERIPHERAL_MANAGER_MAKE_PTR_H +#include "PeripheralManager.h" +#include "VReturnCode.h" +#include +class PeripheralManagerMakePtr +{ +public: + PeripheralManagerMakePtr() = default; + virtual ~PeripheralManagerMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit() { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE CreatePeripheralManager(std::shared_ptr &impl); + virtual RETURN_CODE CreateNetworkModuleHandle(std::shared_ptr &impl); + virtual RETURN_CODE CreateRtcHandle(std::shared_ptr &impl); + virtual RETURN_CODE CreateSDCardHandle(std::shared_ptr &impl); +}; +#endif // !PERIPHERAL_MANAGER_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/RtcTime.cpp b/code/application/sifarsdk/component/PeripheralManager/src/RtcTime.cpp new file mode 100644 index 000000000..55090c061 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/RtcTime.cpp @@ -0,0 +1,87 @@ +#include "RtcTime.h" +#include "Log.h" +#include +#include +#include +#include +#include +RtcTime::RtcTime(const char *rtcDivce) : mRtcDivce(rtcDivce) +{ +} +int RtcTime::Set(const struct rtc_time &rtctm) +{ + SINT32 fdRtc = -1; + SINT32 ret = SF_SUCCESS; + fdRtc = open(mRtcDivce, O_RDWR); + if (fdRtc < 0) + { + LogError("[ERR]open %s error:%d\n", mRtcDivce, fdRtc); + return SF_FAILURE; + } + ret = ioctl(fdRtc, RTC_SET_TIME, &rtctm); + if (ret < 0) + { + LogError("[ERR]ioctl get rtc time error:%d\n", ret); + } + close(fdRtc); + + return ret; +} +int RtcTime::Get(struct rtc_time &rtctm) +{ + SINT32 fdRtc = -1; + int ret = SF_SUCCESS; + fdRtc = open(mRtcDivce, O_RDWR); + if (fdRtc < 0) + { + LogError("open %s error:%s\n", mRtcDivce, strerror(errno)); + return SF_FAILURE; + } + if (ioctl(fdRtc, RTC_RD_TIME, &rtctm) < 0) + { + LogError("ioctl get rtc time error:%s\n", strerror(errno)); + ret = SF_FAILURE; + } + close(fdRtc); + return ret; +} +bool RtcTime::Check(const struct rtc_time &rtctm) +{ + LogInfo("%d-%d-%d %d:%d:%d\n", rtctm.tm_year, rtctm.tm_mon, rtctm.tm_mday, rtctm.tm_hour, rtctm.tm_min, rtctm.tm_sec); + if ((rtctm.tm_year >= 2021) && + (rtctm.tm_year <= 2050) && + (rtctm.tm_mon <= 12) && + (rtctm.tm_mday <= 31) && + (rtctm.tm_hour < 24) && + (rtctm.tm_min < 60) && + (rtctm.tm_sec < 60)) + { + return true; + } + return false; +} +int RtcTime::Reset(void) +{ + SINT32 fdRtc = -1; + SINT32 ret = SF_SUCCESS; + fdRtc = open(mRtcDivce, O_RDWR); + if (fdRtc < 0) + { + LogError("open [%s] error:[%d]\n", mRtcDivce, fdRtc); + return SF_FAILURE; + } + struct rtc_time rtctm; + rtctm.tm_year = 2022 - 1900; + rtctm.tm_mon = 0; + rtctm.tm_mday = 1; + rtctm.tm_hour = 8; + rtctm.tm_min = 0; + rtctm.tm_sec = 0; + ret = ioctl(fdRtc, RTC_SET_TIME, &rtctm); + if (ret < 0) + { + LogError("[ERR]ioctl get rtc time error:%d\n", ret); + } + close(fdRtc); + return ret; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/RtcTime.h b/code/application/sifarsdk/component/PeripheralManager/src/RtcTime.h new file mode 100644 index 000000000..2062f15a8 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/RtcTime.h @@ -0,0 +1,19 @@ +#ifndef RTC_TIME_H +#define RTC_TIME_H +#include "IPeripheralManager.h" +#include "SfTypeDefine.h" +// #define DEFAULT_RTC_DEVICE "/dev/rtc0" // TODO: +class RtcTime : public VRtcTime +{ +public: + RtcTime(const char *rtcDivce); + ~RtcTime() = default; + int Set(const struct rtc_time &rtctm) override; + int Get(struct rtc_time &rtctm) override; + bool Check(const struct rtc_time &rtctm) override; + int Reset(void) override; + +private: + const char *mRtcDivce; +}; +#endif // !RTC_TIME_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/SDCardHandle.cpp b/code/application/sifarsdk/component/PeripheralManager/src/SDCardHandle.cpp new file mode 100644 index 000000000..c10f39145 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/SDCardHandle.cpp @@ -0,0 +1,458 @@ +#include "SDCardHandle.h" +#include "FileManager.h" +#include "Log.h" +#include "IHal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +SDCardHandle::SDCardHandle() +{ + SdStatus = SF_SD_BUTT; + mSDCardHal = std::make_shared(); + mStatusConvert[SdCardEvent::MOUNT_SUCCEED] = SD_MOUNT_SUCCESS; + mStatusConvert[SdCardEvent::MOUNT_FAILED] = SD_MOUNT_FAILURE; + mStatusConvert[SdCardEvent::SD_ERROR] = SF_SD_ERROR; + mStatusConvert[SdCardEvent::SD_OUT] = SD_MOUNT_FAILURE; + mStatusConvert[SdCardEvent::SD_FULL] = SF_SD_FULL; +} +void SDCardHandle::Init(void) +{ + IHal::GetInstance()->GetSDCardHal(mSDCardHal); + mSDCardHal->SetOwner(shared_from_this()); + // mSDCardHal->GetSdCardState(SdStatus); +} +void SDCardHandle::UnInit(void) +{ + mSDCardHal.reset(); +} +void SDCardHandle::GetInfo(SF_STORE_ATTR_S &pstoreattrs) +{ + SINT32 fd = -1; + const char *sdPath = IHal::GetInstance()->GetSDCardSystemPath(); + if (!sdPath) + { + LogError("SD card path not found.\n"); + return; + } + fd = open(sdPath, O_RDONLY, 0); + if (fd >= 0) + { + struct statfs diskInfo; + statfs(sdPath, &diskInfo); + + if (diskInfo.f_bsize > 1024) + { + pstoreattrs.SDTotalSize = (diskInfo.f_blocks * (diskInfo.f_bsize >> 10)) >> 10; // blocks * 4096 / 1024 /1024 = MB + pstoreattrs.SDFree = (diskInfo.f_bavail * (diskInfo.f_bsize >> 10)) >> 10; + } + else + { + pstoreattrs.SDTotalSize = (diskInfo.f_blocks * diskInfo.f_bsize) >> 10; // blocks * 4096 / 1024 /1024 = MB + pstoreattrs.SDFree = (diskInfo.f_bavail * diskInfo.f_bsize) >> 10; + } + close(fd); + + if (pstoreattrs.SDTotalSize > 0) + pstoreattrs.SDStatus = 0; // SD card SUCESS + else + pstoreattrs.SDStatus = 2; // SD card ERROR + } + else + { + LogError("SD card not insert, path = %s\n", sdPath); + pstoreattrs.SDStatus = 1; // SD card not insert + pstoreattrs.SDFree = 0; + pstoreattrs.SDTotalSize = 0; + return; + } + + LogInfo("SDStatus = %d,SDFree = %d MB,SDTotalSize = %d MB\n", pstoreattrs.SDStatus, pstoreattrs.SDFree, pstoreattrs.SDTotalSize); + return; +} +void SDCardHandle::RemoveFile(const char *path, const signed int &threshold) +{ + if (SF_SUCCESS != IsFileExist(path)) + { + LogInfo("%s is empty!!!\n", path); + return; + } + + SINT32 s32ret = SF_SUCCESS; + SINT32 index = 0; + SINT32 fileCnt = 0; + SINT32 totalFile = 0; + SF_CHAR fileabspath[FILENAMELEN] = {0}; + struct dirent **namelist; + + totalFile = scandir(path, &namelist, 0, alphasort); + if (totalFile < 0) + { + LogInfo("open [%s] error!!!\n", path); + return; + } + + while (index < totalFile) + { + // LogInfo("d_name: %s\n",namelist[index]->d_name); + if (strcmp(namelist[index]->d_name, ".") == 0 || strcmp(namelist[index]->d_name, "..") == 0) + { + index++; + continue; + } + sprintf(fileabspath, "%s/%.32s", path, namelist[index]->d_name); + if (!(strstr(fileabspath, SF_DCF_EXT_MOV) || strstr(fileabspath, SF_DCF_EXT_PHOTO))) + { + index++; + continue; + } + if (SF_SUCCESS != IsFileExist(fileabspath)) + { + index++; + continue; + } + s32ret = sf_file_remove(fileabspath); + if (SF_SUCCESS != s32ret) + { + index++; + continue; + } + + index++; + fileCnt++; + + if (threshold <= 0) + continue; + + if (fileCnt > threshold) + break; + } + return; +} +void SDCardHandle::LoopRemove(const char *path) +{ + const char *picThumbPath = IHal::GetInstance()->GetPictureThumbPath(); + const char *videStreamPath = IHal::GetInstance()->GetVideoStreamPath(); + if (nullptr == picThumbPath || nullptr == videStreamPath) + { + LogError("GetPictureThumbPath is nullptr.\n"); + return; + } + int dircnt; + int index = 0; + char strdirTmp[FILENAMELEN] = {0}; + char cPathTmp[FILENAMELEN] = {0}; + char cFileTmp[FILENAMELEN] = {0}; + + char g_cFileList[FILETXTCNT][FILENAMELEN] = {0}; + + int FileCount = 0; + char filedir[4] = {0}; + char filenum[6] = {0}; + char filetype[4] = {0}; + char fname[FILENAMELEN] = {0}; + char *pTemp = NULL; + + DIR *dirsub = SF_NULL; + struct dirent *entrysub = SF_NULL; + struct dirent **namelist; + + SF_STORE_ATTR_S storeattrs = {0}; + UINT32 oldsdFree = 0; + UINT8 sdcnt = 0; + dircnt = scandir(path, &namelist, 0, alphasort); + if (dircnt < 0) + { + LogInfo("open [%s] error!!!\n", path); + return; + } + + while (index < dircnt) + { + LogInfo("d_name: %s\n", namelist[index]->d_name); + if (strcmp(namelist[index]->d_name, ".") == 0 || strcmp(namelist[index]->d_name, "..") == 0) + { + index++; + continue; + } + + memset(strdirTmp, '\0', FILENAMELEN); + strcpy(strdirTmp, namelist[index]->d_name); + /*filter not xxxSYCAM dir*/ + if (!strstr(strdirTmp, SF_DCF_DIR_NAME_SUFFIX)) + { + index++; + continue; + } + + /*Empty Dir, Delete it.*/ + sprintf(cPathTmp, "%s/%.32s", path, namelist[index]->d_name); + if (IsDirEmpty(cPathTmp) == 0) + { + sf_file_remove(cPathTmp); + LogInfo("%s is empty,has removed !!!\n", cPathTmp); + index++; + continue; + } + + /*open subDir*/ + LogInfo("%s\n", cPathTmp); + dirsub = opendir(cPathTmp); + if (dirsub == NULL) + { + LogError("opendir [%s] error!!!\n", cPathTmp); + index++; + continue; + } + + while ((entrysub = readdir(dirsub))) + { + + /*Jump . or .. dir*/ + if (strcmp(entrysub->d_name, ".") == 0 || strcmp(entrysub->d_name, "..") == 0) + continue; + + /*Not Empty , Record File Name*/ + sprintf(cFileTmp, "%.64s/%.32s", cPathTmp, entrysub->d_name); + + strcpy(g_cFileList[FileCount], cFileTmp); + if (SF_NULL != g_cFileList[FileCount]) + { + + pTemp = strstr(g_cFileList[FileCount], SF_DCF_DIR_NAME_SUFFIX); + if (pTemp) + { + pTemp = pTemp - 3; + + filedir[0] = *pTemp++; + filedir[1] = *pTemp++; + filedir[2] = *pTemp++; /*get file group ID*/ + filedir[3] = '\0'; + + pTemp = strstr(g_cFileList[FileCount], SF_DCF_FILE_NAME_PREFIX); + + if (pTemp) + { + pTemp = pTemp + 4; + + filenum[0] = *pTemp++; + filenum[1] = *pTemp++; + filenum[2] = *pTemp++; + filenum[3] = *pTemp++; /* get file ID Added by MaxLi 2022/03/21--13:49:22*/ + filenum[4] = '\0'; + pTemp++; + filetype[0] = *pTemp++; + filetype[1] = *pTemp++; + filetype[2] = *pTemp++; /* get file type Added by MaxLi 2022/03/21--13:49:45*/ + filetype[3] = '\0'; + + if (strstr(filetype, SF_DCF_EXT_MOV)) + { + sprintf(fname, "%sW%s%s.JPG", picThumbPath, filedir, filenum); + if (SF_SUCCESS == IsFileExist(fname)) + { + sf_file_remove(fname); + LogInfo("Will Delete video sub File Name:%s\n", fname); + } + sprintf(fname, "%sS%s%s.MP4", videStreamPath, filedir, filenum); + if (SF_SUCCESS == IsFileExist(fname)) + { + sf_file_remove(fname); + LogInfo("Will Delete smallstream File Name:%s\n", fname); + } + + LogInfo("Will Delete mainstream File Name:%s\n", g_cFileList[FileCount]); + sf_file_remove(g_cFileList[FileCount]); + } + else if (strstr(filetype, SF_DCF_EXT_PHOTO)) + { + sprintf(fname, "%sW%s%s.JPG", picThumbPath, filedir, filenum); + if (SF_SUCCESS == IsFileExist(fname)) + { + sf_file_remove(fname); + LogInfo("Will Delete thumb pic File Name:%s\n", fname); + } + LogInfo("Will Delete initial pic File Name:%s\n", g_cFileList[FileCount]); + sf_file_remove(g_cFileList[FileCount]); + } + } + } + } + + FileCount++; + if (FileCount % 20 == 0) + { + GetInfo(storeattrs); + LogInfo("sdFree=%d,oldsdFree=%d\n", storeattrs.SDFree, oldsdFree); + if (storeattrs.SDFree != oldsdFree) + { + sdcnt = 0; + oldsdFree = storeattrs.SDFree; + } + else + { + sdcnt++; + if (sdcnt > 3) + { + sdcnt = 0; + closedir(dirsub); + free(namelist[index]); + free(namelist); + return; + } + } + if (storeattrs.SDFree > (SDLOOP_REMAIN_SPACE + 50)) + { + FileCount = FILETXTCNT; + break; + } + else + { + // if del 300 files, sd free size < 350, del file + if (FileCount >= FILETXTCNT) + { + FileCount = 0; + } + } + } + } + + closedir(dirsub); + free(namelist[index]); + index++; // index++ + + if (FileCount >= FILETXTCNT) + break; + } + free(namelist); + return; +} +void SDCardHandle::IsFull(signed int &Isfull) +{ + SF_STORE_ATTR_S storeattrs = {0}; + GetInfo(storeattrs); + // if (storeattrs.SDStatus != 0) //TODO: + // return storeattrs.SDStatus; + Isfull = (storeattrs.SDFree <= SD_WARNING_SPACE) ? 1 : 0; +} +SF_SD_STATUS_E SDCardHandle::GetStatus(void) +{ + LogInfo("SdStatus:%d\n", SdStatus); + SdCardEvent event; + mSDCardHal->GetSdCardState(event); + std::map::iterator iter; + iter = mStatusConvert.find(event); + if (iter != mStatusConvert.end()) + { + LogInfo("SDCardHalEvent = %d\n", static_cast(event)); + SdStatus = mStatusConvert[event]; + } + return SdStatus; +} +void SDCardHandle::SetStatus(SF_SD_STATUS_E enStatus) +{ + SdStatus = enStatus; +} +void SDCardHandle::SDCardHalEvent(const SdCardEvent &event) +{ + std::map::iterator iter; + iter = mStatusConvert.find(event); + if (iter != mStatusConvert.end()) + { + LogInfo("SDCardHalEvent = %d\n", static_cast(event)); + SdStatus = mStatusConvert[event]; + ReportSDCardStatus(SdStatus); + return; + } +} +void SDCardHandle::SetMonitor(const std::shared_ptr &monitor) +{ + mMonitor = monitor; +} +RETURN_CODE SDCardHandle::Format(void) +{ + if (SD_MOUNT_FAILURE == SdStatus) + { + LogError("SD card out, format failed.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_UNDEFINE_REASON); + } + mSDCardHal->Format(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE SDCardHandle::USBInsert(void) +{ + if (SD_MOUNT_SUCCESS == SdStatus || SF_SD_FULL == SdStatus) + { + mSDCardHal->MsdcMode(); + } + else + { + mSDCardHal->UvcMode(); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +SINT32 SDCardHandle::IsFileExist(const char *fileName) +{ + return access(fileName, F_OK); +} +SINT32 SDCardHandle::IsDirEmpty(char *dirname) +{ + if (!dirname) + { + LogError("Nullptr pointer.\n"); + return SF_FAILURE; + } + + DIR *dir = opendir(dirname); + if (dir == NULL) + { + perror("seekkey.c-98-opendir"); + return SF_FAILURE; + } + + while (1) + { + struct dirent *ent; + ent = readdir(dir); + if (ent <= 0) + { + break; + } + if ((strcmp(".", ent->d_name) == 0) || (strcmp("..", ent->d_name) == 0)) + { + continue; + } + /*adjust include file or dir*/ + if ((ent->d_type == DT_DIR) || (ent->d_type == DT_REG)) + { + closedir(dir); + return SF_FAILURE; + } + } + closedir(dir); + return SF_SUCCESS; +} +void SDCardHandle::ReportSDCardStatus(const SF_SD_STATUS_E &status) +{ + auto monitor = mMonitor.lock(); + if (!monitor) + { + LogWarning("Owner is nullptr.\n"); + return; + } + if (mMonitor.expired()) + { + LogWarning("Owner shared ptr expired failed.\n"); + return; + } + LogInfo("ReportMessageToOwner.\n"); + monitor->ReportSDCardStatus(status); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/PeripheralManager/src/SDCardHandle.h b/code/application/sifarsdk/component/PeripheralManager/src/SDCardHandle.h new file mode 100644 index 000000000..b131a07c3 --- /dev/null +++ b/code/application/sifarsdk/component/PeripheralManager/src/SDCardHandle.h @@ -0,0 +1,41 @@ +#ifndef SD_CARD_HANDLE_H +#define SD_CARD_HANDLE_H +#include "IPeripheralManager.h" +#include "SfTypeDefine.h" +#include "IHal.h" +#include +// #define SF_SD_ROOT "/mnt/mmc/" +#define SD_WARNING_SPACE 30 /*30MB*/ +#define FILETXTCNT 300 +#define FILENAMELEN 128 +#define SDLOOP_REMAIN_SPACE 300 /*300MB*/ +class SDCardHandle : public VSDCardHandle, public VSDCardOwner, public std::enable_shared_from_this +{ +public: + SDCardHandle(); + ~SDCardHandle() = default; + void Init(void); + void UnInit(void); + void GetInfo(SF_STORE_ATTR_S &pstoreattrs) override; + void RemoveFile(const char *path, const signed int &threshold) override; + void LoopRemove(const char *path) override; + void IsFull(signed int &Isfull) override; + SF_SD_STATUS_E GetStatus(void) override; + void SetStatus(SF_SD_STATUS_E enStatus) override; + void SDCardHalEvent(const SdCardEvent &event) override; + void SetMonitor(const std::shared_ptr &monitor) override; + RETURN_CODE Format(void) override; + RETURN_CODE USBInsert(void) override; + +private: + SINT32 IsFileExist(const char *fileName); + SINT32 IsDirEmpty(char *dirname); + void ReportSDCardStatus(const SF_SD_STATUS_E &status); + +private: + SF_SD_STATUS_E SdStatus; + std::shared_ptr mSDCardHal; + std::map mStatusConvert; + std::weak_ptr mMonitor; +}; +#endif // !SD_CARD_HANDLE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Qrcode/CMakeLists.txt b/code/application/sifarsdk/component/Qrcode/CMakeLists.txt new file mode 100644 index 000000000..b693b7e8f --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/CMakeLists.txt @@ -0,0 +1,25 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/base64/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME Qrcode) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} base64 ReturnCode Log) \ No newline at end of file diff --git a/code/application/sifarsdk/component/Qrcode/include/bitstream.h b/code/application/sifarsdk/component/Qrcode/include/bitstream.h new file mode 100644 index 000000000..6aa545604 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/bitstream.h @@ -0,0 +1,48 @@ +/* + * qrencode - QR Code encoder + * + * Binary sequence class. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __BITSTREAM_H__ +#define __BITSTREAM_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct { + int length; + unsigned char *data; +} BitStream; + +extern BitStream *BitStream_new(void); +extern int BitStream_append(BitStream *bstream, BitStream *arg); +extern int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num); +extern int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data); +#define BitStream_size(__bstream__) (__bstream__->length) +extern unsigned char *BitStream_toByte(BitStream *bstream); +extern void BitStream_free(BitStream *bstream); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __BITSTREAM_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/mask.h b/code/application/sifarsdk/component/Qrcode/include/mask.h new file mode 100644 index 000000000..934fa856f --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/mask.h @@ -0,0 +1,47 @@ +/* + * qrencode - QR Code encoder + * + * Masking. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MASK_H__ +#define __MASK_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level); + +#ifdef WITH_TESTS +extern int Mask_calcN2(int width, unsigned char *frame); +extern int Mask_calcN1N3(int length, int *runLength); +extern int Mask_calcRunLength(int width, unsigned char *frame, int dir, int *runLength); +extern int Mask_evaluateSymbol(int width, unsigned char *frame); +extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __MASK_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/mmask.h b/code/application/sifarsdk/component/Qrcode/include/mmask.h new file mode 100644 index 000000000..f095727b1 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/mmask.h @@ -0,0 +1,44 @@ +/* + * qrencode - QR Code encoder + * + * Masking for Micro QR Code. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MMASK_H__ +#define __MMASK_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level); + +#ifdef WITH_TESTS +extern int MMask_evaluateSymbol(int width, unsigned char *frame); +extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __MMASK_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/mqrspec.h b/code/application/sifarsdk/component/Qrcode/include/mqrspec.h new file mode 100644 index 000000000..71ff5f454 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/mqrspec.h @@ -0,0 +1,167 @@ +/* + * qrencode - QR Code encoder + * + * Micro QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MQRSPEC_H__ +#define __MQRSPEC_H__ + +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +/** + * Maximum width of a symbol + */ +#define MQRSPEC_WIDTH_MAX 17 + +/** + * Return maximum data code length (bits) for the version. + * @param version + * @param level + * @return maximum size (bits) + */ +extern int MQRspec_getDataLengthBit(int version, QRecLevel level); + +/** + * Return maximum data code length (bytes) for the version. + * @param version + * @param level + * @return maximum size (bytes) + */ +extern int MQRspec_getDataLength(int version, QRecLevel level); + +/** + * Return maximum error correction code length (bytes) for the version. + * @param version + * @param level + * @return ECC size (bytes) + */ +extern int MQRspec_getECCLength(int version, QRecLevel level); + +/** + * Return a version number that satisfies the input code length. + * @param size input code length (byte) + * @param level + * @return version number + */ +extern int MQRspec_getMinimumVersion(int size, QRecLevel level); + +/** + * Return the width of the symbol for the version. + * @param version + * @return width + */ +extern int MQRspec_getWidth(int version); + +/** + * Return the numer of remainder bits. + * @param version + * @return number of remainder bits + */ +extern int MQRspec_getRemainder(int version); + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * Return the size of lenght indicator for the mode and version. + * @param mode + * @param version + * @return the size of the appropriate length indicator (bits). + */ +extern int MQRspec_lengthIndicator(QRencodeMode mode, int version); + +/** + * Return the maximum length for the mode and version. + * @param mode + * @param version + * @return the maximum length (bytes) + */ +extern int MQRspec_maximumWords(QRencodeMode mode, int version); + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Return BCH encoded version information pattern that is used for the symbol + * of version 7 or greater. Use lower 18 bits. + * @param version + * @return BCH encoded version information pattern + */ +extern unsigned int MQRspec_getVersionPattern(int version); + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/** + * Return BCH encoded format information pattern. + * @param mask + * @param version + * @param level + * @return BCH encoded format information pattern + */ +extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level); + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Return a copy of initialized frame. + * When the same version is requested twice or more, a copy of cached frame + * is returned. + * @param version + * @return Array of unsigned char. You can free it by free(). + */ +extern unsigned char *MQRspec_newFrame(int version); + +/** + * Clear the frame cache. Typically for debug. + */ +extern void MQRspec_clearCache(void); + +/****************************************************************************** + * Mode indicator + *****************************************************************************/ + +/** + * Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107. + */ +#define MQRSPEC_MODEID_NUM 0 +#define MQRSPEC_MODEID_AN 1 +#define MQRSPEC_MODEID_8 2 +#define MQRSPEC_MODEID_KANJI 3 +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __MQRSPEC_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/qrenc.h b/code/application/sifarsdk/component/Qrcode/include/qrenc.h new file mode 100644 index 000000000..4ecab822f --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/qrenc.h @@ -0,0 +1,44 @@ +/** + * qrencode - QR Code encoder + * + * QR Code encoding tool + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +//#include "getopt.h" +//#include "jpeglib.h" + +#include "qrencode.h" + +#define INCHES_PER_METER (100.0/2.54) + +QRcode *encode(const unsigned char *intext, int length); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/Qrcode/include/qrencode.h b/code/application/sifarsdk/component/Qrcode/include/qrencode.h new file mode 100644 index 000000000..a2d8372e2 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/qrencode.h @@ -0,0 +1,415 @@ +/** + * qrencode - QR Code encoder + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute · it and/or + * modify޸ it under the terms ofʲôʲô the GNU Lesser General Public + * License (GNUȨ)as published (棬)by the Free Software Foundation(); either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** \mainpage + * Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D + * symbology. LibqrencodeQRŵıݣһ2DŵĿ + * + * \section encoding Encoding ֱı + * + * There are two ways to encode data:ַʽ encoding a string Ϊַб or + * encoding a structured dataΪݽб. + * + * \subsection encoding-string Encoding a string encoding-stringһΪַб + * You can encode a string by calling QRcode_encodeString().ͨQRcode_encodeString()Ϊַб + * The given string is parsed automatically and encoded.ַԶͱ If you want to encode + * data that can be represented as a C string style (NUL terminated ֹ), you can + * simply use this way. + * + * If the input data contains Kanji (Shift-JIS) characters and you want to + * encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.ʾʾ + * Otherwise, all of non-alphanumeric ĸַ characters are encoded as 8 bit data. + * If you want to encode a whole string in 8 bit mode, use + * QRcode_encodeString8bit() instead. + * + * Please note that a C string can not contain NUL character. If your data + * contains NUL, you should chose the second way. ע⣬CַܰNULLַаNULӦѡڶַʽ + * + * \subsection encoding-input Encoding a structured data encoding-inputһΪݽб + * You can construct a structured input data manually. ֶһṹݡIf the structure of the + * input data is known, you can use this way. + * At first, create a ::QRinput object by QRinput_new(). Then add input data + * to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput() + * to encode the QRinput data. + * You can reuse the QRinput data again to encode it in other symbols with + * different parameters.ͬ + * + * \section result Result + * The encoded symbol is resulted as a ::QRcode object. It will contain + * its version number汾, width of the symbolŵĿ and an array represents the symbol ʾ. + * See ::QRcode for the details. You can free the object by QRcode_free(). + * + * Please note that the version of the result may be larger than specified. + * In such cases, the input data would be too large to be encoded in a + * symbol of the specified version.ݻΪָ̫汾ķ + * + * \section structured Structured append + * Libqrencode can generate "Structured-appended" symbols that enables to split + * a large data set into mulitple QR codes.һܴݷֳɶQRcode A QR code reader concatenates + * multiple QR code symbols into a string.QRĶӶQRתַ + * Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured() + * to generate structured-appended symbols. This functions returns an instance + * of ::QRcode_List. The returned list is a singly-linked list of QRcode: you + * can retrieve each QR code in this way: + * + * \code + * QRcode_List *qrcodes; + * QRcode_List *entry; + * QRcode *qrcode; + * + * qrcodes = QRcode_encodeStringStructured(...); + * entry = qrcodes; + * while(entry != NULL) { + * qrcode = entry->code; + * // do something + * entry = entry->next; + * } + * QRcode_List_free(entry); + * \endcode + * + * Instead of using auto-parsing functions, you can construct your own + * structured input. At first, instantiate an object of ::QRinput_Struct + * by calling QRinput_Struct_new(). This object can hold multiple ::QRinput, + * and one QR code is generated for a ::QRinput. + * QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct + * object. In order to generate structured-appended symbols, it is required to + * embed headers to each symbol. You can use + * QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate + * headers to each symbol. You should call this function just once before + * encoding symbols. + *ԹԼinputṹȡԶȣQRinput_Struct_new()ʵһQRinput_Struct + *ԱQRinputQRinput_Struct_appendInput()һQRinputQRinput_StructС + *Ϊstructured-appendedţҪǶͷÿСʹQRinput_Struct_insertStructuredAppendHeaders()ʵͷÿС + *ڱǮһΡ + */ + +#ifndef __QRENCODE_H__ +#define __QRENCODE_H__ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +/** + * Encoding mode. + */ +typedef enum { + QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only + QR_MODE_NUM = 0, ///< Numeric mode ģʽ + QR_MODE_AN, ///< Alphabet-numeric mode ĸģʽ + QR_MODE_8, ///< 8-bit data mode 8λģʽ + QR_MODE_KANJI, ///< Kanji (shift-jis) mode ģʽ + QR_MODE_STRUCTURE, ///< Internal use only + QR_MODE_ECI, ///< ECI mode + QR_MODE_FNC1FIRST, ///< FNC1, first position + QR_MODE_FNC1SECOND, ///< FNC1, second position +} QRencodeMode; + +/** + * Level of error correction. + */ +typedef enum { + QR_ECLEVEL_L = 0, ///< lowest + QR_ECLEVEL_M, + QR_ECLEVEL_Q, + QR_ECLEVEL_H ///< highest +} QRecLevel; + +/** + * Maximum version (size) of QR-code symbol. + */ +#define QRSPEC_VERSION_MAX 40 + +/** + * Maximum version (size) of QR-code symbol. + */ +#define MQRSPEC_VERSION_MAX 4 + + +/****************************************************************************** + * Input data (qrinput.c) + *****************************************************************************/ + +/** + * Singly linked list to contain input strings. An instance of this class + * contains its version and error correction level too. It is required to + * set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(), + * or use QRinput_new2() to instantiate an object. + */ +typedef struct _QRinput QRinput; + +/** + * Instantiate an input data object.ʵһݶ The version is set to 0 (auto-select) + * and the error correction level is set to QR_ECLEVEL_L. + * @return an input object (initialized)һʵ. On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory. + */ +extern QRinput *QRinput_new(void); + +/** + * Instantiate an input data object. + * @param version version number. + * @param level Error correction level. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw EINVAL invalid arguments. + */ +extern QRinput *QRinput_new2(int version, QRecLevel level); + +/** + * Instantiate an input data object. Object's Micro QR Code (һֶά,ֻһλΣ洢ȽСڴӡռС)flag is set. + * Unlike with full-sized QR Code, version number must be specified (>0). + * @param version version number (1--4). + * @param level Error correction level. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw EINVAL invalid arguments. + */ +extern QRinput *QRinput_newMQR(int version, QRecLevel level); + +/** + * Append data to an input object. + * The data is copied and appended to the input object. + * @param input input object. + * @param mode encoding mode. + * @param size size of data (byte). + * @param data a pointer to the memory area of the input data. + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL input data is invalid. + * + */ +extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data); + +/** + * Append ECI header.ַ + * @param input input object. + * @param ecinum ECI indicator number (0 - 999999) + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL input data is invalid. + * + */ +extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum); + +/** + * Get current version. + * @param input input object. + * @return current version. + */ +extern int QRinput_getVersion(QRinput *input); + +/** + * Set version of the QR code that is to be encoded. + * This function cannot be applied to Micro QR Code.ð汾ŲMicro QR Code + * @param input input object. + * @param version version number (0 = auto) + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setVersion(QRinput *input, int version); + +/** + * Get current error correction level. + * @param input input object. + * @return Current error correcntion level. + */ +extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input); + +/** + * Set error correction level of the QR code that is to be encoded. + * This function cannot be applied to Micro QR Code. + * @param input input object. + * @param level Error correction level. + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level); + +/** + *ڸMicro QR Code ð汾ź; + * Set version and error correction level of the QR code at once. + * This function is recommened for Micro QR Code. + * @param input input object. + * @param version version number (0 = auto) + * @param level Error correction level. + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level); + +/** + * Free the input object. + * All of data chunks in the input object are freed too. + * @param input input object. + */ +extern void QRinput_free(QRinput *input); + +/** + * Validate the input data. + * @param mode encoding mode. + * @param size size of data (byte). + * @param data a pointer to the memory area of the input data. + * @retval 0 success. + * @retval -1 invalid arguments. + */ +extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data); + + +/** + * Free all of QRinput in the set. + * @param s a structured input object. + */ + + +/****************************************************************************** + * QRcode output (qrencode.c) + *****************************************************************************/ + +/** + * QRcode class. + * Symbol data is represented as an array contains width*width uchars. + * Each uchar represents a module (dot). If the less significant bitλ of + * the uchar is 1, the corresponding module is black. The other bits are + * meaningless for usual applications, but here its specification is described. + * + *
+ * MSB 76543210 LSB
+ *     |||||||`- 1=black/0=white
+ *     ||||||`-- data and ecc code area
+ *     |||||`--- format information
+ *     ||||`---- version information
+ *     |||`----- timing pattern
+ *     ||`------ alignment pattern
+ *     |`------- finder pattern and separator
+ *     `-------- non-data modules (format, timing, etc.)
+ * 
+ */ +typedef struct { + int version; ///< version of the symbol + int width; ///< width of the symbol + unsigned char *data; ///< symbol data +} QRcode; + +/** + * Singly-linked list of QRcode. Used to represent a structured symbols. + * A list is terminated with NULL. + */ +typedef struct _QRcode_List QRcode_List; + +struct _QRcode_List { + QRcode *code; + QRcode_List *next; +}; + +/** + * Create a symbol from the input data. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param input input data. + * @return an instance of QRcode class. The version of the result QRcode may + * be larger than the designated version. On error, NULL is returned, + * and errno is set to indicate the error. See Exceptions for the + * details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern QRcode *QRcode_encodeInput(QRinput *input); + +/** + * Create a symbol from the string. The library automatically parses the input + * string and encodes in a QR Code symbol.ַͨһţַԶַȻΪб롣 + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param string input string. It must be NUL terminated. + * @param version version of the symbol. If 0, the library chooses the minimum + * version for the given input data. + * @param level error correction level. + * @param hint tell the library how non-alphanumerical characters should be + * encoded. If QR_MODE_KANJI is given, kanji characters will be + * encoded as Shif-JIS characters. If QR_MODE_8 is given, all of + * non-alphanumerical characters will be encoded as is. If you want + * to embed UTF-8 string, choose this. + * @param casesensitive case-sensitive(1) or not(0). + * @return an instance of QRcode class. The version of the result QRcode may + * be larger than the designated version. On error, NULL is returned, + * and errno is set to indicate the error. See Exceptions for the + * details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw ERANGE input data is too large. + */ +extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Same to QRcode_encodeString(), but encode whole data in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ + + +/** + * Micro QR Code version of QRcode_encodeString(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Encode byte stream (may include '\0') in 8-bit mode.8λģʽ¶ֽб + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param size size of the input data. + * @param data input data. + * @param version version of the symbol. If 0, the library chooses the minimum + * version for the given input data. + * @param level error correction level. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw ERANGE input data is too large. + */ +extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Micro QR Code version of QRcode_encodeData(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Free the instance of QRcode class. + * @param qrcode an instance of QRcode class. + */ +extern void QRcode_free(QRcode *qrcode); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + +#endif /* __QRENCODE_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/qrencode_inner.h b/code/application/sifarsdk/component/Qrcode/include/qrencode_inner.h new file mode 100644 index 000000000..8dc95f4d0 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/qrencode_inner.h @@ -0,0 +1,97 @@ +/** + * qrencode - QR Code encoder + * + * Header for test use + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRENCODE_INNER_H__ +#define __QRENCODE_INNER_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * This header file includes definitions for test use. + */ + +/****************************************************************************** + * Raw code + *****************************************************************************/ + +typedef struct { + int dataLength; + unsigned char *data; + int eccLength; + unsigned char *ecc; +} RSblock; + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + int b1; + int blocks; + RSblock *rsblock; + int count; +} QRRawCode; + +extern QRRawCode *QRraw_new(QRinput *input); +extern unsigned char QRraw_getCode(QRRawCode *raw); +extern void QRraw_free(QRRawCode *raw); + +/****************************************************************************** + * Raw code for Micro QR Code + *****************************************************************************/ + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + RSblock *rsblock; + int oddbits; + int count; +} MQRRawCode; + +extern MQRRawCode *MQRraw_new(QRinput *input); +extern unsigned char MQRraw_getCode(MQRRawCode *raw); +extern void MQRraw_free(MQRRawCode *raw); + +/****************************************************************************** + * Frame filling + *****************************************************************************/ + + +/****************************************************************************** + * QR-code encoding + *****************************************************************************/ +extern QRcode *QRcode_encodeMask(QRinput *input, int mask); +extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask); +extern QRcode *QRcode_new(int version, int width, unsigned char *data); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __QRENCODE_INNER_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/qrinput.h b/code/application/sifarsdk/component/Qrcode/include/qrinput.h new file mode 100644 index 000000000..8a73402ea --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/qrinput.h @@ -0,0 +1,132 @@ +/* + * qrencode - QR Code encoder + * + * Input data chunk class + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRINPUT_H__ +#define __QRINPUT_H__ + +#include "qrencode.h" +#include "bitstream.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int QRinput_isSplittableMode(QRencodeMode mode); + +/****************************************************************************** + * Entry of input data + *****************************************************************************/ +typedef struct _QRinput_List QRinput_List; + +struct _QRinput_List { + QRencodeMode mode; + int size; ///< Size of data chunk (byte). + unsigned char *data; ///< Data chunk. + BitStream *bstream; + QRinput_List *next; +}; + +/****************************************************************************** + * Input Data + *****************************************************************************/ +struct _QRinput { + int version; + QRecLevel level; + QRinput_List *head; + QRinput_List *tail; + int mqr; + int fnc1; + unsigned char appid; +}; + +/****************************************************************************** + * Structured append input data + *****************************************************************************/ +typedef struct _QRinput_InputList QRinput_InputList; + +struct _QRinput_InputList { + QRinput *input; + QRinput_InputList *next; +}; + +struct _QRinput_Struct { + int size; ///< number of structured symbols + int parity; + QRinput_InputList *head; + QRinput_InputList *tail; +}; + +/** + * Pack all bit streams padding bits into a byte array. + * @param input input data. + * @return padded merged byte stream + */ +extern unsigned char *QRinput_getByteStream(QRinput *input); + + +extern int QRinput_estimateBitsModeNum(int size); +extern int QRinput_estimateBitsModeAn(int size); +extern int QRinput_estimateBitsMode8(int size); +extern int QRinput_estimateBitsModeKanji(int size); + +extern QRinput *QRinput_dup(QRinput *input); + +extern const signed char QRinput_anTable[128]; + +/** + * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19). + * @param __c__ character + * @return value + */ +#define QRinput_lookAnTable(__c__) \ + ((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__]) + +/** + * Length of a standard mode indicator in bits. + */ + +#define MODE_INDICATOR_SIZE 4 + +/** + * Length of a segment of structured-append header. + */ +#define STRUCTURE_HEADER_SIZE 20 + +/** + * Maximum number of symbols in a set of structured-appended symbols. + */ +#define MAX_STRUCTURED_SYMBOLS 16 + +#ifdef WITH_TESTS +extern BitStream *QRinput_mergeBitStream(QRinput *input); +extern BitStream *QRinput_getBitStream(QRinput *input); +extern int QRinput_estimateBitStreamSize(QRinput *input, int version); +extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits); +extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __QRINPUT_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/qrspec.h b/code/application/sifarsdk/component/Qrcode/include/qrspec.h new file mode 100644 index 000000000..78d9deb46 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/qrspec.h @@ -0,0 +1,190 @@ +/* + * qrencode - QR Code encoder + * + * QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRSPEC_H__ +#define __QRSPEC_H__ + +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +/** + * Maximum width of a symbol + */ +#define QRSPEC_WIDTH_MAX 177 + +/** + * Return maximum data code length (bytes) for the version. + * @param version + * @param level + * @return maximum size (bytes) + */ +extern int QRspec_getDataLength(int version, QRecLevel level); + +/** + * Return maximum error correction code length (bytes) for the version. + * @param version + * @param level + * @return ECC size (bytes) + */ +extern int QRspec_getECCLength(int version, QRecLevel level); + +/** + * Return a version number that satisfies the input code length. + * @param size input code length (byte) + * @param level + * @return version number + */ +extern int QRspec_getMinimumVersion(int size, QRecLevel level); + +/** + * Return the width of the symbol for the version. + * @param version + * @return width + */ +extern int QRspec_getWidth(int version); + +/** + * Return the numer of remainder bits. + * @param version + * @return number of remainder bits + */ +extern int QRspec_getRemainder(int version); + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * Return the size of lenght indicator for the mode and version. + * @param mode + * @param version + * @return the size of the appropriate length indicator (bits). + */ +extern int QRspec_lengthIndicator(QRencodeMode mode, int version); + +/** + * Return the maximum length for the mode and version. + * @param mode + * @param version + * @return the maximum length (bytes) + */ +extern int QRspec_maximumWords(QRencodeMode mode, int version); + +/****************************************************************************** + * Error correction code + *****************************************************************************/ + +/** + * Return an array of ECC specification. + * @param version + * @param level + * @param spec an array of ECC specification contains as following: + * {# of type1 blocks, # of data code, # of ecc code, + * # of type2 blocks, # of data code} + */ +void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]); + +#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3]) +#define QRspec_rsBlockNum1(__spec__) (__spec__[0]) +#define QRspec_rsDataCodes1(__spec__) (__spec__[1]) +#define QRspec_rsEccCodes1(__spec__) (__spec__[2]) +#define QRspec_rsBlockNum2(__spec__) (__spec__[3]) +#define QRspec_rsDataCodes2(__spec__) (__spec__[4]) +#define QRspec_rsEccCodes2(__spec__) (__spec__[2]) + +#define QRspec_rsDataLength(__spec__) \ + ((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \ + (QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__))) +#define QRspec_rsEccLength(__spec__) \ + (QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__)) + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Return BCH encoded version information pattern that is used for the symbol + * of version 7 or greater. Use lower 18 bits. + * @param version + * @return BCH encoded version information pattern + */ +extern unsigned int QRspec_getVersionPattern(int version); + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/** + * Return BCH encoded format information pattern. + * @param mask + * @param level + * @return BCH encoded format information pattern + */ +extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level); + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Return a copy of initialized frame. + * When the same version is requested twice or more, a copy of cached frame + * is returned. + * @param version + * @return Array of unsigned char. You can free it by free(). + */ +extern unsigned char *QRspec_newFrame(int version); + +/** + * Clear the frame cache. Typically for debug. + */ +extern void QRspec_clearCache(void); + +/****************************************************************************** + * Mode indicator + *****************************************************************************/ + +/** + * Mode indicator. See Table 2 of JIS X0510:2004, pp.16. + */ +#define QRSPEC_MODEID_ECI 7 +#define QRSPEC_MODEID_NUM 1 +#define QRSPEC_MODEID_AN 2 +#define QRSPEC_MODEID_8 4 +#define QRSPEC_MODEID_KANJI 8 +#define QRSPEC_MODEID_FNC1FIRST 5 +#define QRSPEC_MODEID_FNC1SECOND 9 +#define QRSPEC_MODEID_STRUCTURE 3 +#define QRSPEC_MODEID_TERMINATOR 0 + #ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif /* __QRSPEC_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/rscode.h b/code/application/sifarsdk/component/Qrcode/include/rscode.h new file mode 100644 index 000000000..09a243d2c --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/rscode.h @@ -0,0 +1,51 @@ +/* + * qrencode - QR Code encoder + * + * Reed solomon encoder. This code is taken from Phil Karn's libfec then + * editted and packed into a pair of .c and .h files. + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * (libfec is released under the GNU Lesser General Public License.) + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __RSCODE_H__ +#define __RSCODE_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* + * General purpose RS codec, 8-bit symbols. + */ + +typedef struct _RS RS; + +extern RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad); +extern void encode_rs_char(RS *rs, const unsigned char *data, unsigned char *parity); +extern void free_rs_char(RS *rs); +extern void free_rs_cache(void); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __RSCODE_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/include/sf_bmp.h b/code/application/sifarsdk/component/Qrcode/include/sf_bmp.h new file mode 100644 index 000000000..651832030 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/sf_bmp.h @@ -0,0 +1,47 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: jiamin + * Ver: 1.0.0 2021.04.15 + * Description: creat +**************************************************************************/ +#ifndef _SF_BMP_H_ +#define _SF_BMP_H_ +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct sfBMP_DATA_S +{ + int width; //width of the symbol + int height; //height of the symbol + unsigned char *data; //symbol data + +} SF_BMP_DATA_S; + + +int sf_qrcode_bmpfile_write(QRcode *DataInfo, const char *outfile, int magnification); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + diff --git a/code/application/sifarsdk/component/Qrcode/include/sf_qrcode.h b/code/application/sifarsdk/component/Qrcode/include/sf_qrcode.h new file mode 100644 index 000000000..7977d698f --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/sf_qrcode.h @@ -0,0 +1,30 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: jiamin + * Ver: 1.0.0 2021.04.15 + * Description: creat + **************************************************************************/ +#ifndef _SF_QRCODE_H_ +#define _SF_QRCODE_H_ +#if __cplusplus +extern "C" +{ +#endif + int sf_qrcode_create(const char *pIMEI, const char *pSimID, const char *pVersion, const char *accessKey); +#if __cplusplus +} +#endif +#endif diff --git a/code/application/sifarsdk/component/Qrcode/include/split.h b/code/application/sifarsdk/component/Qrcode/include/split.h new file mode 100644 index 000000000..0881dc402 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/include/split.h @@ -0,0 +1,57 @@ +/* + * qrencode - QR Code encoder + * + * Input data splitter. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SPLIT_H__ +#define __SPLIT_H__ + +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * Split the input string (null terminated) into QRinput. + * @param string input string + * @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8. + * @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS. + * @retval 0 success. + * @retval -1 an error occurred. errno is set to indicate the error. See + * Exceptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern int Split_splitStringToQRinput(const char *string, QRinput *input, + QRencodeMode hint, int casesensitive); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __SPLIT_H__ */ diff --git a/code/application/sifarsdk/component/Qrcode/src/bitstream.c b/code/application/sifarsdk/component/Qrcode/src/bitstream.c new file mode 100644 index 000000000..fb0a4f81a --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/bitstream.c @@ -0,0 +1,250 @@ +/* + * qrencode - QR Code encoder + * + * Binary sequence class. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include + +#include "bitstream.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +BitStream *BitStream_new(void) +{ + BitStream *bstream; + + bstream = (BitStream *)malloc(sizeof(BitStream)); + if(bstream == NULL) return NULL; + + bstream->length = 0; + bstream->data = NULL; + + return bstream; +} + +static int BitStream_allocate(BitStream *bstream, int length) +{ + unsigned char *data; + + if(bstream == NULL) { + return -1; + } + + data = (unsigned char *)malloc(length); + if(data == NULL) { + return -1; + } + + if(bstream->data) { + free(bstream->data); + } + bstream->length = length; + bstream->data = data; + + return 0; +} + +static BitStream *BitStream_newFromNum(int bits, unsigned int num) +{ + unsigned int mask; + int i; + unsigned char *p; + BitStream *bstream; + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + if(BitStream_allocate(bstream, bits)) { + BitStream_free(bstream); + return NULL; + } + + p = bstream->data; + mask = 1 << (bits - 1); + for(i=0; i> 1; + } + + return bstream; +} + +static BitStream *BitStream_newFromBytes(int size, unsigned char *data) +{ + unsigned char mask; + int i, j; + unsigned char *p; + BitStream *bstream; + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + if(BitStream_allocate(bstream, size * 8)) { + BitStream_free(bstream); + return NULL; + } + + p = bstream->data; + for(i=0; i> 1; + } + } + + return bstream; +} + +int BitStream_append(BitStream *bstream, BitStream *arg) +{ + unsigned char *data; + + if(arg == NULL) { + return -1; + } + if(arg->length == 0) { + return 0; + } + if(bstream->length == 0) { + if(BitStream_allocate(bstream, arg->length)) { + return -1; + } + memcpy(bstream->data, arg->data, arg->length); + return 0; + } + + data = (unsigned char *)malloc(bstream->length + arg->length); + if(data == NULL) { + return -1; + } + memcpy(data, bstream->data, bstream->length); + memcpy(data + bstream->length, arg->data, arg->length); + + free(bstream->data); + bstream->length += arg->length; + bstream->data = data; + + return 0; +} + +int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num) +{ + BitStream *b; + int ret; + + if(bits == 0) return 0; + + b = BitStream_newFromNum(bits, num); + if(b == NULL) return -1; + + ret = BitStream_append(bstream, b); + BitStream_free(b); + + return ret; +} + +int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data) +{ + BitStream *b; + int ret; + + if(size == 0) return 0; + + b = BitStream_newFromBytes(size, data); + if(b == NULL) return -1; + + ret = BitStream_append(bstream, b); + BitStream_free(b); + + return ret; +} + +unsigned char *BitStream_toByte(BitStream *bstream) +{ + int i, j, size, bytes; + unsigned char *data, v; + unsigned char *p; + + size = BitStream_size(bstream); + if(size == 0) { + return NULL; + } + data = (unsigned char *)malloc((size + 7) / 8); + if(data == NULL) { + return NULL; + } + + bytes = size / 8; + + p = bstream->data; + for(i=0; idata); + free(bstream); + } +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/Qrcode/src/mask.c b/code/application/sifarsdk/component/Qrcode/src/mask.c new file mode 100644 index 000000000..07f713865 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/mask.c @@ -0,0 +1,408 @@ +/* + * qrencode - QR Code encoder + * + * Masking. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mask.h" + +//__STATIC +int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level) +{ // printf("--------------------Mask_writeFormatInformation start -------------------\n"); + unsigned int format; + unsigned char v; + int i; + int blacks = 0; + + format = QRspec_getFormatInfo(mask, level); + + for (i = 0; i < 8; i++) + { + if (format & 1) + { + blacks += 2; + v = 0x85; + } + else + { + v = 0x84; + } + frame[width * 8 + width - 1 - i] = v; + if (i < 6) + { + frame[width * i + 8] = v; + } + else + { + frame[width * (i + 1) + 8] = v; + } + format = format >> 1; + } + for (i = 0; i < 7; i++) + { + if (format & 1) + { + blacks += 2; + v = 0x85; + } + else + { + v = 0x84; + } + frame[width * (width - 7 + i) + 8] = v; + if (i == 0) + { + frame[width * 8 + 7] = v; + } + else + { + frame[width * 8 + 6 - i] = v; + } + format = format >> 1; + } + // printf("--------------------Mask_writeFormatInformation end -------------------\n"); + return blacks; +} + +/** + * Demerit coefficients. + * See Section 8.8.2, pp.45, JIS X0510:2004. + */ +#define N1 (3) +#define N2 (3) +#define N3 (40) +#define N4 (10) + +#define MASKMAKER(__exp__) \ + int x, y; \ + int b = 0; \ + \ + for (y = 0; y < width; y++) \ + { \ + for (x = 0; x < width; x++) \ + { \ + if (*s & 0x80) \ + { \ + *d = *s; \ + } \ + else \ + { \ + *d = *s ^ ((__exp__) == 0); \ + } \ + b += (int)(*d & 1); \ + s++; \ + d++; \ + } \ + } \ + return b; + +static int Mask_mask0(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((x + y) & 1) +} + +static int Mask_mask1(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(y & 1) +} + +static int Mask_mask2(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(x % 3) +} + +static int Mask_mask3(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((x + y) % 3) +} + +static int Mask_mask4(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(((y / 2) + (x / 3)) & 1) +} + +static int Mask_mask5(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(((x * y) & 1) + (x * y) % 3) +} + +static int Mask_mask6(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((((x * y) & 1) + (x * y) % 3) & 1) +} + +static int Mask_mask7(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((((x * y) % 3) + ((x + y) & 1)) & 1) +} + +#define maskNum (8) +typedef int MaskMaker(int, const unsigned char *, unsigned char *); +static MaskMaker *maskMakers[maskNum] = { + Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3, + Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7}; + +#ifdef WITH_TESTS +unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask) +{ + unsigned char *masked; + + masked = (unsigned char *)malloc(width * width); + if (masked == NULL) + return NULL; + + maskMakers[mask](width, frame, masked); + + return masked; +} +#endif + +unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned char *masked; + + if (mask < 0 || mask >= maskNum) + { + errno = EINVAL; + return NULL; + } + + masked = (unsigned char *)malloc(width * width); + if (masked == NULL) + return NULL; + + maskMakers[mask](width, frame, masked); + Mask_writeFormatInformation(width, masked, mask, level); + + return masked; +} + +// static int n1; +// static int n2; +// static int n3; +// static int n4; + +//__STATIC +int Mask_calcN1N3(int length, int *runLength) +{ + int i; + int demerit = 0; + int fact; + + for (i = 0; i < length; i++) + { + if (runLength[i] >= 5) + { + demerit += N1 + (runLength[i] - 5); + // n1 += N1 + (runLength[i] - 5); + } + if ((i & 1)) + { + if (i >= 3 && i < length - 2 && (runLength[i] % 3) == 0) + { + fact = runLength[i] / 3; + if (runLength[i - 2] == fact && + runLength[i - 1] == fact && + runLength[i + 1] == fact && + runLength[i + 2] == fact) + { + if (i == 3 || runLength[i - 3] >= 4 * fact) + { + demerit += N3; + // n3 += N3; + } + else if (i + 4 >= length || runLength[i + 3] >= 4 * fact) + { + demerit += N3; + // n3 += N3; + } + } + } + } + } + + return demerit; +} + +//__STATIC +int Mask_calcN2(int width, unsigned char *frame) +{ + int x, y; + unsigned char *p; + unsigned char b22, w22; + int demerit = 0; + + p = frame + width + 1; + for (y = 1; y < width; y++) + { + for (x = 1; x < width; x++) + { + b22 = p[0] & p[-1] & p[-width] & p[-width - 1]; + w22 = p[0] | p[-1] | p[-width] | p[-width - 1]; + if ((b22 | (w22 ^ 1)) & 1) + { + demerit += N2; + } + p++; + } + p++; + } + + return demerit; +} + +//__STATIC +int Mask_calcRunLength(int width, unsigned char *frame, int dir, int *runLength) +{ + int head; + int i; + unsigned char *p; + int pitch; + + pitch = (dir == 0) ? 1 : width; + if (frame[0] & 1) + { + runLength[0] = -1; + head = 1; + } + else + { + head = 0; + } + runLength[head] = 1; + p = frame + pitch; + + for (i = 1; i < width; i++) + { + if ((p[0] ^ p[-pitch]) & 1) + { + head++; + runLength[head] = 1; + } + else + { + runLength[head]++; + } + p += pitch; + } + + return head + 1; +} + +//__STATIC +int Mask_evaluateSymbol(int width, unsigned char *frame) +{ // printf("\n--------------Mask_evaluateSymbol start---------------\n"); + int x, y; + int demerit = 0; + int runLength[QRSPEC_WIDTH_MAX + 1]; + int length; + + demerit += Mask_calcN2(width, frame); + + for (y = 0; y < width; y++) + { + length = Mask_calcRunLength(width, frame + y * width, 0, runLength); + demerit += Mask_calcN1N3(length, runLength); + } + + for (x = 0; x < width; x++) + { + length = Mask_calcRunLength(width, frame + x, 1, runLength); + demerit += Mask_calcN1N3(length, runLength); + } + // printf("\n--------------Mask_evaluateSymbol end---------------\n"); + return demerit; +} + +unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level) +{ + int i; + unsigned char *mask, *bestMask; + int minDemerit = INT_MAX; + int blacks; + int bratio; + int demerit; + int w2 = width * width; + // printf("\n--------------Mask_mask start---------------\n"); + mask = (unsigned char *)malloc(w2); + if (mask == NULL) + return NULL; + bestMask = NULL; + + for (i = 0; i < maskNum; i++) + { + // n1 = n2 = n3 = n4 = 0; + demerit = 0; + blacks = maskMakers[i](width, frame, mask); + // printf("--------------Mask_writeFormatInformation will start---------------\n"); + blacks += Mask_writeFormatInformation(width, mask, i, level); + bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */ + demerit = (abs(bratio - 50) / 5) * N4; + // n4 = demerit; + // printf("-------------Mask_evaluateSymbol will start---------------\n"); + demerit += Mask_evaluateSymbol(width, mask); + + if (demerit < minDemerit) + { + minDemerit = demerit; + +#if 0 + if(bestMask == NULL) + printf("bestmask is null!\n"); + else + printf("bestmask is not mull!\n"); + + printf("11111111111111111\n"); + //sp5kFree(bestMask); + printf("222222222222222222222\n"); + if(mask == NULL) + printf("mask is null!\n"); + else + printf("mask is not mull!\n"); +#endif + if (bestMask) + free(bestMask); + bestMask = mask; + // if (mask) + // { + // free(mask); + // mask = NULL; + // } + mask = (unsigned char *)malloc(w2); + if (mask == NULL) + break; + } + } + // printf("\n--------------Mask_mask end---------------\n"); + if (mask) + { + free(mask); + mask = NULL; + } + return bestMask; +} diff --git a/code/application/sifarsdk/component/Qrcode/src/mmask.c b/code/application/sifarsdk/component/Qrcode/src/mmask.c new file mode 100644 index 000000000..d643d5281 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/mmask.c @@ -0,0 +1,191 @@ +/* + * qrencode - QR Code encoder + * + * Masking for Micro QR Code. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "mqrspec.h" +#include "mmask.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +//__STATIC +void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned int format; + unsigned char v; + int i; + + format = MQRspec_getFormatInfo(mask, version, level); + + for(i=0; i<8; i++) { + v = 0x84 | (format & 1); + frame[width * (i + 1) + 8] = v; + format = format >> 1; + } + for(i=0; i<7; i++) { + v = 0x84 | (format & 1); + frame[width * 8 + 7 - i] = v; + format = format >> 1; + } +} + +#define MASKMAKER(__exp__) \ + int x, y;\ +\ + for(y=0; y= maskNum) { + errno = EINVAL; + return NULL; + } + + width = MQRspec_getWidth(version); + masked = (unsigned char *)malloc(width * width); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + MMask_writeFormatInformation(version, width, masked, mask, level); + + return masked; +} + +//__STATIC +int MMask_evaluateSymbol(int width, unsigned char *frame) +{ + int x, y; + unsigned char *p; + int sum1 = 0, sum2 = 0; + + p = frame + width * (width - 1); + for(x=1; x maxScore) { + maxScore = score; + free(bestMask); + bestMask = mask; + mask = (unsigned char *)malloc(width * width); + if(mask == NULL) break; + } + } + free(mask); + return bestMask; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/Qrcode/src/mqrspec.c b/code/application/sifarsdk/component/Qrcode/src/mqrspec.c new file mode 100644 index 000000000..7b7758f1f --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/mqrspec.c @@ -0,0 +1,292 @@ +/* + * qrencode - QR Code encoder + * + * Micor QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#ifdef HAVE_LIBPTHREAD +#include +#endif + +#include "mqrspec.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +typedef struct { + int width; //< Edge length of the symbol + int ec[4]; //< Number of ECC code (bytes) +} MQRspec_Capacity; + +/** + * Table of the capacity of symbols + * See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004. + */ +static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = { + { 0, {0, 0, 0, 0}}, + { 11, {2, 0, 0, 0}}, + { 13, {5, 6, 0, 0}}, + { 15, {6, 8, 0, 0}}, + { 17, {8, 10, 14, 0}} +}; + +int MQRspec_getDataLengthBit(int version, QRecLevel level) +{ + int w; + int ecc; + + w = mqrspecCapacity[version].width - 1; + ecc = mqrspecCapacity[version].ec[level]; + if(ecc == 0) return 0; + return w * w - 64 - ecc * 8; +} + +int MQRspec_getDataLength(int version, QRecLevel level)//ȡݵij +{ + return (MQRspec_getDataLengthBit(version, level) + 4) / 8; +} + +int MQRspec_getECCLength(int version, QRecLevel level)//þλij +{ + return mqrspecCapacity[version].ec[level]; +} + +int MQRspec_getWidth(int version)//ȡ +{ + return mqrspecCapacity[version].width; +} + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * See Table 3 (pp.107) of Appendix 1, JIS X0510:2004. + */ +static const int lengthTableBits[4][4] = { + { 3, 4, 5, 6}, + { 0, 3, 4, 5}, + { 0, 0, 4, 5}, + { 0, 0, 3, 4} +}; + +int MQRspec_lengthIndicator(QRencodeMode mode, int version)//ַͰ汾Ϣȷtableʲô +{ + return lengthTableBits[mode][version - 1]; +} + +int MQRspec_maximumWords(QRencodeMode mode, int version) +{ + int bits; + int words; + + bits = lengthTableBits[mode][version - 1]; + words = (1 << bits) - 1; + if(mode == QR_MODE_KANJI) { + words *= 2; // the number of bytes is required + } + + return words; +} + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/* See calcFormatInfo in tests/test_mqrspec.c */ +static const unsigned int formatInfo[4][8] = { + {0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3}, + {0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4}, + {0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d}, + {0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba} +}; + +/* See Table 10 of Appendix 1. (pp.115) */ +static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = { + {-1, -1, -1}, + { 0, -1, -1}, + { 1, 2, -1}, + { 3, 4, -1}, + { 5, 6, 7} +}; + +unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level) +{ + int type; + + if(mask < 0 || mask > 3) return 0; + if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0; + if(level == QR_ECLEVEL_H) return 0; + type = typeTable[version][level]; + if(type < 0) return 0; + + return formatInfo[mask][type]; +} + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Cache of initial frames. + */ +/* C99 says that static storage shall be initialized to a null pointer + * by compiler. */ +static unsigned char *frames[MQRSPEC_VERSION_MAX + 1]; +#ifdef HAVE_LIBPTHREAD +static pthread_mutex_t frames_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/** + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ +static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)//??????????????????????????????????? +{ + static const unsigned char finder[] = { + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + }; + int x, y; + const unsigned char *s; + + frame += oy * width + ox; + s = finder; + for(y=0; y<7; y++) { + for(x=0; x<7; x++) { + frame[x] = s[x]; + } + frame += width; + s += 7; + } +} + +static unsigned char *MQRspec_createFrame(int version) +{ + unsigned char *frame, *p, *q; + int width; + int x, y; + + width = mqrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + + memset(frame, 0, width * width); + /* Finder pattern */ + putFinderPattern(frame, width, 0, 0); + /* Separator */ + p = frame; + for(y=0; y<7; y++) { + p[7] = 0xc0; + p += width; + } + memset(frame + width * 7, 0xc0, 8); + /* Mask format information area */ + memset(frame + width * 8 + 1, 0x84, 8); + p = frame + width + 8; + for(y=0; y<7; y++) { + *p = 0x84; + p += width; + } + /* Timing pattern */ + p = frame + 8; + q = frame + width * 8; + for(x=1; x MQRSPEC_VERSION_MAX) return NULL; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + if(frames[version] == NULL) { + frames[version] = MQRspec_createFrame(version); + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif + if(frames[version] == NULL) return NULL; + + width = mqrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + memcpy(frame, frames[version], width * width); + + return frame; +} + +void MQRspec_clearCache(void) +{ + int i; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + for(i=1; i<=MQRSPEC_VERSION_MAX; i++) { + free(frames[i]); + frames[i] = NULL; + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/Qrcode/src/qrenc.c b/code/application/sifarsdk/component/Qrcode/src/qrenc.c new file mode 100644 index 000000000..d5b89728b --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/qrenc.c @@ -0,0 +1,358 @@ +/** + * qrencode - QR Code encoder + * + * QR Code encoding tool + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#define INCHES_PER_METER (100.0/2.54) + + + +static int casesensitive = 1; +static int eightbit = 0; +static int version= 0; +static int micro = 0; +static QRecLevel level = QR_ECLEVEL_L; +static QRencodeMode hint = QR_MODE_8; + +#define MAX_DATA_SIZE (7090 * 16) /* from the specification */ + +#if 0 +#define SIZE 4 +typedef unsigned char U1; +typedef unsigned short U2; +typedef unsigned long U4; + +typedef unsigned char BOOL; +#define TRUE (0xFFu) +#define FALSE (0x00u) + + + +void vd_SerializeLittleEndianU2(U1 * u1_ap_serial, U2 u2_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u2_a_value; + u1_ap_serial[1] = (U1)(u2_a_value >> 8); + } while(FALSE); +} + +void vd_SerializeLittleEndianU3(U1 * u1_ap_serial, U4 u4_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u4_a_value; + u1_ap_serial[1] = (U1)(u4_a_value >> 8); + u1_ap_serial[2] = (U1)(u4_a_value >> 16); + } while(FALSE); +} + +void vd_SerializeLittleEndianU4(U1 * u1_ap_serial, U4 u4_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u4_a_value; + u1_ap_serial[1] = (U1)(u4_a_value >> 8); + u1_ap_serial[2] = (U1)(u4_a_value >> 16); + u1_ap_serial[3] = (U1)(u4_a_value >> 24); + } while(FALSE); +} + +// AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB +// 76543210765432107654321076543210 +#define BMP_RGBA32(r,g,b,a) (U4)( ((U4)(U1)(r)<<16) | ((U4)(U1)(g)<<8) | (U4)(U1)(b) | ((U4)(U1)(a)<<24) ) +#define BMP_RGB24(r,g,b) (U4)( ((U4)(U1)(r)<<16) | ((U4)(U1)(g)<<8) | (U4)(U1)(b) ) + +// XRRRRRGGGGGBBBBB +// 0432104321043210 +#define BMP_RGBA32TOBMP16(c) (U2)( (((U4)(c)>>9) & 0x7C00u) | (((U4)(c)>>6) & 0x03E0u) | (((U4)(c)>>3) & 0x001F) ) + + +typedef struct { + U4 u4_image_width; + U4 u4_image_height; + U4 u4_widthbyte; + U4 u4_image_size; + U2 u2_bitcount; + U2 u2_palette_size; + U1* u1_p_image_data; +} ST_BITMAP; + +ST_BITMAP * st_g_CreateBitmap(U4 u4_a_width, U4 u4_a_height, U2 u2_a_bitcount) +{ + ST_BITMAP * st_tp_bitmap = NULL; + U4 u4_t_widthbyte = 0; + U4 u4_t_imagesize = 0; + + do + { + if((u4_a_width == 0) || (u4_a_width > 4096)) + break; + + if((u4_a_height == 0) || (u4_a_height > 4096)) + break; + + if((u2_a_bitcount != 16) && (u2_a_bitcount != 24) && (u2_a_bitcount != 32)) + break; + + // 4-byte aligned bytes for a line of image data + u4_t_widthbyte = (u4_a_width * u2_a_bitcount + 31) / 32 * 4; + u4_t_imagesize = (u4_t_widthbyte * u4_a_height); + + st_tp_bitmap = malloc(sizeof(ST_BITMAP) + u4_t_imagesize); // alloc together + if(st_tp_bitmap == NULL) + break; + + memset(st_tp_bitmap, 0, sizeof(ST_BITMAP) + u4_t_imagesize); + + st_tp_bitmap->u4_image_width = u4_a_width; + st_tp_bitmap->u4_image_height = u4_a_height; + st_tp_bitmap->u4_widthbyte = u4_t_widthbyte; + st_tp_bitmap->u4_image_size = u4_t_imagesize; + st_tp_bitmap->u2_bitcount = u2_a_bitcount; + st_tp_bitmap->u2_palette_size = 0; + // pointer to the address next to the struct + st_tp_bitmap->u1_p_image_data = (U1 *)st_tp_bitmap + sizeof(ST_BITMAP); + + } while(FALSE); + + return st_tp_bitmap; +} + +void vd_g_FreeBitmap(ST_BITMAP * st_ap_bitmap) +{ + + do + { + if(st_ap_bitmap == NULL) + break; + + memset(st_ap_bitmap, 0, sizeof(ST_BITMAP)); + free(st_ap_bitmap); + + } while(FALSE); +} + +void vd_g_SaveBitmap(const ST_BITMAP * st_ap_bitmap, const char * sz_ap_path) +{ + + U1 u1_tp_bitmap_header[] = + { + 0x42, 0x4D, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, // 2 AA->FileSize + 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0x28, 0x00, // 10 BB->OffBits + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, // 18 CC->Width + 0xDD, 0xDD, 0x01, 0x00, 0xEE, 0xEE, 0x00, 0x00, // 22 DD->Height + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, // 28 EE->BitCount + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 34 FF->ImageSize + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + FILE *file_bitmap = NULL; + + U4 u4_t_y; + U4 u4_t_pixel_offset = 0; + + do + { + if(st_ap_bitmap == NULL) + break; + + if((st_ap_bitmap->u2_bitcount != 16) && (st_ap_bitmap->u2_bitcount != 24) && (st_ap_bitmap->u2_bitcount != 32)) + break; + + if(sz_ap_path == NULL) + break; + + file_bitmap = fopen(sz_ap_path, "wb"); + if(file_bitmap == NULL) + break; + + // set bitmap head info + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[2], sizeof(u1_tp_bitmap_header) + st_ap_bitmap->u4_image_size); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[10], sizeof(u1_tp_bitmap_header)); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[18], st_ap_bitmap->u4_image_width); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[22], st_ap_bitmap->u4_image_height); + vd_SerializeLittleEndianU2(&u1_tp_bitmap_header[28], st_ap_bitmap->u2_bitcount); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[34], st_ap_bitmap->u4_image_size); + + // write bitmap file head + fwrite(u1_tp_bitmap_header, sizeof(u1_tp_bitmap_header), 1L, file_bitmap); + + // write bitmap image data, bottom to top + u4_t_pixel_offset = st_ap_bitmap->u4_image_height * st_ap_bitmap->u4_widthbyte; + for(u4_t_y = 0; u4_t_y < st_ap_bitmap->u4_image_height; u4_t_y++) + { + u4_t_pixel_offset -= st_ap_bitmap->u4_widthbyte; + fwrite(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], st_ap_bitmap->u4_widthbyte, 1L, file_bitmap); + } + + + } while(0); + + if(file_bitmap) + fclose(file_bitmap); +} + +void vd_SetBitmapPixel(ST_BITMAP * st_ap_bitmap, U4 u4_a_x, U4 u4_a_y, U4 u4_a_color) +{ + U4 u4_t_pixel_offset = 0; + U2 u2_t_color = 0; + + do + { + + if(st_ap_bitmap == NULL) + break; + + if(u4_a_x >= st_ap_bitmap->u4_image_width) + break; + + if(u4_a_y >= st_ap_bitmap->u4_image_height) + break; + + u4_t_pixel_offset = u4_a_y * st_ap_bitmap->u4_widthbyte + u4_a_x * st_ap_bitmap->u2_bitcount / 8; + + switch(st_ap_bitmap->u2_bitcount) + { + case 16: + u2_t_color = BMP_RGBA32TOBMP16(u4_a_color); + vd_SerializeLittleEndianU2(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u2_t_color); + break; + case 24: + vd_SerializeLittleEndianU3(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u4_a_color); + break; + case 32: + vd_SerializeLittleEndianU4(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u4_a_color); + break; + default: + break; + } + } while(FALSE); +} + +int writeBMP(QRcode *qrcode, const char *outfile) +{ + ST_BITMAP * st_tp_bitmap = NULL; + int width = 0; + int height = 0; + int w = 0; + int i = 0; + int x = 0; + int y = 0; + unsigned char *p = NULL; + + width = qrcode->width * SIZE; + height = qrcode->width * SIZE; + do + { + // create bitmap, size:20x10 format:RGB555->16 + // also support format RGB888->24 and RGBA8888->32 + st_tp_bitmap = st_g_CreateBitmap(width, height, 16); + if(st_tp_bitmap == NULL) + break; + + // draw pixels on bitmap + p = qrcode->data; + for(y = 0; y < qrcode->width; y++) + { + w = 0; + for(x = 0; x < qrcode->width; x++) + { + for(i = 0; i < SIZE; i++) + { + if (((*p) & (1)) == 1) + { + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y, BMP_RGB24(0, 0, 0)); //white + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+1, BMP_RGB24(0, 0, 0)); //white + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+2, BMP_RGB24(0, 0, 0)); //white + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+3, BMP_RGB24(0, 0, 0)); //white + } + else + { + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y, BMP_RGB24(255, 255, 255)); // black + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+1, BMP_RGB24(255, 255, 255)); // black + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+2, BMP_RGB24(255, 255, 255)); // black + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+3, BMP_RGB24(255, 255, 255)); // black + } + w++; + + } + p++; + + } + + } + + // save to file + vd_g_SaveBitmap(st_tp_bitmap, outfile); + + } while(FALSE); + + if(st_tp_bitmap) + vd_g_FreeBitmap(st_tp_bitmap); + + return 0; +} +#endif +QRcode *encode(const unsigned char *intext, int length) +{ + QRcode *code; + if(micro) { + if(eightbit) { + code = QRcode_encodeDataMQR(length, intext, version, level); + } else { + code = QRcode_encodeStringMQR((char *)intext, version, level, hint, casesensitive); + } + } else { + if(eightbit) { + code = QRcode_encodeData(length, intext, version, level); + } else { + code = QRcode_encodeString((char *)intext, version, level, hint, casesensitive); + } + } + return code; + +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/Qrcode/src/qrencode.c b/code/application/sifarsdk/component/Qrcode/src/qrencode.c new file mode 100644 index 000000000..b322f6f4c --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/qrencode.c @@ -0,0 +1,685 @@ +/* + * qrencode - QR Code encoder + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mqrspec.h" +#include "bitstream.h" +#include "qrinput.h" +#include "rscode.h" +#include "split.h" +#include "mask.h" +#include "mmask.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + +/****************************************************************************** + * Raw code + *****************************************************************************/ + +typedef struct { + int dataLength; + unsigned char *data; + int eccLength; + unsigned char *ecc; +} RSblock; + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + int b1; + int blocks; + RSblock *rsblock; + int count; +} QRRawCode; + +static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc, RS *rs) +{ + block->dataLength = dl; + block->data = data; + block->eccLength = el; + block->ecc = ecc; + + encode_rs_char(rs, data, ecc); +} + +static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)/*�Ѵ�������;����������ŵ�һ����*/ +{ + int i; + RSblock *block; + unsigned char *dp, *ep; + RS *rs; + int el, dl; + + dl = QRspec_rsDataCodes1(spec); + el = QRspec_rsEccCodes1(spec); + rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el); + if(rs == NULL) return -1; + + block = blocks; + dp = data; + ep = ecc; + for(i=0; idatacode = QRinput_getByteStream(input); + if(raw->datacode == NULL) { + free(raw); + return NULL; + } + + QRspec_getEccSpec(input->version, input->level, spec); + + raw->version = input->version; + raw->b1 = QRspec_rsBlockNum1(spec); + raw->dataLength = QRspec_rsDataLength(spec); + raw->eccLength = QRspec_rsEccLength(spec); + raw->ecccode = (unsigned char *)malloc(raw->eccLength); + if(raw->ecccode == NULL) { + free(raw->datacode); + free(raw); + return NULL; + } + + raw->blocks = QRspec_rsBlockNum(spec); + raw->rsblock = (RSblock *)malloc(sizeof(RSblock)); + memset(raw->rsblock,raw->blocks,sizeof(RSblock)); + if(raw->rsblock == NULL) { + QRraw_free(raw); + return NULL; + } + ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode); + if(ret < 0) { + QRraw_free(raw); + return NULL; + } + + raw->count = 0; + + return raw; +} + +/** + * Return a code (byte). + * This function can be called iteratively. + * @param raw raw code. + * @return code + */ +//__STATIC +unsigned char QRraw_getCode(QRRawCode *raw) +{ + int col, row; + unsigned char ret; + + if(raw->count < raw->dataLength) { + row = raw->count % raw->blocks; + col = raw->count / raw->blocks; + if(col >= raw->rsblock[0].dataLength) { + row += raw->b1; + } + ret = raw->rsblock[row].data[col]; + } else if(raw->count < raw->dataLength + raw->eccLength) { + row = (raw->count - raw->dataLength) % raw->blocks; + col = (raw->count - raw->dataLength) / raw->blocks; + ret = raw->rsblock[row].ecc[col]; + } else { + return 0; + } + raw->count++; + return ret; +} + +//__STATIC +void QRraw_free(QRRawCode *raw) +{ + if(raw != NULL) { + free(raw->datacode); + free(raw->ecccode); + free(raw->rsblock); + free(raw); + } +} + +/****************************************************************************** + * Raw(δ�ӹ���) code for Micro QR Code + *****************************************************************************/ + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + RSblock *rsblock; + int oddbits; + int count; +} MQRRawCode; + +//__STATIC +void MQRraw_free(MQRRawCode *raw); +//__STATIC +MQRRawCode *MQRraw_new(QRinput *input) +{ + MQRRawCode *raw; + RS *rs; + + raw = (MQRRawCode *)malloc(sizeof(MQRRawCode)); + if(raw == NULL) return NULL; + + raw->version = input->version; + raw->dataLength = MQRspec_getDataLength(input->version, input->level); + raw->eccLength = MQRspec_getECCLength(input->version, input->level); + raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level); + raw->datacode = QRinput_getByteStream(input); + if(raw->datacode == NULL) { + free(raw); + return NULL; + } + raw->ecccode = (unsigned char *)malloc(raw->eccLength); + if(raw->ecccode == NULL) { + free(raw->datacode); + free(raw); + return NULL; + } + + raw->rsblock = (RSblock *)malloc(sizeof(RSblock)); + memset(raw->rsblock,1,sizeof(RSblock)); + if(raw->rsblock == NULL) { + MQRraw_free(raw); + return NULL; + } + + rs = init_rs(8, 0x11d, 0, 1, raw->eccLength, 255 - raw->dataLength - raw->eccLength); + if(rs == NULL) { + MQRraw_free(raw); + return NULL; + } + + RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode, rs); + + raw->count = 0; + + return raw; +} + +/** + * Return a code (byte). + * This function can be called iteratively. + * @param raw raw code. + * @return code + */ +//__STATIC +unsigned char MQRraw_getCode(MQRRawCode *raw) +{ + unsigned char ret; + + if(raw->count < raw->dataLength) { + ret = raw->datacode[raw->count]; + } else if(raw->count < raw->dataLength + raw->eccLength) { + ret = raw->ecccode[raw->count - raw->dataLength]; + } else { + return 0; + } + raw->count++; + return ret; +} + +//__STATIC +void MQRraw_free(MQRRawCode *raw) +{ + if(raw != NULL) { + free(raw->datacode); + free(raw->ecccode); + free(raw->rsblock); + free(raw); + } +} + + +/****************************************************************************** + * Frame(��ܣ��߿�) filling(�����) + *****************************************************************************/ + +typedef struct { + int width; + unsigned char *frame; + int x, y; + int dir; + int bit; + int mqr; +} FrameFiller; + +static FrameFiller *FrameFiller_new(int width, unsigned char *frame, int mqr) +{ + FrameFiller *filler; + + filler = (FrameFiller *)malloc(sizeof(FrameFiller)); + if(filler == NULL) return NULL; + filler->width = width; + filler->frame = frame; + filler->x = width - 1; + filler->y = width - 1; + filler->dir = -1; + filler->bit = -1; + filler->mqr = mqr; + + return filler; +} + +static unsigned char *FrameFiller_next(FrameFiller *filler) +{ + unsigned char *p; + int x, y, w; + + if(filler->bit == -1) { + filler->bit = 0; + return filler->frame + filler->y * filler->width + filler->x; + } + + x = filler->x; + y = filler->y; + p = filler->frame; + w = filler->width; + + if(filler->bit == 0) { + x--; + filler->bit++; + } else { + x++; + y += filler->dir; + filler->bit--; + } + + if(filler->dir < 0) { + if(y < 0) { + y = 0; + x -= 2; + filler->dir = 1; + if(!filler->mqr && x == 6) { + x--; + y = 9; + } + } + } else { + if(y == w) { + y = w - 1; + x -= 2; + filler->dir = -1; + if(!filler->mqr && x == 6) { + x--; + y -= 8; + } + } + } + if(x < 0 || y < 0) return NULL; + + filler->x = x; + filler->y = y; + + if(p[y * w + x] & 0x80) { + // This tail recursion could be optimized. + return FrameFiller_next(filler); + } + return &p[y * w + x]; +} + + +/****************************************************************************** + * QR-code encoding + *****************************************************************************/ + +//__STATIC +QRcode *QRcode_new(int version, int width, unsigned char *data) +{ + QRcode *qrcode; + + qrcode = (QRcode *)malloc(sizeof(QRcode)); + if(qrcode == NULL) return NULL; + + qrcode->version = version; + qrcode->width = width; + qrcode->data = data; + + return qrcode; +} + +void QRcode_free(QRcode *qrcode) +{ + if(qrcode != NULL) { + free(qrcode->data); + free(qrcode); + } +} + +//__STATIC +QRcode *QRcode_encodeMask(QRinput *input, int mask) +{ + //printf("--------------------QRcode_encodeMask start -------------------\n"); + int width, version; + QRRawCode *raw; + unsigned char *frame, *masked, *p, code, bit; + FrameFiller *filler; + int i, j; + QRcode *qrcode = NULL; + + if(input->mqr) { + //errno = EINVAL; + return NULL; + } + if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) { + //errno = EINVAL; + return NULL; + } + if(input->level > QR_ECLEVEL_H) { + //errno = EINVAL; + return NULL; + } + + raw = QRraw_new(input); + if(raw == NULL) return NULL; + + version = raw->version; + width = QRspec_getWidth(version); + frame = QRspec_newFrame(version); + if(frame == NULL) { + QRraw_free(raw); + return NULL; + } + filler = FrameFiller_new(width, frame, 0); + if(filler == NULL) { + QRraw_free(raw); + free(frame); + return NULL; + } + + /* inteleaved data and ecc codes */ + for(i=0; idataLength + raw->eccLength; i++) { + code = QRraw_getCode(raw); + bit = 0x80; + for(j=0; j<8; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } + QRraw_free(raw); + raw = NULL; + /* remainder bits */ + j = QRspec_getRemainder(version); + for(i=0; ilevel); + } else { + masked = Mask_makeMask(width, frame, mask, input->level); + } + if(masked == NULL) { + goto EXIT; + } + qrcode = QRcode_new(version, width, masked); + // free(masked); + +EXIT: + QRraw_free(raw); + free(filler); + free(frame); + //printf("--------------------QRcode_encodeMask end -------------------\n"); + return qrcode; + +} + +//__STATIC +QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask) +{ + int width, version; + MQRRawCode *raw; + unsigned char *frame, *masked, *p, code, bit; + FrameFiller *filler; + int i, j; + QRcode *qrcode = NULL; + + if(!input->mqr) { + //errno = EINVAL; + return NULL; + } + if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) { + //errno = EINVAL; + return NULL; + } + if(input->level > QR_ECLEVEL_Q) { + //errno = EINVAL; + return NULL; + } + + raw = MQRraw_new(input); + if(raw == NULL) return NULL; + + version = raw->version; + width = MQRspec_getWidth(version); + frame = MQRspec_newFrame(version); + if(frame == NULL) { + MQRraw_free(raw); + return NULL; + } + filler = FrameFiller_new(width, frame, 1); + if(filler == NULL) { + MQRraw_free(raw); + free(frame); + return NULL; + } + + /* inteleaved data and ecc codes */ + for(i=0; idataLength + raw->eccLength; i++) { + code = MQRraw_getCode(raw); + if(raw->oddbits && i == raw->dataLength - 1) { + bit = 1 << raw->oddbits; + for(j=0; joddbits; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } else { + bit = 0x80; + for(j=0; j<8; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } + } + MQRraw_free(raw); + raw = NULL; + + /* masking */ + if(mask < 0) { + masked = MMask_mask(version, frame, input->level); + } else { + masked = MMask_makeMask(version, frame, mask, input->level); + } + if(masked == NULL) { + goto EXIT; + } + + qrcode = QRcode_new(version, width, masked); + +EXIT: + MQRraw_free(raw); + free(filler); + free(frame); + return qrcode; +} + +QRcode *QRcode_encodeInput(QRinput *input) +{ + if(input->mqr) { + return QRcode_encodeMaskMQR(input, -1); + } else { + return QRcode_encodeMask(input, -1); + } +} + +static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive) +{ + //printf("--------------------QRcode_encodeStringReal start -------------------\n"); + QRinput *input; + QRcode *code; + int ret; + + if(string == NULL) { + //errno = EINVAL; + return NULL; + } + if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) { + //errno = EINVAL; + return NULL; + } + + if(mqr) { + input = QRinput_newMQR(version, level); + } else { + input = QRinput_new2(version, level); + } + if(input == NULL) return NULL; + + ret = Split_splitStringToQRinput(string, input, hint, casesensitive); + if(ret < 0) { + QRinput_free(input); + return NULL; + } + code = QRcode_encodeInput(input); + QRinput_free(input); + //printf("--------------------QRcode_encodeStringReal end -------------------\n"); + return code; + +} + +QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive); +} + +QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + return QRcode_encodeStringReal(string, version, level, 1, hint, casesensitive); +} + +static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr) +{ + QRinput *input; + QRcode *code; + int ret; + + if(data == NULL || length == 0) { + errno = EINVAL; + return NULL; + } + + if(mqr) { + input = QRinput_newMQR(version, level); + } else { + input = QRinput_new2(version, level); + } + if(input == NULL) return NULL; + + ret = QRinput_append(input, QR_MODE_8, length, data); + if(ret < 0) { + QRinput_free(input); + return NULL; + } + code = QRcode_encodeInput(input); + QRinput_free(input); + + return code; +} + +QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level) +{ + return QRcode_encodeDataReal(data, size, version, level, 0); +} + + +QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level) +{ + return QRcode_encodeDataReal(data, size, version, level, 1); +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/Qrcode/src/qrinput.c b/code/application/sifarsdk/component/Qrcode/src/qrinput.c new file mode 100644 index 000000000..7c95f2e0e --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/qrinput.c @@ -0,0 +1,1438 @@ +/* + * qrencode - QR Code encoder + * + * Input data chunk class + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mqrspec.h" +#include "bitstream.h" +#include "qrinput.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +/****************************************************************************** + * Utilities + *****************************************************************************/ +int QRinput_isSplittableMode(QRencodeMode mode) +{ + return (mode >= QR_MODE_NUM && mode <= QR_MODE_KANJI); +} + +/****************************************************************************** + * Entry of input data + *****************************************************************************/ + +static QRinput_List *QRinput_List_newEntry(QRencodeMode mode, int size, const unsigned char *data) +{ + QRinput_List *entry; + + if(QRinput_check(mode, size, data)) { + //errno = EINVAL; + return NULL; + } + + entry = (QRinput_List *)malloc(sizeof(QRinput_List)); + if(entry == NULL) return NULL; + + entry->mode = mode; + entry->size = size; + if(size > 0) { + entry->data = (unsigned char *)malloc(size); + if(entry->data == NULL) { + free(entry); + return NULL; + } + memcpy(entry->data, data, size); + } + entry->bstream = NULL; + entry->next = NULL; + + return entry; +} + +static void QRinput_List_freeEntry(QRinput_List *entry) +{ + if(entry != NULL) { + free(entry->data); + BitStream_free(entry->bstream); + free(entry); + } +} + +static QRinput_List *QRinput_List_dup(QRinput_List *entry) +{ + QRinput_List *n; + + n = (QRinput_List *)malloc(sizeof(QRinput_List)); + if(n == NULL) return NULL; + + n->mode = entry->mode; + n->size = entry->size; + n->data = (unsigned char *)malloc(n->size); + if(n->data == NULL) { + free(n); + return NULL; + } + memcpy(n->data, entry->data, entry->size); + n->bstream = NULL; + n->next = NULL; + + return n; +} + +/****************************************************************************** + * Input Data + *****************************************************************************/ + +QRinput *QRinput_new(void) +{ + return QRinput_new2(0, QR_ECLEVEL_L); +} + +QRinput *QRinput_new2(int version, QRecLevel level) +{ + QRinput *input; + + if(version < 0 || version > QRSPEC_VERSION_MAX || level > QR_ECLEVEL_H) { + //errno = EINVAL; + return NULL; + } + + input = (QRinput *)malloc(sizeof(QRinput)); + if(input == NULL) return NULL; + + input->head = NULL; + input->tail = NULL; + input->version = version; + input->level = level; + input->mqr = 0; + input->fnc1 = 0; + + return input; +} + +QRinput *QRinput_newMQR(int version, QRecLevel level) +{ + QRinput *input; + + if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID; + if((MQRspec_getECCLength(version, level) == 0)) goto INVALID; + + input = QRinput_new2(version, level); + if(input == NULL) return NULL; + + input->mqr = 1; + + return input; + +INVALID: + //errno = EINVAL; + return NULL; +} + +int QRinput_getVersion(QRinput *input) +{ + return input->version; +} + +int QRinput_setVersion(QRinput *input, int version) +{ + if(input->mqr || version < 0 || version > QRSPEC_VERSION_MAX) { + //errno = EINVAL; + return -1; + } + + input->version = version; + + return 0; +} + +QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input) +{ + return input->level; +} + +int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level) +{ + if(input->mqr || level > QR_ECLEVEL_H) { + //errno = EINVAL; + return -1; + } + + input->level = level; + + return 0; +} + +int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level) +{ + if(input->mqr) { + if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID; + if((MQRspec_getECCLength(version, level) == 0)) goto INVALID; + } else { + if(version < 0 || version > QRSPEC_VERSION_MAX) goto INVALID; + if(level > QR_ECLEVEL_H) goto INVALID; + } + + input->version = version; + input->level = level; + + return 0; + +INVALID: + //errno = EINVAL; + return -1; +} + +static void QRinput_appendEntry(QRinput *input, QRinput_List *entry) +{ + if(input->tail == NULL) { + input->head = entry; + input->tail = entry; + } else { + input->tail->next = entry; + input->tail = entry; + } + entry->next = NULL; +} + +int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data) +{ + QRinput_List *entry; + + entry = QRinput_List_newEntry(mode, size, data); + if(entry == NULL) { + return -1; + } + + QRinput_appendEntry(input, entry); + + return 0; +} + +/** + * Insert a structured-append header to the head of the input data. + * @param input input data. + * @param size number of structured symbols. + * @param index index number of the symbol. (1 <= index <= size) + * @param parity parity among input data. (NOTE: each symbol of a set of structured symbols has the same parity data) + * @retval 0 success. + * @retval -1 error occurred and errno is set to indeicate the error. See Execptions for the details. + * @throw EINVAL invalid parameter. + * @throw ENOMEM unable to allocate memory. + */ +//__STATIC +int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity) +{ + QRinput_List *entry; + unsigned char buf[3]; + + if(size > MAX_STRUCTURED_SYMBOLS) { + //errno = EINVAL; + return -1; + } + if(index <= 0 || index > MAX_STRUCTURED_SYMBOLS) { + //errno = EINVAL; + return -1; + } + + buf[0] = (unsigned char)size; + buf[1] = (unsigned char)index; + buf[2] = parity; + entry = QRinput_List_newEntry(QR_MODE_STRUCTURE, 3, buf); + if(entry == NULL) { + return -1; + } + + entry->next = input->head; + input->head = entry; + + return 0; +} + +int QRinput_appendECIheader(QRinput *input, unsigned int ecinum) +{ + unsigned char data[4]; + + if(ecinum > 999999) { + //errno = EINVAL; + return -1; + } + + /* We manually create byte array of ecinum because + (unsigned char *)&ecinum may cause bus error on some architectures, */ + data[0] = ecinum & 0xff; + data[1] = (ecinum >> 8) & 0xff; + data[2] = (ecinum >> 16) & 0xff; + data[3] = (ecinum >> 24) & 0xff; + return QRinput_append(input, QR_MODE_ECI, 4, data); +} + +void QRinput_free(QRinput *input) +{ + QRinput_List *list, *next; + + if(input != NULL) { + list = input->head; + while(list != NULL) { + next = list->next; + QRinput_List_freeEntry(list); + list = next; + } + free(input); + } +} + +QRinput *QRinput_dup(QRinput *input) +{ + QRinput *n; + QRinput_List *list, *e; + + if(input->mqr) { + n = QRinput_newMQR(input->version, input->level); + } else { + n = QRinput_new2(input->version, input->level); + } + if(n == NULL) return NULL; + + list = input->head; + while(list != NULL) { + e = QRinput_List_dup(list); + if(e == NULL) { + QRinput_free(n); + return NULL; + } + QRinput_appendEntry(n, e); + list = list->next; + } + + return n; +} + +/****************************************************************************** + * Numeric data + *****************************************************************************/ + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeNum(int size, const char *data) +{ + int i; + + for(i=0; i '9') + return -1; + } + + return 0; +} + +/** + * Estimates the length of the encoded bit stream of numeric data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeNum(int size) +{ + int w; + int bits; + + w = size / 3; + bits = w * 10; + switch(size - w * 3) { + case 1: + bits += 4; + break; + case 2: + bits += 7; + break; + default: + break; + } + + return bits; +} + +/** + * Convert the number data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_encodeModeNum(QRinput_List *entry, int version, int mqr) +{ + int words, i, ret; + unsigned int val; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version > 1) { + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_NUM); + if(ret < 0) goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_NUM, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_NUM); + if(ret < 0) goto ABORT; + + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_NUM, version), entry->size); + if(ret < 0) goto ABORT; + } + + words = entry->size / 3; + for(i=0; idata[i*3 ] - '0') * 100; + val += (entry->data[i*3+1] - '0') * 10; + val += (entry->data[i*3+2] - '0'); + + ret = BitStream_appendNum(entry->bstream, 10, val); + if(ret < 0) goto ABORT; + } + + if(entry->size - words * 3 == 1) { + val = entry->data[words*3] - '0'; + ret = BitStream_appendNum(entry->bstream, 4, val); + if(ret < 0) goto ABORT; + } else if(entry->size - words * 3 == 2) { + val = (entry->data[words*3 ] - '0') * 10; + val += (entry->data[words*3+1] - '0'); + BitStream_appendNum(entry->bstream, 7, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Alphabet-numeric data ĸֵ + *****************************************************************************/ + +const signed char QRinput_anTable[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeAn(int size, const char *data) +{ + int i; + + for(i=0; ibstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 2) { + //errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_AN); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_AN, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_AN); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_AN, version), entry->size); + if(ret < 0) goto ABORT; + } + + words = entry->size / 2; + for(i=0; idata[i*2 ]) * 45; + val += (unsigned int)QRinput_lookAnTable(entry->data[i*2+1]); + + ret = BitStream_appendNum(entry->bstream, 11, val); + if(ret < 0) goto ABORT; + } + + if(entry->size & 1) { + val = (unsigned int)QRinput_lookAnTable(entry->data[words * 2]); + + ret = BitStream_appendNum(entry->bstream, 6, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * 8 bit data + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream of 8 bit data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsMode8(int size) +{ + return size * 8; +} + +/** + * Convert the 8bits data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_encodeMode8(QRinput_List *entry, int version, int mqr) +{ + int ret; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 3) { + //errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_8); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_8, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_8); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_8, version), entry->size); + if(ret < 0) goto ABORT; + } + + ret = BitStream_appendBytes(entry->bstream, entry->size, entry->data); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + + +/****************************************************************************** + * Kanji data + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream of kanji data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeKanji(int size) +{ + return (size / 2) * 13; +} + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeKanji(int size, const unsigned char *data) +{ + int i; + unsigned int val; + + if(size & 1) + return -1; + + for(i=0; i 0x9ffc && val < 0xe040) || val > 0xebbf) { + return -1; + } + } + + return 0; +} + +/** + * Convert the kanji data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid version. + */ +static int QRinput_encodeModeKanji(QRinput_List *entry, int version, int mqr) +{ + int ret, i; + unsigned int val, h; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 2) { + errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_KANJI); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_KANJI, version), entry->size/2); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_KANJI); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_KANJI, version), entry->size/2); + if(ret < 0) goto ABORT; + } + + for(i=0; isize; i+=2) { + val = ((unsigned int)entry->data[i] << 8) | entry->data[i+1]; + if(val <= 0x9ffc) { + val -= 0x8140; + } else { + val -= 0xc140; + } + h = (val >> 8) * 0xc0; + val = (val & 0xff) + h; + + ret = BitStream_appendNum(entry->bstream, 13, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Structured Symbol + *****************************************************************************/ + +/** + * Convert a structure symbol code to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid entry. + */ +static int QRinput_encodeModeStructure(QRinput_List *entry, int mqr) +{ + int ret; + + if(mqr) { + //errno = EINVAL; + return -1; + } + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_STRUCTURE); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 4, entry->data[1] - 1); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 4, entry->data[0] - 1); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 8, entry->data[2]); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * FNC1 + *****************************************************************************/ + +static int QRinput_checkModeFNC1Second(int size, const unsigned char *data) +{ + if(size != 1) return -1; + + return 0; +} + +static int QRinput_encodeModeFNC1Second(QRinput_List *entry, int version) +{ + int ret; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_FNC1SECOND); + if(ret < 0) goto ABORT; + + ret = BitStream_appendBytes(entry->bstream, 1, entry->data); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * ECI header + *****************************************************************************/ +static unsigned int QRinput_decodeECIfromByteArray(unsigned char *data) +{ + int i; + unsigned int ecinum; + + ecinum = 0; + for(i=0; i<4; i++) { + ecinum = ecinum << 8; + ecinum |= data[3-i]; + } + + return ecinum; +} + +int QRinput_estimateBitsModeECI(unsigned char *data) +{ + unsigned int ecinum; + + ecinum = QRinput_decodeECIfromByteArray(data);; + + /* See Table 4 of JISX 0510:2004 pp.17. */ + if(ecinum < 128) { + return MODE_INDICATOR_SIZE + 8; + } else if(ecinum < 16384) { + return MODE_INDICATOR_SIZE + 16; + } else { + return MODE_INDICATOR_SIZE + 24; + } +} + +static int QRinput_encodeModeECI(QRinput_List *entry, int version) +{ + int ret, words; + unsigned int ecinum, code; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ecinum = QRinput_decodeECIfromByteArray(entry->data);; + + /* See Table 4 of JISX 0510:2004 pp.17. */ + if(ecinum < 128) { + words = 1; + code = ecinum; + } else if(ecinum < 16384) { + words = 2; + code = 0x8000 + ecinum; + } else { + words = 3; + code = 0xc0000 + ecinum; + } + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_ECI); + if(ret < 0) goto ABORT; + + ret = BitStream_appendNum(entry->bstream, words * 8, code); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Validation֤ + *****************************************************************************/ + +int QRinput_check(QRencodeMode mode, int size, const unsigned char *data) +{ + if((mode == QR_MODE_FNC1FIRST && size < 0) || size <= 0) return -1; + + switch(mode) { + case QR_MODE_NUM: + return QRinput_checkModeNum(size, (const char *)data); + case QR_MODE_AN: + return QRinput_checkModeAn(size, (const char *)data); + case QR_MODE_KANJI: + return QRinput_checkModeKanji(size, data); + case QR_MODE_8: + return 0; + case QR_MODE_STRUCTURE: + return 0; + case QR_MODE_ECI: + return 0; + case QR_MODE_FNC1FIRST: + return 0; + case QR_MODE_FNC1SECOND: + return QRinput_checkModeFNC1Second(size, data); + case QR_MODE_NUL: + break; + } + + return -1; +} + +/****************************************************************************** + * Estimation of the bit length + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream on the current version. + * @param entry + * @param version version of the symbol + * @param mqr + * @return number of bits + */ +static int QRinput_estimateBitStreamSizeOfEntry(QRinput_List *entry, int version, int mqr) +{ + int bits = 0; + int l, m; + int num; + + if(version == 0) version = 1; + + switch(entry->mode) { + case QR_MODE_NUM: + bits = QRinput_estimateBitsModeNum(entry->size); + break; + case QR_MODE_AN: + bits = QRinput_estimateBitsModeAn(entry->size); + break; + case QR_MODE_8: + bits = QRinput_estimateBitsMode8(entry->size); + break; + case QR_MODE_KANJI: + bits = QRinput_estimateBitsModeKanji(entry->size); + break; + case QR_MODE_STRUCTURE: + return STRUCTURE_HEADER_SIZE; + case QR_MODE_ECI: + bits = QRinput_estimateBitsModeECI(entry->data); + break; + case QR_MODE_FNC1FIRST: + return MODE_INDICATOR_SIZE; + break; + case QR_MODE_FNC1SECOND: + return MODE_INDICATOR_SIZE + 8; + default: + return 0; + } + + if(mqr) { + l = QRspec_lengthIndicator(entry->mode, version); + m = version - 1; + bits += l + m; + } else { + l = QRspec_lengthIndicator(entry->mode, version); + m = 1 << l; + num = (entry->size + m - 1) / m; + + bits += num * (MODE_INDICATOR_SIZE + l); + } + + return bits; +} + +/** + * Estimates the length of the encoded bit stream of the data. + * @param input input data + * @param version version of the symbol + * @return number of bits + */ +//__STATIC +int QRinput_estimateBitStreamSize(QRinput *input, int version) +{ + QRinput_List *list; + int bits = 0; + + list = input->head; + while(list != NULL) { + bits += QRinput_estimateBitStreamSizeOfEntry(list, version, input->mqr); + list = list->next; + } + + return bits; +} + +/** + * Estimates the required version number of the symbol. + * @param input input data + * @return required version number + */ +static int QRinput_estimateVersion(QRinput *input) +{ + int bits; + int version, prev; + + version = 0; + do { + prev = version; + bits = QRinput_estimateBitStreamSize(input, prev); + version = QRspec_getMinimumVersion((bits + 7) / 8, input->level); + if (version < 0) { + return -1; + } + } while (version > prev); + + return version; +} + +/** + * Returns required length in bytes for specified mode, version and bits. + * @param mode + * @param version + * @param bits + * @return required length of code words in bytes. + */ +//__STATIC +int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits) +{ + int payload, size, chunks, remain, maxsize; + + payload = bits - 4 - QRspec_lengthIndicator(mode, version); + switch(mode) { + case QR_MODE_NUM: + chunks = payload / 10; + remain = payload - chunks * 10; + size = chunks * 3; + if(remain >= 7) { + size += 2; + } else if(remain >= 4) { + size += 1; + } + break; + case QR_MODE_AN: + chunks = payload / 11; + remain = payload - chunks * 11; + size = chunks * 2; + if(remain >= 6) size++; + break; + case QR_MODE_8: + size = payload / 8; + break; + case QR_MODE_KANJI: + size = (payload / 13) * 2; + break; + case QR_MODE_STRUCTURE: + size = payload / 8; + break; + default: + size = 0; + break; + } + maxsize = QRspec_maximumWords(mode, version); + if(size < 0) size = 0; + if(maxsize > 0 && size > maxsize) size = maxsize; + + return size; +} + +/****************************************************************************** + * Data conversion ת + *****************************************************************************/ + +/** + * Convert the input data in the data chunk to a bit stream. + * @param entry + * @return number of bits (>0) or -1 for failure. + */ +static int QRinput_encodeBitStream(QRinput_List *entry, int version, int mqr) +{ + int words, ret; + QRinput_List *st1 = NULL, *st2 = NULL; + + if(entry->bstream != NULL) { + BitStream_free(entry->bstream); + entry->bstream = NULL; + } + + words = QRspec_maximumWords(entry->mode, version); + if(words != 0 && entry->size > words) { + st1 = QRinput_List_newEntry(entry->mode, words, entry->data); + if(st1 == NULL) goto ABORT; + st2 = QRinput_List_newEntry(entry->mode, entry->size - words, &entry->data[words]); + if(st2 == NULL) goto ABORT; + + ret = QRinput_encodeBitStream(st1, version, mqr); + if(ret < 0) goto ABORT; + ret = QRinput_encodeBitStream(st2, version, mqr); + if(ret < 0) goto ABORT; + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) goto ABORT; + ret = BitStream_append(entry->bstream, st1->bstream); + if(ret < 0) goto ABORT; + ret = BitStream_append(entry->bstream, st2->bstream); + if(ret < 0) goto ABORT; + QRinput_List_freeEntry(st1); + QRinput_List_freeEntry(st2); + } else { + ret = 0; + switch(entry->mode) { + case QR_MODE_NUM: + ret = QRinput_encodeModeNum(entry, version, mqr); + break; + case QR_MODE_AN: + ret = QRinput_encodeModeAn(entry, version, mqr); + break; + case QR_MODE_8: + ret = QRinput_encodeMode8(entry, version, mqr); + break; + case QR_MODE_KANJI: + ret = QRinput_encodeModeKanji(entry, version, mqr); + break; + case QR_MODE_STRUCTURE: + ret = QRinput_encodeModeStructure(entry, mqr); + break; + case QR_MODE_ECI: + ret = QRinput_encodeModeECI(entry, version); + break; + case QR_MODE_FNC1SECOND: + ret = QRinput_encodeModeFNC1Second(entry, version); + default: + break; + } + if(ret < 0) return -1; + } + + return BitStream_size(entry->bstream); +ABORT: + QRinput_List_freeEntry(st1); + QRinput_List_freeEntry(st2); + return -1; +} + +/** + * Convert the input data to a bit stream. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_createBitStream(QRinput *input) +{ + QRinput_List *list; + int bits, total = 0; + + list = input->head; + while(list != NULL) { + bits = QRinput_encodeBitStream(list, input->version, input->mqr); + if(bits < 0) return -1; + total += bits; + list = list->next; + } + + return total; +} + +/** + * Convert the input data to a bit stream. + * When the version number is given and that is not sufficient, it is increased + * automatically. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw ERANGE input is too large. + */ +static int QRinput_convertData(QRinput *input) +{ + int bits; + int ver; + + ver = QRinput_estimateVersion(input); + if(ver > QRinput_getVersion(input)) { + QRinput_setVersion(input, ver); + } + + for(;;) { + bits = QRinput_createBitStream(input); + if(bits < 0) return -1; + ver = QRspec_getMinimumVersion((bits + 7) / 8, input->level); + if(ver < 0) { + //errno = ERANGE; + return -1; + } else if(ver > QRinput_getVersion(input)) { + QRinput_setVersion(input, ver); + } else { + break; + } + } + + return 0; +} + +/** + * Append padding bits for the input data. + * @param bstream Bitstream to be appended. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ERANGE input data is too large. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_appendPaddingBit(BitStream *bstream, QRinput *input) +{ + int bits, maxbits, words, maxwords, i, ret; + BitStream *padding = NULL; + unsigned char *padbuf; + int padlen; + + bits = BitStream_size(bstream); + maxwords = QRspec_getDataLength(input->version, input->level); + maxbits = maxwords * 8; + + if(maxbits < bits) { + //errno = ERANGE; + return -1; + } + if(maxbits == bits) { + return 0; + } + + if(maxbits - bits <= 4) { + ret = BitStream_appendNum(bstream, maxbits - bits, 0); + goto DONE; + } + + words = (bits + 4 + 7) / 8; + + padding = BitStream_new(); + if(padding == NULL) return -1; + ret = BitStream_appendNum(padding, words * 8 - bits, 0); + if(ret < 0) goto DONE; + + padlen = maxwords - words; + if(padlen > 0) { + padbuf = (unsigned char *)malloc(padlen); + if(padbuf == NULL) { + ret = -1; + goto DONE; + } + for(i=0; iversion, input->level); + maxwords = maxbits / 8; + + if(maxbits < bits) { + //errno = ERANGE; + return -1; + } + if(maxbits == bits) { + return 0; + } + + termbits = input->version * 2 + 1; + + if(maxbits - bits <= termbits) { + ret = BitStream_appendNum(bstream, maxbits - bits, 0); + goto DONE; + } + + bits += termbits; + + words = (bits + 7) / 8; + if(maxbits - words * 8 > 0) { + termbits += words * 8 - bits; + if(words == maxwords) termbits += maxbits - words * 8; + } else { + termbits += words * 8 - bits; + } + padding = BitStream_new(); + if(padding == NULL) return -1; + ret = BitStream_appendNum(padding, termbits, 0); + if(ret < 0) goto DONE; + + padlen = maxwords - words; + if(padlen > 0) { + padbuf = (unsigned char *)malloc(padlen); + if(padbuf == NULL) { + ret = -1; + goto DONE; + } + for(i=0; i 0) { + ret = BitStream_appendNum(padding, termbits, 0); + if(ret < 0) goto DONE; + } + } + + ret = BitStream_append(bstream, padding); + +DONE: + BitStream_free(padding); + return ret; +} + +static int QRinput_insertFNC1Header(QRinput *input) +{ + QRinput_List *entry = NULL; + + if(input->fnc1 == 1) { + entry = QRinput_List_newEntry(QR_MODE_FNC1FIRST, 0, NULL); + } else if(input->fnc1 == 2) { + entry = QRinput_List_newEntry(QR_MODE_FNC1SECOND, 1, &(input->appid)); + } + if(entry == NULL) { + return -1; + } + + if(input->head->mode != QR_MODE_STRUCTURE || input->head->mode != QR_MODE_ECI) { + entry->next = input->head; + input->head = entry; + } else { + entry->next = input->head->next; + input->head->next = entry; + } + + return 0; +} + +/** + * Merge all bit streams in the input data. + * @param input input data. + * @return merged bit stream + */ + +//__STATIC +BitStream *QRinput_mergeBitStream(QRinput *input) +{ + BitStream *bstream; + QRinput_List *list; + int ret; + + if(input->mqr) { + if(QRinput_createBitStream(input) < 0) { + return NULL; + } + } else { + if(input->fnc1) { + if(QRinput_insertFNC1Header(input) < 0) { + return NULL; + } + } + if(QRinput_convertData(input) < 0) { + return NULL; + } + } + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + list = input->head; + while(list != NULL) { + ret = BitStream_append(bstream, list->bstream); + if(ret < 0) { + BitStream_free(bstream); + return NULL; + } + list = list->next; + } + + return bstream; +} + +/** + * Merge all bit streams in the input data and append padding bits + * @param input input data. + * @return padded merged bit stream + */ + +//__STATIC +BitStream *QRinput_getBitStream(QRinput *input) +{ + BitStream *bstream; + int ret; + + bstream = QRinput_mergeBitStream(input); + if(bstream == NULL) { + return NULL; + } + if(input->mqr) { + ret = QRinput_appendPaddingBitMQR(bstream, input); + } else { + ret = QRinput_appendPaddingBit(bstream, input); + } + if(ret < 0) { + BitStream_free(bstream); + return NULL; + } + + return bstream; +} + +/** + * Pack all bit streams padding bits into a byte array. + * @param input input data. + * @return padded merged byte stream + */ + +unsigned char *QRinput_getByteStream(QRinput *input) +{ + BitStream *bstream; + unsigned char *array; + + bstream = QRinput_getBitStream(input); + if(bstream == NULL) { + return NULL; + } + array = BitStream_toByte(bstream); + BitStream_free(bstream); + + return array; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/Qrcode/src/qrspec.c b/code/application/sifarsdk/component/Qrcode/src/qrspec.c new file mode 100644 index 000000000..85f602487 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/qrspec.c @@ -0,0 +1,573 @@ +/* + * qrencode - QR Code encoder + * + * QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#ifdef HAVE_LIBPTHREAD +#include +#endif + +#include "qrspec.h" +#include "qrinput.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +typedef struct { + int width; //< Edge length of the symbol + int words; //< Data capacity (bytes) + int remainder; //< Remainder bit (bits) + int ec[4]; //< Number of ECC code (bytes) +} QRspec_Capacity; + +/** + * Table of the capacity of symbols + * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004. + */ +static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = { + { 0, 0, 0, { 0, 0, 0, 0}}, + { 21, 26, 0, { 7, 10, 13, 17}}, // 1 + { 25, 44, 7, { 10, 16, 22, 28}}, + { 29, 70, 7, { 15, 26, 36, 44}}, + { 33, 100, 7, { 20, 36, 52, 64}}, + { 37, 134, 7, { 26, 48, 72, 88}}, // 5 + { 41, 172, 7, { 36, 64, 96, 112}}, + { 45, 196, 0, { 40, 72, 108, 130}}, + { 49, 242, 0, { 48, 88, 132, 156}}, + { 53, 292, 0, { 60, 110, 160, 192}}, + { 57, 346, 0, { 72, 130, 192, 224}}, //10 + { 61, 404, 0, { 80, 150, 224, 264}}, + { 65, 466, 0, { 96, 176, 260, 308}}, + { 69, 532, 0, { 104, 198, 288, 352}}, + { 73, 581, 3, { 120, 216, 320, 384}}, + { 77, 655, 3, { 132, 240, 360, 432}}, //15 + { 81, 733, 3, { 144, 280, 408, 480}}, + { 85, 815, 3, { 168, 308, 448, 532}}, + { 89, 901, 3, { 180, 338, 504, 588}}, + { 93, 991, 3, { 196, 364, 546, 650}}, + { 97, 1085, 3, { 224, 416, 600, 700}}, //20 + {101, 1156, 4, { 224, 442, 644, 750}}, + {105, 1258, 4, { 252, 476, 690, 816}}, + {109, 1364, 4, { 270, 504, 750, 900}}, + {113, 1474, 4, { 300, 560, 810, 960}}, + {117, 1588, 4, { 312, 588, 870, 1050}}, //25 + {121, 1706, 4, { 336, 644, 952, 1110}}, + {125, 1828, 4, { 360, 700, 1020, 1200}}, + {129, 1921, 3, { 390, 728, 1050, 1260}}, + {133, 2051, 3, { 420, 784, 1140, 1350}}, + {137, 2185, 3, { 450, 812, 1200, 1440}}, //30 + {141, 2323, 3, { 480, 868, 1290, 1530}}, + {145, 2465, 3, { 510, 924, 1350, 1620}}, + {149, 2611, 3, { 540, 980, 1440, 1710}}, + {153, 2761, 3, { 570, 1036, 1530, 1800}}, + {157, 2876, 0, { 570, 1064, 1590, 1890}}, //35 + {161, 3034, 0, { 600, 1120, 1680, 1980}}, + {165, 3196, 0, { 630, 1204, 1770, 2100}}, + {169, 3362, 0, { 660, 1260, 1860, 2220}}, + {173, 3532, 0, { 720, 1316, 1950, 2310}}, + {177, 3706, 0, { 750, 1372, 2040, 2430}} //40 +}; + +int QRspec_getDataLength(int version, QRecLevel level) +{ + return qrspecCapacity[version].words - qrspecCapacity[version].ec[level]; +} + +int QRspec_getECCLength(int version, QRecLevel level) +{ + return qrspecCapacity[version].ec[level]; +} + +int QRspec_getMinimumVersion(int size, QRecLevel level) +{ + int i; + int words; + + for(i=1; i<= QRSPEC_VERSION_MAX; i++) { + words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level]; + if(words >= size) return i; + } + + return -1; +} + +int QRspec_getWidth(int version) +{ + return qrspecCapacity[version].width; +} + +int QRspec_getRemainder(int version) +{ + return qrspecCapacity[version].remainder; +} + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +static const int lengthTableBits[4][3] = { + {10, 12, 14}, + { 9, 11, 13}, + { 8, 16, 16}, + { 8, 10, 12} +}; + +int QRspec_lengthIndicator(QRencodeMode mode, int version) +{ + int l; + + if(!QRinput_isSplittableMode(mode)) return 0; + if(version <= 9) { + l = 0; + } else if(version <= 26) { + l = 1; + } else { + l = 2; + } + + return lengthTableBits[mode][l]; +} + +int QRspec_maximumWords(QRencodeMode mode, int version) +{ + int l; + int bits; + int words; + + if(!QRinput_isSplittableMode(mode)) return 0; + if(version <= 9) { + l = 0; + } else if(version <= 26) { + l = 1; + } else { + l = 2; + } + + bits = lengthTableBits[mode][l]; + words = (1 << bits) - 1; + if(mode == QR_MODE_KANJI) { + words *= 2; // the number of bytes is required + } + + return words; +} + +/****************************************************************************** + * Error correction code + *****************************************************************************/ + +/** + * Table of the error correction code (Reed-Solomon block) + * See Table 12-16 (pp.30-36), JIS X0510:2004. + */ +static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = { + {{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}, + {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1 + {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, + {{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}}, + {{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}}, + {{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5 + {{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}}, + {{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}}, + {{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}}, + {{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}}, + {{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10 + {{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}}, + {{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}}, + {{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}}, + {{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}}, + {{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15 + {{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}}, + {{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}}, + {{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}}, + {{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}}, + {{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20 + {{ 4, 4}, {17, 0}, {17, 6}, {19, 6}}, + {{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}}, + {{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}}, + {{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}}, + {{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25 + {{10, 2}, {19, 4}, {28, 6}, {33, 4}}, + {{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}}, + {{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}}, + {{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}}, + {{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30 + {{13, 3}, { 2, 29}, {42, 1}, {23, 28}}, + {{17, 0}, {10, 23}, {10, 35}, {19, 35}}, + {{17, 1}, {14, 21}, {29, 19}, {11, 46}}, + {{13, 6}, {14, 23}, {44, 7}, {59, 1}}, + {{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35 + {{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}}, + {{17, 4}, {29, 14}, {49, 10}, {24, 46}}, + {{ 4, 18}, {13, 32}, {48, 14}, {42, 32}}, + {{20, 4}, {40, 7}, {43, 22}, {10, 67}}, + {{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40 +}; + +void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]) +{ + int b1, b2; + int data, ecc; + + b1 = eccTable[version][level][0]; + b2 = eccTable[version][level][1]; + data = QRspec_getDataLength(version, level); + ecc = QRspec_getECCLength(version, level); + + if(b2 == 0) { + spec[0] = b1; + spec[1] = data / b1; + spec[2] = ecc / b1; + spec[3] = spec[4] = 0; + } else { + spec[0] = b1; + spec[1] = data / (b1 + b2); + spec[2] = ecc / (b1 + b2); + spec[3] = b2; + spec[4] = spec[1] + 1; + } +} + +/****************************************************************************** + * Alignment pattern + *****************************************************************************/ + +/** + * Positions of alignment patterns. + * This array includes only the second and the third position of the alignment + * patterns. Rest of them can be calculated from the distance between them. + * + * See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + */ +static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = { + { 0, 0}, + { 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5 + {34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10 + {30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15 + {26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20 + {28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25 + {30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30 + {30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35 + {24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40 +}; + +/** + * Put an alignment marker. + * @param frame + * @param width + * @param ox,oy center coordinate of the pattern + */ +static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa1, 0xa0, 0xa1, 0xa0, 0xa1, + 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + }; + int x, y; + const unsigned char *s; + + frame += (oy - 2) * width + ox - 2; + s = finder; + for(y=0; y<5; y++) { + for(x=0; x<5; x++) { + frame[x] = s[x]; + } + frame += width; + s += 5; + } +} + +static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width) +{ + int d, w, x, y, cx, cy; + + if(version < 2) return; + + d = alignmentPattern[version][1] - alignmentPattern[version][0]; + if(d < 0) { + w = 2; + } else { + w = (width - alignmentPattern[version][0]) / d + 2; + } + + if(w * w - 3 == 1) { + x = alignmentPattern[version][0]; + y = alignmentPattern[version][0]; + QRspec_putAlignmentMarker(frame, width, x, y); + return; + } + + cx = alignmentPattern[version][0]; + for(x=1; x QRSPEC_VERSION_MAX) return 0; + + return versionPattern[version - 7]; +} + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/* See calcFormatInfo in tests/test_qrspec.c */ +static const unsigned int formatInfo[4][8] = { + {0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976}, + {0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0}, + {0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed}, + {0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b} +}; + +unsigned int QRspec_getFormatInfo(int mask, QRecLevel level) +{ + if(mask < 0 || mask > 7) return 0; + + return formatInfo[level][mask]; +} + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Cache of initial frames. + */ +/* C99 says that static storage shall be initialized to a null pointer + * by compiler. */ +static unsigned char *frames[QRSPEC_VERSION_MAX + 1]; +#ifdef HAVE_LIBPTHREAD +static pthread_mutex_t frames_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/** + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ +static void putFinderPattern(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + }; + int x, y; + const unsigned char *s; + + frame += oy * width + ox; + s = finder; + for(y=0; y<7; y++) { + for(x=0; x<7; x++) { + frame[x] = s[x]; + } + frame += width; + s += 7; + } +} + + +static unsigned char *QRspec_createFrame(int version) +{ + unsigned char *frame, *p, *q; + int width; + int x, y; + unsigned int verinfo, v; + + width = qrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + + memset(frame, 0, width * width); + /* Finder pattern */ + putFinderPattern(frame, width, 0, 0); + putFinderPattern(frame, width, width - 7, 0); + putFinderPattern(frame, width, 0, width - 7); + /* Separator */ + p = frame; + q = frame + width * (width - 7); + for(y=0; y<7; y++) { + p[7] = 0xc0; + p[width - 8] = 0xc0; + q[7] = 0xc0; + p += width; + q += width; + } + memset(frame + width * 7, 0xc0, 8); + memset(frame + width * 8 - 8, 0xc0, 8); + memset(frame + width * (width - 8), 0xc0, 8); + /* Mask format information area */ + memset(frame + width * 8, 0x84, 9); + memset(frame + width * 9 - 8, 0x84, 8); + p = frame + 8; + for(y=0; y<8; y++) { + *p = 0x84; + p += width; + } + p = frame + width * (width - 7) + 8; + for(y=0; y<7; y++) { + *p = 0x84; + p += width; + } + /* Timing pattern */ + p = frame + width * 6 + 8; + q = frame + width * 8 + 6; + for(x=1; x= 7) { + verinfo = QRspec_getVersionPattern(version); + + p = frame + width * (width - 11); + v = verinfo; + for(x=0; x<6; x++) { + for(y=0; y<3; y++) { + p[width * y + x] = 0x88 | (v & 1); + v = v >> 1; + } + } + + p = frame + width - 11; + v = verinfo; + for(y=0; y<6; y++) { + for(x=0; x<3; x++) { + p[x] = 0x88 | (v & 1); + v = v >> 1; + } + p += width; + } + } + /* and a little bit... */ + frame[width * (width - 8) + 8] = 0x81; + + return frame; +} + +unsigned char *QRspec_newFrame(int version) +{ + unsigned char *frame; + int width; + + if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + if(frames[version] == NULL) { + frames[version] = QRspec_createFrame(version); + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif + if(frames[version] == NULL) return NULL; + + width = qrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + memcpy(frame, frames[version], width * width); + + return frame; +} + +void QRspec_clearCache(void) +{ + int i; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + for(i=1; i<=QRSPEC_VERSION_MAX; i++) { + free(frames[i]); + frames[i] = NULL; + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/Qrcode/src/rscode.c b/code/application/sifarsdk/component/Qrcode/src/rscode.c new file mode 100644 index 000000000..5e677065a --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/rscode.c @@ -0,0 +1,340 @@ +/* + * qrencode - QR Code encoder + * + * Reed solomon encoder. This code is taken from Phil Karn's libfec then + * editted and packed into a pair of .c and .h files. + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * (libfec is released under the GNU Lesser General Public License.) + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#ifdef HAVE_LIBPTHREAD +# include +#endif + + +#include "rscode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* Stuff specific to the 8-bit symbol version of the general purpose RS codecs + * + */ +typedef unsigned char data_t; + + +/** + * Reed-Solomon codec control block + */ +struct _RS { + int mm; /* Bits per symbol */ + int nn; /* Symbols per block (= (1<= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} + + +#define MODNN(x) modnn(rs,x) + +#define MM (rs->mm) +#define NN (rs->nn) +#define ALPHA_TO (rs->alpha_to) +#define INDEX_OF (rs->index_of) +#define GENPOLY (rs->genpoly) +#define NROOTS (rs->nroots) +#define FCR (rs->fcr) +#define PRIM (rs->prim) +#define IPRIM (rs->iprim) +#define PAD (rs->pad) +#define A0 (NN) + + +/* Initialize a Reed-Solomon codec + * symsize = symbol size, bits + * gfpoly = Field generator polynomial coefficients + * fcr = first root of RS code generator polynomial, index form + * prim = primitive element to generate polynomial roots + * nroots = RS code generator polynomial degree (number of roots) + * pad = padding bytes at front of shortened block + */ +static RS *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) +{ + RS *rs; + + +/* Common code for intializing a Reed-Solomon control block (char or int symbols) + * Copyright 2004 Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + */ +//#undef NULL +//#define NULL ((void *)0) + + int i, j, sr,root,iprim; + + rs = NULL; + /* Check parameter ranges */ + if(symsize < 0 || symsize > (int)(8*sizeof(data_t))){ + goto done; + } + + if(fcr < 0 || fcr >= (1<= (1<= (1<= ((1<mm = symsize; + rs->nn = (1<pad = pad; + + rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); + if(rs->alpha_to == NULL){ + free(rs); + rs = NULL; + goto done; + } + rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); + if(rs->index_of == NULL){ + free(rs->alpha_to); + free(rs); + rs = NULL; + goto done; + } + + /* Generate Galois field lookup tables */ + rs->index_of[0] = A0; /* log(zero) = -inf */ + rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ + sr = 1; + for(i=0;inn;i++){ + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if(sr & (1<nn; + } + if(sr != 1){ + /* field generator polynomial is not primitive! */ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + rs = NULL; + goto done; + } + + /* Form RS code generator polynomial from its roots */ + rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1)); + if(rs->genpoly == NULL){ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + rs = NULL; + goto done; + } + rs->fcr = fcr; + rs->prim = prim; + rs->nroots = nroots; + rs->gfpoly = gfpoly; + + /* Find prim-th root of 1, used in decoding */ + for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) + ; + rs->iprim = iprim / prim; + + rs->genpoly[0] = 1; + for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { + rs->genpoly[i+1] = 1; + + /* Multiply rs->genpoly[] by @**(root + x) */ + for (j = i; j > 0; j--){ + if (rs->genpoly[j] != 0) + rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; + else + rs->genpoly[j] = rs->genpoly[j-1]; + } + /* rs->genpoly[0] can never be zero */ + rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; + } + /* convert rs->genpoly[] to index form for quicker encoding */ + for (i = 0; i <= nroots; i++) + rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; + done:; + + return rs; +} + +RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) +{ + RS *rs; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&rslist_mutex); +#endif + for(rs = rslist; rs != NULL; rs = rs->next) { + if(rs->pad != pad) continue; + if(rs->nroots != nroots) continue; + if(rs->mm != symsize) continue; + if(rs->gfpoly != gfpoly) continue; + if(rs->fcr != fcr) continue; + if(rs->prim != prim) continue; + + goto DONE; + } + + rs = init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad); + if(rs == NULL) goto DONE; + rs->next = rslist; + rslist = rs; + +DONE: +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&rslist_mutex); +#endif + return rs; +} + + +void free_rs_char(RS *rs) +{ + free(rs->alpha_to); + free(rs->index_of); + free(rs->genpoly); + free(rs); +} + +void free_rs_cache(void) +{ + RS *rs, *next; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&rslist_mutex); +#endif + rs = rslist; + while(rs != NULL) { + next = rs->next; + free_rs_char(rs); + rs = next; + } + rslist = NULL; +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&rslist_mutex); +#endif +} + +/* The guts of the Reed-Solomon encoder, meant to be #included + * into a function body with the following typedefs, macros and variables supplied + * according to the code parameters: + + * data_t - a typedef for the data symbol + * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded + * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols + * NROOTS - the number of roots in the RS code generator polynomial, + * which is the same as the number of parity symbols in a block. + Integer variable or literal. + * + * NN - the total number of symbols in a RS block. Integer variable or literal. + * PAD - the number of pad symbols in a block. Integer variable or literal. + * ALPHA_TO - The address of an array of NN elements to convert Galois field + * elements in index (log) form to polynomial form. Read only. + * INDEX_OF - The address of an array of NN elements to convert Galois field + * elements in polynomial form to index (log) form. Read only. + * MODNN - a function to reduce its argument modulo NN. May be inline or a macro. + * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form + + * The memset() and memmove() functions are used. The appropriate header + * file declaring these functions (usually ) must be included by the calling + * program. + + * Copyright 2004, Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + */ + +#undef A0 +#define A0 (NN) /* Special reserved value encoding zero in index form */ + +void encode_rs_char(RS *rs, const data_t *data, data_t *parity) +{ + int i, j; + data_t feedback; + + memset(parity,0,NROOTS*sizeof(data_t));/*sָijһڴеǰn ֽڵȫΪchָASCIIֵ һֵΪָڴַĴСɵָͨΪڴʼ ䷵ֵΪָsָ롣*/ + + for(i=0;i +#include +#include +#include "sf_bmp.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef unsigned char U1; +typedef unsigned short U2; +typedef unsigned long U4; + +typedef unsigned char BOOL; +#define TRUE (0xFFu) +#define FALSE (0x00u) + + + +void vd_SerializeLittleEndianU2(U1 * u1_ap_serial, U2 u2_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u2_a_value; + u1_ap_serial[1] = (U1)(u2_a_value >> 8); + } while(FALSE); +} + +void vd_SerializeLittleEndianU3(U1 * u1_ap_serial, U4 u4_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u4_a_value; + u1_ap_serial[1] = (U1)(u4_a_value >> 8); + u1_ap_serial[2] = (U1)(u4_a_value >> 16); + } while(FALSE); +} + +void vd_SerializeLittleEndianU4(U1 * u1_ap_serial, U4 u4_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u4_a_value; + u1_ap_serial[1] = (U1)(u4_a_value >> 8); + u1_ap_serial[2] = (U1)(u4_a_value >> 16); + u1_ap_serial[3] = (U1)(u4_a_value >> 24); + } while(FALSE); +} + +// AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB +// 76543210765432107654321076543210 +#define BMP_RGBA32(r,g,b,a) (U4)( ((U4)(U1)(r)<<16) | ((U4)(U1)(g)<<8) | (U4)(U1)(b) | ((U4)(U1)(a)<<24) ) +#define BMP_RGB24(r,g,b) (U4)( ((U4)(U1)(r)<<16) | ((U4)(U1)(g)<<8) | (U4)(U1)(b) ) + +// XRRRRRGGGGGBBBBB +// 0432104321043210 +#define BMP_RGBA32TOBMP16(c) (U2)( (((U4)(c)>>9) & 0x7C00u) | (((U4)(c)>>6) & 0x03E0u) | (((U4)(c)>>3) & 0x001F) ) + + +typedef struct { + U4 u4_image_width; + U4 u4_image_height; + U4 u4_widthbyte; + U4 u4_image_size; + U2 u2_bitcount; + U2 u2_palette_size; + U1* u1_p_image_data; +} ST_BITMAP; + +ST_BITMAP * st_g_CreateBitmap(U4 u4_a_width, U4 u4_a_height, U2 u2_a_bitcount) +{ + ST_BITMAP * st_tp_bitmap = NULL; + U4 u4_t_widthbyte = 0; + U4 u4_t_imagesize = 0; + + do + { + if((u4_a_width == 0) || (u4_a_width > 4096)) + break; + + if((u4_a_height == 0) || (u4_a_height > 4096)) + break; + + if((u2_a_bitcount != 16) && (u2_a_bitcount != 24) && (u2_a_bitcount != 32)) + break; + + // 4-byte aligned bytes for a line of image data + u4_t_widthbyte = (u4_a_width * u2_a_bitcount + 31) / 32 * 4; + u4_t_imagesize = (u4_t_widthbyte * u4_a_height); + + st_tp_bitmap = malloc(sizeof(ST_BITMAP) + u4_t_imagesize); // alloc together + if(st_tp_bitmap == NULL) + break; + + memset(st_tp_bitmap, 0, sizeof(ST_BITMAP) + u4_t_imagesize); + + st_tp_bitmap->u4_image_width = u4_a_width; + st_tp_bitmap->u4_image_height = u4_a_height; + st_tp_bitmap->u4_widthbyte = u4_t_widthbyte; + st_tp_bitmap->u4_image_size = u4_t_imagesize; + st_tp_bitmap->u2_bitcount = u2_a_bitcount; + st_tp_bitmap->u2_palette_size = 0; + // pointer to the address next to the struct + st_tp_bitmap->u1_p_image_data = (U1 *)st_tp_bitmap + sizeof(ST_BITMAP); + + } while(FALSE); + + return st_tp_bitmap; +} + +void vd_g_FreeBitmap(ST_BITMAP * st_ap_bitmap) +{ + + do + { + if(st_ap_bitmap == NULL) + break; + + memset(st_ap_bitmap, 0, sizeof(ST_BITMAP)); + free(st_ap_bitmap); + + } while(FALSE); +} + +void vd_g_SaveBitmap(const ST_BITMAP * st_ap_bitmap, const char * sz_ap_path) +{ + + U1 u1_tp_bitmap_header[] = + { + 0x42, 0x4D, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, // 2 AA->FileSize + 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0x28, 0x00, // 10 BB->OffBits + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, // 18 CC->Width + 0xDD, 0xDD, 0x01, 0x00, 0xEE, 0xEE, 0x00, 0x00, // 22 DD->Height + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, // 28 EE->BitCount + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 34 FF->ImageSize + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + FILE *file_bitmap = NULL; + + U4 u4_t_y; + U4 u4_t_pixel_offset = 0; + + do + { + if(st_ap_bitmap == NULL) + break; + + if((st_ap_bitmap->u2_bitcount != 16) && (st_ap_bitmap->u2_bitcount != 24) && (st_ap_bitmap->u2_bitcount != 32)) + break; + + if(sz_ap_path == NULL) + break; + + file_bitmap = fopen(sz_ap_path, "wb"); + if(file_bitmap == NULL) + break; + + // set bitmap head info + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[2], sizeof(u1_tp_bitmap_header) + st_ap_bitmap->u4_image_size); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[10], sizeof(u1_tp_bitmap_header)); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[18], st_ap_bitmap->u4_image_width); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[22], st_ap_bitmap->u4_image_height); + vd_SerializeLittleEndianU2(&u1_tp_bitmap_header[28], st_ap_bitmap->u2_bitcount); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[34], st_ap_bitmap->u4_image_size); + + // write bitmap file head + fwrite(u1_tp_bitmap_header, sizeof(u1_tp_bitmap_header), 1L, file_bitmap); + + // write bitmap image data, bottom to top + u4_t_pixel_offset = st_ap_bitmap->u4_image_height * st_ap_bitmap->u4_widthbyte; + for(u4_t_y = 0; u4_t_y < st_ap_bitmap->u4_image_height; u4_t_y++) + { + u4_t_pixel_offset -= st_ap_bitmap->u4_widthbyte; + fwrite(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], st_ap_bitmap->u4_widthbyte, 1L, file_bitmap); + } + + + } while(0); + + if(file_bitmap) + fclose(file_bitmap); +} + +void vd_SetBitmapPixel(ST_BITMAP * st_ap_bitmap, U4 u4_a_x, U4 u4_a_y, U4 u4_a_color) +{ + U4 u4_t_pixel_offset = 0; + U2 u2_t_color = 0; + + do + { + + if(st_ap_bitmap == NULL) + break; + + if(u4_a_x >= st_ap_bitmap->u4_image_width) + break; + + if(u4_a_y >= st_ap_bitmap->u4_image_height) + break; + + u4_t_pixel_offset = u4_a_y * st_ap_bitmap->u4_widthbyte + u4_a_x * st_ap_bitmap->u2_bitcount / 8; + + switch(st_ap_bitmap->u2_bitcount) + { + case 16: + u2_t_color = BMP_RGBA32TOBMP16(u4_a_color); + vd_SerializeLittleEndianU2(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u2_t_color); + break; + case 24: + vd_SerializeLittleEndianU3(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u4_a_color); + break; + case 32: + vd_SerializeLittleEndianU4(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u4_a_color); + break; + default: + break; + } + } while(FALSE); +} + +int sf_qrcode_bmpfile_write(QRcode *DataInfo, const char *outfile, int magnification) +{ + ST_BITMAP * st_tp_bitmap = NULL; + int width = 0; + int height = 0; + int w = 0; + int i = 0; + int j = 0; + int x = 0; + int y = 0; + unsigned char *p = NULL; + + width = DataInfo->width * magnification; + height = DataInfo->width * magnification; + do + { + // create bitmap, size:20x10 format:RGB555->16 + // also support format RGB888->24 and RGBA8888->32 + st_tp_bitmap = st_g_CreateBitmap(width, height, 16); + if(st_tp_bitmap == NULL) + break; + + // draw pixels on bitmap + p = DataInfo->data; + for(y = 0; y < DataInfo->width; y++) + { + w = 0; + for(x = 0; x < DataInfo->width; x++) + { + for(i = 0; i < magnification; i++) + { + if (((*p) & (1)) == 1) + { + for(j = 0; j < magnification; j++) + { + vd_SetBitmapPixel(st_tp_bitmap, w, magnification*y + j, BMP_RGB24(0, 0, 0)); //white + } + } + else + { + for(j = 0; j < magnification; j++) + { + vd_SetBitmapPixel(st_tp_bitmap, w, magnification*y + j, BMP_RGB24(255, 255, 255)); //white + } + } + w++; + } + p++; + } + } + + // save to file + vd_g_SaveBitmap(st_tp_bitmap, outfile); + } while(FALSE); + + if(st_tp_bitmap) + vd_g_FreeBitmap(st_tp_bitmap); + + return 0; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/Qrcode/src/sf_qrcode.c b/code/application/sifarsdk/component/Qrcode/src/sf_qrcode.c new file mode 100644 index 000000000..03b591f72 --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/sf_qrcode.c @@ -0,0 +1,113 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: jiamin + * Ver: 1.0.0 2020.05.22 + * Description: creat + **************************************************************************/ + +#include "qrenc.h" +#include "sf_bmp.h" +// #include "sf_log.h" +#include "Log.h" +#include "SfTypeDefine.h" +#include "sf_base64.h" +#include "sf_qrcode.h" + +#define SIZE 6 + +static void strConv(char *p) +{ + int i; + int len = strlen(p); + char temp; + + for (i = 0; i < len;) + { + temp = *(p + i); + if (*(p + i + 1) != '\0') + { + *(p + i) = *(p + i + 1); + *(p + i + 1) = temp; + } + i += 2; + } +} + +static SINT32 sf_qrcode_encrypt(char *psrc_Str, char *pdst_Str) +{ + char encodeStr[160] = {0}; + char encodeUrlStr[160] = {0}; + + sf_base64_encode(psrc_Str, encodeStr, strlen(psrc_Str), 0); + strConv(encodeStr); + URLEncode(encodeStr, strlen(encodeStr), encodeUrlStr, sizeof(encodeUrlStr) / sizeof(char)); + strcpy(pdst_Str, encodeUrlStr); + return SF_SUCCESS; +} + +static int sf_qrcode_encode(char *intext, int length, char *outfile) +{ + QRcode *qrcode = NULL; + int ret = 0; + + qrcode = encode((const unsigned char *)intext, length); + if (qrcode == NULL) + { + printf("Failed to encode the input data"); + return 1; + } + + ret = sf_qrcode_bmpfile_write(qrcode, outfile, SIZE); + + QRcode_free(qrcode); + + return ret; +} +int sf_qrcode_create(const char *pIMEI, const char *pSimID, const char *pVersion, const char *accessKey) +{ + int ret = SF_SUCCESS; + SF_CHAR qrsrc_Str[160] = {0}; + SF_CHAR qrdst_Str[160] = {0}; + const int MAX_LEN = 100; + if (strlen(pIMEI) == 0) + { + LogError("the current IEMI is null!!!\n"); + return SF_FAILURE; + } + + if (strlen(pVersion) == 0) + { + LogError("the current Version is null!!!\n"); + return SF_FAILURE; + } + + sprintf(qrsrc_Str, "m2m-%s-%s-%s-%s-T11000001", pIMEI, pSimID, accessKey, pVersion); + + LogInfo("qrStr = %s\n", qrsrc_Str); + + sf_qrcode_encrypt(qrsrc_Str, qrdst_Str); + LogInfo("qrStr = %s ,len = %d\n", qrdst_Str, strlen(qrdst_Str)); + if (strlen(qrdst_Str) > MAX_LEN) + { + LogError("Create qrcode failed, param too long.\n"); + return -1; + } + + sf_qrcode_encode(qrdst_Str, strlen(qrdst_Str), "/mnt/mmc/addCam.bmp"); + // sf_qrcode_encode(qrdst_Str, strlen(qrdst_Str), "./addCam.bmp"); + LogInfo("addCam.bmp have existed \n"); + return ret; +} diff --git a/code/application/sifarsdk/component/Qrcode/src/split.c b/code/application/sifarsdk/component/Qrcode/src/split.c new file mode 100644 index 000000000..232580e2d --- /dev/null +++ b/code/application/sifarsdk/component/Qrcode/src/split.c @@ -0,0 +1,324 @@ +/* + * qrencode - QR Code encoder + * + * Input data splitter. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + + +#include "qrencode.h" +#include "qrinput.h" +#include "qrspec.h" +#include "split.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10) +#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0) + +#if !HAVE_STRDUP +#undef strdup +char *strdup(const char *s) +{ + size_t len = strlen(s) + 1; + void *new = malloc(len); + if(new == NULL) return NULL; + return (char *)memcpy(new, s, len); +} +#endif + +static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint) +{ + unsigned char c, d; + unsigned int word; + + c = string[0]; + + if(c == '\0') return QR_MODE_NUL; + if(isdigit(c)) { + return QR_MODE_NUM; + } else if(isalnum(c)) { + return QR_MODE_AN; + } else if(hint == QR_MODE_KANJI) { + d = string[1]; + if(d != '\0') { + word = ((unsigned int)c << 8) | d; + if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) { + return QR_MODE_KANJI; + } + } + } + + return QR_MODE_8; +} + +static int Split_eatNum(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint); + +static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint) +{ + const char *p; + int ret; + int run; + int dif; + int ln; + QRencodeMode mode; + + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string; + while(isdigit(*p)) { + p++; + } + run = p - string; + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_8) { + dif = QRinput_estimateBitsModeNum(run) + 4 + ln + + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ + - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; + if(dif > 0) { + return Split_eat8(string, input, hint); + } + } + if(mode == QR_MODE_AN) { + dif = QRinput_estimateBitsModeNum(run) + 4 + ln + + QRinput_estimateBitsModeAn(1) /* + 4 + la */ + - QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */; + if(dif > 0) { + return Split_eatAn(string, input, hint); + } + } + + ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p, *q; + int ret; + int run; + int dif; + int la, ln; + + la = QRspec_lengthIndicator(QR_MODE_AN, input->version); + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string; + while(isalnum(*p)) { + if(isdigit(*p)) { + q = p; + while(isdigit(*q)) { + q++; + } + dif = QRinput_estimateBitsModeAn(p - string) /* + 4 + la */ + + QRinput_estimateBitsModeNum(q - p) + 4 + ln + - QRinput_estimateBitsModeAn(q - string) /* - 4 - la */; + if(dif < 0) { + break; + } else { + p = q; + } + } else { + p++; + } + } + + run = p - string; + + if(*p && !isalnum(*p)) { + dif = QRinput_estimateBitsModeAn(run) + 4 + la + + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ + - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; + if(dif > 0) { + return Split_eat8(string, input, hint); + } + } + + ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p; + int ret; + int run; + + p = string; + while(Split_identifyMode(p, hint) == QR_MODE_KANJI) { + p += 2; + } + run = p - string; + ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p, *q; + QRencodeMode mode; + int ret; + int run; + int dif; + int la, ln; + + la = QRspec_lengthIndicator(QR_MODE_AN, input->version); + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string + 1; + while(*p != '\0') { + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_KANJI) { + break; + } + if(mode == QR_MODE_NUM) { + q = p; + while(isdigit(*q)) { + q++; + } + dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */ + + QRinput_estimateBitsModeNum(q - p) + 4 + ln + - QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */; + if(dif < 0) { + break; + } else { + p = q; + } + } else if(mode == QR_MODE_AN) { + q = p; + while(isalnum(*q)) { + q++; + } + dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */ + + QRinput_estimateBitsModeAn(q - p) + 4 + la + - QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */; + if(dif < 0) { + break; + } else { + p = q; + } + } else { + p++; + } + } + + run = p - string; + ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_splitString(const char *string, QRinput *input, + QRencodeMode hint) +{ + int length; + QRencodeMode mode; + + if(*string == '\0') return 0; + + mode = Split_identifyMode(string, hint); + if(mode == QR_MODE_NUM) { + length = Split_eatNum(string, input, hint); + } else if(mode == QR_MODE_AN) { + length = Split_eatAn(string, input, hint); + } else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) { + length = Split_eatKanji(string, input, hint); + } else { + length = Split_eat8(string, input, hint); + } + if(length == 0) return 0; + if(length < 0) return -1; + return Split_splitString(&string[length], input, hint); +} + +static char *dupAndToUpper(const char *str, QRencodeMode hint) +{ + char *newstr, *p; + QRencodeMode mode; + + newstr = strdup(str); + if(newstr == NULL) return NULL; + + p = newstr; + while(*p != '\0') { + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_KANJI) { + p += 2; + } else { + if (*p >= 'a' && *p <= 'z') { + *p = (char)((int)*p - 32); + } + p++; + } + } + + return newstr; +} + +int Split_splitStringToQRinput(const char *string, QRinput *input, + QRencodeMode hint, int casesensitive) +{ + char *newstr; + int ret; + + if(string == NULL || *string == '\0') { + return -1; + } + if(!casesensitive) { + newstr = dupAndToUpper(string, hint); + if(newstr == NULL) return -1; + ret = Split_splitString(newstr, input, hint); + free(newstr); + } else { + ret = Split_splitString(string, input, hint); + } + + return ret; +} +#ifdef __cplusplus +#if __cplusplus + } +#endif +#endif + diff --git a/code/application/sifarsdk/component/README.md b/code/application/sifarsdk/component/README.md new file mode 100644 index 000000000..54466b482 --- /dev/null +++ b/code/application/sifarsdk/component/README.md @@ -0,0 +1,19 @@ +# 1. 组件层 + +## 1.1. 概述 +   存放通用组件模块代码。 + +## 1.2. 目录 + +### 1.2.1. Global模块 +   Global模块为功能通用单一的模块,可以给任意的其它模块依赖使用,本身并不依赖其它任意模块。 +* Common: 高频的公共定义或者方法 +* Log:日志模块 +* ReturnCode:返回码模块 +* cJSON:cjson开源代码 +* base64:base64数据处理 + +### 1.2.2. 带业务属性的组件模块 +   具有某种特定功能的模块,组件层里面的带业务属性的模块之间不应该互相依赖。 +* GpioManager:Gpio管理 +* StateMachineManager:状态机管理模块 \ No newline at end of file diff --git a/code/application/sifarsdk/component/ReturnCode/CMakeLists.txt b/code/application/sifarsdk/component/ReturnCode/CMakeLists.txt new file mode 100644 index 000000000..9979520ac --- /dev/null +++ b/code/application/sifarsdk/component/ReturnCode/CMakeLists.txt @@ -0,0 +1,24 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME ReturnCode) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} Log) + diff --git a/code/application/sifarsdk/component/ReturnCode/include/ReturnCode.h b/code/application/sifarsdk/component/ReturnCode/include/ReturnCode.h new file mode 100644 index 000000000..a75e91953 --- /dev/null +++ b/code/application/sifarsdk/component/ReturnCode/include/ReturnCode.h @@ -0,0 +1,28 @@ +#ifndef RETURN_CODE_H +#define RETURN_CODE_H +enum C_RETURN_CODE +{ + C_RETURN_CODE_OK = 0, + C_RETURN_CODE_NOT_OK, + C_RETURN_CODE_INVALID_PARAMENTER, + C_RETURN_CODE_END +}; +typedef struct returnCodeC RETURN_CODE_C; +typedef struct returnCodeC +{ + const char *(*printStringCode)(const RETURN_CODE_C); + const long int mCode; +} RETURN_CODE_C; + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" +{ +#endif +const RETURN_CODE_C CreateReturnCode(const long int code); +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/ReturnCode/include/VReturnCode.h b/code/application/sifarsdk/component/ReturnCode/include/VReturnCode.h new file mode 100644 index 000000000..91786745e --- /dev/null +++ b/code/application/sifarsdk/component/ReturnCode/include/VReturnCode.h @@ -0,0 +1,54 @@ +#ifndef V_RETURN_CODE_H +#define V_RETURN_CODE_H +#include +#include +/** + * @brief + * The base return code. + * Attention: VReturnCOdeDefineStr must be added one item when define one new code. + */ +enum class VReturnCodeDefine +{ + OK = 0, + NOT_OK_UNDEFINE_REASON, + NOT_OK_VIRTUAL_FUNCTION, + MAKE_SHARED_PTR_FAILED, + END +}; +class VReturnCode +{ +protected: + VReturnCode(const int &code) : mCode(code) + { + } + +public: + virtual ~VReturnCode() = default; + virtual const int GetIntCode() { return mCode; } + bool IsCodeOK(); + /** + * @brief + * Print the code translate into a readable string. + * @return int + */ + virtual std::string PrintStringCode(); + void SetTips(const std::string &tips) { mTips = tips; } + const std::string &GetTips() { return mTips; } + /** + * @brief + * Create a new return code, which is the only way to create a code shared ptr. + * @param code + * @return std::make_shared + */ + static std::shared_ptr NewCode(const VReturnCodeDefine &code); + +private: + const int mCode; // Can't be reset. + std::string mTips; // Give some tips for return code, such as the not OK detail. +}; +/** + * @brief + * Define the VReturnCode as shared ptr, which other modules can redefine VReturnCode. + */ +using RETURN_CODE = std::shared_ptr; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/ReturnCode/src/ReturnCode.c b/code/application/sifarsdk/component/ReturnCode/src/ReturnCode.c new file mode 100644 index 000000000..dba1442b5 --- /dev/null +++ b/code/application/sifarsdk/component/ReturnCode/src/ReturnCode.c @@ -0,0 +1,35 @@ +#include "ReturnCode.h" +#include "Log.h" +#include +static const char *RETRUN_CODE_STRING[C_RETURN_CODE_END + 1]={ + "C_RETURN_CODE_OK", + "C_RETURN_CODE_NOT_OK", + "C_RETURN_CODE_INVALID_PARAMENTER", + "C_RETURN_CODE_END" +}; +static const char *PrintStringCode(const RETURN_CODE_C this) +{ + if (C_RETURN_CODE_OK <= this.mCode && this.mCode <= C_RETURN_CODE_END) + { + LogInfo("Return code = [ %s ]\n", RETRUN_CODE_STRING[this.mCode]); + return RETRUN_CODE_STRING[this.mCode]; + } + LogError("Return code = [ %s ]\n", RETRUN_CODE_STRING[C_RETURN_CODE_INVALID_PARAMENTER]); + return RETRUN_CODE_STRING[C_RETURN_CODE_INVALID_PARAMENTER]; +} +const RETURN_CODE_C CreateReturnCode(const long int code) +{ + if (C_RETURN_CODE_OK <= code && code <= C_RETURN_CODE_END) + { + RETURN_CODE_C result = {NULL, code}; + result.printStringCode = PrintStringCode; + return result; + } + else + { + LogError("undefined code.\n"); + RETURN_CODE_C result = {NULL, C_RETURN_CODE_INVALID_PARAMENTER}; + result.printStringCode = PrintStringCode; + return result; + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/ReturnCode/src/VReturnCode.cpp b/code/application/sifarsdk/component/ReturnCode/src/VReturnCode.cpp new file mode 100644 index 000000000..bf687cb87 --- /dev/null +++ b/code/application/sifarsdk/component/ReturnCode/src/VReturnCode.cpp @@ -0,0 +1,44 @@ +#include "VReturnCode.h" +#include "Log.h" +const std::string VReturnCOdeDefineStr[static_cast(VReturnCodeDefine::END) + 1] = { + "OK", + "NOT_OK_UNDEFINE_REASON, undefine reason", + "NOT_OK_VIRTUAL_FUNCTION, do nothing function", + "MAKE_SHARED_PTR_FAILED, std::make_shared failed", + "END"}; +std::shared_ptr VReturnCode::NewCode(const VReturnCodeDefine &code) +{ + // return std::make_shared(static_cast(code)); + class MakeShared : public VReturnCode + { + public: + MakeShared(const int &code) : VReturnCode(code) {} + }; + return std::make_shared(static_cast(code)); +} +bool VReturnCode::IsCodeOK() +{ + bool result = mCode == static_cast(VReturnCodeDefine::OK) ? true : false; + // if (!result) + // { + // PrintStringCode(); // Don't print code when run ok. + // } + return result; +} +std::string VReturnCode::PrintStringCode() +{ + if (mCode < static_cast(VReturnCodeDefine::OK) || mCode > static_cast(VReturnCodeDefine::END)) + { + LogError("Illegal code, cross the border.\n"); + return "Illegal code."; + } + if (mCode > static_cast(VReturnCodeDefine::OK)) + { + LogError("Return code:[ %s ]\n", VReturnCOdeDefineStr[mCode].c_str()); + } + else + { + LogInfo("Return code:[ %s %s]\n", VReturnCOdeDefineStr[mCode].c_str(), GetTips().c_str()); + } + return VReturnCOdeDefineStr[mCode]; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/CMakeLists.txt b/code/application/sifarsdk/component/Servers/CMakeLists.txt new file mode 100755 index 000000000..c7b294a8d --- /dev/null +++ b/code/application/sifarsdk/component/Servers/CMakeLists.txt @@ -0,0 +1,93 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/include +) +#do not rely on any other library +# link_directories( +# ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/build/lib +# ) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME Servers) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} Log) +if(${CURL_OPENSSL_LIB_SHARED_ENABLE} MATCHES "false") + target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.a) +else() + target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.so) +endif() + + +add_subdirectory(test) +# ------------------ openssl ------------------ start +execute_process(COMMAND sh build_openssl.sh WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/openssl/) + +if(${CURL_OPENSSL_LIB_SHARED_ENABLE} MATCHES "false") + set(OPENSSL_TAILOR no-asm no-async no-md2 no-mdc2 no-poly1305 no-blake2 + no-siphash no-sm3 no-rc2 no-rc4 no-rc5 no-idea no-aria no-bf no-cast + no-camellia no-chacha no-ec no-sm2 no-dso + no-err no-comp no-cms no-ts no-cmac no-ct + no-hw-padlock no-nextprotoneg no-psk no-rfc3779 no-srtp + no-dgram no-dynamic-engine no-ec2m no-filenames no-gost + no-afalgeng no-async no-autoalginit no-autoerrinit no-capieng + no-tests + no-ssl-trace no-static-engine no-stdio no-threads no-deprecated no-makedepend + no-multiblock) +else() + set(OPENSSL_TAILOR no-asm no-tests) +endif() +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) + set(OPENSSL_OS_PLATFORM "linux-x86_64") +else() + set(OPENSSL_OS_PLATFORM "linux-armv4") + # set(LINK_FLAGS "${LINK_FLAGS} -Wl,-rpath,${CURL_SHARED_LIBS_PATH}") + # set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINK_FLAGS}") + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINK_FLAGS}") +endif() +add_custom_target( + openssl + COMMAND echo "Build openssl." + COMMAND rm -rf ${EXTERNAL_SOURCE_PATH}/openssl/build + COMMAND ./Configure ${OPENSSL_TAILOR} ${OPENSSL_OS_PLATFORM} --prefix=${EXTERNAL_SOURCE_PATH}/openssl/build --openssldir=${EXTERNAL_SOURCE_PATH}/openssl/build --cross-compile-prefix=${CROSS_COMPILE_PREFIX} CC=gcc AR=ar + COMMAND make + COMMAND make install + WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/openssl/openssl-1.1.1s/ +) +# ------------------ openssl ------------------ end + +# ------------------ curl ------------------ start +execute_process(COMMAND sh build_curl.sh WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/curl/) +set(CURL_TAILOR --disable-dict --disable-file --disable-gopher + --disable-imap --disable-ldap --disable-pop3 --disable-rtmp + --disable-rtsp --disable-scp --disable-sftp --disable-smb + --disable-telnet --disable-tftp --disable-ipv6) +if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) + set(CURL_HOST "") +else() + set(CURL_HOST "--host=arm-linux") +endif() +add_custom_target( + curl + DEPENDS openssl + COMMAND echo "Build curl." + COMMAND ./configure --without-zlib --prefix=${EXTERNAL_SOURCE_PATH}/curl --with-ssl=${EXTERNAL_SOURCE_PATH}/openssl/build ${CURL_HOST} CC=${CMAKE_C_COMPILER} + COMMAND make + COMMAND cp ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/lib*.a ${LIBS_OUTPUT_PATH} + COMMAND cp ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/lib*.a ${LIBS_OUTPUT_PATH} + # COMMAND cp ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/lib*.so* ${LIBS_OUTPUT_PATH} + # COMMAND cp ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/lib*.so* ${LIBS_OUTPUT_PATH} + WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/ +) +# ------------------ curl ------------------ end \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/README.md b/code/application/sifarsdk/component/Servers/README.md new file mode 100644 index 000000000..68435440e --- /dev/null +++ b/code/application/sifarsdk/component/Servers/README.md @@ -0,0 +1,110 @@ +# 1. 服务器协议接口 + +## 1.1. 概述 +   提供HTTP/FTP/SMTP协议的接口数据,使用**curl+openssl开源库**二次封装。 + +## 1.2. 开发过程记录 +1. 先编译openssl,再编译curl,curl的构建配置需要指定openssl的输出文件目录,否则curl将会构建失败; +2. http协议,指定url,指定post数据,curl即可按照POST发送请求; +3. ftp/ftps协议对应不同的服务器IP,必须一一对应; +4. curl配置了忽略证书校验,未知有什么实际影响; +5. 分别对openssl和curl进行了裁剪; + +## 1.3. 关于MQTT +   curl源码包里并未提供MQTT相关的example,网上搜索编码示例未找到。 + +## 1.4. Servers协议栈模块构建 +   使用SifarSDK的构建体系进行编译,编译curl时自动关联openssl进行编译。 +* 配置文件(此处以/build/cmake/toolchain/linux.toolchain.cmake为示例): +``` +# ------------ build curl + openssl ------------ start +# 工具链前缀 +set(CROSS_COMPILE_PREFIX "") +# 是否启动动态库(预留,暂未支持) +set(CURL_OPENSSL_LIB_SHARED_ENABLE "false") +# ------------ build curl + openssl ------------ end +``` +* 项目根目录编译 +``` +make cmake +cd cmake-shell-linux/ +make curl // 由于curl属于三方构建的开源库,首次需要先编译curl + openssl +make Servers +``` + +## 1.5. Example +头文件:servser.h +链接库:libServers.a,libLog.a +三方依赖库(依次按序): libcurl.a,libssl.a,libcrypto.a + +下述以FTP为例子: +``` +TEST(ServersTest, FtpsUpload) + { + const char *url = "ftp://150.109.112.64/ServersTest";test/bin/ServersTest"; + const char *uploadFile = "./ServersTest"; + const char *user_password = "ftp_user:Sifar%123456"; + SERVERS_INIT init = { + .logFlag = LOG_FLAG_ENABLE, // 开启curl日志 + .sslVerifyFlag = SSL_VERIFY_DISABLE, //关闭ssl的证书校验功能 + }; + InitLog(LOG_EASYLOGGING, nullptr); // 初始化自研log库 + servers_init(init); // 初始化Servers模块 + LogInfo("servers test start.\n"); + SERVERS_FTP *ftp = new_servers_ftp(url, FTPS_FLAG_ENABLE); // 创建ftp的参数“句柄” + if (ftp) + { + ftp->user_password = (char *)user_password; + ftp->filePath = (char *)uploadFile; + ftp_upload(ftp); // 使用FTP上传文件 + if (SERVERS_CODE_OK == ftp->code) + { + LogInfo("ftp succeed.\n"); + } + else + { + LogError("ftp failed, code = %d.\n", static_cast(ftp->code)); + } + delete_servers_ftp(ftp); // 释放ftp“句柄” + } + UnInitLog(); + } +``` +**注意:** +* 必须调用servers_init()函数初始化Servers协议栈库; +* 必须使用模块接口创建对应的协议参数“句柄”,示例为new_servers_ftp(); +* 必须释放协议参数“句柄”; + +更多示例详见:/test/component/Servers/src/ServersTest.cpp + +## 1.6. 测试 +   libServers.a自研代码通过asan测试,未存在内存安全相关漏洞。 +测试用例详见:/test/component/Servers/src/ServersTest.cpp + +* 测试用例编译 +``` +make cmake +cd cmake-shell-linux/ +make curl // 由于curl属于三方构建的开源库,首次需要先编译curl + openssl +make ServersTest +``` + +## 1.7. 总结 +* 实现http/https/ftp/ftps/smtp/smtps接口; +* 交叉编译测试ftp/ftps上传下载速率大概为1M/s(333DE芯片平台); +* 裁剪openssl和curl后编译的demo大小 < 1.2M; + +## 1.8. S530项目配置 +* 工具链 +``` +set(CMAKE_C_COMPILER /opt/arm-ca9-linux-uclibcgnueabihf-8.4.01/usr/bin/arm-linux-gcc) +set(CMAKE_CXX_COMPILER /opt/arm-ca9-linux-uclibcgnueabihf-8.4.01/usr/bin/arm-linux-g++) +``` +* curl + openssl +``` +# ------------ build curl + openssl ------------ start +set(CROSS_COMPILE_PREFIX "/opt/arm-ca9-linux-uclibcgnueabihf-8.4.01/usr/bin/arm-linux-") +set(CURL_OPENSSL_LIB_SHARED_ENABLE "false") +set(CURL_SHARED_LIBS_PATH "/mnt/mmc") +# ------------ build curl + openssl ------------ end +``` \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/include/servers.h b/code/application/sifarsdk/component/Servers/include/servers.h new file mode 100644 index 000000000..deab075ca --- /dev/null +++ b/code/application/sifarsdk/component/Servers/include/servers.h @@ -0,0 +1,98 @@ +#ifndef SERVERS_H +#define SERVERS_H +#ifdef __cplusplus +extern "C" +{ +#endif +#define SERVERS_PARAM_NULL_MEANS_END NULL + typedef enum + { + SERVERS_CODE_DEFAULT = -1, + SERVERS_CODE_OK = 0, + SERVERS_CODE_END + } ServersCode; + typedef enum + { + FTPS_FLAG_ENABLE = 0, + FTPS_FLAG_DISABLE, + FTPS_FLAG_END + } FtpsFlag; + typedef enum + { + LOG_FLAG_ENABLE = 0, + LOG_FLAG_DISABLE, + LOG_FLAG_END + } LogFlag; + typedef enum + { + SSL_VERIFY_ENABLE = 0, + SSL_VERIFY_DISABLE, + SSL_VERIFY_END + } SslFlag; + typedef struct servers_init + { + LogFlag logFlag; + SslFlag sslVerifyFlag; + } SERVERS_INIT; + typedef struct servers_http + { + const char *url; + char *postData; + char *filePath; + char **header; + char *reply; + unsigned int replyLength; + int code; + } SERVERS_HTTP; + typedef struct servers_ftp + { + const char *url; + const FtpsFlag ftpsFlag; + char *user_password; + char *filePath; + int code; + } SERVERS_FTP; + typedef struct servers_smtp + { + const char *url; + const char *subject; + const char *from; + const char *to; + const char *userName; + const char *password; + const char *date; + char *inlineText; + char **toList; + unsigned int toListLength; + // char *text; + // unsigned int textLength; + char **attachment; + int code; + } SERVERS_SMTP; + void servers_init(SERVERS_INIT init); + void servers_unit(void); + // HTTP API + SERVERS_HTTP *new_servers_http(const char *url); + void delete_servers_http(SERVERS_HTTP *ptr); + void http_get(SERVERS_HTTP *param); + void http_post(SERVERS_HTTP *param); + void http_put(SERVERS_HTTP *param); + // FTP API + SERVERS_FTP *new_servers_ftp(const char *url, const FtpsFlag ftpsFlag); + void delete_servers_ftp(SERVERS_FTP *ptr); + void ftp_download(SERVERS_FTP *param); + void ftp_upload(SERVERS_FTP *param); + // SMTP API + SERVERS_SMTP *new_servers_smtp(const char *url, + const char *subject, + const char *from, + const char *to, + const char *userName, + const char *password, + const char *date); + void delete_servers_smtp(SERVERS_SMTP *ptr); + void smtp_send_email(SERVERS_SMTP *param); +#ifdef __cplusplus +} +#endif +#endif // !SERVERS_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/curl_serve.c b/code/application/sifarsdk/component/Servers/src/curl_serve.c new file mode 100644 index 000000000..31cddfac9 --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/curl_serve.c @@ -0,0 +1,47 @@ +#include "curl_serve.h" +static SERVERS_INIT gCurlServe; +void set_verbose_log(LogFlag flag) +{ + gCurlServe.logFlag = flag; +} +void set_ssl_verify(SslFlag flag) +{ + gCurlServe.sslVerifyFlag = flag; +} +CURL *curl_easy_make(void) +{ + CURL *curl; + curl = curl_easy_init(); + if (!curl) + { + return curl; + } + if (SSL_VERIFY_DISABLE == gCurlServe.sslVerifyFlag) + { + + /* + * If you want to connect to a site who is not using a certificate that is + * signed by one of the certs in the CA bundle you have, you can skip the + * verification of the server's certificate. This makes the connection + * A LOT LESS SECURE. + * + * If you have a CA cert for the server stored someplace else than in the + * default bundle, then the CURLOPT_CAPATH option might come handy for + * you. + */ + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + /* + * If the site you are connecting to uses a different host name that what + * they have mentioned in their server certificate's commonName (or + * subjectAltName) fields, libcurl will refuse to connect. You can skip + * this check, but this will make the connection less secure. + */ + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + } + if (LOG_FLAG_ENABLE == gCurlServe.logFlag) + { + /* Switch on full protocol/debug output */ + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + } + return curl; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/curl_serve.h b/code/application/sifarsdk/component/Servers/src/curl_serve.h new file mode 100644 index 000000000..a780a46ca --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/curl_serve.h @@ -0,0 +1,15 @@ +#ifndef CURL_SERVE_H +#define CURL_SERVE_H +#include "servers.h" +#include +#ifdef __cplusplus +extern "C" +{ +#endif + void set_verbose_log(LogFlag flag); + void set_ssl_verify(SslFlag flag); + CURL *curl_easy_make(void); +#ifdef __cplusplus +} +#endif +#endif // !CURL_SERVE_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/ftp_servers.c b/code/application/sifarsdk/component/Servers/src/ftp_servers.c new file mode 100644 index 000000000..8ecbec29d --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/ftp_servers.c @@ -0,0 +1,191 @@ +#include "ftp_servers.h" +#include "Log.h" +#include "curl_serve.h" +#include +#include +#include +#include +#include +struct FtpFile +{ + const char *filename; + FILE *stream; +}; +static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) +{ + struct FtpFile *out = (struct FtpFile *)stream; + if (!out->stream) + { + /* open file for writing */ + out->stream = fopen(out->filename, "wb"); + if (!out->stream) + return -1; /* failure, cannot open file to write */ + } + return fwrite(buffer, size, nmemb, out->stream); +} +void ftp_servers_download(SERVERS_FTP *param) +{ + if (!param) + { + LogError("null pointer.\n"); + return; + } + CURL *curl; + CURLcode res; + struct FtpFile ftpfile = { + param->filePath, /* name to store the file as if successful */ + NULL}; + + curl_global_init(CURL_GLOBAL_DEFAULT); + + curl = curl_easy_make(); + if (curl) + { + /* + * You better replace the URL with one that works! + */ + curl_easy_setopt(curl, CURLOPT_URL, param->url); + /* User and password for the FTP login */ + if (param->user_password) + { + curl_easy_setopt(curl, CURLOPT_USERPWD, param->user_password); + } + /* We activate SSL and we require it for both control and data */ + if (FTPS_FLAG_ENABLE == param->ftpsFlag) + { + curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); + } + /* Define our callback to get called when there's data to be written */ + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + /* Set a pointer to our struct to pass to the callback */ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); + + res = curl_easy_perform(curl); + param->code = res; + + /* always cleanup */ + curl_easy_cleanup(curl); + + if (CURLE_OK != res) + { + /* we failed */ + fprintf(stderr, "curl told us %d\n", res); + } + } + + if (ftpfile.stream) + fclose(ftpfile.stream); /* close the local file */ + + curl_global_cleanup(); +} +/* NOTE: if you want this example to work on Windows with libcurl as a + DLL, you MUST also provide a read callback with CURLOPT_READFUNCTION. + Failing to do so will give you a crash since a DLL may not use the + variable's memory when passed in to it from an app like this. */ +static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) +{ + unsigned long nread; + /* in real-world cases, this would probably get this data differently + as this fread() stuff is exactly what the library already would do + by default internally */ + size_t retcode = fread(ptr, size, nmemb, stream); + + if (retcode > 0) + { + nread = (unsigned long)retcode; + fprintf(stderr, "*** We read %lu bytes from file\n", nread); + } + + return retcode; +} +void ftp_servers_upload(SERVERS_FTP *param) +{ + if (!param) + { + LogError("null pointer.\n"); + return; + } + CURL *curl; + CURLcode res; + FILE *hd_src; + struct stat file_info; + unsigned long fsize; + + struct curl_slist *headerlist = NULL; + // static const char buf_1[] = "RNFR " UPLOAD_FILE_AS; // TODO: + // static const char buf_2[] = "RNTO " RENAME_FILE_TO; + + /* get the file size of the local file */ + if (stat(param->filePath, &file_info)) + { + LogInfo("Couldn't open '%s'\n", param->filePath); + return; + } + fsize = (unsigned long)file_info.st_size; + + LogInfo("Local file size: %lu bytes.\n", fsize); + + /* get a FILE * of the same file */ + hd_src = fopen(param->filePath, "rb"); + + /* In windows, this will init the winsock stuff */ + curl_global_init(CURL_GLOBAL_ALL); + + /* get a curl handle */ + curl = curl_easy_make(); + if (curl) + { + /* build a list of commands to pass to libcurl */ + // headerlist = curl_slist_append(headerlist, buf_1); // TODO: + // headerlist = curl_slist_append(headerlist, buf_2); + + /* we want to use our own read function */ + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + + /* enable uploading */ + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + + /* specify target */ + curl_easy_setopt(curl, CURLOPT_URL, param->url); + /* User and password for the FTP login */ + if (param->user_password) + { + curl_easy_setopt(curl, CURLOPT_USERPWD, param->user_password); + } + /* We activate SSL and we require it for both control and data */ + if (FTPS_FLAG_ENABLE == param->ftpsFlag) + { + curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); + } + + /* pass in that last of FTP commands to run after the transfer */ + curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist); + + /* now specify which file to upload */ + curl_easy_setopt(curl, CURLOPT_READDATA, hd_src); + + /* Set the size of the file to upload (optional). If you give a *_LARGE + option you MUST make sure that the type of the passed-in argument is a + curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must + make sure that to pass in a type 'long' argument. */ + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, + (curl_off_t)fsize); + + /* Now run off and do what you have been told! */ + res = curl_easy_perform(curl); + param->code = res; + /* Check for errors */ + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + + /* clean up the FTP commands list */ + curl_slist_free_all(headerlist); + + /* always cleanup */ + curl_easy_cleanup(curl); + } + fclose(hd_src); /* close the local file */ + + curl_global_cleanup(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/ftp_servers.h b/code/application/sifarsdk/component/Servers/src/ftp_servers.h new file mode 100644 index 000000000..5f3abbe88 --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/ftp_servers.h @@ -0,0 +1,13 @@ +#ifndef FTP_SERVERS_H +#define FTP_SERVERS_H +#include "servers.h" +#ifdef __cplusplus +extern "C" +{ +#endif + void ftp_servers_download(SERVERS_FTP *param); + void ftp_servers_upload(SERVERS_FTP *param); +#ifdef __cplusplus +} +#endif +#endif // !FTP_SERVERS_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/http_servers.c b/code/application/sifarsdk/component/Servers/src/http_servers.c new file mode 100644 index 000000000..ed7e176b4 --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/http_servers.c @@ -0,0 +1,230 @@ +#include "http_servers.h" +#include "Log.h" +#include "curl_serve.h" +#include +#include +#include +#include +#include +#include + +static size_t write_cb(char *data, size_t n, size_t l, void *userp) +{ + /* take care of the data here, ignored in this example */ + (void)data; + (void)userp; + SERVERS_HTTP *p = (SERVERS_HTTP *)userp; + const int LENGTH = n * l; + // p->reply = (char *)realloc(p->reply, LENGTH); + char *newData = (char *)malloc(p->replyLength + LENGTH); + if (newData) + { + if (p->reply) + { + memcpy(newData, p->reply, p->replyLength); + free(p->reply); + p->reply = NULL; + } + memcpy(newData + p->replyLength, data, LENGTH); + p->replyLength += LENGTH; + p->reply = newData; + } + return n * l; +} +void http_servers_get(SERVERS_HTTP *param) +{ + if (!param) + { + LogError("null pointer.\n"); + return; + } + CURL *curl; + CURLcode res; + + curl = curl_easy_make(); + if (curl) + { + curl_easy_setopt(curl, CURLOPT_URL, param->url); + /* example.com is redirected, so we tell libcurl to follow redirection */ + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + // + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, param); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + param->code = res; + /* Check for errors */ + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + + /* always cleanup */ + curl_easy_cleanup(curl); + } +} +void http_servers_post(SERVERS_HTTP *param) +{ + if (!param) + { + LogError("null pointer.\n"); + return; + } + CURL *curl; + CURLcode res; + + /* In windows, this will init the winsock stuff */ + curl_global_init(CURL_GLOBAL_ALL); + + /* get a curl handle */ + curl = curl_easy_make(); + if (curl) + { + /* First set the URL that is about to receive our POST. This URL can + just as well be an https:// URL if that is what should receive the + data. */ + curl_easy_setopt(curl, CURLOPT_URL, param->url); + struct curl_slist *headers = NULL; + + /* default type with postfields is application/x-www-form-urlencoded, + change it if you want */ + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + /* Now specify the POST data */ + if (param->postData) + { + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, param->postData); + } + else + { + const char *NULL_POST_DATA = "{}"; + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL_POST_DATA); + } + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, param); + // curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L); + // curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000L); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + /* Check for errors */ + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + + /* always cleanup */ + curl_easy_cleanup(curl); + /* free headers */ + curl_slist_free_all(headers); + } + curl_global_cleanup(); +} +static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) +{ + size_t retcode; + unsigned long nread; + + /* in real-world cases, this would probably get this data differently + as this fread() stuff is exactly what the library already would do + by default internally */ + retcode = fread(ptr, size, nmemb, stream); + + if (retcode > 0) + { + nread = (unsigned long)retcode; + fprintf(stderr, "*** We read %lu bytes from file\n", nread); + } + + return retcode; +} +void http_servers_put(SERVERS_HTTP *param) +{ + if (!param) + { + LogError("null pointer.\n"); + return; + } + CURL *curl; + CURLcode res; + FILE *hd_src; + struct stat file_info; + struct curl_slist *headers = NULL; + + char *file; + if (!param->filePath) + { + LogError("file path is needed.\n"); + return; + } + + file = param->filePath; + + /* get the file size of the local file */ + stat(file, &file_info); + + /* get a FILE * of the same file, could also be made with + fdopen() from the previous descriptor, but hey this is just + an example! */ + hd_src = fopen(file, "rb"); + if (!hd_src) + { + LogError("fopen files failed.\n"); + return; + } + + /* In windows, this will init the winsock stuff */ + curl_global_init(CURL_GLOBAL_ALL); + + /* get a curl handle */ + curl = curl_easy_make(); + if (curl) + { + /* we want to use our own read function */ + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + + /* enable uploading (implies PUT over HTTP) */ + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + + /* specify target URL, and note that this URL should include a file + name, not only a directory */ + curl_easy_setopt(curl, CURLOPT_URL, param->url); + + /* now specify which file to upload */ + curl_easy_setopt(curl, CURLOPT_READDATA, hd_src); + + /* provide the size of the upload, we typecast the value to curl_off_t + since we must be sure to use the correct data size */ + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, + (curl_off_t)file_info.st_size); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, param); + // Add header + char **cpp = NULL; + for (cpp = param->header; *cpp; cpp++) + { + headers = curl_slist_append(headers, *cpp); + } + if (headers) + { + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + } + + /* Now run off and do what you have been told! */ + res = curl_easy_perform(curl); + /* Check for errors */ + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + + /* always cleanup */ + curl_easy_cleanup(curl); + /* free headers */ + if (headers) + { + curl_slist_free_all(headers); + } + } + fclose(hd_src); /* close the local file */ + + curl_global_cleanup(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/http_servers.h b/code/application/sifarsdk/component/Servers/src/http_servers.h new file mode 100644 index 000000000..73cfd6dcb --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/http_servers.h @@ -0,0 +1,14 @@ +#ifndef HTTP_SERVERS_H +#define HTTP_SERVERS_H +#include "servers.h" +#ifdef __cplusplus +extern "C" +{ +#endif + void http_servers_get(SERVERS_HTTP *param); + void http_servers_post(SERVERS_HTTP *param); + void http_servers_put(SERVERS_HTTP *param); +#ifdef __cplusplus +} +#endif +#endif // !HTTP_SERVERS_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/servers.c b/code/application/sifarsdk/component/Servers/src/servers.c new file mode 100644 index 000000000..94953c1ea --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/servers.c @@ -0,0 +1,155 @@ +#include "servers.h" +#include "Log.h" +#include "http_servers.h" +#include "ftp_servers.h" +#include "smtp_servers.h" +#include "curl_serve.h" +#include +#include +#include +void servers_init(SERVERS_INIT init) +{ + set_verbose_log(init.logFlag); + set_ssl_verify(init.sslVerifyFlag); +} +void servers_unit(void) +{ +} +void http_get(SERVERS_HTTP *param) +{ + LogInfo("http_get\n"); + http_servers_get(param); +} +void http_post(SERVERS_HTTP *param) +{ + LogInfo("http_post\n"); + http_servers_post(param); +} +void http_put(SERVERS_HTTP *param) +{ + LogInfo("http_put\n"); + http_servers_put(param); +} +void smtp_send_email(SERVERS_SMTP *param) +{ + LogInfo("smtp_send_email\n"); + smtp_servers_send_email(param); + // smtp_servers_send_email_only_text(param); +} +SERVERS_HTTP *new_servers_http(const char *url) +{ + if (!url) + { + LogError("new_servers_http failed.\n"); + return NULL; + } + SERVERS_HTTP result = { + .url = url, + .postData = NULL, + .filePath = NULL, + .header = NULL, + .reply = NULL, + .replyLength = 0, + .code = 0}; + const int LENGTH = sizeof(SERVERS_HTTP); + SERVERS_HTTP *p = (SERVERS_HTTP *)malloc(LENGTH); + if (p) + { + LogInfo("malloc succeed.\n"); + memcpy(p, &result, LENGTH); + } + return p; +} +void delete_servers_http(SERVERS_HTTP *ptr) +{ + if (ptr) + { + if (ptr->reply) + { + free(ptr->reply); + ptr->reply = NULL; + } + free(ptr); + } +} +SERVERS_FTP *new_servers_ftp(const char *url, const FtpsFlag ftpsFlag) +{ + if (!url) + { + LogError("new_servers_ftp failed.\n"); + return NULL; + } + SERVERS_FTP result = { + .url = url, + .ftpsFlag = ftpsFlag, + .user_password = NULL, + .filePath = NULL, + .code = -1}; + const int LENGTH = sizeof(SERVERS_FTP); + SERVERS_FTP *p = (SERVERS_FTP *)malloc(LENGTH); + if (p) + { + LogInfo("malloc succeed.\n"); + memcpy(p, &result, LENGTH); + } + return p; +} +void delete_servers_ftp(SERVERS_FTP *ptr) +{ + if (ptr) + { + free(ptr); + } +} +void ftp_download(SERVERS_FTP *param) +{ + LogInfo("ftp_download\n"); + ftp_servers_download(param); +} +void ftp_upload(SERVERS_FTP *param) +{ + LogInfo("ftp_upload\n"); + ftp_servers_upload(param); +} +SERVERS_SMTP *new_servers_smtp(const char *url, + const char *subject, + const char *from, + const char *to, + const char *userName, + const char *password, + const char *date) +{ + if (!url || !from || !to || !userName || !password || !subject || !date) + { + LogError("new_servers_smtp failed.\n"); + return NULL; + } + SERVERS_SMTP result = { + .url = url, + .subject = subject, + .from = from, + .to = to, + .userName = userName, + .password = password, + .date = date, + .inlineText = NULL, + // .text = NULL, + // .textLength = 0, + .attachment = NULL, + .code = -1}; + const int LENGTH = sizeof(SERVERS_SMTP); + SERVERS_SMTP *p = (SERVERS_SMTP *)malloc(LENGTH); + if (p) + { + LogInfo("malloc succeed.\n"); + memcpy(p, &result, LENGTH); + } + return p; +} +void delete_servers_smtp(SERVERS_SMTP *ptr) +{ + if (ptr) + { + free(ptr); + } +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/smtp_servers.c b/code/application/sifarsdk/component/Servers/src/smtp_servers.c new file mode 100644 index 000000000..56ce8a3e0 --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/smtp_servers.c @@ -0,0 +1,344 @@ +#include "smtp_servers.h" +#include "Log.h" +#include "curl_serve.h" +#include +#include +#include +#include +struct upload_status +{ + char *payload_text; + size_t bytes_read; +}; +// static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) +// { +// struct upload_status *upload_ctx = (struct upload_status *)userp; +// const char *data; +// size_t room = size * nmemb; + +// if ((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) +// { +// return 0; +// } + +// data = &upload_ctx->payload_text[upload_ctx->bytes_read]; + +// if (data) +// { +// size_t len = strlen(data); +// if (room < len) +// len = room; +// memcpy(ptr, data, len); +// upload_ctx->bytes_read += len; + +// return len; +// } + +// return 0; +// } +// static const char inline_html[] = +// "\r\n" +// "

This is the inline HTML message of the email.

" +// "
\r\n" +// "

It could be a lot of HTML data that would be displayed by " +// "email viewers able to handle HTML.

" +// "\r\n"; +#define SEND_EMAIL_HEADERS_ARRAY_LENGTH 5 +#define SEND_EMAIL_HEADERS_TEXT_LENGTH 1024 +#define DATE "Date: " +#define TO "To: " +#define FROM "From: " +#define SUBJECT "Subject: " +#define HEADER_END "\r\n" +enum HEADERS_NAME +{ + HEADERS_NAME_DATE = 0, + HEADERS_NAME_TO, + HEADERS_NAME_FROM, + HEADERS_NAME_SUBJECT, + HEADERS_NAME_END +}; +static void headers_make(char **headers, SERVERS_SMTP *param) +{ + int textLength = strlen(DATE) + strlen(param->date) + 1; + char *text = (char *)malloc(textLength); + if (text) + { + memset(text, 0, textLength); + snprintf(text, textLength, "%s%s", DATE, param->date); + headers[HEADERS_NAME_DATE] = text; + LogInfo("HEADERS_NAME_DATE:%s\n", text); + } + textLength = strlen(TO) + strlen(param->to) + 1; + text = (char *)malloc(textLength); + if (text) + { + memset(text, 0, textLength); + snprintf(text, textLength, "%s%s", TO, param->to); + headers[HEADERS_NAME_TO] = text; + LogInfo("HEADERS_NAME_TO:%s\n", text); + } + textLength = strlen(FROM) + strlen(param->from) + strlen(param->userName) + strlen("()") + 1; + text = (char *)malloc(textLength); + if (text) + { + memset(text, 0, textLength); + snprintf(text, textLength, "%s%s(%s)", FROM, param->from, param->userName); + headers[HEADERS_NAME_FROM] = text; + LogInfo("HEADERS_NAME_FROM:%s\n", text); + } + textLength = strlen(SUBJECT) + strlen(param->subject) + 1; + text = (char *)malloc(textLength); + if (text) + { + memset(text, 0, textLength); + snprintf(text, textLength, "%s%s", SUBJECT, param->subject); + headers[HEADERS_NAME_SUBJECT] = text; + LogInfo("HEADERS_NAME_SUBJECT:%s\n", text); + } +} +static void headers_free(char **headers) +{ + char **cpp = headers; + for (int i = 0; i < SEND_EMAIL_HEADERS_ARRAY_LENGTH; i++) + { + if (*cpp) + { + free(*cpp); + headers[i] = NULL; + } + cpp++; + } +} +void smtp_servers_send_email(SERVERS_SMTP *param) +{ + if (!param) + { + LogError("null pointer.\n"); + return; + } + char *headers_text[SEND_EMAIL_HEADERS_ARRAY_LENGTH] = {NULL}; + headers_make(headers_text, param); + CURL *curl; + CURLcode res = CURLE_OK; + + curl = curl_easy_make(); + if (curl) + { + struct curl_slist *headers = NULL; + struct curl_slist *recipients = NULL; + struct curl_slist *slist = NULL; + curl_mime *mime; + curl_mime *alt; + curl_mimepart *part; + const char **cpp; + const char **attachment; + + /* This is the URL for your mailserver */ + curl_easy_setopt(curl, CURLOPT_URL, param->url); + /* Set the username and password */ + curl_easy_setopt(curl, CURLOPT_USERNAME, param->userName); + curl_easy_setopt(curl, CURLOPT_PASSWORD, param->password); + + /* Note that this option is not strictly required, omitting it will result + * in libcurl sending the MAIL FROM command with empty sender data. All + * autoresponses should have an empty reverse-path, and should be directed + * to the address in the reverse-path which triggered them. Otherwise, + * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more + * details. + */ + curl_easy_setopt(curl, CURLOPT_MAIL_FROM, param->from); + + /* Add two recipients, in this particular case they correspond to the + * To: and Cc: addressees in the header, but they could be any kind of + * recipient. */ + recipients = curl_slist_append(recipients, param->to); + // recipients = curl_slist_append(recipients, CC); + curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); + + /* Build and set the message header list. */ + for (cpp = (const char **)headers_text; *cpp; cpp++) + { + headers = curl_slist_append(headers, *cpp); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + /* Build the mime message. */ + mime = curl_mime_init(curl); + + /* The inline part is an alternative proposing the html and the text + versions of the email. */ + alt = curl_mime_init(curl); + + /* HTML message. */ + // part = curl_mime_addpart(alt); + // curl_mime_data(part, inline_html, CURL_ZERO_TERMINATED); + // curl_mime_type(part, "text/html"); + + /* Text message. */ + if (param->inlineText) + { + part = curl_mime_addpart(alt); + curl_mime_data(part, param->inlineText, CURL_ZERO_TERMINATED); + curl_mime_type(part, "text/plain"); + } + + /* Create the inline part. */ + part = curl_mime_addpart(mime); + curl_mime_subparts(part, alt); + curl_mime_type(part, "multipart/alternative"); + slist = curl_slist_append(NULL, "Content-Disposition: inline"); + curl_mime_headers(part, slist, 1); + + /* Add the attachment. */ + if (param->attachment) + { + for (attachment = (const char **)param->attachment; *attachment; attachment++) + { + part = curl_mime_addpart(mime); + curl_mime_filedata(part, *attachment); + } + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + } + + /* Send the message */ + res = curl_easy_perform(curl); + param->code = res; + + /* Check for errors */ + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + + /* Free lists. */ + curl_slist_free_all(recipients); + if (headers) + curl_slist_free_all(headers); + + /* curl will not send the QUIT command until you call cleanup, so you + * should be able to re-use this connection for additional messages + * (setting CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and + * calling curl_easy_perform() again. It may not be a good idea to keep + * the connection open for a very long time though (more than a few + * minutes may result in the server timing out the connection), and you do + * want to clean up in the end. + */ + curl_easy_cleanup(curl); + + /* Free multipart message. */ + curl_mime_free(mime); + headers_free(headers_text); + } +} +void smtp_servers_send_email_only_text(SERVERS_SMTP *param) +{ +#if 0 // only for test. + if (!param) + { + LogError("null pointer.\n"); + return; + } + int payloadTextLength = + strlen(DATE HEADER_END) + strlen(TO HEADER_END) + strlen(FROM HEADER_END) + strlen(SUBJECT HEADER_END) + + strlen(param->date) + strlen(param->to) + strlen(param->from) + strlen(param->subject); + if (param->inlineText) + { + payloadTextLength += strlen(param->inlineText); + } + char *payload_text = (char *)malloc(payloadTextLength); + if (!payload_text) + { + LogError("null pointer.\n"); + return; + } + snprintf(payload_text, payloadTextLength, "%s%s%s" + "%s%s%s" + "%s%s%s" + "%s%s%s" + "%s", + DATE, param->date, HEADER_END, + TO, param->to, HEADER_END, + FROM, param->from, HEADER_END, + SUBJECT, param->subject, HEADER_END HEADER_END, + param->inlineText); + // LogInfo("payload_text =\n%s\n", payload_text); + CURL *curl; + CURLcode res = CURLE_OK; + struct curl_slist *recipients = NULL; + struct upload_status upload_ctx = {0}; + upload_ctx.payload_text = payload_text; + + curl = curl_easy_make(); + if (curl) + { + curl_mime *mime; + curl_mime *alt; + curl_mimepart *part; + struct curl_slist *slist = NULL; + /* This is the URL for your mailserver */ + curl_easy_setopt(curl, CURLOPT_URL, param->url); + /* Set the username and password */ + curl_easy_setopt(curl, CURLOPT_USERNAME, param->userName); + curl_easy_setopt(curl, CURLOPT_PASSWORD, param->password); + + /* Note that this option is not strictly required, omitting it will result + * in libcurl sending the MAIL FROM command with empty sender data. All + * autoresponses should have an empty reverse-path, and should be directed + * to the address in the reverse-path which triggered them. Otherwise, + * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more + * details. + */ + curl_easy_setopt(curl, CURLOPT_MAIL_FROM, param->from); + + /* Add two recipients, in this particular case they correspond to the + * To: and Cc: addressees in the header, but they could be any kind of + * recipient. */ + recipients = curl_slist_append(recipients, param->to); + // recipients = curl_slist_append(recipients, CC_ADDR); + curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); + + /* We are using a callback function to specify the payload (the headers and + * body of the message). You could just use the CURLOPT_READDATA option to + * specify a FILE pointer to read from. */ + curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); + curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + + // /* Build the mime message. */ + // mime = curl_mime_init(curl); + // /* Create the inline part. */ + // part = curl_mime_addpart(mime); + // curl_mime_subparts(part, alt); + // curl_mime_type(part, "multipart/alternative"); + // slist = curl_slist_append(NULL, "Content-Disposition: inline"); + // curl_mime_headers(part, slist, 1); + // curl_mime_filedata(part, "./Makefile"); + // curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + + /* Send the message */ + res = curl_easy_perform(curl); + param->code = res; + + /* Check for errors */ + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + + /* Free the list of recipients */ + curl_slist_free_all(recipients); + + /* curl will not send the QUIT command until you call cleanup, so you + * should be able to re-use this connection for additional messages + * (setting CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and + * calling curl_easy_perform() again. It may not be a good idea to keep + * the connection open for a very long time though (more than a few + * minutes may result in the server timing out the connection), and you do + * want to clean up in the end. + */ + curl_easy_cleanup(curl); + /* Free multipart message. */ + curl_mime_free(mime); + free(payload_text); + } +#endif +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/src/smtp_servers.h b/code/application/sifarsdk/component/Servers/src/smtp_servers.h new file mode 100644 index 000000000..5684575a2 --- /dev/null +++ b/code/application/sifarsdk/component/Servers/src/smtp_servers.h @@ -0,0 +1,13 @@ +#ifndef SMTP_SERVERS_H +#define SMTP_SERVERS_H +#include "servers.h" +#ifdef __cplusplus +extern "C" +{ +#endif + void smtp_servers_send_email(SERVERS_SMTP *param); + void smtp_servers_send_email_only_text(SERVERS_SMTP *param); +#ifdef __cplusplus +} +#endif +#endif // !SMTP_SERVERS_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/test/CMakeLists.txt b/code/application/sifarsdk/component/Servers/test/CMakeLists.txt new file mode 100644 index 000000000..1045d0f5f --- /dev/null +++ b/code/application/sifarsdk/component/Servers/test/CMakeLists.txt @@ -0,0 +1,35 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/Servers/include +) +#do not rely on any other library +# link_directories( +# ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/build/lib +# ) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES1) + +set(TARGET_NAME ServersMainTest) +add_executable(${TARGET_NAME} ${SRC_FILES1}) +target_link_libraries(${TARGET_NAME} Servers) +if(${CURL_OPENSSL_LIB_SHARED_ENABLE} MATCHES "false") + target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.a) + target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/libssl.a) + target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/libcrypto.a) +else() + target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.so) + target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/libssl.so) + target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/libcrypto.so) +endif() +target_link_libraries(${TARGET_NAME} pthread dl) +if(${COVERAGE_ON} MATCHES "true") + target_link_libraries(${TARGET_NAME} gcov) +endif() \ No newline at end of file diff --git a/code/application/sifarsdk/component/Servers/test/test_main.c b/code/application/sifarsdk/component/Servers/test/test_main.c new file mode 100644 index 000000000..4bfbf383a --- /dev/null +++ b/code/application/sifarsdk/component/Servers/test/test_main.c @@ -0,0 +1,38 @@ +#include +#include "servers.h" +void test0() +{ + // InitLog(LOG_EASYLOGGING, NULL); + // LogInfo("servers test start.\n"); + SERVERS_HTTP *http = new_servers_http("http://example.com"); + if (http) + { + http_get(http); + if (http->reply) + { + // LogInfo("HttpGet ========\n %s\n", http->reply); + } + delete_servers_http(http); + } + // UnInitLog(); +} +void test1() +{ + // InitLog(LOG_EASYLOGGING, NULL); + // LogInfo("servers test start.\n"); + // SERVERS_HTTP *http = new_servers_http("https://example.com"); + // if (http) + // { + // http_get(http); + // if (http->reply) + // { + // LogInfo("HttpGet ========\n %s\n", http->reply); + // } + // delete_servers_http(http); + // } + // UnInitLog(); +} +int main(int argc, char *argv[]) +{ + return 0; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/SignatureManager/CMakeLists.txt b/code/application/sifarsdk/component/SignatureManager/CMakeLists.txt new file mode 100644 index 000000000..b616e1e46 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/CMakeLists.txt @@ -0,0 +1,27 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/SystemTime/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME SignatureManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +# 这个模块暴露头文件过多,待梳理和优化 \ No newline at end of file diff --git a/code/application/sifarsdk/component/SignatureManager/include/HMACSHA.h b/code/application/sifarsdk/component/SignatureManager/include/HMACSHA.h new file mode 100644 index 000000000..78df103dd --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/HMACSHA.h @@ -0,0 +1,21 @@ +#ifndef HMACSHA_H +#define HMACSHA_H +#include "SfTypeDefine.h" +#if __cplusplus +extern "C" +{ +#endif + typedef struct SignatureTime + { + unsigned short Year; + unsigned short Mon; + unsigned short Day; + unsigned short Hour; + unsigned short Min; + unsigned short Sec; + } SignatureTime; + void amz_signature(UINT8 *signatureStr, UINT32 content_len, UINT8 *objectName, UINT8 *typestr, UINT8 *password, UINT8 *bucket, UINT8 *region, const SignatureTime time); +#if __cplusplus +} +#endif +#endif diff --git a/code/application/sifarsdk/component/SignatureManager/include/HttpCommon.h b/code/application/sifarsdk/component/SignatureManager/include/HttpCommon.h new file mode 100644 index 000000000..e61fd26da --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/HttpCommon.h @@ -0,0 +1,16 @@ +#ifndef HTTP_COMMON_H +#define HTTP_COMMON_H +#include "SfTypeDefine.h" +#include +#define SF_MAX_PATH_LEN 128 +#define SF_MAX_PIC_LEN 64 +#define SF_SRCFILE_MAX 4 +#define SF_THUMB_FILE_MAX_LEN 20 +#define SF_IMEI_MAX_LEN (32) +#define SF_SD_ROOT "/mnt/mmc/" // TODO: +#define AMZ_HOST "s3.amazonaws.com" // TODO: +#define AMZ_PW_TITLE "AWS4" // TODO: +#define SECRET_TYPE "AWS4-HMAC-SHA256" // TODO: +#define SECRET_VER "aws4_request" // TODO: +#define AMZ "s3" // TODO: +#endif // !HTTP_COMMON_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/SignatureManager/include/RtcTimeCpp.h b/code/application/sifarsdk/component/SignatureManager/include/RtcTimeCpp.h new file mode 100644 index 000000000..5f7767f99 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/RtcTimeCpp.h @@ -0,0 +1,12 @@ +#ifndef RTC_TIME_CPP_H +#define RTC_TIME_CPP_H +#include +#ifdef __cplusplus +extern "C" +{ +#endif +struct rtc_time GetRtcTime(void); +#ifdef __cplusplus +} +#endif +#endif // !RTC_TIME_CPP_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/SignatureManager/include/aos_util.h b/code/application/sifarsdk/component/SignatureManager/include/aos_util.h new file mode 100644 index 000000000..56f7647f8 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/aos_util.h @@ -0,0 +1,41 @@ +#ifndef LIBAOS_UTIL_H +#define LIBAOS_UTIL_H +#include "SfTypeDefine.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + + + +#define APR_SHA1_DIGESTSIZE 20 + +/** + * base64 encode bytes. The output buffer must have at least + * ((4 * (inLen + 1)) / 3) bytes in it. Returns the number of bytes written + * to [out]. + */ +int aos_base64_encode(const UINT8 *in, int inLen, UINT8 *out); + +/** + * Compute HMAC-SHA-1 with key [key] and message [message], storing result + * in [hmac] + */ +void HMAC_SHA1(UINT8 hmac[20], const UINT8 *key, int key_len, + const UINT8 *message, int message_len); + +/*void oss_sign_headers(aos_pool_t *p, const aos_string_t *signstr, const aos_string_t *access_key_id, + const aos_string_t *access_key_secret, aos_table_t *headers);*/ + +void oss_sign_headers(); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr.h b/code/application/sifarsdk/component/SignatureManager/include/apr.h new file mode 100644 index 000000000..a75bc6029 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr.h @@ -0,0 +1,644 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_H +#define APR_H + +/* GENERATED FILE WARNING! DO NOT EDIT apr.h + * + * You must modify apr.hw instead. + * + * And please, make an effort to stub apr.hnw and apr.h.in in the process. + * + * This is the Win32 specific version of apr.h. It is copied from + * apr.hw by the apr.dsp and libapr.dsp projects. + */ + +/** + * @file apr.h + * @brief APR Platform Definitions + * @remark This is a generated header generated from include/apr.h.in by + * ./configure, or copied from include/apr.hw or include/apr.hnw + * for Win32 or Netware by those build environments, respectively. + */ + +/* Make sure we have our platform identifier macro defined we ask for later. + */ +#if defined(_WIN32) && !defined(WIN32) +#define WIN32 1 +#endif + +#if defined(WIN32) || defined(DOXYGEN) + +/* Ignore most warnings (back down to /W3) for poorly constructed headers + */ +#if defined(_MSC_VER) && _MSC_VER >= 1200 +#pragma warning(push, 3) +#endif + +/* disable or reduce the frequency of... + * C4057: indirection to slightly different base types + * C4075: slight indirection changes (unsigned short* vs short[]) + * C4100: unreferenced formal parameter + * C4127: conditional expression is constant + * C4163: '_rotl64' : not available as an intrinsic function + * C4201: nonstandard extension nameless struct/unions + * C4244: int to char/short - precision loss + * C4514: unreferenced inline function removed + */ +#pragma warning(disable: 4100 4127 4163 4201 4514; once: 4057 4075 4244) + +/* Ignore Microsoft's interpretation of secure development + * and the POSIX string handling API + */ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif +#pragma warning(disable: 4996) +#endif + +/* Has windows.h already been included? If so, our preferences don't matter, + * but we will still need the winsock things no matter what was included. + * If not, include a restricted set of windows headers to our tastes. + */ +#ifndef _WINDOWS_ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef _WIN32_WINNT + +/* Restrict the server to a subset of Windows XP header files by default + */ +#define _WIN32_WINNT 0x0501 +#endif +#ifndef NOUSER +#define NOUSER +#endif +#ifndef NOMCX +#define NOMCX +#endif +#ifndef NOIME +#define NOIME +#endif +#include +/* + * Add a _very_few_ declarations missing from the restricted set of headers + * (If this list becomes extensive, re-enable the required headers above!) + * winsock headers were excluded by WIN32_LEAN_AND_MEAN, so include them now + */ +#define SW_HIDE 0 +#ifndef _WIN32_WCE +#include +#include +#include +#else +#include +#endif +#endif /* !_WINDOWS_ */ + +/** + * @defgroup APR Apache Portability Runtime library + * @{ + */ +/** + * @defgroup apr_platform Platform Definitions + * @{ + * @warning + * The actual values of macros and typedefs on this page
+ * are platform specific and should NOT be relied upon!
+ */ + +#define APR_INLINE __inline +#define APR_HAS_INLINE 1 +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(__x) +#endif + +#ifndef _WIN32_WCE +#define APR_HAVE_ARPA_INET_H 0 +#define APR_HAVE_CONIO_H 1 +#define APR_HAVE_CRYPT_H 0 +#define APR_HAVE_CTYPE_H 1 +#define APR_HAVE_DIRENT_H 0 +#define APR_HAVE_ERRNO_H 1 +#define APR_HAVE_FCNTL_H 1 +#define APR_HAVE_IO_H 1 +#define APR_HAVE_LIMITS_H 1 +#define APR_HAVE_NETDB_H 0 +#define APR_HAVE_NETINET_IN_H 0 +#define APR_HAVE_NETINET_SCTP_H 0 +#define APR_HAVE_NETINET_SCTP_UIO_H 0 +#define APR_HAVE_NETINET_TCP_H 0 +#define APR_HAVE_PTHREAD_H 0 +#define APR_HAVE_SEMAPHORE_H 0 +#define APR_HAVE_SIGNAL_H 1 +#define APR_HAVE_STDARG_H 1 +#define APR_HAVE_STDINT_H 0 +#define APR_HAVE_STDIO_H 1 +#define APR_HAVE_STDLIB_H 1 +#define APR_HAVE_STRING_H 1 +#define APR_HAVE_STRINGS_H 0 +#define APR_HAVE_SYS_IOCTL_H 0 +#define APR_HAVE_SYS_SENDFILE_H 0 +#define APR_HAVE_SYS_SIGNAL_H 0 +#define APR_HAVE_SYS_SOCKET_H 0 +#define APR_HAVE_SYS_SOCKIO_H 0 +#define APR_HAVE_SYS_SYSLIMITS_H 0 +#define APR_HAVE_SYS_TIME_H 0 +#define APR_HAVE_SYS_TYPES_H 1 +#define APR_HAVE_SYS_UIO_H 0 +#define APR_HAVE_SYS_UN_H 0 +#define APR_HAVE_SYS_WAIT_H 0 +#define APR_HAVE_TIME_H 1 +#define APR_HAVE_UNISTD_H 0 +#define APR_HAVE_STDDEF_H 1 +#define APR_HAVE_PROCESS_H 1 +#else +#define APR_HAVE_ARPA_INET_H 0 +#define APR_HAVE_CONIO_H 0 +#define APR_HAVE_CRYPT_H 0 +#define APR_HAVE_CTYPE_H 0 +#define APR_HAVE_DIRENT_H 0 +#define APR_HAVE_ERRNO_H 0 +#define APR_HAVE_FCNTL_H 0 +#define APR_HAVE_IO_H 0 +#define APR_HAVE_LIMITS_H 0 +#define APR_HAVE_NETDB_H 0 +#define APR_HAVE_NETINET_IN_H 0 +#define APR_HAVE_NETINET_SCTP_H 0 +#define APR_HAVE_NETINET_SCTP_UIO_H 0 +#define APR_HAVE_NETINET_TCP_H 0 +#define APR_HAVE_PTHREAD_H 0 +#define APR_HAVE_SEMAPHORE_H 0 +#define APR_HAVE_SIGNAL_H 0 +#define APR_HAVE_STDARG_H 0 +#define APR_HAVE_STDINT_H 0 +#define APR_HAVE_STDIO_H 1 +#define APR_HAVE_STDLIB_H 1 +#define APR_HAVE_STRING_H 1 +#define APR_HAVE_STRINGS_H 0 +#define APR_HAVE_SYS_IOCTL_H 0 +#define APR_HAVE_SYS_SENDFILE_H 0 +#define APR_HAVE_SYS_SIGNAL_H 0 +#define APR_HAVE_SYS_SOCKET_H 0 +#define APR_HAVE_SYS_SOCKIO_H 0 +#define APR_HAVE_SYS_SYSLIMITS_H 0 +#define APR_HAVE_SYS_TIME_H 0 +#define APR_HAVE_SYS_TYPES_H 0 +#define APR_HAVE_SYS_UIO_H 0 +#define APR_HAVE_SYS_UN_H 0 +#define APR_HAVE_SYS_WAIT_H 0 +#define APR_HAVE_TIME_H 0 +#define APR_HAVE_UNISTD_H 0 +#define APR_HAVE_STDDEF_H 0 +#define APR_HAVE_PROCESS_H 0 +#endif + +/** @} */ +/** @} */ + +/* We don't include our conditional headers within the doxyblocks + * or the extern "C" namespace + */ + +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_STDDEF_H +#include +#endif +#if APR_HAVE_TIME_H +#include +#endif +#if APR_HAVE_PROCESS_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup apr_platform + * @ingroup APR + * @{ + */ + +#define APR_HAVE_SHMEM_MMAP_TMP 0 +#define APR_HAVE_SHMEM_MMAP_SHM 0 +#define APR_HAVE_SHMEM_MMAP_ZERO 0 +#define APR_HAVE_SHMEM_SHMGET_ANON 0 +#define APR_HAVE_SHMEM_SHMGET 0 +#define APR_HAVE_SHMEM_MMAP_ANON 0 +#define APR_HAVE_SHMEM_BEOS 0 + +#define APR_USE_SHMEM_MMAP_TMP 0 +#define APR_USE_SHMEM_MMAP_SHM 0 +#define APR_USE_SHMEM_MMAP_ZERO 0 +#define APR_USE_SHMEM_SHMGET_ANON 0 +#define APR_USE_SHMEM_SHMGET 0 +#define APR_USE_SHMEM_MMAP_ANON 0 +#define APR_USE_SHMEM_BEOS 0 + +#define APR_USE_FLOCK_SERIALIZE 0 +#define APR_USE_POSIXSEM_SERIALIZE 0 +#define APR_USE_SYSVSEM_SERIALIZE 0 +#define APR_USE_FCNTL_SERIALIZE 0 +#define APR_USE_PROC_PTHREAD_SERIALIZE 0 +#define APR_USE_PTHREAD_SERIALIZE 0 + +#define APR_HAS_FLOCK_SERIALIZE 0 +#define APR_HAS_SYSVSEM_SERIALIZE 0 +#define APR_HAS_POSIXSEM_SERIALIZE 0 +#define APR_HAS_FCNTL_SERIALIZE 0 +#define APR_HAS_PROC_PTHREAD_SERIALIZE 0 + +#define APR_PROCESS_LOCK_IS_GLOBAL 0 + +#define APR_HAVE_CORKABLE_TCP 0 +#define APR_HAVE_GETRLIMIT 0 +#define APR_HAVE_ICONV 0 +#define APR_HAVE_IN_ADDR 1 +#define APR_HAVE_INET_ADDR 1 +#define APR_HAVE_INET_NETWORK 0 +#define APR_HAVE_IPV6 0 +#define APR_HAVE_MEMMOVE 1 +#define APR_HAVE_SETRLIMIT 0 +#define APR_HAVE_SIGACTION 0 +#define APR_HAVE_SIGSUSPEND 0 +#define APR_HAVE_SIGWAIT 0 +#define APR_HAVE_SA_STORAGE 0 +#define APR_HAVE_STRCASECMP 0 +#define APR_HAVE_STRDUP 1 +#define APR_HAVE_STRNCASECMP 0 +#define APR_HAVE_STRSTR 1 +#define APR_HAVE_MEMCHR 1 +#define APR_HAVE_STRUCT_RLIMIT 0 +#define APR_HAVE_UNION_SEMUN 0 +#define APR_HAVE_SCTP 0 +#define APR_HAVE_IOVEC 0 + +#ifndef _WIN32_WCE +#define APR_HAVE_STRICMP 1 +#define APR_HAVE_STRNICMP 1 +#else +#define APR_HAVE_STRICMP 0 +#define APR_HAVE_STRNICMP 0 +#endif + +/* APR Feature Macros */ +#define APR_HAS_SHARED_MEMORY 1 +#define APR_HAS_THREADS 1 +#define APR_HAS_MMAP 1 +#define APR_HAS_FORK 0 +#define APR_HAS_RANDOM 1 +#define APR_HAS_OTHER_CHILD 1 +#define APR_HAS_DSO 1 +#define APR_HAS_SO_ACCEPTFILTER 0 +#define APR_HAS_UNICODE_FS 1 +#define APR_HAS_PROC_INVOKED 1 +#define APR_HAS_OS_UUID 1 + +#ifndef _WIN32_WCE +#define APR_HAS_SENDFILE 1 +#define APR_HAS_USER 1 +#define APR_HAS_LARGE_FILES 1 +#define APR_HAS_XTHREAD_FILES 1 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 1 +#else +#define APR_HAS_SENDFILE 0 +#define APR_HAS_USER 0 +#define APR_HAS_LARGE_FILES 0 +#define APR_HAS_XTHREAD_FILES 0 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0 +#endif + +/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible + * to poll on files/pipes. + */ +#define APR_FILES_AS_SOCKETS 0 + +/* This macro indicates whether or not EBCDIC is the native character set. + */ +#define APR_CHARSET_EBCDIC 0 + +/* If we have a TCP implementation that can be "corked", what flag + * do we use? + */ +#define APR_TCP_NOPUSH_FLAG @apr_tcp_nopush_flag@ + +/* Is the TCP_NODELAY socket option inherited from listening sockets? + */ +#define APR_TCP_NODELAY_INHERITED 1 + +/* Is the O_NONBLOCK flag inherited from listening sockets? + */ +#define APR_O_NONBLOCK_INHERITED 1 + +/* Typedefs that APR needs. */ + +typedef unsigned char apr_byte_t; + +typedef short apr_int16_t; +typedef unsigned short apr_uint16_t; + +typedef int apr_int32_t; +typedef unsigned int apr_uint32_t; + +typedef __int64 apr_int64_t; +typedef unsigned __int64 apr_uint64_t; + +typedef size_t apr_size_t; +#if APR_HAVE_STDDEF_H +typedef ptrdiff_t apr_ssize_t; +#else +typedef int apr_ssize_t; +#endif +#if APR_HAS_LARGE_FILES +typedef __int64 apr_off_t; +#else +typedef int apr_off_t; +#endif +typedef int apr_socklen_t; +typedef apr_uint64_t apr_ino_t; + +#ifdef _WIN64 +#define APR_SIZEOF_VOIDP 8 +#else +#define APR_SIZEOF_VOIDP 4 +#endif + +#if APR_SIZEOF_VOIDP == 8 +typedef apr_uint64_t apr_uintptr_t; +#else +typedef apr_uint32_t apr_uintptr_t; +#endif + +/* Are we big endian? */ +/* XXX: Fatal assumption on Alpha platforms */ +#define APR_IS_BIGENDIAN 0 + +/* Mechanisms to properly type numeric literals */ + +#ifndef __GNUC__ +#define APR_INT64_C(val) (val##i64) +#define APR_UINT64_C(val) (val##Ui64) +#else +#define APR_INT64_C(val) (val##LL) +#define APR_UINT64_C(val) (val##ULL) +#endif + +#ifdef INT16_MIN +#define APR_INT16_MIN INT16_MIN +#else +#define APR_INT16_MIN (-0x7fff - 1) +#endif + +#ifdef INT16_MAX +#define APR_INT16_MAX INT16_MAX +#else +#define APR_INT16_MAX (0x7fff) +#endif + +#ifdef UINT16_MAX +#define APR_UINT16_MAX UINT16_MAX +#else +#define APR_UINT16_MAX (0xffff) +#endif + +#ifdef INT32_MIN +#define APR_INT32_MIN INT32_MIN +#else +#define APR_INT32_MIN (-0x7fffffff - 1) +#endif + +#ifdef INT32_MAX +#define APR_INT32_MAX INT32_MAX +#else +#define APR_INT32_MAX 0x7fffffff +#endif + +#ifdef UINT32_MAX +#define APR_UINT32_MAX UINT32_MAX +#else +#define APR_UINT32_MAX (0xffffffffU) +#endif + +#ifdef INT64_MIN +#define APR_INT64_MIN INT64_MIN +#else +#define APR_INT64_MIN (APR_INT64_C(-0x7fffffffffffffff) - 1) +#endif + +#ifdef INT64_MAX +#define APR_INT64_MAX INT64_MAX +#else +#define APR_INT64_MAX APR_INT64_C(0x7fffffffffffffff) +#endif + +#ifdef UINT64_MAX +#define APR_UINT64_MAX UINT64_MAX +#else +#define APR_UINT64_MAX APR_UINT64_C(0xffffffffffffffff) +#endif + +#define APR_SIZE_MAX (~((apr_size_t)0)) + +/* Definitions that APR programs need to work properly. */ + +/** + * APR public API wrap for C++ compilers. + */ +#ifdef __cplusplus +#define APR_BEGIN_DECLS extern "C" { +#define APR_END_DECLS } +#else +#define APR_BEGIN_DECLS +#define APR_END_DECLS +#endif + +/** + * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC, + * so that they follow the platform's calling convention. + *
+ *
+ * void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
+ *
+ * 
+ */ +#define APR_THREAD_FUNC __stdcall + + +#if defined(DOXYGEN) || !defined(WIN32) + +/** + * The public APR functions are declared with APR_DECLARE(), so they may + * use the most appropriate calling convention. Public APR functions with + * variable arguments must use APR_DECLARE_NONSTD(). + * + * @remark Both the declaration and implementations must use the same macro. + * + *
+ * APR_DECLARE(rettype) apr_func(args)
+ * 
+ * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA + * @remark Note that when APR compiles the library itself, it passes the + * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32) + * to export public symbols from the dynamic library build.\n + * The user must define the APR_DECLARE_STATIC when compiling to target + * the static APR library on some platforms (e.g. Win32.) The public symbols + * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n + * By default, compiling an application and including the APR public + * headers, without defining APR_DECLARE_STATIC, will prepare the code to be + * linked to the dynamic library. + */ +#define APR_DECLARE(type) type + +/** + * The public APR functions using variable arguments are declared with + * APR_DECLARE_NONSTD(), as they must follow the C language calling convention. + * @see APR_DECLARE @see APR_DECLARE_DATA + * @remark Both the declaration and implementations must use the same macro. + *
+ *
+ * APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ *
+ * 
+ */ +#define APR_DECLARE_NONSTD(type) type + +/** + * The public APR variables are declared with AP_MODULE_DECLARE_DATA. + * This assures the appropriate indirection is invoked at compile time. + * @see APR_DECLARE @see APR_DECLARE_NONSTD + * @remark Note that the declaration and implementations use different forms, + * but both must include the macro. + * + *
+ *
+ * extern APR_DECLARE_DATA type apr_variable;\n
+ * APR_DECLARE_DATA type apr_variable = value;
+ *
+ * 
+ */ +#define APR_DECLARE_DATA + +#elif defined(APR_DECLARE_STATIC) +#define APR_DECLARE(type) type __stdcall +#define APR_DECLARE_NONSTD(type) type __cdecl +#define APR_DECLARE_DATA +#elif defined(APR_DECLARE_EXPORT) +#define APR_DECLARE(type) __declspec(dllexport) type __stdcall +#define APR_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl +#define APR_DECLARE_DATA __declspec(dllexport) +#else +#define APR_DECLARE(type) __declspec(dllimport) type __stdcall +#define APR_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl +#define APR_DECLARE_DATA __declspec(dllimport) +#endif + +#ifdef _WIN64 +#define APR_SSIZE_T_FMT "I64d" +#define APR_SIZE_T_FMT "I64u" +#else +#define APR_SSIZE_T_FMT "d" +#define APR_SIZE_T_FMT "u" +#endif + +#if APR_HAS_LARGE_FILES +#define APR_OFF_T_FMT "I64d" +#else +#define APR_OFF_T_FMT "d" +#endif + +#define APR_PID_T_FMT "d" + +#define APR_INT64_T_FMT "I64d" +#define APR_UINT64_T_FMT "I64u" +#define APR_UINT64_T_HEX_FMT "I64x" + +/* No difference between PROC and GLOBAL mutex */ +#define APR_PROC_MUTEX_IS_GLOBAL 1 + +/* Local machine definition for console and log output. */ +#define APR_EOL_STR "\r\n" + +typedef int apr_wait_t; + +#if APR_HAS_UNICODE_FS +/* An arbitrary size that is digestable. True max is a bit less than 32000 */ +#define APR_PATH_MAX 8192 +#else /* !APR_HAS_UNICODE_FS */ +#define APR_PATH_MAX MAX_PATH +#endif + +#define APR_DSOPATH "PATH" + +/** @} */ + +/* Definitions that only Win32 programs need to compile properly. */ + +/* XXX These simply don't belong here, perhaps in apr_portable.h + * based on some APR_HAVE_PID/GID/UID? + */ +#ifndef __GNUC__ +typedef int pid_t; +#endif +typedef int uid_t; +typedef int gid_t; + +/* Win32 .h ommissions we really need */ +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#if APR_HAVE_IPV6 + +/* Appears in later flavors, not the originals. */ +#ifndef in_addr6 +#define in6_addr in_addr6 +#endif + +#ifndef WS2TCPIP_INLINE +#define IN6_IS_ADDR_V4MAPPED(a) \ + ( (*(const apr_uint64_t *)(const void *)(&(a)->s6_addr[0]) == 0) \ + && (*(const apr_uint32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff))) +#endif + +#endif /* APR_HAS_IPV6 */ + +#ifdef __cplusplus +} +#endif + +/* Done with badly written headers + */ +#if defined(_MSC_VER) && _MSC_VER >= 1200 +#pragma warning(pop) +#pragma warning(disable: 4996) +#endif + +#endif /* WIN32 */ + +#endif /* APR_H */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr_errno.h b/code/application/sifarsdk/component/SignatureManager/include/apr_errno.h new file mode 100644 index 000000000..b60822b24 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr_errno.h @@ -0,0 +1,1316 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_ERRNO_H +#define APR_ERRNO_H + +/** + * @file apr_errno.h + * @brief APR Error Codes + */ + +#include "apr.h" + +#if APR_HAVE_ERRNO_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_errno Error Codes + * @ingroup APR + * @{ + */ + +/** + * Type for specifying an error or status code. + */ +typedef int apr_status_t; + +/** + * Return a human readable string describing the specified error. + * @param statcode The error code to get a string for. + * @param buf A buffer to hold the error string. + * @param bufsize Size of the buffer to hold the string. + */ +/*APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf, + apr_size_t bufsize);*/ + +#if 0 +defined(DOXYGEN) +/** + * @def APR_FROM_OS_ERROR(os_err_type syserr) + * Fold a platform specific error into an apr_status_t code. + * @return apr_status_t + * @param e The platform os error code. + * @warning macro implementation; the syserr argument may be evaluated + * multiple times. + */ +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) + +/** + * @def APR_TO_OS_ERROR(apr_status_t statcode) + * @return os_err_type + * Fold an apr_status_t code back to the native platform defined error. + * @param e The apr_status_t folded platform os error code. + * @warning macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. + */ +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +/** @def apr_get_os_error() + * @return apr_status_t the last platform error, folded into apr_status_t, on most platforms + * @remark This retrieves errno, or calls a GetLastError() style function, and + * folds it with APR_FROM_OS_ERROR. Some platforms (such as OS2) have no + * such mechanism, so this call may be unsupported. Do NOT use this + * call for socket errors from socket, send, recv etc! + */ + +/** @def apr_set_os_error(e) + * Reset the last platform error, unfolded from an apr_status_t, on some platforms + * @param e The OS error folded in a prior call to APR_FROM_OS_ERROR() + * @warning This is a macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. This macro sets + * errno, or calls a SetLastError() style function, unfolding statcode + * with APR_TO_OS_ERROR. Some platforms (such as OS2) have no such + * mechanism, so this call may be unsupported. + */ + +/** @def apr_get_netos_error() + * Return the last socket error, folded into apr_status_t, on all platforms + * @remark This retrieves errno or calls a GetLastSocketError() style function, + * and folds it with APR_FROM_OS_ERROR. + */ + +/** @def apr_set_netos_error(e) + * Reset the last socket error, unfolded from an apr_status_t + * @param e The socket error folded in a prior call to APR_FROM_OS_ERROR() + * @warning This is a macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. This macro sets + * errno, or calls a WSASetLastError() style function, unfolding + * socketcode with APR_TO_OS_ERROR. + */ + +#endif /* defined(DOXYGEN) */ + +/** + * APR_OS_START_ERROR is where the APR specific error values start. + */ +#define APR_OS_START_ERROR 20000 +/** + * APR_OS_ERRSPACE_SIZE is the maximum number of errors you can fit + * into one of the error/status ranges below -- except for + * APR_OS_START_USERERR, which see. + */ +#define APR_OS_ERRSPACE_SIZE 50000 +/** + * APR_UTIL_ERRSPACE_SIZE is the size of the space that is reserved for + * use within apr-util. This space is reserved above that used by APR + * internally. + * @note This number MUST be smaller than APR_OS_ERRSPACE_SIZE by a + * large enough amount that APR has sufficient room for its + * codes. + */ +#define APR_UTIL_ERRSPACE_SIZE 20000 +/** + * APR_OS_START_STATUS is where the APR specific status codes start. + */ +#define APR_OS_START_STATUS (APR_OS_START_ERROR + APR_OS_ERRSPACE_SIZE) +/** + * APR_UTIL_START_STATUS is where APR-Util starts defining its + * status codes. + */ +#define APR_UTIL_START_STATUS (APR_OS_START_STATUS + \ + (APR_OS_ERRSPACE_SIZE - APR_UTIL_ERRSPACE_SIZE)) +/** + * APR_OS_START_USERERR are reserved for applications that use APR that + * layer their own error codes along with APR's. Note that the + * error immediately following this one is set ten times farther + * away than usual, so that users of apr have a lot of room in + * which to declare custom error codes. + * + * In general applications should try and create unique error codes. To try + * and assist in finding suitable ranges of numbers to use, the following + * ranges are known to be used by the listed applications. If your + * application defines error codes please advise the range of numbers it + * uses to dev@apr.apache.org for inclusion in this list. + * + * Ranges shown are in relation to APR_OS_START_USERERR + * + * Subversion - Defined ranges, of less than 100, at intervals of 5000 + * starting at an offset of 5000, e.g. + * +5000 to 5100, +10000 to 10100 + * + * Apache HTTPD - +2000 to 2999 + */ +#define APR_OS_START_USERERR (APR_OS_START_STATUS + APR_OS_ERRSPACE_SIZE) +/** + * APR_OS_START_USEERR is obsolete, defined for compatibility only. + * Use APR_OS_START_USERERR instead. + */ +#define APR_OS_START_USEERR APR_OS_START_USERERR +/** + * APR_OS_START_CANONERR is where APR versions of errno values are defined + * on systems which don't have the corresponding errno. + */ +#define APR_OS_START_CANONERR (APR_OS_START_USERERR \ + + (APR_OS_ERRSPACE_SIZE * 10)) +/** + * APR_OS_START_EAIERR folds EAI_ error codes from getaddrinfo() into + * apr_status_t values. + */ +#define APR_OS_START_EAIERR (APR_OS_START_CANONERR + APR_OS_ERRSPACE_SIZE) +/** + * APR_OS_START_SYSERR folds platform-specific system error values into + * apr_status_t values. + */ +#define APR_OS_START_SYSERR (APR_OS_START_EAIERR + APR_OS_ERRSPACE_SIZE) + +/** + * @defgroup APR_ERROR_map APR Error Space + *
+ * The following attempts to show the relation of the various constants
+ * used for mapping APR Status codes.
+ *
+ *       0
+ *
+ *  20,000     APR_OS_START_ERROR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ *  70,000      APR_OS_START_STATUS
+ *
+ *         + APR_OS_ERRSPACE_SIZE - APR_UTIL_ERRSPACE_SIZE (30,000)
+ *
+ * 100,000      APR_UTIL_START_STATUS
+ *
+ *         + APR_UTIL_ERRSPACE_SIZE (20,000)
+ *
+ * 120,000      APR_OS_START_USERERR
+ *
+ *         + 10 x APR_OS_ERRSPACE_SIZE (50,000 * 10)
+ *
+ * 620,000      APR_OS_START_CANONERR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ * 670,000      APR_OS_START_EAIERR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ * 720,000      APR_OS_START_SYSERR
+ *
+ * 
+ */ + +/** no error. */ +#define APR_SUCCESS 0 + +/** + * @defgroup APR_Error APR Error Values + *
+ * APR ERROR VALUES
+ * APR_ENOSTAT      APR was unable to perform a stat on the file
+ * APR_ENOPOOL      APR was not provided a pool with which to allocate memory
+ * APR_EBADDATE     APR was given an invalid date
+ * APR_EINVALSOCK   APR was given an invalid socket
+ * APR_ENOPROC      APR was not given a process structure
+ * APR_ENOTIME      APR was not given a time structure
+ * APR_ENODIR       APR was not given a directory structure
+ * APR_ENOLOCK      APR was not given a lock structure
+ * APR_ENOPOLL      APR was not given a poll structure
+ * APR_ENOSOCKET    APR was not given a socket
+ * APR_ENOTHREAD    APR was not given a thread structure
+ * APR_ENOTHDKEY    APR was not given a thread key structure
+ * APR_ENOSHMAVAIL  There is no more shared memory available
+ * APR_EDSOOPEN     APR was unable to open the dso object.  For more
+ *                  information call apr_dso_error().
+ * APR_EGENERAL     General failure (specific information not available)
+ * APR_EBADIP       The specified IP address is invalid
+ * APR_EBADMASK     The specified netmask is invalid
+ * APR_ESYMNOTFOUND Could not find the requested symbol
+ * APR_ENOTENOUGHENTROPY Not enough entropy to continue
+ * 
+ * + *
+ * APR STATUS VALUES
+ * APR_INCHILD        Program is currently executing in the child
+ * APR_INPARENT       Program is currently executing in the parent
+ * APR_DETACH         The thread is detached
+ * APR_NOTDETACH      The thread is not detached
+ * APR_CHILD_DONE     The child has finished executing
+ * APR_CHILD_NOTDONE  The child has not finished executing
+ * APR_TIMEUP         The operation did not finish before the timeout
+ * APR_INCOMPLETE     The operation was incomplete although some processing
+ *                    was performed and the results are partially valid
+ * APR_BADCH          Getopt found an option not in the option string
+ * APR_BADARG         Getopt found an option that is missing an argument
+ *                    and an argument was specified in the option string
+ * APR_EOF            APR has encountered the end of the file
+ * APR_NOTFOUND       APR was unable to find the socket in the poll structure
+ * APR_ANONYMOUS      APR is using anonymous shared memory
+ * APR_FILEBASED      APR is using a file name as the key to the shared memory
+ * APR_KEYBASED       APR is using a shared key as the key to the shared memory
+ * APR_EINIT          Ininitalizer value.  If no option has been found, but
+ *                    the status variable requires a value, this should be used
+ * APR_ENOTIMPL       The APR function has not been implemented on this
+ *                    platform, either because nobody has gotten to it yet,
+ *                    or the function is impossible on this platform.
+ * APR_EMISMATCH      Two passwords do not match.
+ * APR_EABSOLUTE      The given path was absolute.
+ * APR_ERELATIVE      The given path was relative.
+ * APR_EINCOMPLETE    The given path was neither relative nor absolute.
+ * APR_EABOVEROOT     The given path was above the root path.
+ * APR_EBUSY          The given lock was busy.
+ * APR_EPROC_UNKNOWN  The given process wasn't recognized by APR
+ * 
+ * @{ + */ +/** @see APR_STATUS_IS_ENOSTAT */ +#define APR_ENOSTAT (APR_OS_START_ERROR + 1) +/** @see APR_STATUS_IS_ENOPOOL */ +#define APR_ENOPOOL (APR_OS_START_ERROR + 2) +/* empty slot: +3 */ +/** @see APR_STATUS_IS_EBADDATE */ +#define APR_EBADDATE (APR_OS_START_ERROR + 4) +/** @see APR_STATUS_IS_EINVALSOCK */ +#define APR_EINVALSOCK (APR_OS_START_ERROR + 5) +/** @see APR_STATUS_IS_ENOPROC */ +#define APR_ENOPROC (APR_OS_START_ERROR + 6) +/** @see APR_STATUS_IS_ENOTIME */ +#define APR_ENOTIME (APR_OS_START_ERROR + 7) +/** @see APR_STATUS_IS_ENODIR */ +#define APR_ENODIR (APR_OS_START_ERROR + 8) +/** @see APR_STATUS_IS_ENOLOCK */ +#define APR_ENOLOCK (APR_OS_START_ERROR + 9) +/** @see APR_STATUS_IS_ENOPOLL */ +#define APR_ENOPOLL (APR_OS_START_ERROR + 10) +/** @see APR_STATUS_IS_ENOSOCKET */ +#define APR_ENOSOCKET (APR_OS_START_ERROR + 11) +/** @see APR_STATUS_IS_ENOTHREAD */ +#define APR_ENOTHREAD (APR_OS_START_ERROR + 12) +/** @see APR_STATUS_IS_ENOTHDKEY */ +#define APR_ENOTHDKEY (APR_OS_START_ERROR + 13) +/** @see APR_STATUS_IS_EGENERAL */ +#define APR_EGENERAL (APR_OS_START_ERROR + 14) +/** @see APR_STATUS_IS_ENOSHMAVAIL */ +#define APR_ENOSHMAVAIL (APR_OS_START_ERROR + 15) +/** @see APR_STATUS_IS_EBADIP */ +#define APR_EBADIP (APR_OS_START_ERROR + 16) +/** @see APR_STATUS_IS_EBADMASK */ +#define APR_EBADMASK (APR_OS_START_ERROR + 17) +/* empty slot: +18 */ +/** @see APR_STATUS_IS_EDSOPEN */ +#define APR_EDSOOPEN (APR_OS_START_ERROR + 19) +/** @see APR_STATUS_IS_EABSOLUTE */ +#define APR_EABSOLUTE (APR_OS_START_ERROR + 20) +/** @see APR_STATUS_IS_ERELATIVE */ +#define APR_ERELATIVE (APR_OS_START_ERROR + 21) +/** @see APR_STATUS_IS_EINCOMPLETE */ +#define APR_EINCOMPLETE (APR_OS_START_ERROR + 22) +/** @see APR_STATUS_IS_EABOVEROOT */ +#define APR_EABOVEROOT (APR_OS_START_ERROR + 23) +/** @see APR_STATUS_IS_EBADPATH */ +#define APR_EBADPATH (APR_OS_START_ERROR + 24) +/** @see APR_STATUS_IS_EPATHWILD */ +#define APR_EPATHWILD (APR_OS_START_ERROR + 25) +/** @see APR_STATUS_IS_ESYMNOTFOUND */ +#define APR_ESYMNOTFOUND (APR_OS_START_ERROR + 26) +/** @see APR_STATUS_IS_EPROC_UNKNOWN */ +#define APR_EPROC_UNKNOWN (APR_OS_START_ERROR + 27) +/** @see APR_STATUS_IS_ENOTENOUGHENTROPY */ +#define APR_ENOTENOUGHENTROPY (APR_OS_START_ERROR + 28) +/** @} */ + +/** + * @defgroup APR_STATUS_IS Status Value Tests + * @warning For any particular error condition, more than one of these tests + * may match. This is because platform-specific error codes may not + * always match the semantics of the POSIX codes these tests (and the + * corresponding APR error codes) are named after. A notable example + * are the APR_STATUS_IS_ENOENT and APR_STATUS_IS_ENOTDIR tests on + * Win32 platforms. The programmer should always be aware of this and + * adjust the order of the tests accordingly. + * @{ + */ +/** + * APR was unable to perform a stat on the file + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOSTAT(s) ((s) == APR_ENOSTAT) +/** + * APR was not provided a pool with which to allocate memory + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOPOOL(s) ((s) == APR_ENOPOOL) +/** APR was given an invalid date */ +#define APR_STATUS_IS_EBADDATE(s) ((s) == APR_EBADDATE) +/** APR was given an invalid socket */ +#define APR_STATUS_IS_EINVALSOCK(s) ((s) == APR_EINVALSOCK) +/** APR was not given a process structure */ +#define APR_STATUS_IS_ENOPROC(s) ((s) == APR_ENOPROC) +/** APR was not given a time structure */ +#define APR_STATUS_IS_ENOTIME(s) ((s) == APR_ENOTIME) +/** APR was not given a directory structure */ +#define APR_STATUS_IS_ENODIR(s) ((s) == APR_ENODIR) +/** APR was not given a lock structure */ +#define APR_STATUS_IS_ENOLOCK(s) ((s) == APR_ENOLOCK) +/** APR was not given a poll structure */ +#define APR_STATUS_IS_ENOPOLL(s) ((s) == APR_ENOPOLL) +/** APR was not given a socket */ +#define APR_STATUS_IS_ENOSOCKET(s) ((s) == APR_ENOSOCKET) +/** APR was not given a thread structure */ +#define APR_STATUS_IS_ENOTHREAD(s) ((s) == APR_ENOTHREAD) +/** APR was not given a thread key structure */ +#define APR_STATUS_IS_ENOTHDKEY(s) ((s) == APR_ENOTHDKEY) +/** Generic Error which can not be put into another spot */ +#define APR_STATUS_IS_EGENERAL(s) ((s) == APR_EGENERAL) +/** There is no more shared memory available */ +#define APR_STATUS_IS_ENOSHMAVAIL(s) ((s) == APR_ENOSHMAVAIL) +/** The specified IP address is invalid */ +#define APR_STATUS_IS_EBADIP(s) ((s) == APR_EBADIP) +/** The specified netmask is invalid */ +#define APR_STATUS_IS_EBADMASK(s) ((s) == APR_EBADMASK) +/* empty slot: +18 */ +/** + * APR was unable to open the dso object. + * For more information call apr_dso_error(). + */ +#if defined(WIN32) +#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN \ + || APR_TO_OS_ERROR(s) == ERROR_MOD_NOT_FOUND) +#else +#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN) +#endif +/** The given path was absolute. */ +#define APR_STATUS_IS_EABSOLUTE(s) ((s) == APR_EABSOLUTE) +/** The given path was relative. */ +#define APR_STATUS_IS_ERELATIVE(s) ((s) == APR_ERELATIVE) +/** The given path was neither relative nor absolute. */ +#define APR_STATUS_IS_EINCOMPLETE(s) ((s) == APR_EINCOMPLETE) +/** The given path was above the root path. */ +#define APR_STATUS_IS_EABOVEROOT(s) ((s) == APR_EABOVEROOT) +/** The given path was bad. */ +#define APR_STATUS_IS_EBADPATH(s) ((s) == APR_EBADPATH) +/** The given path contained wildcards. */ +#define APR_STATUS_IS_EPATHWILD(s) ((s) == APR_EPATHWILD) +/** Could not find the requested symbol. + * For more information call apr_dso_error(). + */ +#if defined(WIN32) +#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND \ + || APR_TO_OS_ERROR(s) == ERROR_PROC_NOT_FOUND) +#else +#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND) +#endif +/** The given process was not recognized by APR. */ +#define APR_STATUS_IS_EPROC_UNKNOWN(s) ((s) == APR_EPROC_UNKNOWN) +/** APR could not gather enough entropy to continue. */ +#define APR_STATUS_IS_ENOTENOUGHENTROPY(s) ((s) == APR_ENOTENOUGHENTROPY) + +/** @} */ + +/** + * @addtogroup APR_Error + * @{ + */ +/** @see APR_STATUS_IS_INCHILD */ +#define APR_INCHILD (APR_OS_START_STATUS + 1) +/** @see APR_STATUS_IS_INPARENT */ +#define APR_INPARENT (APR_OS_START_STATUS + 2) +/** @see APR_STATUS_IS_DETACH */ +#define APR_DETACH (APR_OS_START_STATUS + 3) +/** @see APR_STATUS_IS_NOTDETACH */ +#define APR_NOTDETACH (APR_OS_START_STATUS + 4) +/** @see APR_STATUS_IS_CHILD_DONE */ +#define APR_CHILD_DONE (APR_OS_START_STATUS + 5) +/** @see APR_STATUS_IS_CHILD_NOTDONE */ +#define APR_CHILD_NOTDONE (APR_OS_START_STATUS + 6) +/** @see APR_STATUS_IS_TIMEUP */ +#define APR_TIMEUP (APR_OS_START_STATUS + 7) +/** @see APR_STATUS_IS_INCOMPLETE */ +#define APR_INCOMPLETE (APR_OS_START_STATUS + 8) +/* empty slot: +9 */ +/* empty slot: +10 */ +/* empty slot: +11 */ +/** @see APR_STATUS_IS_BADCH */ +#define APR_BADCH (APR_OS_START_STATUS + 12) +/** @see APR_STATUS_IS_BADARG */ +#define APR_BADARG (APR_OS_START_STATUS + 13) +/** @see APR_STATUS_IS_EOF */ +#define APR_EOF (APR_OS_START_STATUS + 14) +/** @see APR_STATUS_IS_NOTFOUND */ +#define APR_NOTFOUND (APR_OS_START_STATUS + 15) +/* empty slot: +16 */ +/* empty slot: +17 */ +/* empty slot: +18 */ +/** @see APR_STATUS_IS_ANONYMOUS */ +#define APR_ANONYMOUS (APR_OS_START_STATUS + 19) +/** @see APR_STATUS_IS_FILEBASED */ +#define APR_FILEBASED (APR_OS_START_STATUS + 20) +/** @see APR_STATUS_IS_KEYBASED */ +#define APR_KEYBASED (APR_OS_START_STATUS + 21) +/** @see APR_STATUS_IS_EINIT */ +#define APR_EINIT (APR_OS_START_STATUS + 22) +/** @see APR_STATUS_IS_ENOTIMPL */ +#define APR_ENOTIMPL (APR_OS_START_STATUS + 23) +/** @see APR_STATUS_IS_EMISMATCH */ +#define APR_EMISMATCH (APR_OS_START_STATUS + 24) +/** @see APR_STATUS_IS_EBUSY */ +#define APR_EBUSY (APR_OS_START_STATUS + 25) +/** @} */ + +/** + * @addtogroup APR_STATUS_IS + * @{ + */ +/** + * Program is currently executing in the child + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code */ +#define APR_STATUS_IS_INCHILD(s) ((s) == APR_INCHILD) +/** + * Program is currently executing in the parent + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_INPARENT(s) ((s) == APR_INPARENT) +/** + * The thread is detached + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_DETACH(s) ((s) == APR_DETACH) +/** + * The thread is not detached + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_NOTDETACH(s) ((s) == APR_NOTDETACH) +/** + * The child has finished executing + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_CHILD_DONE(s) ((s) == APR_CHILD_DONE) +/** + * The child has not finished executing + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_CHILD_NOTDONE(s) ((s) == APR_CHILD_NOTDONE) +/** + * The operation did not finish before the timeout + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP) +/** + * The operation was incomplete although some processing was performed + * and the results are partially valid. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_INCOMPLETE(s) ((s) == APR_INCOMPLETE) +/* empty slot: +9 */ +/* empty slot: +10 */ +/* empty slot: +11 */ +/** + * Getopt found an option not in the option string + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_BADCH(s) ((s) == APR_BADCH) +/** + * Getopt found an option not in the option string and an argument was + * specified in the option string + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_BADARG(s) ((s) == APR_BADARG) +/** + * APR has encountered the end of the file + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EOF(s) ((s) == APR_EOF) +/** + * APR was unable to find the socket in the poll structure + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_NOTFOUND(s) ((s) == APR_NOTFOUND) +/* empty slot: +16 */ +/* empty slot: +17 */ +/* empty slot: +18 */ +/** + * APR is using anonymous shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ANONYMOUS(s) ((s) == APR_ANONYMOUS) +/** + * APR is using a file name as the key to the shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_FILEBASED(s) ((s) == APR_FILEBASED) +/** + * APR is using a shared key as the key to the shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_KEYBASED(s) ((s) == APR_KEYBASED) +/** + * Ininitalizer value. If no option has been found, but + * the status variable requires a value, this should be used + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EINIT(s) ((s) == APR_EINIT) +/** + * The APR function has not been implemented on this + * platform, either because nobody has gotten to it yet, + * or the function is impossible on this platform. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOTIMPL(s) ((s) == APR_ENOTIMPL) +/** + * Two passwords do not match. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EMISMATCH(s) ((s) == APR_EMISMATCH) +/** + * The given lock was busy + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EBUSY(s) ((s) == APR_EBUSY) + +/** @} */ + +/** + * @addtogroup APR_Error APR Error Values + * @{ + */ +/* APR CANONICAL ERROR VALUES */ +/** @see APR_STATUS_IS_EACCES */ +#ifdef EACCES +#define APR_EACCES EACCES +#else +#define APR_EACCES (APR_OS_START_CANONERR + 1) +#endif + +/** @see APR_STATUS_IS_EEXIST */ +#ifdef EEXIST +#define APR_EEXIST EEXIST +#else +#define APR_EEXIST (APR_OS_START_CANONERR + 2) +#endif + +/** @see APR_STATUS_IS_ENAMETOOLONG */ +#ifdef ENAMETOOLONG +#define APR_ENAMETOOLONG ENAMETOOLONG +#else +#define APR_ENAMETOOLONG (APR_OS_START_CANONERR + 3) +#endif + +/** @see APR_STATUS_IS_ENOENT */ +#ifdef ENOENT +#define APR_ENOENT ENOENT +#else +#define APR_ENOENT (APR_OS_START_CANONERR + 4) +#endif + +/** @see APR_STATUS_IS_ENOTDIR */ +#ifdef ENOTDIR +#define APR_ENOTDIR ENOTDIR +#else +#define APR_ENOTDIR (APR_OS_START_CANONERR + 5) +#endif + +/** @see APR_STATUS_IS_ENOSPC */ +#ifdef ENOSPC +#define APR_ENOSPC ENOSPC +#else +#define APR_ENOSPC (APR_OS_START_CANONERR + 6) +#endif + +/** @see APR_STATUS_IS_ENOMEM */ +#ifdef ENOMEM +#define APR_ENOMEM ENOMEM +#else +#define APR_ENOMEM (APR_OS_START_CANONERR + 7) +#endif + +/** @see APR_STATUS_IS_EMFILE */ +#ifdef EMFILE +#define APR_EMFILE EMFILE +#else +#define APR_EMFILE (APR_OS_START_CANONERR + 8) +#endif + +/** @see APR_STATUS_IS_ENFILE */ +#ifdef ENFILE +#define APR_ENFILE ENFILE +#else +#define APR_ENFILE (APR_OS_START_CANONERR + 9) +#endif + +/** @see APR_STATUS_IS_EBADF */ +#ifdef EBADF +#define APR_EBADF EBADF +#else +#define APR_EBADF (APR_OS_START_CANONERR + 10) +#endif + +/** @see APR_STATUS_IS_EINVAL */ +#ifdef EINVAL +#define APR_EINVAL EINVAL +#else +#define APR_EINVAL (APR_OS_START_CANONERR + 11) +#endif + +/** @see APR_STATUS_IS_ESPIPE */ +#ifdef ESPIPE +#define APR_ESPIPE ESPIPE +#else +#define APR_ESPIPE (APR_OS_START_CANONERR + 12) +#endif + +/** + * @see APR_STATUS_IS_EAGAIN + * @warning use APR_STATUS_IS_EAGAIN instead of just testing this value + */ +#ifdef EAGAIN +#define APR_EAGAIN EAGAIN +#elif defined(EWOULDBLOCK) +#define APR_EAGAIN EWOULDBLOCK +#else +#define APR_EAGAIN (APR_OS_START_CANONERR + 13) +#endif + +/** @see APR_STATUS_IS_EINTR */ +#ifdef EINTR +#define APR_EINTR EINTR +#else +#define APR_EINTR (APR_OS_START_CANONERR + 14) +#endif + +/** @see APR_STATUS_IS_ENOTSOCK */ +#ifdef ENOTSOCK +#define APR_ENOTSOCK ENOTSOCK +#else +#define APR_ENOTSOCK (APR_OS_START_CANONERR + 15) +#endif + +/** @see APR_STATUS_IS_ECONNREFUSED */ +#ifdef ECONNREFUSED +#define APR_ECONNREFUSED ECONNREFUSED +#else +#define APR_ECONNREFUSED (APR_OS_START_CANONERR + 16) +#endif + +/** @see APR_STATUS_IS_EINPROGRESS */ +#ifdef EINPROGRESS +#define APR_EINPROGRESS EINPROGRESS +#else +#define APR_EINPROGRESS (APR_OS_START_CANONERR + 17) +#endif + +/** + * @see APR_STATUS_IS_ECONNABORTED + * @warning use APR_STATUS_IS_ECONNABORTED instead of just testing this value + */ + +#ifdef ECONNABORTED +#define APR_ECONNABORTED ECONNABORTED +#else +#define APR_ECONNABORTED (APR_OS_START_CANONERR + 18) +#endif + +/** @see APR_STATUS_IS_ECONNRESET */ +#ifdef ECONNRESET +#define APR_ECONNRESET ECONNRESET +#else +#define APR_ECONNRESET (APR_OS_START_CANONERR + 19) +#endif + +/** @see APR_STATUS_IS_ETIMEDOUT + * @deprecated */ +#ifdef ETIMEDOUT +#define APR_ETIMEDOUT ETIMEDOUT +#else +#define APR_ETIMEDOUT (APR_OS_START_CANONERR + 20) +#endif + +/** @see APR_STATUS_IS_EHOSTUNREACH */ +#ifdef EHOSTUNREACH +#define APR_EHOSTUNREACH EHOSTUNREACH +#else +#define APR_EHOSTUNREACH (APR_OS_START_CANONERR + 21) +#endif + +/** @see APR_STATUS_IS_ENETUNREACH */ +#ifdef ENETUNREACH +#define APR_ENETUNREACH ENETUNREACH +#else +#define APR_ENETUNREACH (APR_OS_START_CANONERR + 22) +#endif + +/** @see APR_STATUS_IS_EFTYPE */ +#ifdef EFTYPE +#define APR_EFTYPE EFTYPE +#else +#define APR_EFTYPE (APR_OS_START_CANONERR + 23) +#endif + +/** @see APR_STATUS_IS_EPIPE */ +#ifdef EPIPE +#define APR_EPIPE EPIPE +#else +#define APR_EPIPE (APR_OS_START_CANONERR + 24) +#endif + +/** @see APR_STATUS_IS_EXDEV */ +#ifdef EXDEV +#define APR_EXDEV EXDEV +#else +#define APR_EXDEV (APR_OS_START_CANONERR + 25) +#endif + +/** @see APR_STATUS_IS_ENOTEMPTY */ +#ifdef ENOTEMPTY +#define APR_ENOTEMPTY ENOTEMPTY +#else +#define APR_ENOTEMPTY (APR_OS_START_CANONERR + 26) +#endif + +/** @see APR_STATUS_IS_EAFNOSUPPORT */ +#ifdef EAFNOSUPPORT +#define APR_EAFNOSUPPORT EAFNOSUPPORT +#else +#define APR_EAFNOSUPPORT (APR_OS_START_CANONERR + 27) +#endif + +/** @} */ + +#if defined(OS2) && !defined(DOXYGEN) + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define INCL_DOSERRORS +#define INCL_DOS + +/* Leave these undefined. + * OS2 doesn't rely on the errno concept. + * The API calls always return a result codes which + * should be filtered through APR_FROM_OS_ERROR(). + * + * #define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) + * #define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) + */ + +/* A special case, only socket calls require this; + */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(errno)) +#define apr_set_netos_error(e) (errno = APR_TO_OS_ERROR(e)) + +/* And this needs to be greped away for good: + */ +#define APR_OS2_STATUS(e) (APR_FROM_OS_ERROR(e)) + +/* These can't sit in a private header, so in spite of the extra size, + * they need to be made available here. + */ +#define SOCBASEERR 10000 +#define SOCEPERM (SOCBASEERR+1) /* Not owner */ +#define SOCESRCH (SOCBASEERR+3) /* No such process */ +#define SOCEINTR (SOCBASEERR+4) /* Interrupted system call */ +#define SOCENXIO (SOCBASEERR+6) /* No such device or address */ +#define SOCEBADF (SOCBASEERR+9) /* Bad file number */ +#define SOCEACCES (SOCBASEERR+13) /* Permission denied */ +#define SOCEFAULT (SOCBASEERR+14) /* Bad address */ +#define SOCEINVAL (SOCBASEERR+22) /* Invalid argument */ +#define SOCEMFILE (SOCBASEERR+24) /* Too many open files */ +#define SOCEPIPE (SOCBASEERR+32) /* Broken pipe */ +#define SOCEOS2ERR (SOCBASEERR+100) /* OS/2 Error */ +#define SOCEWOULDBLOCK (SOCBASEERR+35) /* Operation would block */ +#define SOCEINPROGRESS (SOCBASEERR+36) /* Operation now in progress */ +#define SOCEALREADY (SOCBASEERR+37) /* Operation already in progress */ +#define SOCENOTSOCK (SOCBASEERR+38) /* Socket operation on non-socket */ +#define SOCEDESTADDRREQ (SOCBASEERR+39) /* Destination address required */ +#define SOCEMSGSIZE (SOCBASEERR+40) /* Message too long */ +#define SOCEPROTOTYPE (SOCBASEERR+41) /* Protocol wrong type for socket */ +#define SOCENOPROTOOPT (SOCBASEERR+42) /* Protocol not available */ +#define SOCEPROTONOSUPPORT (SOCBASEERR+43) /* Protocol not supported */ +#define SOCESOCKTNOSUPPORT (SOCBASEERR+44) /* Socket type not supported */ +#define SOCEOPNOTSUPP (SOCBASEERR+45) /* Operation not supported on socket */ +#define SOCEPFNOSUPPORT (SOCBASEERR+46) /* Protocol family not supported */ +#define SOCEAFNOSUPPORT (SOCBASEERR+47) /* Address family not supported by protocol family */ +#define SOCEADDRINUSE (SOCBASEERR+48) /* Address already in use */ +#define SOCEADDRNOTAVAIL (SOCBASEERR+49) /* Can't assign requested address */ +#define SOCENETDOWN (SOCBASEERR+50) /* Network is down */ +#define SOCENETUNREACH (SOCBASEERR+51) /* Network is unreachable */ +#define SOCENETRESET (SOCBASEERR+52) /* Network dropped connection on reset */ +#define SOCECONNABORTED (SOCBASEERR+53) /* Software caused connection abort */ +#define SOCECONNRESET (SOCBASEERR+54) /* Connection reset by peer */ +#define SOCENOBUFS (SOCBASEERR+55) /* No buffer space available */ +#define SOCEISCONN (SOCBASEERR+56) /* Socket is already connected */ +#define SOCENOTCONN (SOCBASEERR+57) /* Socket is not connected */ +#define SOCESHUTDOWN (SOCBASEERR+58) /* Can't send after socket shutdown */ +#define SOCETOOMANYREFS (SOCBASEERR+59) /* Too many references: can't splice */ +#define SOCETIMEDOUT (SOCBASEERR+60) /* Connection timed out */ +#define SOCECONNREFUSED (SOCBASEERR+61) /* Connection refused */ +#define SOCELOOP (SOCBASEERR+62) /* Too many levels of symbolic links */ +#define SOCENAMETOOLONG (SOCBASEERR+63) /* File name too long */ +#define SOCEHOSTDOWN (SOCBASEERR+64) /* Host is down */ +#define SOCEHOSTUNREACH (SOCBASEERR+65) /* No route to host */ +#define SOCENOTEMPTY (SOCBASEERR+66) /* Directory not empty */ + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ + || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ + || (s) == APR_OS_START_SYSERR + SOCENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ + || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ + || (s) == APR_OS_START_SYSERR + SOCEWOULDBLOCK \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + SOCEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + SOCENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + SOCECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + SOCEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + SOCECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + SOCECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + SOCEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + SOCENETUNREACH) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE \ + || (s) == APR_OS_START_SYSERR + SOCEPIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) +#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_AFNOSUPPORT \ + || (s) == APR_OS_START_SYSERR + SOCEAFNOSUPPORT) + +/* + Sorry, too tired to wrap this up for OS2... feel free to + fit the following into their best matches. + + { ERROR_NO_SIGNAL_SENT, ESRCH }, + { SOCEALREADY, EALREADY }, + { SOCEDESTADDRREQ, EDESTADDRREQ }, + { SOCEMSGSIZE, EMSGSIZE }, + { SOCEPROTOTYPE, EPROTOTYPE }, + { SOCENOPROTOOPT, ENOPROTOOPT }, + { SOCEPROTONOSUPPORT, EPROTONOSUPPORT }, + { SOCESOCKTNOSUPPORT, ESOCKTNOSUPPORT }, + { SOCEOPNOTSUPP, EOPNOTSUPP }, + { SOCEPFNOSUPPORT, EPFNOSUPPORT }, + { SOCEADDRINUSE, EADDRINUSE }, + { SOCEADDRNOTAVAIL, EADDRNOTAVAIL }, + { SOCENETDOWN, ENETDOWN }, + { SOCENETRESET, ENETRESET }, + { SOCENOBUFS, ENOBUFS }, + { SOCEISCONN, EISCONN }, + { SOCENOTCONN, ENOTCONN }, + { SOCESHUTDOWN, ESHUTDOWN }, + { SOCETOOMANYREFS, ETOOMANYREFS }, + { SOCELOOP, ELOOP }, + { SOCEHOSTDOWN, EHOSTDOWN }, + { SOCENOTEMPTY, ENOTEMPTY }, + { SOCEPIPE, EPIPE } +*/ + +#elif defined(WIN32) && !defined(DOXYGEN) /* !defined(OS2) */ + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) +#define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) + +/* A special case, only socket calls require this: + */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) +#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_CANNOT_MAKE \ + || (s) == APR_OS_START_SYSERR + ERROR_CURRENT_DIRECTORY \ + || (s) == APR_OS_START_SYSERR + ERROR_DRIVE_LOCKED \ + || (s) == APR_OS_START_SYSERR + ERROR_FAIL_I24 \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_LOCKED \ + || (s) == APR_OS_START_SYSERR + ERROR_NETWORK_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ + || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ + || (s) == APR_OS_START_SYSERR + WSAENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_NETPATH \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_NET_NAME \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_PATHNAME \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DRIVE \ + || (s) == APR_OS_START_SYSERR + ERROR_DIRECTORY) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM \ + || (s) == APR_OS_START_SYSERR + ERROR_ARENA_TRASHED \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_MEMORY \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_BLOCK \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_QUOTA \ + || (s) == APR_OS_START_SYSERR + ERROR_OUTOFMEMORY) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ + || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_TARGET_HANDLE) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_ACCESS \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DATA \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_SEEK_ON_DEVICE \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_PROC_SLOTS \ + || (s) == APR_OS_START_SYSERR + ERROR_NESTING_NOT_ALLOWED \ + || (s) == APR_OS_START_SYSERR + ERROR_MAX_THRDS_REACHED \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ + || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + WSAEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + ERROR_NETNAME_DELETED \ + || (s) == APR_OS_START_SYSERR + WSAECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE \ + || (s) == APR_OS_START_SYSERR + ERROR_EXE_MACHINE_TYPE_MISMATCH \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DLL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_MODULETYPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_EXE_FORMAT \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_EXE_SIGNATURE \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_CORRUPT \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_FORMAT) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY) +#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_EAFNOSUPPORT \ + || (s) == APR_OS_START_SYSERR + WSAEAFNOSUPPORT) + +#elif defined(NETWARE) && defined(USE_WINSOCK) && !defined(DOXYGEN) /* !defined(OS2) && !defined(WIN32) */ + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define apr_get_os_error() (errno) +#define apr_set_os_error(e) (errno = (e)) + +/* A special case, only socket calls require this: */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) +#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) + +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == EWOULDBLOCK \ + || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + WSAEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + WSAECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) +#define APR_STATUS_IS_ENETDOWN(s) ((s) == APR_OS_START_SYSERR + WSAENETDOWN) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY) +#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_EAFNOSUPPORT \ + || (s) == APR_OS_START_SYSERR + WSAEAFNOSUPPORT) + +#else /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ + +/* + * os error codes are clib error codes + */ +#define APR_FROM_OS_ERROR(e) (e) +#define APR_TO_OS_ERROR(e) (e) + +#define apr_get_os_error() (errno) +#define apr_set_os_error(e) (errno = (e)) + +/* A special case, only socket calls require this: + */ +#define apr_get_netos_error() (errno) +#define apr_set_netos_error(e) (errno = (e)) + +/** + * @addtogroup APR_STATUS_IS + * @{ + */ + +/** permission denied */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) +/** file exists */ +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) +/** path name is too long */ +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) +/** + * no such file or directory + * @remark + * EMVSCATLG can be returned by the automounter on z/OS for + * paths which do not exist. + */ +#ifdef EMVSCATLG +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ + || (s) == EMVSCATLG) +#else +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) +#endif +/** not a directory */ +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +/** no space left on device */ +#ifdef EDQUOT +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == EDQUOT) +#else +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) +#endif +/** not enough memory */ +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +/** too many open files */ +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) +/** file table overflow */ +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +/** bad file # */ +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) +/** invalid argument */ +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) +/** illegal seek */ +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) + +/** operation would block */ +#if !defined(EWOULDBLOCK) || !defined(EAGAIN) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) +#elif (EWOULDBLOCK == EAGAIN) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) +#else +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == EWOULDBLOCK) +#endif + +/** interrupted system call */ +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR) +/** socket operation on a non-socket */ +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK) +/** Connection Refused */ +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED) +/** operation now in progress */ +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS) + +/** + * Software caused connection abort + * @remark + * EPROTO on certain older kernels really means ECONNABORTED, so we need to + * ignore it for them. See discussion in new-httpd archives nh.9701 & nh.9603 + * + * There is potentially a bug in Solaris 2.x x<6, and other boxes that + * implement tcp sockets in userland (i.e. on top of STREAMS). On these + * systems, EPROTO can actually result in a fatal loop. See PR#981 for + * example. It's hard to handle both uses of EPROTO. + */ +#ifdef EPROTO +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == EPROTO) +#else +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED) +#endif + +/** Connection Reset by peer */ +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET) +/** Operation timed out + * @deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT) +/** no route to host */ +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH) +/** network is unreachable */ +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH) +/** inappropiate file type or format */ +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +/** broken pipe */ +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) +/** cross device link */ +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) +/** Directory Not Empty */ +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY || \ + (s) == APR_EEXIST) +/** Address Family not supported */ +#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_EAFNOSUPPORT) +/** @} */ + +#endif /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_ERRNO_H */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr_general.h b/code/application/sifarsdk/component/SignatureManager/include/apr_general.h new file mode 100644 index 000000000..46883c9a0 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr_general.h @@ -0,0 +1,243 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_GENERAL_H +#define APR_GENERAL_H + +/** + * @file apr_general.h + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @brief APR Miscellaneous library routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#if APR_HAVE_SIGNAL_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_general Miscellaneous library routines + * @ingroup APR + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @{ + */ + +/** FALSE */ +#ifndef FALSE +#define FALSE 0 +#endif +/** TRUE */ +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +/** a space */ +#define APR_ASCII_BLANK '\040' +/** a carrige return */ +#define APR_ASCII_CR '\015' +/** a line feed */ +#define APR_ASCII_LF '\012' +/** a tab */ +#define APR_ASCII_TAB '\011' + +/** signal numbers typedef */ +typedef int apr_signum_t; + +/** + * Finding offsets of elements within structures. + * Taken from the X code... they've sweated portability of this stuff + * so we don't have to. Sigh... + * @param p_type pointer type name + * @param field data field within the structure pointed to + * @return offset + */ + +#if defined(CRAY) || (defined(__arm) && !(defined(LINUX) || defined(__FreeBSD__))) +#ifdef __STDC__ +#define APR_OFFSET(p_type,field) _Offsetof(p_type,field) +#else +#ifdef CRAY2 +#define APR_OFFSET(p_type,field) \ + (sizeof(int)*((unsigned int)&(((p_type)NULL)->field))) + +#else /* !CRAY2 */ + +#define APR_OFFSET(p_type,field) ((unsigned int)&(((p_type)NULL)->field)) + +#endif /* !CRAY2 */ +#endif /* __STDC__ */ +#else /* ! (CRAY || __arm) */ + +#define APR_OFFSET(p_type,field) \ + ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL))) + +#endif /* !CRAY */ + +/** + * Finding offsets of elements within structures. + * @param s_type structure type name + * @param field data field within the structure + * @return offset + */ +#if defined(offsetof) && !defined(__cplusplus) +#define APR_OFFSETOF(s_type,field) offsetof(s_type,field) +#else +#define APR_OFFSETOF(s_type,field) APR_OFFSET(s_type*,field) +#endif + +#ifndef DOXYGEN + +/* A couple of prototypes for functions in case some platform doesn't + * have it + */ +#if (!APR_HAVE_STRCASECMP) && (APR_HAVE_STRICMP) +#define strcasecmp(s1, s2) stricmp(s1, s2) +#elif (!APR_HAVE_STRCASECMP) +int strcasecmp(const char *a, const char *b); +#endif + +#if (!APR_HAVE_STRNCASECMP) && (APR_HAVE_STRNICMP) +#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n) +#elif (!APR_HAVE_STRNCASECMP) +//int strncasecmp(const char *a, const char *b, size_t n); +#endif + +#endif + +/** + * Alignment macros + */ + +/* APR_ALIGN() is only to be used to align on a power of 2 boundary */ +#define APR_ALIGN(size, boundary) \ + (((size) + ((boundary) - 1)) & ~((boundary) - 1)) + +/** Default alignment */ +#define APR_ALIGN_DEFAULT(size) APR_ALIGN(size, 8) + + +/** + * String and memory functions + */ + +/* APR_STRINGIFY is defined here, and also in apr_release.h, so wrap it */ +#ifndef APR_STRINGIFY +/** Properly quote a value as a string in the C preprocessor */ +#define APR_STRINGIFY(n) APR_STRINGIFY_HELPER(n) +/** Helper macro for APR_STRINGIFY */ +#define APR_STRINGIFY_HELPER(n) #n +#endif + +#if (!APR_HAVE_MEMMOVE) +//#define memmove(a,b,c) bcopy(b,a,c) +#endif + +#if (!APR_HAVE_MEMCHR) +//void *memchr(const void *s, int c, size_t n); +#endif + +/** @} */ + +/** + * @defgroup apr_library Library initialization and termination + * @{ + */ + +/** + * Setup any APR internal data structures. This MUST be the first function + * called for any APR library. It is safe to call apr_initialize several + * times as long as apr_terminate is called the same number of times. + * @remark See apr_app_initialize if this is an application, rather than + * a library consumer of apr. + */ +//APR_DECLARE(apr_status_t) apr_initialize(void); + +/** + * Set up an application with normalized argc, argv (and optionally env) in + * order to deal with platform-specific oddities, such as Win32 services, + * code pages and signals. This must be the first function called for any + * APR program. + * @param argc Pointer to the argc that may be corrected + * @param argv Pointer to the argv that may be corrected + * @param env Pointer to the env that may be corrected, may be NULL + * @remark See apr_initialize if this is a library consumer of apr. + * Otherwise, this call is identical to apr_initialize, and must be closed + * with a call to apr_terminate at the end of program execution. + */ +/*APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, + char const * const * *argv, + char const * const * *env); +*/ +/** + * Tear down any APR internal data structures which aren't torn down + * automatically. apr_terminate must be called once for every call to + * apr_initialize() or apr_app_initialize(). + * @remark An APR program must call this function at termination once it + * has stopped using APR services. The APR developers suggest using + * atexit to ensure this is called. When using APR from a language + * other than C that has problems with the calling convention, use + * apr_terminate2() instead. + */ +//APR_DECLARE_NONSTD(void) apr_terminate(void); + +/** + * Tear down any APR internal data structures which aren't torn down + * automatically, same as apr_terminate + * @remark An APR program must call either the apr_terminate or apr_terminate2 + * function once it it has finished using APR services. The APR + * developers suggest using atexit(apr_terminate) to ensure this is done. + * apr_terminate2 exists to allow non-c language apps to tear down apr, + * while apr_terminate is recommended from c language applications. + */ +//APR_DECLARE(void) apr_terminate2(void); + +/** @} */ + +/** + * @defgroup apr_random Random Functions + * @{ + */ + +#if APR_HAS_RANDOM || defined(DOXYGEN) + +/* TODO: I'm not sure this is the best place to put this prototype...*/ +/** + * Generate random bytes. + * @param buf Buffer to fill with random bytes + * @param length Length of buffer in bytes + */ +APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf, + apr_size_t length); + +#endif +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_GENERAL_H */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr_lib.h b/code/application/sifarsdk/component/SignatureManager/include/apr_lib.h new file mode 100644 index 000000000..03b9ee401 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr_lib.h @@ -0,0 +1,243 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_LIB_H +#define APR_LIB_H + +/** + * @file apr_lib.h + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @brief APR general purpose library routines + */ + +#include "apr.h" +#include "apr_errno.h" + +#if APR_HAVE_CTYPE_H +#include +#endif +#if APR_HAVE_STDARG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_lib General Purpose Library Routines + * @ingroup APR + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @{ + */ + +/** A constant representing a 'large' string. */ +#define HUGE_STRING_LEN 8192 + +/* + * Define the structures used by the APR general-purpose library. + */ + +/** @see apr_vformatter_buff_t */ +typedef struct apr_vformatter_buff_t apr_vformatter_buff_t; + +/** + * Structure used by the variable-formatter routines. + */ +struct apr_vformatter_buff_t { + /** The current position */ + char *curpos; + /** The end position of the format string */ + char *endpos; +}; + +/** + * return the final element of the pathname + * @param pathname The path to get the final element of + * @return the final element of the path + * @remark + *
+ * For example:
+ *                 "/foo/bar/gum"    -> "gum"
+ *                 "/foo/bar/gum/"   -> ""
+ *                 "gum"             -> "gum"
+ *                 "bs\\path\\stuff" -> "stuff"
+ * 
+ */ +//APR_DECLARE(const char *) apr_filepath_name_get(const char *pathname); + +/** + * apr_killpg + * Small utility macros to make things easier to read. Not usually a + * goal, to be sure.. + */ + +#ifdef WIN32 +#define apr_killpg(x, y) +#else /* WIN32 */ +#ifdef NO_KILLPG +#define apr_killpg(x, y) (kill (-(x), (y))) +#else /* NO_KILLPG */ +#define apr_killpg(x, y) (killpg ((x), (y))) +#endif /* NO_KILLPG */ +#endif /* WIN32 */ + +/** + * apr_vformatter() is a generic printf-style formatting routine + * with some extensions. + * @param flush_func The function to call when the buffer is full + * @param c The buffer to write to + * @param fmt The format string + * @param ap The arguments to use to fill out the format string. + * + * @remark + *
+ * The extensions are:
+ *
+ * - %%pA takes a struct in_addr *, and prints it as a.b.c.d
+ * - %%pI takes an apr_sockaddr_t * and prints it as a.b.c.d:port or
+ * \[ipv6-address\]:port
+ * - %%pT takes an apr_os_thread_t * and prints it in decimal
+ * ('0' is printed if !APR_HAS_THREADS)
+ * - %%pt takes an apr_os_thread_t * and prints it in hexadecimal
+ * ('0' is printed if !APR_HAS_THREADS)
+ * - %%pm takes an apr_status_t * and prints the appropriate error
+ * string (from apr_strerror) corresponding to that error code.
+ * - %%pp takes a void * and outputs it in hex
+ * - %%pB takes a apr_uint32_t * as bytes and outputs it's apr_strfsize
+ * - %%pF same as above, but takes a apr_off_t *
+ * - %%pS same as above, but takes a apr_size_t *
+ *
+ * %%pA, %%pI, %%pT, %%pp are available from APR 1.0.0 onwards (and in 0.9.x).
+ * %%pt is only available from APR 1.2.0 onwards.
+ * %%pm, %%pB, %%pF and %%pS are only available from APR 1.3.0 onwards.
+ *
+ * The %%p hacks are to force gcc's printf warning code to skip
+ * over a pointer argument without complaining.  This does
+ * mean that the ANSI-style %%p (output a void * in hex format) won't
+ * work as expected at all, but that seems to be a fair trade-off
+ * for the increased robustness of having printf-warnings work.
+ *
+ * Additionally, apr_vformatter allows for arbitrary output methods
+ * using the apr_vformatter_buff and flush_func.
+ *
+ * The apr_vformatter_buff has two elements curpos and endpos.
+ * curpos is where apr_vformatter will write the next byte of output.
+ * It proceeds writing output to curpos, and updating curpos, until
+ * either the end of output is reached, or curpos == endpos (i.e. the
+ * buffer is full).
+ *
+ * If the end of output is reached, apr_vformatter returns the
+ * number of bytes written.
+ *
+ * When the buffer is full, the flush_func is called.  The flush_func
+ * can return -1 to indicate that no further output should be attempted,
+ * and apr_vformatter will return immediately with -1.  Otherwise
+ * the flush_func should flush the buffer in whatever manner is
+ * appropriate, re apr_pool_t nitialize curpos and endpos, and return 0.
+ *
+ * Note that flush_func is only invoked as a result of attempting to
+ * write another byte at curpos when curpos >= endpos.  So for
+ * example, it's possible when the output exactly matches the buffer
+ * space available that curpos == endpos will be true when
+ * apr_vformatter returns.
+ *
+ * apr_vformatter does not call out to any other code, it is entirely
+ * self-contained.  This allows the callers to do things which are
+ * otherwise "unsafe".  For example, apr_psprintf uses the "scratch"
+ * space at the unallocated end of a block, and doesn't actually
+ * complete the allocation until apr_vformatter returns.  apr_psprintf
+ * would be completely broken if apr_vformatter were to call anything
+ * that used this same pool.  Similarly http_bprintf() uses the "scratch"
+ * space at the end of its output buffer, and doesn't actually note
+ * that the space is in use until it either has to flush the buffer
+ * or until apr_vformatter returns.
+ * 
+ +APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *b), + apr_vformatter_buff_t *c, const char *fmt, + va_list ap); +*/ + +/** + * Display a prompt and read in the password from stdin. + * @param prompt The prompt to display + * @param pwbuf Buffer to store the password + * @param bufsize The length of the password buffer. + * @remark If the password entered must be truncated to fit in + * the provided buffer, APR_ENAMETOOLONG will be returned. + * Note that the bufsize paramater is passed by reference for no + * reason; its value will never be modified by the apr_password_get() + * function. + +APR_DECLARE(apr_status_t) apr_password_get(const char *prompt, char *pwbuf, + apr_size_t *bufsize); +*/ + +/** @} */ + +/** + * @defgroup apr_ctype ctype functions + * These macros allow correct support of 8-bit characters on systems which + * support 8-bit characters. Pretty dumb how the cast is required, but + * that's legacy libc for ya. These new macros do not support EOF like + * the standard macros do. Tough. + * @{ + */ +/** @see isalnum */ +#define apr_isalnum(c) (isalnum(((unsigned char)(c)))) +/** @see isalpha */ +#define apr_isalpha(c) (isalpha(((unsigned char)(c)))) +/** @see iscntrl */ +#define apr_iscntrl(c) (iscntrl(((unsigned char)(c)))) +/** @see isdigit */ +#define apr_isdigit(c) (isdigit(((unsigned char)(c)))) +/** @see isgraph */ +#define apr_isgraph(c) (isgraph(((unsigned char)(c)))) +/** @see islower*/ +#define apr_islower(c) (islower(((unsigned char)(c)))) +/** @see isascii */ +#ifdef isascii +#define apr_isascii(c) (isascii(((unsigned char)(c)))) +#else +#define apr_isascii(c) (((c) & ~0x7f)==0) +#endif +/** @see isprint */ +#define apr_isprint(c) (isprint(((unsigned char)(c)))) +/** @see ispunct */ +#define apr_ispunct(c) (ispunct(((unsigned char)(c)))) +/** @see isspace */ +#define apr_isspace(c) (isspace(((unsigned char)(c)))) +/** @see isupper */ +#define apr_isupper(c) (isupper(((unsigned char)(c)))) +/** @see isxdigit */ +#define apr_isxdigit(c) (isxdigit(((unsigned char)(c)))) +/** @see tolower */ +#define apr_tolower(c) (tolower(((unsigned char)(c)))) +/** @see toupper */ +#define apr_toupper(c) (toupper(((unsigned char)(c)))) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_LIB_H */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr_pools.h b/code/application/sifarsdk/component/SignatureManager/include/apr_pools.h new file mode 100644 index 000000000..2bb0822f2 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr_pools.h @@ -0,0 +1,817 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_POOLS_H +#define APR_POOLS_H + +/** + * @file apr_pools.h + * @brief APR memory allocation + * + * Resource allocation routines... + * + * designed so that we don't have to keep track of EVERYTHING so that + * it can be explicitly freed later (a fundamentally unsound strategy --- + * particularly in the presence of die()). + * + * Instead, we maintain pools, and allocate items (both memory and I/O + * handlers) from the pools --- currently there are two, one for + * per-transaction info, and one for config info. When a transaction is + * over, we can delete everything in the per-transaction apr_pool_t without + * fear, and without thinking too hard about it either. + * + * Note that most operations on pools are not thread-safe: a single pool + * should only be accessed by a single thread at any given time. The one + * exception to this rule is creating a subpool of a given pool: one or more + * threads can safely create subpools at the same time that another thread + * accesses the parent pool. + */ + +#include "apr.h" +#include "apr_errno.h" +#include "apr_general.h" /* for APR_STRINGIFY */ +#define APR_WANT_MEMFUNC /**< for no good reason? */ +#include "apr_want.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_pools Memory Pool Functions + * @ingroup APR + * @{ + */ + +/** The fundamental pool type */ +typedef struct apr_pool_t apr_pool_t; + + +/** + * Declaration helper macro to construct apr_foo_pool_get()s. + * + * This standardized macro is used by opaque (APR) data types to return + * the apr_pool_t that is associated with the data type. + * + * APR_POOL_DECLARE_ACCESSOR() is used in a header file to declare the + * accessor function. A typical usage and result would be: + *
+ *    APR_POOL_DECLARE_ACCESSOR(file);
+ * becomes:
+ *    APR_DECLARE(apr_pool_t *) apr_file_pool_get(const apr_file_t *thefile);
+ * 
+ * @remark Doxygen unwraps this macro (via doxygen.conf) to provide + * actual help for each specific occurrence of apr_foo_pool_get. + * @remark the linkage is specified for APR. It would be possible to expand + * the macros to support other linkages. + */ +#define APR_POOL_DECLARE_ACCESSOR(type) \ + APR_DECLARE(apr_pool_t *) apr_##type##_pool_get \ + (const apr_##type##_t *the##type) + +/** + * Implementation helper macro to provide apr_foo_pool_get()s. + * + * In the implementation, the APR_POOL_IMPLEMENT_ACCESSOR() is used to + * actually define the function. It assumes the field is named "pool". + */ +#define APR_POOL_IMPLEMENT_ACCESSOR(type) \ + APR_DECLARE(apr_pool_t *) apr_##type##_pool_get \ + (const apr_##type##_t *the##type) \ + { return the##type->pool; } + + +/** + * Pool debug levels + * + *
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * ---------------------------------
+ * |   |   |   |   |   |   |   | x |  General debug code enabled (useful in
+ *                                    combination with --with-efence).
+ *
+ * |   |   |   |   |   |   | x |   |  Verbose output on stderr (report
+ *                                    CREATE, CLEAR, DESTROY).
+ *
+ * |   |   |   | x |   |   |   |   |  Verbose output on stderr (report
+ *                                    PALLOC, PCALLOC).
+ *
+ * |   |   |   |   |   | x |   |   |  Lifetime checking. On each use of a
+ *                                    pool, check its lifetime.  If the pool
+ *                                    is out of scope, abort().
+ *                                    In combination with the verbose flag
+ *                                    above, it will output LIFE in such an
+ *                                    event prior to aborting.
+ *
+ * |   |   |   |   | x |   |   |   |  Pool owner checking.  On each use of a
+ *                                    pool, check if the current thread is the
+ *                                    pool's owner.  If not, abort().  In
+ *                                    combination with the verbose flag above,
+ *                                    it will output OWNER in such an event
+ *                                    prior to aborting.  Use the debug
+ *                                    function apr_pool_owner_set() to switch
+ *                                    a pool's ownership.
+ *
+ * When no debug level was specified, assume general debug mode.
+ * If level 0 was specified, debugging is switched off.
+ * 
+ */ +#if defined(APR_POOL_DEBUG) +/* If APR_POOL_DEBUG is blank, we get 1; if it is a number, we get -1. */ +#if (APR_POOL_DEBUG - APR_POOL_DEBUG -1 == 1) +#undef APR_POOL_DEBUG +#define APR_POOL_DEBUG 1 +#endif +#else +#define APR_POOL_DEBUG 0 +#endif + +/** the place in the code where the particular function was called */ +#define APR_POOL__FILE_LINE__ __FILE__ ":" APR_STRINGIFY(__LINE__) + + +#if 0 +/** A function that is called when allocation fails. */ +typedef int (*apr_abortfunc_t)(int retcode); + +/* + * APR memory structure manipulators (pools, tables, and arrays). + */ + +/* + * Initialization + */ + +/** + * Setup all of the internal structures required to use pools + * @remark Programs do NOT need to call this directly. APR will call this + * automatically from apr_initialize. + * @internal + */ +//APR_DECLARE(apr_status_t) apr_pool_initialize(void); + +/** + * Tear down all of the internal structures required to use pools + * @remark Programs do NOT need to call this directly. APR will call this + * automatically from apr_terminate. + * @internal + */ +//APR_DECLARE(void) apr_pool_terminate(void); + + +/* + * Pool creation/destruction + */ + +//#include "apr_allocator.h" + +/** + * Create a new pool. + * @param newpool The pool we have just created. + * @param parent The parent pool. If this is NULL, the new pool is a root + * pool. If it is non-NULL, the new pool will inherit all + * of its parent pool's attributes, except the apr_pool_t will + * be a sub-pool. + * @param abort_fn A function to use if the pool cannot allocate more memory. + * @param allocator The allocator to use with the new pool. If NULL the + * allocator of the parent pool will be used. + * @remark This function is thread-safe, in the sense that multiple threads + * can safely create subpools of the same parent pool concurrently. + * Similarly, a subpool can be created by one thread at the same + * time that another thread accesses the parent pool. + */ +APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) + __attribute__((nonnull(1))); + +/** + * Create a new pool. + * @deprecated @see apr_pool_create_unmanaged_ex. + */ +APR_DECLARE(apr_status_t) apr_pool_create_core_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator); + +/** + * Create a new unmanaged pool. + * @param newpool The pool we have just created. + * @param abort_fn A function to use if the pool cannot allocate more memory. + * @param allocator The allocator to use with the new pool. If NULL a + * new allocator will be created with the new pool as owner. + * @remark An unmanaged pool is a special pool without a parent; it will + * NOT be destroyed upon apr_terminate. It must be explicitly + * destroyed by calling apr_pool_destroy, to prevent memory leaks. + * Use of this function is discouraged, think twice about whether + * you really really need it. + * @warning Any child cleanups registered against the new pool, or + * against sub-pools thereof, will not be executed during an + * invocation of apr_proc_create(), so resources created in an + * "unmanaged" pool hierarchy will leak to child processes. + */ +APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) + __attribute__((nonnull(1))); + +/** + * Debug version of apr_pool_create_ex. + * @param newpool @see apr_pool_create. + * @param parent @see apr_pool_create. + * @param abort_fn @see apr_pool_create. + * @param allocator @see apr_pool_create. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have your apr_pool_create_ex + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_create_ex in a wrapper, trust the macro + * and don't call apr_pool_create_ex_debug directly. + */ +APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pool_create_ex(newpool, parent, abort_fn, allocator) \ + apr_pool_create_ex_debug(newpool, parent, abort_fn, allocator, \ + APR_POOL__FILE_LINE__) +#endif + +/** + * Debug version of apr_pool_create_core_ex. + * @deprecated @see apr_pool_create_unmanaged_ex_debug. + */ +APR_DECLARE(apr_status_t) apr_pool_create_core_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line); + +/** + * Debug version of apr_pool_create_unmanaged_ex. + * @param newpool @see apr_pool_create_unmanaged. + * @param abort_fn @see apr_pool_create_unmanaged. + * @param allocator @see apr_pool_create_unmanaged. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have your apr_pool_create_unmanaged_ex + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_create_core_ex in a wrapper, trust the macro + * and don't call apr_pool_create_core_ex_debug directly. + */ +APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pool_create_core_ex(newpool, abort_fn, allocator) \ + apr_pool_create_unmanaged_ex_debug(newpool, abort_fn, allocator, \ + APR_POOL__FILE_LINE__) + +#define apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator) \ + apr_pool_create_unmanaged_ex_debug(newpool, abort_fn, allocator, \ + APR_POOL__FILE_LINE__) + +#endif + +/** + * Create a new pool. + * @param newpool The pool we have just created. + * @param parent The parent pool. If this is NULL, the new pool is a root + * pool. If it is non-NULL, the new pool will inherit all + * of its parent pool's attributes, except the apr_pool_t will + * be a sub-pool. + * @remark This function is thread-safe, in the sense that multiple threads + * can safely create subpools of the same parent pool concurrently. + * Similarly, a subpool can be created by one thread at the same + * time that another thread accesses the parent pool. + */ +#if defined(DOXYGEN) +APR_DECLARE(apr_status_t) apr_pool_create(apr_pool_t **newpool, + apr_pool_t *parent); +#else +#if APR_POOL_DEBUG +#define apr_pool_create(newpool, parent) \ + apr_pool_create_ex_debug(newpool, parent, NULL, NULL, \ + APR_POOL__FILE_LINE__) +#else +#define apr_pool_create(newpool, parent) \ + apr_pool_create_ex(newpool, parent, NULL, NULL) +#endif +#endif + +/** + * Create a new unmanaged pool. + * @param newpool The pool we have just created. + */ +#if defined(DOXYGEN) +APR_DECLARE(apr_status_t) apr_pool_create_core(apr_pool_t **newpool); +APR_DECLARE(apr_status_t) apr_pool_create_unmanaged(apr_pool_t **newpool); +#else +#if APR_POOL_DEBUG +#define apr_pool_create_core(newpool) \ + apr_pool_create_unmanaged_ex_debug(newpool, NULL, NULL, \ + APR_POOL__FILE_LINE__) +#define apr_pool_create_unmanaged(newpool) \ + apr_pool_create_unmanaged_ex_debug(newpool, NULL, NULL, \ + APR_POOL__FILE_LINE__) +#else +#define apr_pool_create_core(newpool) \ + apr_pool_create_unmanaged_ex(newpool, NULL, NULL) +#define apr_pool_create_unmanaged(newpool) \ + apr_pool_create_unmanaged_ex(newpool, NULL, NULL) +#endif +#endif + +/** + * Find the pool's allocator + * @param pool The pool to get the allocator from. + */ +APR_DECLARE(apr_allocator_t *) apr_pool_allocator_get(apr_pool_t *pool) + __attribute__((nonnull(1))); + +/** + * Clear all memory in the pool and run all the cleanups. This also destroys all + * subpools. + * @param p The pool to clear + * @remark This does not actually free the memory, it just allows the pool + * to re-use this memory for the next allocation. + * @see apr_pool_destroy() + */ +APR_DECLARE(void) apr_pool_clear(apr_pool_t *p) __attribute__((nonnull(1))); + +/** + * Debug version of apr_pool_clear. + * @param p See: apr_pool_clear. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have your apr_pool_clear + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_clear in a wrapper, trust the macro + * and don't call apr_pool_destroy_clear directly. + */ +APR_DECLARE(void) apr_pool_clear_debug(apr_pool_t *p, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pool_clear(p) \ + apr_pool_clear_debug(p, APR_POOL__FILE_LINE__) +#endif + +/** + * Destroy the pool. This takes similar action as apr_pool_clear() and then + * frees all the memory. + * @param p The pool to destroy + * @remark This will actually free the memory + */ +APR_DECLARE(void) apr_pool_destroy(apr_pool_t *p) __attribute__((nonnull(1))); + +/** + * Debug version of apr_pool_destroy. + * @param p See: apr_pool_destroy. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have your apr_pool_destroy + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_destroy in a wrapper, trust the macro + * and don't call apr_pool_destroy_debug directly. + */ +APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *p, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pool_destroy(p) \ + apr_pool_destroy_debug(p, APR_POOL__FILE_LINE__) +#endif + + +/* + * Memory allocation + */ + +/** + * Allocate a block of memory from a pool + * @param p The pool to allocate from + * @param size The amount of memory to allocate + * @return The allocated memory + */ +APR_DECLARE(void *) apr_palloc(apr_pool_t *p, apr_size_t size) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __attribute__((alloc_size(2))) +#endif + __attribute__((nonnull(1))); + +/** + * Debug version of apr_palloc + * @param p See: apr_palloc + * @param size See: apr_palloc + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @return See: apr_palloc + */ +APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __attribute__((alloc_size(2))) +#endif + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_palloc(p, size) \ + apr_palloc_debug(p, size, APR_POOL__FILE_LINE__) +#endif + +/** + * Allocate a block of memory from a pool and set all of the memory to 0 + * @param p The pool to allocate from + * @param size The amount of memory to allocate + * @return The allocated memory + */ +#if defined(DOXYGEN) +APR_DECLARE(void *) apr_pcalloc(apr_pool_t *p, apr_size_t size); +#elif !APR_POOL_DEBUG +#define apr_pcalloc(p, size) memset(apr_palloc(p, size), 0, size) +#endif + +/** + * Debug version of apr_pcalloc + * @param p See: apr_pcalloc + * @param size See: apr_pcalloc + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @return See: apr_pcalloc + */ +APR_DECLARE(void *) apr_pcalloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pcalloc(p, size) \ + apr_pcalloc_debug(p, size, APR_POOL__FILE_LINE__) +#endif + + +/* + * Pool Properties + */ + +/** + * Set the function to be called when an allocation failure occurs. + * @remark If the program wants APR to exit on a memory allocation error, + * then this function can be called to set the callback to use (for + * performing cleanup and then exiting). If this function is not called, + * then APR will return an error and expect the calling program to + * deal with the error accordingly. + */ +APR_DECLARE(void) apr_pool_abort_set(apr_abortfunc_t abortfunc, + apr_pool_t *pool) + __attribute__((nonnull(2))); + +/** + * Get the abort function associated with the specified pool. + * @param pool The pool for retrieving the abort function. + * @return The abort function for the given pool. + */ +APR_DECLARE(apr_abortfunc_t) apr_pool_abort_get(apr_pool_t *pool) + __attribute__((nonnull(1))); + +/** + * Get the parent pool of the specified pool. + * @param pool The pool for retrieving the parent pool. + * @return The parent of the given pool. + */ +APR_DECLARE(apr_pool_t *) apr_pool_parent_get(apr_pool_t *pool) + __attribute__((nonnull(1))); + +/** + * Determine if pool a is an ancestor of pool b. + * @param a The pool to search + * @param b The pool to search for + * @return True if a is an ancestor of b, NULL is considered an ancestor + * of all pools. + * @remark if compiled with APR_POOL_DEBUG, this function will also + * return true if A is a pool which has been guaranteed by the caller + * (using apr_pool_join) to have a lifetime at least as long as some + * ancestor of pool B. + */ +APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b); + +/** + * Tag a pool (give it a name) + * @param pool The pool to tag + * @param tag The tag + */ +APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag) + __attribute__((nonnull(1))); + + +/* + * User data management + */ + +/** + * Set the data associated with the current pool + * @param data The user data associated with the pool. + * @param key The key to use for association + * @param cleanup The cleanup program to use to cleanup the data (NULL if none) + * @param pool The current pool + * @warning The data to be attached to the pool should have a life span + * at least as long as the pool it is being attached to. + * + * Users of APR must take EXTREME care when choosing a key to + * use for their data. It is possible to accidentally overwrite + * data by choosing a key that another part of the program is using. + * Therefore it is advised that steps are taken to ensure that unique + * keys are used for all of the userdata objects in a particular pool + * (the same key in two different pools or a pool and one of its + * subpools is okay) at all times. Careful namespace prefixing of + * key names is a typical way to help ensure this uniqueness. + * + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_set(const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) + __attribute__((nonnull(2,4))); + +/** + * Set the data associated with the current pool + * @param data The user data associated with the pool. + * @param key The key to use for association + * @param cleanup The cleanup program to use to cleanup the data (NULL if none) + * @param pool The current pool + * @note same as apr_pool_userdata_set(), except that this version doesn't + * make a copy of the key (this function is useful, for example, when + * the key is a string literal) + * @warning This should NOT be used if the key could change addresses by + * any means between the apr_pool_userdata_setn() call and a + * subsequent apr_pool_userdata_get() on that key, such as if a + * static string is used as a userdata key in a DSO and the DSO could + * be unloaded and reloaded between the _setn() and the _get(). You + * MUST use apr_pool_userdata_set() in such cases. + * @warning More generally, the key and the data to be attached to the + * pool should have a life span at least as long as the pool itself. + * + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_setn( + const void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) + __attribute__((nonnull(2,4))); + +/** + * Return the data associated with the current pool. + * @param data The user data associated with the pool. + * @param key The key for the data to retrieve + * @param pool The current pool. + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_get(void **data, const char *key, + apr_pool_t *pool) + __attribute__((nonnull(1,2,3))); + + +/** + * @defgroup PoolCleanup Pool Cleanup Functions + * + * Cleanups are performed in the reverse order they were registered. That is: + * Last In, First Out. A cleanup function can safely allocate memory from + * the pool that is being cleaned up. It can also safely register additional + * cleanups which will be run LIFO, directly after the current cleanup + * terminates. Cleanups have to take caution in calling functions that + * create subpools. Subpools, created during cleanup will NOT automatically + * be cleaned up. In other words, cleanups are to clean up after themselves. + * + * @{ + */ + +/** + * Register a function to be called when a pool is cleared or destroyed + * @param p The pool to register the cleanup with + * @param data The data to pass to the cleanup function. + * @param plain_cleanup The function to call when the pool is cleared + * or destroyed + * @param child_cleanup The function to call when a child process is about + * to exec - this function is called in the child, obviously! + */ +APR_DECLARE(void) apr_pool_cleanup_register( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)) + __attribute__((nonnull(3,4))); + +/** + * Register a function to be called when a pool is cleared or destroyed. + * + * Unlike apr_pool_cleanup_register which registers a cleanup + * that is called AFTER all subpools are destroyed, this function registers + * a function that will be called before any of the subpools are destroyed. + * + * @param p The pool to register the cleanup with + * @param data The data to pass to the cleanup function. + * @param plain_cleanup The function to call when the pool is cleared + * or destroyed + */ +APR_DECLARE(void) apr_pool_pre_cleanup_register( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *)) + __attribute__((nonnull(3))); + +/** + * Remove a previously registered cleanup function. + * + * The cleanup most recently registered with @a p having the same values of + * @a data and @a cleanup will be removed. + * + * @param p The pool to remove the cleanup from + * @param data The data of the registered cleanup + * @param cleanup The function to remove from cleanup + * @remarks For some strange reason only the plain_cleanup is handled by this + * function + */ +APR_DECLARE(void) apr_pool_cleanup_kill(apr_pool_t *p, const void *data, + apr_status_t (*cleanup)(void *)) + __attribute__((nonnull(3))); + +/** + * Replace the child cleanup function of a previously registered cleanup. + * + * The cleanup most recently registered with @a p having the same values of + * @a data and @a plain_cleanup will have the registered child cleanup + * function replaced with @a child_cleanup. + * + * @param p The pool of the registered cleanup + * @param data The data of the registered cleanup + * @param plain_cleanup The plain cleanup function of the registered cleanup + * @param child_cleanup The function to register as the child cleanup + */ +APR_DECLARE(void) apr_pool_child_cleanup_set( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)) + __attribute__((nonnull(3,4))); + +/** + * Run the specified cleanup function immediately and unregister it. + * + * The cleanup most recently registered with @a p having the same values of + * @a data and @a cleanup will be removed and @a cleanup will be called + * with @a data as the argument. + * + * @param p The pool to remove the cleanup from + * @param data The data to remove from cleanup + * @param cleanup The function to remove from cleanup + */ +APR_DECLARE(apr_status_t) apr_pool_cleanup_run(apr_pool_t *p, void *data, + apr_status_t (*cleanup)(void *)) + __attribute__((nonnull(3))); + +/** + * An empty cleanup function. + * + * Passed to apr_pool_cleanup_register() when no cleanup is required. + * + * @param data The data to cleanup, will not be used by this function. + */ +APR_DECLARE_NONSTD(apr_status_t) apr_pool_cleanup_null(void *data); + +/** + * Run all registered child cleanups, in preparation for an exec() + * call in a forked child -- close files, etc., but *don't* flush I/O + * buffers, *don't* wait for subprocesses, and *don't* free any + * memory. + */ +APR_DECLARE(void) apr_pool_cleanup_for_exec(void); + +/** @} */ + +/** + * @defgroup PoolDebug Pool Debugging functions. + * + * pools have nested lifetimes -- sub_pools are destroyed when the + * parent pool is cleared. We allow certain liberties with operations + * on things such as tables (and on other structures in a more general + * sense) where we allow the caller to insert values into a table which + * were not allocated from the table's pool. The table's data will + * remain valid as long as all the pools from which its values are + * allocated remain valid. + * + * For example, if B is a sub pool of A, and you build a table T in + * pool B, then it's safe to insert data allocated in A or B into T + * (because B lives at most as long as A does, and T is destroyed when + * B is cleared/destroyed). On the other hand, if S is a table in + * pool A, it is safe to insert data allocated in A into S, but it + * is *not safe* to insert data allocated from B into S... because + * B can be cleared/destroyed before A is (which would leave dangling + * pointers in T's data structures). + * + * In general we say that it is safe to insert data into a table T + * if the data is allocated in any ancestor of T's pool. This is the + * basis on which the APR_POOL_DEBUG code works -- it tests these ancestor + * relationships for all data inserted into tables. APR_POOL_DEBUG also + * provides tools (apr_pool_find, and apr_pool_is_ancestor) for other + * folks to implement similar restrictions for their own data + * structures. + * + * However, sometimes this ancestor requirement is inconvenient -- + * sometimes it's necessary to create a sub pool where the sub pool is + * guaranteed to have the same lifetime as the parent pool. This is a + * guarantee implemented by the *caller*, not by the pool code. That + * is, the caller guarantees they won't destroy the sub pool + * individually prior to destroying the parent pool. + * + * In this case the caller must call apr_pool_join() to indicate this + * guarantee to the APR_POOL_DEBUG code. + * + * These functions are only implemented when #APR_POOL_DEBUG is set. + * + * @{ + */ +#if APR_POOL_DEBUG || defined(DOXYGEN) +/** + * Guarantee that a subpool has the same lifetime as the parent. + * @param p The parent pool + * @param sub The subpool + */ +APR_DECLARE(void) apr_pool_join(apr_pool_t *p, apr_pool_t *sub) + __attribute__((nonnull(2))); + +/** + * Find a pool from something allocated in it. + * @param mem The thing allocated in the pool + * @return The pool it is allocated in + */ +APR_DECLARE(apr_pool_t *) apr_pool_find(const void *mem); + +/** + * Report the number of bytes currently in the pool + * @param p The pool to inspect + * @param recurse Recurse/include the subpools' sizes + * @return The number of bytes + */ +APR_DECLARE(apr_size_t) apr_pool_num_bytes(apr_pool_t *p, int recurse) + __attribute__((nonnull(1))); + +/** + * Lock a pool + * @param pool The pool to lock + * @param flag The flag + */ +APR_DECLARE(void) apr_pool_lock(apr_pool_t *pool, int flag); + +/* @} */ + +#else /* APR_POOL_DEBUG or DOXYGEN */ + +#ifdef apr_pool_join +#undef apr_pool_join +#endif +#define apr_pool_join(a,b) + +#ifdef apr_pool_lock +#undef apr_pool_lock +#endif +#define apr_pool_lock(pool, lock) + +#endif /* APR_POOL_DEBUG or DOXYGEN */ + +/** @} */ + + +#endif +#ifdef __cplusplus +} +#endif + +#endif /* !APR_POOLS_H */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr_sha1.h b/code/application/sifarsdk/component/SignatureManager/include/apr_sha1.h new file mode 100644 index 000000000..a679261ca --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr_sha1.h @@ -0,0 +1,122 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* NIST Secure Hash Algorithm + * heavily modified by Uwe Hollerbach uh@alumni.caltech edu + * from Peter C. Gutmann's implementation as found in + * Applied Cryptography by Bruce Schneier + * This code is hereby placed in the public domain + */ + +#ifndef APR_SHA1_H +#define APR_SHA1_H + +#include "apu.h" +#include "apr_general.h" +#include "SfTypeDefine.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file apr_sha1.h + * @brief APR-UTIL SHA1 library + */ + +/** size of the SHA1 DIGEST */ +#define APR_SHA1_DIGESTSIZE 20 + +/** + * Define the Magic String prefix that identifies a password as being + * hashed using our algorithm. + */ +#define APR_SHA1PW_ID "{SHA}" + +/** length of the SHA Password */ +#define APR_SHA1PW_IDLEN 5 + +/** @see apr_sha1_ctx_t */ +typedef struct apr_sha1_ctx_t apr_sha1_ctx_t; + +/** + * SHA1 context structure + */ +struct apr_sha1_ctx_t { + /** message digest */ + UINT32 digest[5]; + /** 64-bit bit counts */ + UINT32 count_lo, count_hi; + /** SHA data buffer */ + UINT32 data[16]; + /** unprocessed amount in data */ + int local; +}; + +/** + * Provide a means to SHA1 crypt/encode a plaintext password in a way which + * makes password file compatible with those commonly use in netscape web + * and ldap installations. + * @param clear The plaintext password + * @param len The length of the plaintext password + * @param out The encrypted/encoded password + * @note SHA1 support is useful for migration purposes, but is less + * secure than Apache's password format, since Apache's (MD5) + * password format uses a random eight character salt to generate + * one of many possible hashes for the same password. Netscape + * uses plain SHA1 without a salt, so the same password + * will always generate the same hash, making it easier + * to break since the search space is smaller. + */ +APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out); + +/** + * Initialize the SHA digest + * @param context The SHA context to initialize + */ +APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *context); + +/** + * Update the SHA digest + * @param context The SHA1 context to update + * @param input The buffer to add to the SHA digest + * @param inputLen The length of the input buffer + */ +APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *context, const char *input, + unsigned int inputLen); + +/** + * Update the SHA digest with binary data + * @param context The SHA1 context to update + * @param input The buffer to add to the SHA digest + * @param inputLen The length of the input buffer + */ +APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *context, + const unsigned char *input, + unsigned int inputLen); + +/** + * Finish computing the SHA digest + * @param digest the output buffer in which to store the digest + * @param context The context to finalize + */ +APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE], + apr_sha1_ctx_t *context); + +#ifdef __cplusplus +} +#endif + +#endif /* APR_SHA1_H */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr_strings.h b/code/application/sifarsdk/component/SignatureManager/include/apr_strings.h new file mode 100644 index 000000000..9dd029f1c --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr_strings.h @@ -0,0 +1,390 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Portions of this file are covered by */ +/* -*- mode: c; c-file-style: "k&r" -*- + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef APR_STRINGS_H +#define APR_STRINGS_H + +/** + * @file apr_strings.h + * @brief APR Strings library + */ + +#include "apr.h" +#include "apr_errno.h" +#include "apr_pools.h" +#define APR_WANT_IOVEC +#include "apr_want.h" + +#if APR_HAVE_STDARG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_strings String routines + * @ingroup APR + * @{ + */ + +/** + * Do a natural order comparison of two strings. + * @param a The first string to compare + * @param b The second string to compare + * @return Either <0, 0, or >0. If the first string is less than the second + * this returns <0, if they are equivalent it returns 0, and if the + * first string is greater than second string it retuns >0. + */ +//APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b); + +/** + * Do a natural order comparison of two strings ignoring the case of the + * strings. + * @param a The first string to compare + * @param b The second string to compare + * @return Either <0, 0, or >0. If the first string is less than the second + * this returns <0, if they are equivalent it returns 0, and if the + * first string is greater than second string it retuns >0. + */ +//APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b); + +/** + * duplicate a string into memory allocated out of a pool + * @param p The pool to allocate out of + * @param s The string to duplicate + * @return The new string or NULL if s == NULL + */ +//APR_DECLARE(char *) apr_pstrdup(apr_pool_t *p, const char *s); + +/** + * Create a null-terminated string by making a copy of a sequence + * of characters and appending a null byte + * @param p The pool to allocate out of + * @param s The block of characters to duplicate + * @param n The number of characters to duplicate + * @return The new string or NULL if s == NULL + * @remark This is a faster alternative to apr_pstrndup, for use + * when you know that the string being duplicated really + * has 'n' or more characters. If the string might contain + * fewer characters, use apr_pstrndup. + +APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *p, const char *s, apr_size_t n) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __attribute__((alloc_size(3))) +#endif + ; +*/ + +/** + * Duplicate at most n characters of a string into memory allocated + * out of a pool; the new string will be NUL-terminated + * @param p The pool to allocate out of + * @param s The string to duplicate + * @param n The maximum number of characters to duplicate + * @return The new string or NULL if s == NULL + * @remark The amount of memory allocated from the pool is the length + * of the returned string including the NUL terminator + */ +//APR_DECLARE(char *) apr_pstrndup(apr_pool_t *p, const char *s, apr_size_t n); + +/** + * Duplicate a block of memory. + * + * @param p The pool to allocate from + * @param m The memory to duplicate + * @param n The number of bytes to duplicate + * @return The new block of memory or NULL if m == NULL + +APR_DECLARE(void *) apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __attribute__((alloc_size(3))) +#endif + ; +*/ + +/** + * Concatenate multiple strings, allocating memory out a pool + * @param p The pool to allocate out of + * @param ... The strings to concatenate. The final string must be NULL + * @return The new string + +APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *p, ...) +#if defined(__GNUC__) && __GNUC__ >= 4 + __attribute__((sentinel)) +#endif + ; +*/ + +/** + * Concatenate multiple strings specified in a writev-style vector + * @param p The pool from which to allocate + * @param vec The strings to concatenate + * @param nvec The number of strings to concatenate + * @param nbytes (output) strlen of new string (pass in NULL to omit) + * @return The new string + +APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *p, const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes); +*/ + +/** + * printf-style style printing routine. The data is output to a string + * allocated from a pool + * @param p The pool to allocate out of + * @param fmt The format of the string + * @param ap The arguments to use while printing the data + * @return The new string + */ +//APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap); + +/** + * printf-style style printing routine. The data is output to a string + * allocated from a pool + * @param p The pool to allocate out of + * @param fmt The format of the string + * @param ... The arguments to use while printing the data + * @return The new string + +APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...) + __attribute__((format(printf,2,3))); +*/ + +/** + * Copy up to dst_size characters from src to dst; does not copy + * past a NUL terminator in src, but always terminates dst with a NUL + * regardless. + * @param dst The destination string + * @param src The source string + * @param dst_size The space available in dst; dst always receives + * NUL termination, so if src is longer than + * dst_size, the actual number of characters copied is + * dst_size - 1. + * @return Pointer to the NUL terminator of the destination string, dst + * @remark + *
+ * Note the differences between this function and strncpy():
+ *  1) strncpy() doesn't always NUL terminate; apr_cpystrn() does.
+ *  2) strncpy() pads the destination string with NULs, which is often 
+ *     unnecessary; apr_cpystrn() does not.
+ *  3) strncpy() returns a pointer to the beginning of the dst string;
+ *     apr_cpystrn() returns a pointer to the NUL terminator of dst, 
+ *     to allow a check for truncation.
+ * 
+ +APR_DECLARE(char *) apr_cpystrn(char *dst, const char *src, + apr_size_t dst_size); +*/ + +/** + * Remove all whitespace from a string + * @param dest The destination string. It is okay to modify the string + * in place. Namely dest == src + * @param src The string to rid the spaces from. + * @return A pointer to the destination string's null terminator. + */ +//APR_DECLARE(char *) apr_collapse_spaces(char *dest, const char *src); + +/** + * Convert the arguments to a program from one string to an array of + * strings terminated by a NULL pointer + * @param arg_str The arguments to convert + * @param argv_out Output location. This is a pointer to an array of strings. + * @param token_context Pool to use. + +APR_DECLARE(apr_status_t) apr_tokenize_to_argv(const char *arg_str, + char ***argv_out, + apr_pool_t *token_context); +*/ + +/** + * Split a string into separate null-terminated tokens. The tokens are + * delimited in the string by one or more characters from the sep + * argument. + * @param str The string to separate; this should be specified on the + * first call to apr_strtok() for a given string, and NULL + * on subsequent calls. + * @param sep The set of delimiters + * @param last State saved by apr_strtok() between calls. + * @return The next token from the string + * @note the 'last' state points to the trailing NUL char of the final + * token, otherwise it points to the character following the current + * token (all successive or empty occurances of sep are skiped on the + * subsequent call to apr_strtok). Therefore it is possible to avoid + * a strlen() determination, with the following logic; + * toklen = last - retval; if (*last) --toklen; + */ +//APR_DECLARE(char *) apr_strtok(char *str, const char *sep, char **last); + +/** + * @defgroup APR_Strings_Snprintf snprintf implementations + * @warning + * These are snprintf implementations based on apr_vformatter(). + * + * Note that various standards and implementations disagree on the return + * value of snprintf, and side-effects due to %n in the formatting string. + * apr_snprintf (and apr_vsnprintf) behaves as follows: + * + * Process the format string until the entire string is exhausted, or + * the buffer fills. If the buffer fills then stop processing immediately + * (so no further %n arguments are processed), and return the buffer + * length. In all cases the buffer is NUL terminated. It will return the + * number of characters inserted into the buffer, not including the + * terminating NUL. As a special case, if len is 0, apr_snprintf will + * return the number of characters that would have been inserted if + * the buffer had been infinite (in this case, *buffer can be NULL) + * + * In no event does apr_snprintf return a negative number. + * @{ + */ + +/** + * snprintf routine based on apr_vformatter. This means it understands the + * same extensions. + * @param buf The buffer to write to + * @param len The size of the buffer + * @param format The format string + * @param ... The arguments to use to fill out the format string. + +APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, + const char *format, ...) + __attribute__((format(printf,3,4))); +*/ + +/** + * vsnprintf routine based on apr_vformatter. This means it understands the + * same extensions. + * @param buf The buffer to write to + * @param len The size of the buffer + * @param format The format string + * @param ap The arguments to use to fill out the format string. + +APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, + va_list ap); +*/ +/** @} */ + +/** + * create a string representation of an int, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +//APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n); + +/** + * create a string representation of a long, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +//APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n); + +/** + * create a string representation of an apr_off_t, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +//APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n); + +/** + * Convert a numeric string into an apr_off_t numeric value. + * @param offset The value of the parsed string. + * @param buf The string to parse. It may contain optional whitespace, + * followed by an optional '+' (positive, default) or '-' (negative) + * character, followed by an optional '0x' prefix if base is 0 or 16, + * followed by numeric digits appropriate for base. + * @param end A pointer to the end of the valid character in buf. If + * not NULL, it is set to the first invalid character in buf. + * @param base A numeric base in the range between 2 and 36 inclusive, + * or 0. If base is zero, buf will be treated as base ten unless its + * digits are prefixed with '0x', in which case it will be treated as + * base 16. + * @bug *end breaks type safety; where *buf is const, *end needs to be + * declared as const in APR 2.0 + +APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *buf, + char **end, int base); +*/ + +/** + * parse a numeric string into a 64-bit numeric value + * @param buf The string to parse. It may contain optional whitespace, + * followed by an optional '+' (positive, default) or '-' (negative) + * character, followed by an optional '0x' prefix if base is 0 or 16, + * followed by numeric digits appropriate for base. + * @param end A pointer to the end of the valid character in buf. If + * not NULL, it is set to the first invalid character in buf. + * @param base A numeric base in the range between 2 and 36 inclusive, + * or 0. If base is zero, buf will be treated as base ten unless its + * digits are prefixed with '0x', in which case it will be treated as + * base 16. + * @return The numeric value of the string. On overflow, errno is set + * to ERANGE. On success, errno is set to 0. + */ +//APR_DECLARE(apr_int64_t) apr_strtoi64(const char *buf, char **end, int base); + +/** + * parse a base-10 numeric string into a 64-bit numeric value. + * Equivalent to apr_strtoi64(buf, (char**)NULL, 10). + * @param buf The string to parse + * @return The numeric value of the string. On overflow, errno is set + * to ERANGE. On success, errno is set to 0. + */ +//APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf); + +/** + * Format a binary size (magnitiudes are 2^10 rather than 10^3) from an apr_off_t, + * as bytes, K, M, T, etc, to a four character compacted human readable string. + * @param size The size to format + * @param buf The 5 byte text buffer (counting the trailing null) + * @return The buf passed to apr_strfsize() + * @remark All negative sizes report ' - ', apr_strfsize only formats positive values. + */ +//APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !APR_STRINGS_H */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr_want.h b/code/application/sifarsdk/component/SignatureManager/include/apr_want.h new file mode 100644 index 000000000..f48d3549b --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr_want.h @@ -0,0 +1,126 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "apr.h" /* configuration data */ +/** + * @file apr_want.h + * @brief APR Standard Headers Support + * + *
+ * Features:
+ *
+ *   APR_WANT_STRFUNC:  strcmp, strcat, strcpy, etc
+ *   APR_WANT_MEMFUNC:  memcmp, memcpy, etc
+ *   APR_WANT_STDIO:     and related bits
+ *   APR_WANT_IOVEC:    struct iovec
+ *   APR_WANT_BYTEFUNC: htons, htonl, ntohl, ntohs
+ *
+ * Typical usage:
+ *
+ *   \#define APR_WANT_STRFUNC
+ *   \#define APR_WANT_MEMFUNC
+ *   \#include "apr_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ *       headers' or source files' use of apr_want.h)
+ * 
+ */ + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_STRFUNC + +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STRINGS_H +#include +#endif + +#undef APR_WANT_STRFUNC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_MEMFUNC + +#if APR_HAVE_STRING_H +#include +#endif + +#undef APR_WANT_MEMFUNC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_STDIO + +#if APR_HAVE_STDIO_H +#include +#endif + +#undef APR_WANT_STDIO +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_IOVEC + +#if APR_HAVE_IOVEC + +#if APR_HAVE_SYS_UIO_H +#include +#endif + +#else + +#ifndef APR_IOVEC_DEFINED +#define APR_IOVEC_DEFINED +#if 0 +struct iovec +{ + void *iov_base; + size_t iov_len; +}; +#endif +#endif /* !APR_IOVEC_DEFINED */ + +#endif /* APR_HAVE_IOVEC */ + +#undef APR_WANT_IOVEC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_BYTEFUNC + +/* Single Unix says they are in arpa/inet.h. Linux has them in + * netinet/in.h. FreeBSD has them in arpa/inet.h but requires that + * netinet/in.h be included first. + */ +#if APR_HAVE_NETINET_IN_H +#include +#endif +#if APR_HAVE_ARPA_INET_H +#include +#endif + +#undef APR_WANT_BYTEFUNC +#endif + +/* --------------------------------------------------------------------- */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apr_xlate.h b/code/application/sifarsdk/component/SignatureManager/include/apr_xlate.h new file mode 100644 index 000000000..5d98903de --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apr_xlate.h @@ -0,0 +1,164 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_XLATE_H +#define APR_XLATE_H + +#include "apu.h" +#include "apr_pools.h" +#include "apr_errno.h" + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file apr_xlate.h + * @brief APR I18N translation library + */ + +/** + * @defgroup APR_XLATE I18N translation library + * @ingroup APR + * @{ + */ +/** Opaque translation buffer */ +typedef struct apr_xlate_t apr_xlate_t; + +/** + * Set up for converting text from one charset to another. + * @param convset The handle to be filled in by this function + * @param topage The name of the target charset + * @param frompage The name of the source charset + * @param pool The pool to use + * @remark + * Specify APR_DEFAULT_CHARSET for one of the charset + * names to indicate the charset of the source code at + * compile time. This is useful if there are literal + * strings in the source code which must be translated + * according to the charset of the source code. + * APR_DEFAULT_CHARSET is not useful if the source code + * of the caller was not encoded in the same charset as + * APR at compile time. + * + * @remark + * Specify APR_LOCALE_CHARSET for one of the charset + * names to indicate the charset of the current locale. + * + * @remark + * Return APR_EINVAL if unable to procure a convset, or APR_ENOTIMPL + * if charset transcoding is not available in this instance of + * apr-util at all (i.e., APR_HAS_XLATE is undefined). + */ +APU_DECLARE(apr_status_t) apr_xlate_open(apr_xlate_t **convset, + const char *topage, + const char *frompage, + apr_pool_t *pool); + +/** + * This is to indicate the charset of the sourcecode at compile time + * names to indicate the charset of the source code at + * compile time. This is useful if there are literal + * strings in the source code which must be translated + * according to the charset of the source code. + */ +#define APR_DEFAULT_CHARSET (const char *)0 +/** + * To indicate charset names of the current locale + */ +#define APR_LOCALE_CHARSET (const char *)1 + +/** + * Find out whether or not the specified conversion is single-byte-only. + * @param convset The handle allocated by apr_xlate_open, specifying the + * parameters of conversion + * @param onoff Output: whether or not the conversion is single-byte-only + * @remark + * Return APR_ENOTIMPL if charset transcoding is not available + * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined). + */ +APU_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff); + +/** + * Convert a buffer of text from one codepage to another. + * @param convset The handle allocated by apr_xlate_open, specifying + * the parameters of conversion + * @param inbuf The address of the source buffer + * @param inbytes_left Input: the amount of input data to be translated + * Output: the amount of input data not yet translated + * @param outbuf The address of the destination buffer + * @param outbytes_left Input: the size of the output buffer + * Output: the amount of the output buffer not yet used + * @remark + * Returns APR_ENOTIMPL if charset transcoding is not available + * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined). + * Returns APR_INCOMPLETE if the input buffer ends in an incomplete + * multi-byte character. + * + * To correctly terminate the output buffer for some multi-byte + * character set encodings, a final call must be made to this function + * after the complete input string has been converted, passing + * the inbuf and inbytes_left parameters as NULL. (Note that this + * mode only works from version 1.1.0 onwards) + */ +APU_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset, + const char *inbuf, + UINT32 *inbytes_left, + char *outbuf, + UINT32 *outbytes_left); + +/* @see apr_file_io.h the comment in apr_file_io.h about this hack */ +#ifdef APR_NOT_DONE_YET +/** + * The purpose of apr_xlate_conv_char is to translate one character + * at a time. This needs to be written carefully so that it works + * with double-byte character sets. + * @param convset The handle allocated by apr_xlate_open, specifying the + * parameters of conversion + * @param inchar The character to convert + * @param outchar The converted character + */ +APU_DECLARE(apr_status_t) apr_xlate_conv_char(apr_xlate_t *convset, + char inchar, char outchar); +#endif + +/** + * Convert a single-byte character from one charset to another. + * @param convset The handle allocated by apr_xlate_open, specifying the + * parameters of conversion + * @param inchar The single-byte character to convert. + * @warning This only works when converting between single-byte character sets. + * -1 will be returned if the conversion can't be performed. + */ +//APU_DECLARE(apr_int32_t) apr_xlate_conv_byte(apr_xlate_t *convset, + // unsigned char inchar); + +/** + * Close a codepage translation handle. + * @param convset The codepage translation handle to close + * @remark + * Return APR_ENOTIMPL if charset transcoding is not available + * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined). + */ +APU_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset); + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_XLATE_H */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apu.h b/code/application/sifarsdk/component/SignatureManager/include/apu.h new file mode 100644 index 000000000..450dfbff8 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apu.h @@ -0,0 +1,146 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * apu.h is duplicated from apu.hw at build time -- do not edit apu.h + */ +/* @file apu.h + * @brief APR-Utility main file + */ +/** + * @defgroup APR_Util APR Utility Functions + * @{ + */ + + +#ifndef APU_H +#define APU_H + +/** + * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library, + * so that all public symbols are exported. + * + * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers, + * to provide static linkage when the dynamic library may be unavailable. + * + * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when + * including the APR-UTIL public headers, to import and link the symbols from + * the dynamic APR-UTIL library and assure appropriate indirection and calling + * conventions at compile time. + */ + +/* Make sure we have our platform identifier macro defined we ask for later. + */ +#if defined(_WIN32) && !defined(WIN32) +#define WIN32 1 +#endif + +#if defined(DOXYGEN) || !defined(WIN32) +/** + * The public APR-UTIL functions are declared with APU_DECLARE(), so they may + * use the most appropriate calling convention. Public APR functions with + * variable arguments must use APU_DECLARE_NONSTD(). + * + * @fn APU_DECLARE(rettype) apr_func(args); + */ +#define APU_DECLARE(type) type +/** + * The public APR-UTIL functions using variable arguments are declared with + * APU_DECLARE_NONSTD(), as they must use the C language calling convention. + * + * @fn APU_DECLARE_NONSTD(rettype) apr_func(args, ...); + */ +#define APU_DECLARE_NONSTD(type) type +/** + * The public APR-UTIL variables are declared with APU_DECLARE_DATA. + * This assures the appropriate indirection is invoked at compile time. + * + * @fn APU_DECLARE_DATA type apr_variable; + * @note extern APU_DECLARE_DATA type apr_variable; syntax is required for + * declarations within headers to properly import the variable. + */ +#define APU_DECLARE_DATA +#elif defined(APU_DECLARE_STATIC) +#define APU_DECLARE(type) type __stdcall +#define APU_DECLARE_NONSTD(type) type __cdecl +#define APU_DECLARE_DATA +#elif defined(APU_DECLARE_EXPORT) +#define APU_DECLARE(type) __declspec(dllexport) type __stdcall +#define APU_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl +#define APU_DECLARE_DATA __declspec(dllexport) +#else +#define APU_DECLARE(type) __declspec(dllimport) type __stdcall +#define APU_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl +#define APU_DECLARE_DATA __declspec(dllimport) +#endif + +#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC) +/** + * Declare a dso module's exported module structure as APU_MODULE_DECLARE_DATA. + * + * Unless APU_MODULE_DECLARE_STATIC is defined at compile time, symbols + * declared with APU_MODULE_DECLARE_DATA are always exported. + * @code + * module APU_MODULE_DECLARE_DATA mod_tag + * @endcode + */ +#define APU_MODULE_DECLARE_DATA +#else +#define APU_MODULE_DECLARE_DATA __declspec(dllexport) +#endif + +/* + * we always have SDBM (it's in our codebase) + */ +#define APU_HAVE_SDBM 1 + +#ifndef APU_DSO_MODULE_BUILD +#define APU_HAVE_GDBM 0 +#define APU_HAVE_NDBM 0 +#define APU_HAVE_DB 0 + +#if APU_HAVE_DB +#define APU_HAVE_DB_VERSION 0 +#endif +#endif + +/* + * we always enable dynamic driver loads within apr_dbd + * Win32 always has odbc (it's always installed) + */ +#ifndef APU_DSO_MODULE_BUILD +#define APU_HAVE_PGSQL 0 +#define APU_HAVE_MYSQL 0 +#define APU_HAVE_SQLITE3 0 +#define APU_HAVE_SQLITE2 0 +#define APU_HAVE_ORACLE 0 +#define APU_HAVE_FREETDS 0 +#define APU_HAVE_ODBC 1 +#endif + +#define APU_HAVE_CRYPTO 0 + +#ifndef APU_DSO_MODULE_BUILD +#define APU_HAVE_OPENSSL 0 +#define APU_HAVE_NSS 0 +#endif + +#define APU_HAVE_APR_ICONV 0 +#define APU_HAVE_ICONV 0 +#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV) + +#endif /* APU_H */ +/** @} */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/apu_config.h b/code/application/sifarsdk/component/SignatureManager/include/apu_config.h new file mode 100644 index 000000000..b0e203932 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/apu_config.h @@ -0,0 +1,52 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Note: This is a Windows specific version of apu_config.hw. It is copied + * as apu_config.h at the start of a Windows build. + */ + +#ifdef WIN32 + +#ifndef APU_CONFIG_H +#define APU_CONFIG_H + +/* Compile win32 with DSO support for .dll builds */ +#ifdef APU_DECLARE_STATIC +#define APU_DSO_BUILD 0 +#else +#define APU_DSO_BUILD 1 +#endif + +/* Presume a standard, modern (5.x) mysql sdk/ +#define HAVE_MY_GLOBAL_H 1 + +/* my_sys.h is broken on VC/Win32, and apparently not required */ +/* #undef HAVE_MY_SYS_H 0 */ + +/* + * Windows does not have GDBM, and we always use the bundled (new) Expat + */ + +/* Define if you have the gdbm library (-lgdbm). */ +/* #undef HAVE_LIBGDBM */ + +/* define if Expat 1.0 or 1.1 was found */ +/* #undef APR_HAVE_OLD_EXPAT */ + + +#endif /* APU_CONFIG_H */ +#endif /* WIN32 */ diff --git a/code/application/sifarsdk/component/SignatureManager/include/sha256.h b/code/application/sifarsdk/component/SignatureManager/include/sha256.h new file mode 100644 index 000000000..d239859b5 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/include/sha256.h @@ -0,0 +1,33 @@ +#include "SfTypeDefine.h" + +#define SHA256_HASH_SIZE 32 + +/* Hash size in 32-bit words */ +#define SHA256_HASH_WORDS 8 + +struct _SHA256Context { + unsigned long long totalLength; + UINT32 hash[SHA256_HASH_WORDS]; + UINT32 bufferLength; + union { + UINT32 words[16]; + UINT8 bytes[64]; + } buffer; +#ifdef RUNTIME_ENDIAN + int littleEndian; +#endif /* RUNTIME_ENDIAN */ +}; + +typedef struct _SHA256Context SHA256Context; + +#ifdef __cplusplus +extern "C" { +#endif + + void SHA256Init (SHA256Context *sc); + void SHA256Update (SHA256Context *sc, const void *data, UINT32 len); + void SHA256Final (SHA256Context *sc, UINT8 hash[SHA256_HASH_SIZE]); + +#ifdef __cplusplus +} +#endif diff --git a/code/application/sifarsdk/component/SignatureManager/src/HMACSHA.c b/code/application/sifarsdk/component/SignatureManager/src/HMACSHA.c new file mode 100644 index 000000000..9154ef4f0 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/src/HMACSHA.c @@ -0,0 +1,288 @@ +//iamshuke@hotmail.com sha1/sha256/hmac +#include +#include +#include +#include +#include +// #include + +#include "sha256.h" +#include "SfTypeDefine.h" +// #include "sf_param_common.h" +// #include "RtcTimeCpp.h" +#include "HttpCommon.h" +#include "HMACSHA.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#define SHA_BLOCKSIZE 64 +#define AMZ_DEBUG 0 +int hmacLen = 32; + +void convert_to_hexString(UINT8* hexString,UINT8* str, int len) +{ + int i ; + UINT8 hexDigits[16] = { '0', '1', '2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; + //UINT8 tempStr[65] = { 0 }; + + for (i = 0; i < len; i++) + { + int temp_num = 0; + temp_num = str[i]; + if (temp_num < 0) + temp_num = 256 + temp_num; + int d1 = temp_num / 16; + int d2 = temp_num % 16; + printf("%c%c", hexDigits[d1], hexDigits[d2]); + hexString[i * 2] = hexDigits[d1]; + hexString[i * 2 + 1] = hexDigits[d2]; + + } + +} + +/* Function to print the digest */ +void pr_sha(UINT8* s, int t) +{ + int i ; + + for(i=0;i SHA256_HASH_SIZE ? SHA256_HASH_SIZE : *t; + datatranslate(isha, out, *t) ; +} + +void hmac_sha256 +( + const UINT8* k, /* secret key */ + int lk, /* length of the key in bytes */ + const UINT8* d, /* data */ + int ld, /* length of data in bytes */ + UINT8* out, /* output buffer, at least "t" bytes */ + int* t + ) +{ + SHA256Context ictx, octx ; + UINT8 isha[SHA256_HASH_SIZE]; + UINT8 osha[SHA256_HASH_SIZE] ; + UINT8 key[SHA256_HASH_SIZE] ; + UINT8 buf[SHA_BLOCKSIZE] ; + int i ; + + if (lk > SHA_BLOCKSIZE) { + + SHA256Context tctx ; + + SHA256Init(&tctx) ; + SHA256Update(&tctx, k, lk) ; + SHA256Final(&tctx, key) ; + + k = key ; + lk = SHA256_HASH_SIZE ; + } + /**** Inner Digest ****/ + + SHA256Init(&ictx) ; + /* Pad the key for inner digest */ + for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ; + for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ; + SHA256Update(&ictx, buf, SHA_BLOCKSIZE) ; + SHA256Update(&ictx, d, ld) ; + SHA256Final(&ictx, isha) ; + /**** Outter Digest ****/ + + SHA256Init(&octx) ; + /* Pad the key for outter digest */ + + for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ; + for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ; + SHA256Update(&octx, buf, SHA_BLOCKSIZE); + SHA256Update(&octx, isha, SHA256_HASH_SIZE); + SHA256Final(&octx, osha) ; + /* truncate and print the results */ + *t = *t > SHA256_HASH_SIZE ? SHA256_HASH_SIZE : *t; + + datatranslate(osha, out, *t); +} + +void amz_get_canonicalRequest_sha256(UINT8 *requestSha256, UINT32 content_len, UINT8 *objectName, UINT8 *typestr, UINT8 *bucket, const SignatureTime time) +{ + char canonicalReq[512] = { 0 }; + UINT8 out[65] = {0}; +// UINT32 pos = 0;/* Added by MaxLi 2022/03/02--9:46:21*/ + UINT32 lenCanonicalReq = 0; + int lenOut = 32; + UINT8 hexString[65] = {0}; + char tempbuf[128] = {0}; + // SystemTime time = GetSystemTime(); + + sprintf(tempbuf,"PUT\n"); + strcpy(canonicalReq,tempbuf); + + sprintf(tempbuf,"/%s\n\n",objectName); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"content-length:%d\n",content_len); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"content-type:%s\n",typestr); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"host:%s.%s\n",bucket,AMZ_HOST); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"x-amz-date:%d%02d%02dT%02d%02d%02dZ\n\n", time.Year, time.Mon, time.Day, time.Hour, time.Min, time.Sec); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"content-length;content-type;host;x-amz-date\nUNSIGNED-PAYLOAD"); + strcat(canonicalReq,tempbuf); + + printf("CanonicalRequest:\n--------\n%s\n----------\n",canonicalReq); + + lenCanonicalReq = strlen(canonicalReq); + printf("lenCanonicalReq:%d\n----------\n",lenCanonicalReq); + + sha256((UINT8*)canonicalReq, lenCanonicalReq, out, &lenOut); + #if AMZ_DEBUG + pr_sha(out, lenOut); + #endif + convert_to_hexString(hexString, out, lenOut); + + sprintf((char*)requestSha256,"%s",hexString); + + +} +void amz_get_signString(UINT8 *signstr, UINT8 *region, UINT8 *requestSha256, const SignatureTime time) +{ +// UINT32 signPos = 0;/* Added by MaxLi 2022/03/02--9:48:34*/ + char tempbuf[66]={0}; + // SystemTime time = GetSystemTime(); + + printf("amz_get_signString begin\n"); + sprintf(tempbuf, "%s\n", SECRET_TYPE); + strcpy((char*)signstr, tempbuf); + + sprintf(tempbuf, "%d%02d%02dT%02d%02d%02dZ\n", time.Year, time.Mon, time.Day, time.Hour, time.Min, time.Sec); + strcat((char*)signstr, tempbuf); + + sprintf(tempbuf, "%d%02d%02d/%s/%s/%s\n", time.Year, time.Mon, time.Day, region, AMZ,SECRET_VER); + strcat((char*)signstr, tempbuf); + + sprintf(tempbuf, "%s", requestSha256); + strcat((char*)signstr, tempbuf); + #if AMZ_DEBUG + printf("signstr:%s\n", signstr); + #endif +} +void amz_signature(UINT8 *signatureStr, UINT32 content_len, UINT8 *objectName, UINT8 *typestr, UINT8 *password, UINT8 *bucket, UINT8 *region, const SignatureTime time) +{ + UINT8 requestSha256[66] = {0}; + UINT8 signStr[256] = {0}; + UINT8 date[20] = {0}; + UINT8 amz[3] = {0}; + UINT8 secretVer[16] = {0}; + UINT8 hmac_keydate[66] = {0}; + UINT8 hmac_keyregion[66] = {0}; + UINT8 hmac_keyamz[66] = {0}; + UINT8 hmac_keysecretver[66] = {0}; + UINT8 hmac_signature[66] = {0}; + + // SystemTime time = GetSystemTime(); + + amz_get_canonicalRequest_sha256(requestSha256, content_len, objectName, typestr, bucket, time); + printf("requestSha256=%s\n", requestSha256); + + amz_get_signString(signStr, region, requestSha256, time); + sprintf((char*)date,"%d%02d%02d",time.Year, time.Mon, time.Day); + sprintf((char*)amz,"%s",AMZ); + printf("amz:%s\n",amz); + sprintf((char*)secretVer,"%s",SECRET_VER); + printf("date:%s,key:%s\n",date,password); + hmac_sha256(password, strlen((char*)password), date, strlen((char*)date), hmac_keydate, &hmacLen); + + #if AMZ_DEBUG + printf("HMAC-KEYDATE:\n"); + pr_sha(hmac_keydate, hmacLen); + printf("region:%s\n",region); + #endif + + hmac_sha256(hmac_keydate, hmacLen, region, strlen((char*)region), hmac_keyregion, &hmacLen); + + #if AMZ_DEBUG + printf("HMAC-KEYREGION:\n"); + pr_sha(hmac_keyregion, hmacLen); + printf("amz:%s\n",amz); + #endif + hmac_sha256(hmac_keyregion, hmacLen, amz, strlen((char*)amz), hmac_keyamz, &hmacLen); + + #if AMZ_DEBUG + printf("HMAC-KEYAMZ:\n"); + pr_sha(hmac_keyamz, hmacLen); + printf("secretVer:%s\n",secretVer); + #endif + + hmac_sha256(hmac_keyamz, hmacLen, secretVer, strlen((char*)secretVer), hmac_keysecretver, &hmacLen); + + #if AMZ_DEBUG + printf("HMAC-KEYSECRETVER:\n"); + pr_sha(hmac_keysecretver, hmacLen); + #endif + + hmac_sha256(hmac_keysecretver, hmacLen, signStr, strlen((char*)signStr), hmac_signature, &hmacLen); + + #if 1 + printf("HMAC-SIGNATURER:\n"); + pr_sha(hmac_signature, hmacLen); + #endif + + convert_to_hexString(signatureStr, hmac_signature, hmacLen); + printf("signatureStr:%s\n",signatureStr); + +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/SignatureManager/src/RtcTimeCpp.cpp b/code/application/sifarsdk/component/SignatureManager/src/RtcTimeCpp.cpp new file mode 100644 index 000000000..48db009a6 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/src/RtcTimeCpp.cpp @@ -0,0 +1,10 @@ +#include "RtcTimeCpp.h" +#include "IPeripheralManager.h" +struct rtc_time GetRtcTime(void) +{ + struct rtc_time rtctm; + std::shared_ptr rtc = std::make_shared(); + IPeripheralManager::GetInstance()->GetRtcTimeHandle(rtc); + rtc->Get(rtctm); + return rtctm; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/SignatureManager/src/aos_util.c b/code/application/sifarsdk/component/SignatureManager/src/aos_util.c new file mode 100644 index 000000000..2e53ca51e --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/src/aos_util.c @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include + + +#include "aos_util.h" +#include "apr_sha1.h" +#include "SfTypeDefine.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + +int aos_base64_encode(const UINT8 *in, int inLen, UINT8 *out) +{ + static const char *ENC = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + UINT8 *original_out = out; + + while (inLen) { + // first 6 bits of UINT8 1 + *out++ = ENC[*in >> 2]; + if (!--inLen) { + // last 2 bits of UINT8 1, 4 bits of 0 + *out++ = ENC[(*in & 0x3) << 4]; + *out++ = '='; + *out++ = '='; + break; + } + // last 2 bits of UINT8 1, first 4 bits of UINT8 2 + *out++ = ENC[((*in & 0x3) << 4) | (*(in + 1) >> 4)]; + in++; + if (!--inLen) { + // last 4 bits of UINT8 2, 2 bits of 0 + *out++ = ENC[(*in & 0xF) << 2]; + *out++ = '='; + break; + } + // last 4 bits of UINT8 2, first 2 bits of UINT8 3 + *out++ = ENC[((*in & 0xF) << 2) | (*(in + 1) >> 6)]; + in++; + // last 6 bits of UINT8 3 + *out++ = ENC[*in & 0x3F]; + in++, inLen--; + } + + return (out - original_out); +} + +// HMAC-SHA-1: +// +// K - is key padded with zeros to 512 bits +// m - is message +// OPAD - 0x5c5c5c... +// IPAD - 0x363636... +// +// HMAC(K,m) = SHA1((K ^ OPAD) . SHA1((K ^ IPAD) . m)) + + +void HMAC_SHA1(UINT8 hmac[20], const UINT8 *key, int key_len, + const UINT8 *message, int message_len) +{ + UINT8 kopad[64], kipad[64]; + int i; + UINT8 digest[APR_SHA1_DIGESTSIZE]; + apr_sha1_ctx_t context; + + if (key_len > 64) { + key_len = 64; + } + + for (i = 0; i < key_len; i++) { + kopad[i] = key[i] ^ 0x5c; + kipad[i] = key[i] ^ 0x36; + } + + for ( ; i < 64; i++) { + kopad[i] = 0 ^ 0x5c; + kipad[i] = 0 ^ 0x36; + } + + apr_sha1_init(&context); + apr_sha1_update(&context, (const char *)kipad, 64); + apr_sha1_update(&context, (const char *)message, (unsigned int)message_len); + apr_sha1_final(digest, &context); + + apr_sha1_init(&context); + apr_sha1_update(&context, (const char *)kopad, 64); + apr_sha1_update(&context, (const char *)digest, 20); + apr_sha1_final(hmac, &context); +} + +void oss_sign_headers(UINT8*value,UINT8*datestr,UINT8*namestr,UINT8*typestr,UINT8*password,UINT8*bucket) +{ +// int b64Len; + UINT8 hmac[20]; + UINT8 b64[((20 + 1) * 4) / 3]; + UINT8 access_key_secret[64]; + UINT8 signstr[150];/*WARNING!!!, need to adjust the array len,avoid the array bounds*/ + UINT8 b64str[29]={0}; + + sprintf((char*)access_key_secret,"%s",password);//"N2mzlsRZUpGITLBZ03vxMMhUfZSvEl" + sprintf((char*)signstr,"PUT\n\n%s\n%s\n/%s/%s",typestr,datestr,bucket,namestr); + printf("signstr:%s--\n",signstr); + + //printf("+++%d,%d+++\n",strlen(access_key_secret),strlen(signstr)); + HMAC_SHA1(hmac, access_key_secret,strlen((char*)access_key_secret),signstr,strlen((char*)signstr)); + + // Now base-64 encode the results +// b64Len = aos_base64_encode(hmac, 20, b64); + aos_base64_encode(hmac, 20, b64); + #if 0 + int i; + for(i = 0;i<28;i++) + { + printf("%c",b64[i]); + } + printf("\nb64---------------------\n"); + #endif + printf("b64:%s--\n",b64); + strncpy((char*)b64str,(char*)b64,28); + #if 0 + for(i = 0;i<28;i++) + { + printf("%c",b64str[i]); + } + printf("\nb64str---------------------\n"); + #endif + printf("b64str:%s--\n",b64str); + sprintf((char*)value, "%s",b64str); + return; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/SignatureManager/src/apr_sha1.c b/code/application/sifarsdk/component/SignatureManager/src/apr_sha1.c new file mode 100644 index 000000000..a57f1484d --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/src/apr_sha1.c @@ -0,0 +1,376 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The exported function: + * + * apr_sha1_base64(const char *clear, int len, char *out); + * + * provides a means to SHA1 crypt/encode a plaintext password in + * a way which makes password files compatible with those commonly + * used in netscape web and ldap installations. It was put together + * by Clinton Wong , who also notes that: + * + * Note: SHA1 support is useful for migration purposes, but is less + * secure than Apache's password format, since Apache's (MD5) + * password format uses a random eight character salt to generate + * one of many possible hashes for the same password. Netscape + * uses plain SHA1 without a salt, so the same password + * will always generate the same hash, making it easier + * to break since the search space is smaller. + * + * See also the documentation in support/SHA1 as to hints on how to + * migrate an existing netscape installation and other supplied utitlites. + * + * This software also makes use of the following component: + * + * NIST Secure Hash Algorithm + * heavily modified by Uwe Hollerbach uh@alumni.caltech edu + * from Peter C. Gutmann's implementation as found in + * Applied Cryptography by Bruce Schneier + * This code is hereby placed in the public domain + */ + +#include "apr_sha1.h" +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + +/* a bit faster & bigger, if defined */ +#define UNROLL_LOOPS + +/* NIST's proposed modification to SHA, 7/11/94 */ +#define USE_MODIFIED_SHA + +/* SHA f()-functions */ +#define f1(x,y,z) ((x & y) | (~x & z)) +#define f2(x,y,z) (x ^ y ^ z) +#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) +#define f4(x,y,z) (x ^ y ^ z) + +/* SHA constants */ +#define CONST1 0x5a827999L +#define CONST2 0x6ed9eba1L +#define CONST3 0x8f1bbcdcL +#define CONST4 0xca62c1d6L + +/* 32-bit rotate */ + +#define ROT32(x,n) ((x << n) | (x >> (32 - n))) + +#define FUNC(n,i) \ + temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \ + E = D; D = C; C = ROT32(B,30); B = A; A = temp + +#define SHA_BLOCKSIZE 64 + +#if APR_CHARSET_EBCDIC +static apr_xlate_t *ebcdic2ascii_xlate; + +APU_DECLARE(apr_status_t) apr_SHA1InitEBCDIC(apr_xlate_t *x) +{ + apr_status_t rv; + int onoff; + + /* Only single-byte conversion is supported. + */ + rv = apr_xlate_sb_get(x, &onoff); + if (rv) { + return rv; + } + if (!onoff) { /* If conversion is not single-byte-only */ + return APR_EINVAL; + } + ebcdic2ascii_xlate = x; + return APR_SUCCESS; +} +#endif + +/* do SHA transformation */ +static void sha_transform(apr_sha1_ctx_t *sha_info) +{ + int i; + UINT32 temp, A, B, C, D, E, W[80]; + + for (i = 0; i < 16; ++i) { + W[i] = sha_info->data[i]; + } + for (i = 16; i < 80; ++i) { + W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; +#ifdef USE_MODIFIED_SHA + W[i] = ROT32(W[i], 1); +#endif /* USE_MODIFIED_SHA */ + } + A = sha_info->digest[0]; + B = sha_info->digest[1]; + C = sha_info->digest[2]; + D = sha_info->digest[3]; + E = sha_info->digest[4]; +#ifdef UNROLL_LOOPS + FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4); + FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9); + FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14); + FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19); + + FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24); + FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29); + FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34); + FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39); + + FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44); + FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49); + FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54); + FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59); + + FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64); + FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69); + FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74); + FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79); +#else /* !UNROLL_LOOPS */ + for (i = 0; i < 20; ++i) { + FUNC(1,i); + } + for (i = 20; i < 40; ++i) { + FUNC(2,i); + } + for (i = 40; i < 60; ++i) { + FUNC(3,i); + } + for (i = 60; i < 80; ++i) { + FUNC(4,i); + } +#endif /* !UNROLL_LOOPS */ + sha_info->digest[0] += A; + sha_info->digest[1] += B; + sha_info->digest[2] += C; + sha_info->digest[3] += D; + sha_info->digest[4] += E; +} + +union endianTest { + long Long; + char Char[sizeof(long)]; +}; + +static char isLittleEndian(void) +{ + static union endianTest u; + u.Long = 1; + return (u.Char[0] == 1); +} + +/* change endianness of data */ + +/* count is the number of bytes to do an endian flip */ +static void maybe_byte_reverse(UINT32 *buffer, int count) +{ + int i; + UINT8 ct[4], *cp; + + if (isLittleEndian()) { /* do the swap only if it is little endian */ + count /= sizeof(UINT32); + cp = (UINT8 *) buffer; + for (i = 0; i < count; ++i) { + ct[0] = cp[0]; + ct[1] = cp[1]; + ct[2] = cp[2]; + ct[3] = cp[3]; + cp[0] = ct[3]; + cp[1] = ct[2]; + cp[2] = ct[1]; + cp[3] = ct[0]; + cp += sizeof(UINT32); + } + } +} + +/* initialize the SHA digest */ + +APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *sha_info) +{ + sha_info->digest[0] = 0x67452301L; + sha_info->digest[1] = 0xefcdab89L; + sha_info->digest[2] = 0x98badcfeL; + sha_info->digest[3] = 0x10325476L; + sha_info->digest[4] = 0xc3d2e1f0L; + sha_info->count_lo = 0L; + sha_info->count_hi = 0L; + sha_info->local = 0; +} + +/* update the SHA digest */ + +APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *sha_info, + const unsigned char *buffer, + unsigned int count) +{ + unsigned int i; + + if ((sha_info->count_lo + ((UINT32) count << 3)) < sha_info->count_lo) { + ++sha_info->count_hi; + } + sha_info->count_lo += (UINT32) count << 3; + sha_info->count_hi += (UINT32) count >> 29; + if (sha_info->local) { + i = SHA_BLOCKSIZE - sha_info->local; + if (i > count) { + i = count; + } + memcpy(((UINT8 *) sha_info->data) + sha_info->local, buffer, i); + count -= i; + buffer += i; + sha_info->local += i; + if (sha_info->local == SHA_BLOCKSIZE) { + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + } + else { + return; + } + } + while (count >= SHA_BLOCKSIZE) { + memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); + buffer += SHA_BLOCKSIZE; + count -= SHA_BLOCKSIZE; + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + } + memcpy(sha_info->data, buffer, count); + sha_info->local = count; +} + +APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *sha_info, const char *buf, + unsigned int count) +{ +#if APR_CHARSET_EBCDIC + int i; + const UINT8 *buffer = (const UINT8 *) buf; + apr_size_t inbytes_left, outbytes_left; + + if ((sha_info->count_lo + ((UINT32) count << 3)) < sha_info->count_lo) { + ++sha_info->count_hi; + } + sha_info->count_lo += (UINT32) count << 3; + sha_info->count_hi += (UINT32) count >> 29; + /* Is there a remainder of the previous Update operation? */ + if (sha_info->local) { + i = SHA_BLOCKSIZE - sha_info->local; + if (i > count) { + i = count; + } + inbytes_left = outbytes_left = i; + apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, + ((UINT8 *) sha_info->data) + sha_info->local, + &outbytes_left); + count -= i; + buffer += i; + sha_info->local += i; + if (sha_info->local == SHA_BLOCKSIZE) { + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + } + else { + return; + } + } + while (count >= SHA_BLOCKSIZE) { + inbytes_left = outbytes_left = SHA_BLOCKSIZE; + apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, + (UINT8 *) sha_info->data, &outbytes_left); + buffer += SHA_BLOCKSIZE; + count -= SHA_BLOCKSIZE; + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + } + inbytes_left = outbytes_left = count; + apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, + (UINT8 *) sha_info->data, &outbytes_left); + sha_info->local = count; +#else + apr_sha1_update_binary(sha_info, (const unsigned char *) buf, count); +#endif +} + +/* finish computing the SHA digest */ + +APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE], + apr_sha1_ctx_t *sha_info) +{ + int count, i, j; + UINT32 lo_bit_count, hi_bit_count, k; + + lo_bit_count = sha_info->count_lo; + hi_bit_count = sha_info->count_hi; + count = (int) ((lo_bit_count >> 3) & 0x3f); + ((UINT8 *) sha_info->data)[count++] = 0x80; + if (count > SHA_BLOCKSIZE - 8) { + memset(((UINT8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count); + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + memset((UINT8 *) sha_info->data, 0, SHA_BLOCKSIZE - 8); + } + else { + memset(((UINT8 *) sha_info->data) + count, 0, + SHA_BLOCKSIZE - 8 - count); + } + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_info->data[14] = hi_bit_count; + sha_info->data[15] = lo_bit_count; + sha_transform(sha_info); + + for (i = 0, j = 0; j < APR_SHA1_DIGESTSIZE; i++) { + k = sha_info->digest[i]; + digest[j++] = (unsigned char) ((k >> 24) & 0xff); + digest[j++] = (unsigned char) ((k >> 16) & 0xff); + digest[j++] = (unsigned char) ((k >> 8) & 0xff); + digest[j++] = (unsigned char) (k & 0xff); + } +} + +#if 0 +APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out) +{ + int l; + apr_sha1_ctx_t context; + apr_byte_t digest[APR_SHA1_DIGESTSIZE]; + + apr_sha1_init(&context); + apr_sha1_update(&context, clear, len); + apr_sha1_final(digest, &context); + + /* private marker. */ + apr_cpystrn(out, APR_SHA1PW_ID, APR_SHA1PW_IDLEN + 1); + + /* SHA1 hash is always 20 chars */ + l = apr_base64_encode_binary(out + APR_SHA1PW_IDLEN, digest, sizeof(digest)); + out[l + APR_SHA1PW_IDLEN] = '\0'; + + /* + * output of base64 encoded SHA1 is always 28 chars + APR_SHA1PW_IDLEN + */ +} +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/SignatureManager/src/sha256.c b/code/application/sifarsdk/component/SignatureManager/src/sha256.c new file mode 100644 index 000000000..51faa143d --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/src/sha256.c @@ -0,0 +1,331 @@ +#include +#include +#include +#include +#include +#include "sha256.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifndef lint +/* +static const char rcsid[] = +"$Id: sha256.c 680 2003-07-25 21:57:49Z asaddi $"; +*/ +#endif /* !lint */ + +#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) +#define SIGMA0(x) (ROTR((x), 2) ^ ROTR((x), 13) ^ ROTR((x), 22)) +#define SIGMA1(x) (ROTR((x), 6) ^ ROTR((x), 11) ^ ROTR((x), 25)) +#define sigma0(x) (ROTR((x), 7) ^ ROTR((x), 18) ^ ((x) >> 3)) +#define sigma1(x) (ROTR((x), 17) ^ ROTR((x), 19) ^ ((x) >> 10)) + +#define DO_ROUND() { \ + t1 = h + SIGMA1(e) + Ch(e, f, g) + *(Kp++) + *(W++); \ + t2 = SIGMA0(a) + Maj(a, b, c); \ + h = g; \ + g = f; \ + f = e; \ + e = d + t1; \ + d = c; \ + c = b; \ + b = a; \ + a = t1 + t2; \ +} + +static const UINT32 K[64] = { + 0x428a2f98L, 0x71374491L, 0xb5c0fbcfL, 0xe9b5dba5L, + 0x3956c25bL, 0x59f111f1L, 0x923f82a4L, 0xab1c5ed5L, + 0xd807aa98L, 0x12835b01L, 0x243185beL, 0x550c7dc3L, + 0x72be5d74L, 0x80deb1feL, 0x9bdc06a7L, 0xc19bf174L, + 0xe49b69c1L, 0xefbe4786L, 0x0fc19dc6L, 0x240ca1ccL, + 0x2de92c6fL, 0x4a7484aaL, 0x5cb0a9dcL, 0x76f988daL, + 0x983e5152L, 0xa831c66dL, 0xb00327c8L, 0xbf597fc7L, + 0xc6e00bf3L, 0xd5a79147L, 0x06ca6351L, 0x14292967L, + 0x27b70a85L, 0x2e1b2138L, 0x4d2c6dfcL, 0x53380d13L, + 0x650a7354L, 0x766a0abbL, 0x81c2c92eL, 0x92722c85L, + 0xa2bfe8a1L, 0xa81a664bL, 0xc24b8b70L, 0xc76c51a3L, + 0xd192e819L, 0xd6990624L, 0xf40e3585L, 0x106aa070L, + 0x19a4c116L, 0x1e376c08L, 0x2748774cL, 0x34b0bcb5L, + 0x391c0cb3L, 0x4ed8aa4aL, 0x5b9cca4fL, 0x682e6ff3L, + 0x748f82eeL, 0x78a5636fL, 0x84c87814L, 0x8cc70208L, + 0x90befffaL, 0xa4506cebL, 0xbef9a3f7L, 0xc67178f2L +}; + + +#ifndef RUNTIME_ENDIAN + +#ifdef WORDS_BIGENDIAN + +#define BYTESWAP(x) (x) +#define BYTESWAP64(x) (x) + +#else /* WORDS_BIGENDIAN */ + +#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \ + (ROTL((x), 8) & 0x00ff00ffL)) +#define BYTESWAP64(x) _byteswap64(x) + +//static inline uint64_t _byteswap64(uint64_t x) +unsigned long long _byteswap64(unsigned long long x) +{ + UINT32 a = x >> 32; + UINT32 b = (UINT32) x; + return ((unsigned long long) BYTESWAP(b) << 32) | (unsigned long long) BYTESWAP(a); +} + +#endif /* WORDS_BIGENDIAN */ + +#endif /* !RUNTIME_ENDIAN */ + +static const UINT8 padding[64] = { + 0x80, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +void +SHA256Init (SHA256Context *sc) +{ +#ifdef RUNTIME_ENDIAN + setEndian (&sc->littleEndian); +#endif /* RUNTIME_ENDIAN */ + + sc->totalLength = 0LL; + sc->hash[0] = 0x6a09e667L; + sc->hash[1] = 0xbb67ae85L; + sc->hash[2] = 0x3c6ef372L; + sc->hash[3] = 0xa54ff53aL; + sc->hash[4] = 0x510e527fL; + sc->hash[5] = 0x9b05688cL; + sc->hash[6] = 0x1f83d9abL; + sc->hash[7] = 0x5be0cd19L; + sc->bufferLength = 0L; +} + +static void +burnStack (int size) +{ + char buf[128]; + + memset (buf, 0, sizeof (buf)); + size -= sizeof (buf); + if (size > 0) + burnStack (size); +} + +static void +SHA256Guts (SHA256Context *sc, const UINT32 *cbuf) +{ + UINT32 buf[64]; + UINT32 *W, *W2, *W7, *W15, *W16; + UINT32 a, b, c, d, e, f, g, h; + UINT32 t1, t2; + const UINT32 *Kp; + int i; + + W = buf; + + for (i = 15; i >= 0; i--) { + *(W++) = BYTESWAP(*cbuf); + cbuf++; + } + + W16 = &buf[0]; + W15 = &buf[1]; + W7 = &buf[9]; + W2 = &buf[14]; + + for (i = 47; i >= 0; i--) { + *(W++) = sigma1(*W2) + *(W7++) + sigma0(*W15) + *(W16++); + W2++; + W15++; + } + + a = sc->hash[0]; + b = sc->hash[1]; + c = sc->hash[2]; + d = sc->hash[3]; + e = sc->hash[4]; + f = sc->hash[5]; + g = sc->hash[6]; + h = sc->hash[7]; + + Kp = K; + W = buf; + +#ifndef SHA256_UNROLL +#define SHA256_UNROLL 1 +#endif /* !SHA256_UNROLL */ + +#if SHA256_UNROLL == 1 + for (i = 63; i >= 0; i--) + DO_ROUND(); +#elif SHA256_UNROLL == 2 + for (i = 31; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 4 + for (i = 15; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 8 + for (i = 7; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 16 + for (i = 3; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 32 + for (i = 1; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 64 + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); +#elif SHA256_UNROLL == 68 + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); +#else +#error "SHA256_UNROLL must be 1, 2, 4, 8, 16, 32, or 64!" +#endif + + sc->hash[0] += a; + sc->hash[1] += b; + sc->hash[2] += c; + sc->hash[3] += d; + sc->hash[4] += e; + sc->hash[5] += f; + sc->hash[6] += g; + sc->hash[7] += h; + +} + +void +SHA256Update (SHA256Context *sc, const void *vdata, UINT32 len) +{ + const UINT8 *data = (const UINT8 *)vdata; + UINT32 bufferBytesLeft; + UINT32 bytesToCopy; + int needBurn = 0; + +#ifdef SHA256_FAST_COPY +#else /* SHA256_FAST_COPY */ + while (len) + { + bufferBytesLeft = 64L - sc->bufferLength; + + bytesToCopy = bufferBytesLeft; + if (bytesToCopy > len) + bytesToCopy = len; + + memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy); + + sc->totalLength += bytesToCopy * 8L; + + sc->bufferLength += bytesToCopy; + data += bytesToCopy; + len -= bytesToCopy; + + if (sc->bufferLength == 64L) { + SHA256Guts (sc, sc->buffer.words); + needBurn = 1; + sc->bufferLength = 0L; + } + } +#endif /* SHA256_FAST_COPY */ + + if (needBurn) + burnStack (sizeof (UINT32[74]) + sizeof (UINT32 *[6]) + sizeof (int)); +} + +void +SHA256Final (SHA256Context *sc, UINT8 hash[SHA256_HASH_SIZE]) +{ + UINT32 bytesToPad; + unsigned long long lengthPad; + int i; + + bytesToPad = 120L - sc->bufferLength; + if (bytesToPad > 64L) + bytesToPad -= 64L; + + lengthPad = BYTESWAP64(sc->totalLength); + + SHA256Update (sc, padding, bytesToPad); + SHA256Update (sc, &lengthPad, 8L); + + if (hash) { + for (i = 0; i < SHA256_HASH_WORDS; i++) { +#ifdef SHA256_FAST_COPY + *((UINT32 *) hash) = BYTESWAP(sc->hash[i]); +#else /* SHA256_FAST_COPY */ + hash[0] = (UINT8) (sc->hash[i] >> 24); + hash[1] = (UINT8) (sc->hash[i] >> 16); + hash[2] = (UINT8) (sc->hash[i] >> 8); + hash[3] = (UINT8) sc->hash[i]; +#endif /* SHA256_FAST_COPY */ + hash += 4; + + } + } +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/SignatureManager/src/xlate.c_bak b/code/application/sifarsdk/component/SignatureManager/src/xlate.c_bak new file mode 100644 index 000000000..e1653c7b0 --- /dev/null +++ b/code/application/sifarsdk/component/SignatureManager/src/xlate.c_bak @@ -0,0 +1,345 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "apu.h" +#include "apu_config.h" +#include "apr_lib.h" +#include "apr_strings.h" +//#include "apr_portable.h" +#include "apr_xlate.h" + +/* If no implementation is available, don't generate code here since + * apr_xlate.h emitted macros which return APR_ENOTIMPL. + */ +#include "app_com_def.h" +#include "app_com_api.h" +#include "sp5k_rsvblk_api.h" +#include "sp5k_fs_api.h" +#include "app_osd_api.h" + +#if APR_HAS_XLATE + +#ifdef HAVE_STDDEF_H +#include /* for NULL */ +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STRINGS_H +#include +#endif +#ifdef HAVE_ICONV_H +#include +#endif +#if APU_HAVE_APR_ICONV +#include +#endif + +#if defined(APU_ICONV_INBUF_CONST) || APU_HAVE_APR_ICONV +#define ICONV_INBUF_TYPE const char ** +#else +#define ICONV_INBUF_TYPE char ** +#endif + +#ifndef min +#define min(x,y) ((x) <= (y) ? (x) : (y)) +#endif + +struct apr_xlate_t { + apr_pool_t *pool; + char *frompage; + char *topage; + char *sbcs_table; +#if APU_HAVE_ICONV + iconv_t ich; +#elif APU_HAVE_APR_ICONV + apr_iconv_t ich; +#endif +}; + + + +static apr_status_t apr_xlate_cleanup(void *convset) +{ + apr_xlate_t *old = convset; + +#if APU_HAVE_APR_ICONV + if (old->ich != (apr_iconv_t)-1) { + return apr_iconv_close(old->ich, old->pool); + } + +#elif APU_HAVE_ICONV + if (old->ich != (iconv_t)-1) { + if (iconv_close(old->ich)) { + int rv = errno; + + /* Sometimes, iconv is not good about setting errno. */ + return rv ? rv : APR_EINVAL; + } + } +#endif + + return APR_SUCCESS; +} + +#if APU_HAVE_ICONV +static void check_sbcs(apr_xlate_t *convset) +{ + char inbuf[256], outbuf[256]; + char *inbufptr = inbuf; + char *outbufptr = outbuf; + apr_size_t inbytes_left, outbytes_left; + int i; + apr_size_t translated; + + for (i = 0; i < sizeof(inbuf); i++) { + inbuf[i] = i; + } + + inbytes_left = outbytes_left = sizeof(inbuf); + translated = iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr, + &inbytes_left, &outbufptr, &outbytes_left); + + if (translated != (apr_size_t)-1 + && inbytes_left == 0 + && outbytes_left == 0) { + /* hurray... this is simple translation; save the table, + * close the iconv descriptor + */ + + convset->sbcs_table = apr_palloc(convset->pool, sizeof(outbuf)); + memcpy(convset->sbcs_table, outbuf, sizeof(outbuf)); + iconv_close(convset->ich); + convset->ich = (iconv_t)-1; + + /* TODO: add the table to the cache */ + } + else { + /* reset the iconv descriptor, since it's now in an undefined + * state. */ + iconv_close(convset->ich); + convset->ich = iconv_open(convset->topage, convset->frompage); + } +} +#elif APU_HAVE_APR_ICONV +static void check_sbcs(apr_xlate_t *convset) +{ + char inbuf[256], outbuf[256]; + char *inbufptr = inbuf; + char *outbufptr = outbuf; + apr_size_t inbytes_left, outbytes_left; + int i; + apr_size_t translated; + apr_status_t rv; + + for (i = 0; i < sizeof(inbuf); i++) { + inbuf[i] = i; + } + + inbytes_left = outbytes_left = sizeof(inbuf); + rv = apr_iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr, + &inbytes_left, &outbufptr, &outbytes_left, + &translated); + + if ((rv == APR_SUCCESS) + && (translated != (apr_size_t)-1) + && inbytes_left == 0 + && outbytes_left == 0) { + /* hurray... this is simple translation; save the table, + * close the iconv descriptor + */ + + convset->sbcs_table = apr_palloc(convset->pool, sizeof(outbuf)); + memcpy(convset->sbcs_table, outbuf, sizeof(outbuf)); + apr_iconv_close(convset->ich, convset->pool); + convset->ich = (apr_iconv_t)-1; + + /* TODO: add the table to the cache */ + } + else { + /* reset the iconv descriptor, since it's now in an undefined + * state. */ + apr_iconv_close(convset->ich, convset->pool); + rv = apr_iconv_open(convset->topage, convset->frompage, + convset->pool, &convset->ich); + } +} +#endif /* APU_HAVE_APR_ICONV */ + +static void make_identity_table(apr_xlate_t *convset) +{ + int i; + + convset->sbcs_table = apr_palloc(convset->pool, 256); + for (i = 0; i < 256; i++) + convset->sbcs_table[i] = i; +} + + + +APU_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff) +{ + *onoff = convset->sbcs_table != NULL; + return APR_SUCCESS; +} + +APU_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset, + const char *inbuf, + apr_size_t *inbytes_left, + char *outbuf, + apr_size_t *outbytes_left) +{ + apr_status_t status = APR_SUCCESS; + +#if APU_HAVE_APR_ICONV + if (convset->ich != (apr_iconv_t)-1) { + const char *inbufptr = inbuf; + apr_size_t translated; + char *outbufptr = outbuf; + status = apr_iconv(convset->ich, &inbufptr, inbytes_left, + &outbufptr, outbytes_left, &translated); + + /* If everything went fine but we ran out of buffer, don't + * report it as an error. Caller needs to look at the two + * bytes-left values anyway. + * + * There are three expected cases where rc is -1. In each of + * these cases, *inbytes_left != 0. + * a) the non-error condition where we ran out of output + * buffer + * b) the non-error condition where we ran out of input (i.e., + * the last input character is incomplete) + * c) the error condition where the input is invalid + */ + switch (status) { + + case APR_BADARG: /* out of space on output */ + status = 0; /* change table lookup code below if you + make this an error */ + break; + + case APR_EINVAL: /* input character not complete (yet) */ + status = APR_INCOMPLETE; + break; + + case APR_BADCH: /* bad input byte */ + status = APR_EINVAL; + break; + + /* Sometimes, iconv is not good about setting errno. */ + case 0: + if (inbytes_left && *inbytes_left) + status = APR_INCOMPLETE; + break; + + default: + break; + } + } + else + +#elif APU_HAVE_ICONV + if (convset->ich != (iconv_t)-1) { + const char *inbufptr = inbuf; + char *outbufptr = outbuf; + apr_size_t translated; + translated = iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr, + inbytes_left, &outbufptr, outbytes_left); + + /* If everything went fine but we ran out of buffer, don't + * report it as an error. Caller needs to look at the two + * bytes-left values anyway. + * + * There are three expected cases where rc is -1. In each of + * these cases, *inbytes_left != 0. + * a) the non-error condition where we ran out of output + * buffer + * b) the non-error condition where we ran out of input (i.e., + * the last input character is incomplete) + * c) the error condition where the input is invalid + */ + if (translated == (apr_size_t)-1) { + int rv = errno; + switch (rv) { + + case E2BIG: /* out of space on output */ + status = 0; /* change table lookup code below if you + make this an error */ + break; + + case EINVAL: /* input character not complete (yet) */ + status = APR_INCOMPLETE; + break; + + case EILSEQ: /* bad input byte */ + status = APR_EINVAL; + break; + + /* Sometimes, iconv is not good about setting errno. */ + case 0: + status = APR_INCOMPLETE; + break; + + default: + status = rv; + break; + } + } + } + else +#endif + + if (inbuf) { + apr_size_t to_convert = min(*inbytes_left, *outbytes_left); + apr_size_t converted = to_convert; + char *table = convset->sbcs_table; + + while (to_convert) { + *outbuf = table[(unsigned char)*inbuf]; + ++outbuf; + ++inbuf; + --to_convert; + } + *inbytes_left -= converted; + *outbytes_left -= converted; + } + + return status; +} + +#else /* !APR_HAS_XLATE */ + + +APU_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff) +{ + return APR_ENOTIMPL; +} + +APU_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset, + const char *inbuf, + UINT32 *inbytes_left, + char *outbuf, + UINT32 *outbytes_left) +{ + return APR_ENOTIMPL; +} + +APU_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset) +{ + return APR_ENOTIMPL; +} + +#endif /* APR_HAS_XLATE */ diff --git a/code/application/sifarsdk/component/StateMachineManager/CMakeLists.txt b/code/application/sifarsdk/component/StateMachineManager/CMakeLists.txt new file mode 100644 index 000000000..a4197bc75 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/CMakeLists.txt @@ -0,0 +1,27 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ./src/stateMachine + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) +aux_source_directory(./src/stateMachine SRC_FILES) + +set(TARGET_NAME StateMachineManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} ReturnCode Log) \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/include/IStateMachineManager.h b/code/application/sifarsdk/component/StateMachineManager/include/IStateMachineManager.h new file mode 100644 index 000000000..639dd4a6f --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/include/IStateMachineManager.h @@ -0,0 +1,115 @@ +#ifndef I_STATE_MACHINE_MANAGER_H +#define I_STATE_MACHINE_MANAGER_H +#include "VReturnCode.h" +#include +/** + * @brief + * Use for sending message to state. + */ +/** + * @brief + * virtural class, which will be used to send all kind of message classes. + */ +class VMessageObject +{ +public: + VMessageObject() = default; + virtual ~VMessageObject() = default; +}; +class VStateMachineMessage +{ +public: + VStateMachineMessage() = default; + virtual ~VStateMachineMessage() = default; + virtual int GetMessageName() const = 0; + virtual const std::shared_ptr &GetMessageObj(void) const = 0; +}; +/** + * @brief + * Use for users to define specific state in their code. + */ +class State +{ +public: + /** + * @Description Construct a new State:: State object. + * + * @param name - State name.[in] + */ + explicit State(const std::string &name) : mStateName(name) {} + + /** + * @Description Destroy the State:: State object. + * + */ + virtual ~State() = default; + +public: + virtual void GoInState() = 0; + virtual void GoOutState() = 0; + virtual bool ExecuteStateMsg(VStateMachineMessage *msg) = 0; + + /** + * @Description : Obtains state name. + * + * @return std::string + */ + std::string GetStateName() { return mStateName; } + +private: + std::string mStateName; +}; +/** + * @brief + * A virtual state machine class, user must create the real state machine by IStateMachineManager. + */ +class VStateMachine +{ +public: + VStateMachine() = default; + virtual ~VStateMachine() = default; + virtual bool InitialStateMachine() { return false; } + virtual void StatePlus(State *state, State *upper) {} + virtual void SetFirstState(State *firstState) {} + virtual void StartStateMachine() {} + virtual void SendMessage(int msgName) {} + virtual void StopHandlerThread() {} + virtual void SendMessage(int msgName, const std::shared_ptr &messageObj) {} + virtual void MessageExecutedLater(int msgName, const std::shared_ptr &messageObj, int64_t delayTimeMs) {} + virtual void SwitchState(State *targetState) {} + virtual void StopTimer(int timerName) {} + virtual void DelayMessage(VStateMachineMessage *msg) {} +}; +class IStateMachineManager +{ +public: + IStateMachineManager() = default; + virtual ~IStateMachineManager() = default; + /** + * @brief Get the Instance object + * Return reference for runing faster. Usage : IStateMachineManager::GetInstance()->Init(); + * Don't use IStateMachineManager like this: + * std::shared_ptr &log = IStateMachineManager::GetInstance(); + * or std::shared_ptr log = IStateMachineManager::GetInstance(); + * @param impl + * @return std::shared_ptr& + */ + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + /** + * @brief Create a State Machine object + * Create a state machine for user. + * @return std::shared_prt Return the real state machine. + */ + virtual RETURN_CODE CreateStateMachine(std::shared_ptr &stateMachine) + { + return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); + } +}; +/** + * @brief Create a State Machine Manager object + * Create the real module object, which should be called in main thread. + * @return true + * @return false + */ +bool CreateStateMachineManager(void); +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/IStateMachineManager.cpp b/code/application/sifarsdk/component/StateMachineManager/src/IStateMachineManager.cpp new file mode 100644 index 000000000..0a562cae3 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/IStateMachineManager.cpp @@ -0,0 +1,32 @@ +#include "IStateMachineManager.h" +#include "Log.h" +#include +std::shared_ptr &IStateMachineManager::GetInstance(std::shared_ptr *impl) +{ + static std::shared_ptr instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + // Don't use std::mutex for runing faster. + // Sleep for difference thread to release instance. + // TODO: How to make sure that don't sleep when power on? We must design code to finish the task. + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Don't sleep and make sure that start fast. + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static std::shared_ptr tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerImpl.cpp b/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerImpl.cpp new file mode 100644 index 000000000..975453a79 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerImpl.cpp @@ -0,0 +1,6 @@ +#include "StateMachineManagerImpl.h" +#include "StateMachineManagerMakePtr.h" +RETURN_CODE StateMachineManagerImpl::CreateStateMachine(std::shared_ptr &stateMachine) +{ + return StateMachineManagerMakePtr::GetInstance()->CreateStateMachine(stateMachine); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerImpl.h b/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerImpl.h new file mode 100644 index 000000000..c0f79b65e --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerImpl.h @@ -0,0 +1,11 @@ +#ifndef STATE_MACHINE_MANAGER_IMPL_H +#define STATE_MACHINE_MANAGER_IMPL_H +#include "IStateMachineManager.h" +class StateMachineManagerImpl : public IStateMachineManager +{ +public: + StateMachineManagerImpl() = default; + ~StateMachineManagerImpl() = default; + RETURN_CODE CreateStateMachine(std::shared_ptr &stateMachine) override; +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerMakePtr.cpp b/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerMakePtr.cpp new file mode 100644 index 000000000..7414a1f7f --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerMakePtr.cpp @@ -0,0 +1,54 @@ +#include "StateMachineManagerMakePtr.h" +#include "Log.h" +#include "state_machine.h" +#include "IStateMachineManager.h" +#include "StateMachineManagerImpl.h" +#include +bool CreateStateMachineManager(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = StateMachineManagerMakePtr::GetInstance()->CreateStateMachineManager(instance); + if (code->IsCodeOK()) + { + LogInfo("State machine manager instance is ok.\n"); + IStateMachineManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &StateMachineManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + /** + * @brief + * The non-thread-safe changing is only for gtest. + */ + instance = *impl; + } + return instance; +} +RETURN_CODE StateMachineManagerMakePtr::CreateStateMachine(std::shared_ptr &stateMachine) +{ + // TODO: need a name ? + auto tmp = std::make_shared("TODO"); + if (tmp) + { + stateMachine = std::move(tmp); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + LogError("Create state machine module failed.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::MAKE_SHARED_PTR_FAILED); +} +RETURN_CODE StateMachineManagerMakePtr::CreateStateMachineManager(std::shared_ptr &instance) +{ + auto tmp = std::make_shared(); + if (tmp) + { + instance = std::move(tmp); + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + LogError("Create state machine module failed.\n"); + return VReturnCode::NewCode(VReturnCodeDefine::MAKE_SHARED_PTR_FAILED); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerMakePtr.h b/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerMakePtr.h new file mode 100644 index 000000000..1cc99515f --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/StateMachineManagerMakePtr.h @@ -0,0 +1,30 @@ +#ifndef STATE_MACHINE_MANAGER_MAKE_PTR_H +#define STATE_MACHINE_MANAGER_MAKE_PTR_H +#include "VReturnCode.h" +#include "IStateMachineManager.h" +#include +class StateMachineManagerMakePtr +{ +public: + StateMachineManagerMakePtr() = default; + virtual ~StateMachineManagerMakePtr() = default; + /** + * @brief Get the Instance object + * Return reference for runing faster. Usage : StateMachineManagerMakePtr::GetInstance()->Init(); + * Don't use StateMachineManagerMakePtr like this: + * std::shared_ptr &log = StateMachineManagerMakePtr::GetInstance(); + * or std::shared_ptr log = StateMachineManagerMakePtr::GetInstance(); + * @param impl + * @return std::shared_ptr& + */ + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + /** + * @brief Create a State Machine object + * Create a state + * @param instance + * @return RETURN_CODE + */ + virtual RETURN_CODE CreateStateMachine(std::shared_ptr &stateMachine); + virtual RETURN_CODE CreateStateMachineManager(std::shared_ptr &instance); +}; +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/handler.cpp b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/handler.cpp new file mode 100644 index 000000000..8b4b3f4bf --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/handler.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "handler.h" +#include +#include +#include "Log.h" + +#undef LOG_TAG +#define LOG_TAG "OHWIFI_HANDLER" + +// namespace OHOS { +// namespace Wifi { +Handler::Handler() : pMyQueue(nullptr), handleThread(0), isRunning(true) +{} + +Handler::~Handler() +{ + LogInfo("Handler::~Handler\n"); + StopHandlerThread(); + return; +} + +bool Handler::InitialHandler() +{ + if (handleThread != 0) { + return true; + } + if (pMyQueue == nullptr) { + pMyQueue = std::make_unique(); + if (pMyQueue == nullptr) { + LogError("pMyQueue alloc failed.\n"); + return false; + } + } + + int ret = pthread_create(&handleThread, nullptr, RunHandleThreadFunc, this); + if (ret < 0) { + LogError("pthread_create failed.\n"); + return false; + } + + return true; +} + +void Handler::StopHandlerThread() +{ + LogInfo("Handler::StopHandlerThread\n"); + if (isRunning) { + isRunning = false; + if (pMyQueue != nullptr) { + pMyQueue->StopQueueLoop(); + } + + if (handleThread != 0) { + pthread_join(handleThread, nullptr); + } + } + + return; +} + +void *Handler::RunHandleThreadFunc(void *pInstance) +{ + if (pInstance == nullptr) { + LogError("pInstance is null.\n"); + return nullptr; + } + + Handler *pHandler = (Handler *)pInstance; + pHandler->GetAndDistributeMessage(); + + return nullptr; +} + +void Handler::GetAndDistributeMessage() +{ + if (pMyQueue == nullptr) { + LogError("pMyQueue is null.\n"); + return; + } + + while (isRunning) { + InternalMessage *msg = pMyQueue->GetNextMessage(); + if (msg == nullptr) { + LogError("GetNextMessage failed.\n"); + continue; + } + + DistributeMessage(msg); + MessageManage::GetInstance().ReclaimMsg(msg); + } + + return; +} + +void Handler::SendMessage(InternalMessage *msg) +{ + if (msg == nullptr) { + LogError("Handler::SendMessage: msg is null.\n"); + return; + } + + // LogInfo("Handler::SendMessage msg:%d\n", msg->GetMessageName()); + MessageExecutedLater(msg, 0); + return; +} + +void Handler::MessageExecutedLater(InternalMessage *msg, int64_t delayTimeMs) +{ + if (msg == nullptr) { + LogError("Handler::MessageExecutedLater: msg is null.\n"); + return; + } + + // LogInfo("Handler::MessageExecutedLater msg:%d\n", msg->GetMessageName()); + int64_t delayTime = delayTimeMs; + if (delayTime < 0) { + delayTime = 0; + } + + /* Obtains the current time, accurate to milliseconds. */ + struct timeval curTime = {0, 0}; + if (gettimeofday(&curTime, nullptr) != 0) { + LogError("gettimeofday failed.\n"); + MessageManage::GetInstance().ReclaimMsg(msg); + return; + } + int64_t nowTime = static_cast(curTime.tv_sec) * USEC_1000 + curTime.tv_usec / USEC_1000; + + MessageExecutedAtTime(msg, nowTime + delayTime); + return; +} + +void Handler::MessageExecutedAtTime(InternalMessage *msg, int64_t execTime) +{ + if (msg == nullptr) { + LogError("Handler::MessageExecutedAtTime: msg is null.\n"); + return; + } + + // LogInfo("Handler::MessageExecutedAtTime msg: %d\n", msg->GetMessageName()); + if (pMyQueue == nullptr) { + LogError("pMyQueue is null.\n"); + MessageManage::GetInstance().ReclaimMsg(msg); + return; + } + + if (pMyQueue->AddMessageToQueue(msg, execTime) != true) { + LogError("AddMessageToQueue failed.\n"); + return; + } + + return; +} + +void Handler::PlaceMessageTopOfQueue(InternalMessage *msg) +{ + if (msg == nullptr) { + LogError("Handler::PlaceMessageTopOfQueue: msg is null.\n"); + return; + } + + // LogInfo("Handler::PlaceMessageTopOfQueue msg: %d\n", msg->GetMessageName()); + if (pMyQueue == nullptr) { + LogError("pMyQueue is null.\n"); + MessageManage::GetInstance().ReclaimMsg(msg); + return; + } + + if (!pMyQueue->AddMessageToQueue(msg, 0)) { + LogError("AddMessageToQueue failed.\n"); + return; + } + + return; +} + +void Handler::DeleteMessageFromQueue(int messageName) +{ + // LogInfo("Handler::DeleteMessageFromQueue msg is: %d\n", messageName); + if (pMyQueue == nullptr) { + LogError("pMyQueue is null.\n"); + return; + } + + if (!pMyQueue->DeleteMessageFromQueue(messageName)) { + LogError("DeleteMessageFromQueue failed.\n"); + return; + } + + return; +} + +void Handler::DistributeMessage(InternalMessage *msg) +{ + if (msg == nullptr) { + return; + } + ExecuteMessage(msg); + return; +} +// } // namespace Wifi +// } // namespace OHOS \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/handler.h b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/handler.h new file mode 100644 index 000000000..85e136339 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/handler.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_HANDLER_H +#define OHOS_HANDLER_H + +#include +#include "internal_message.h" +#include "message_queue.h" + +// namespace OHOS { +// namespace Wifi { +const int USEC_1000 = 1000; + +class Handler { +public: + /** + * @Description : Construct a new Handler:: Handler object. + * + */ + Handler(); + + /** + * @Description : Destroy the Handler:: Handler object. + * + */ + virtual ~Handler(); + + /** + * @Description : Initialize Handler + * + * @return true : Initialize Handler success, false: Initialize Handler failed. + */ + bool InitialHandler(); + + /** + * @Description : Thread processing function + * + * @param pInstance - Handler Instance pointer.[in] + */ + static void *RunHandleThreadFunc(void *pInstance); + + /** + * @Description :Stop the thread for obtaining messages. + * + */ + void StopHandlerThread(); + + /** + * @Description : Send a message and place the message in the message queue. + * + * @param msg - Message to be sent.[in] + */ + void SendMessage(InternalMessage *msg); + + /** + * @Description : Send a message, place the message in the message queue, and + process the message after delayTimeMs is delayed. + * + * @param msg - Message to be sent.[in] + * @param delayTimeMs - Delay Time.[in] + */ + void MessageExecutedLater(InternalMessage *msg, int64_t delayTimeMs); + + /** + * @Description : Send a message, place the message in the message queue, and + process the message at the execTime time point. + * + * @param msg - Message to be sent.[in] + * @param execTime - Time when a message is processed.[in] + */ + void MessageExecutedAtTime(InternalMessage *msg, int64_t execTime); + + /** + * @Description : Send a message and place the message at the top of the message queue. + * + * @param msg - Message to be sent.[in] + */ + void PlaceMessageTopOfQueue(InternalMessage *msg); + + /** + * @Description : Delete messages from the queue. + * + * @param messageName - Name of the message to be deleted.[in] + */ + void DeleteMessageFromQueue(int messageName); + + /** + * @Description : Distributing Messages. + * + * @param msg - Messages to be processed.[in] + */ + void DistributeMessage(InternalMessage *msg); + + /** + * @Description : Invoke the ExecuteStateMsg interface of the current state + to process messages sent to the state machine. The entry/exit + of the state machine is also called, and the delayed message + is put back into queue when transitioning to a new state. + * + * @param msg - Messages.[in] + */ + virtual void ExecuteMessage(InternalMessage *msg) = 0; + + /** + * @Description : Obtains messages from the message queue, distributes the + messages, and recycles the messages. + * + */ + void GetAndDistributeMessage(); + +private: + /* message queue. */ + std::unique_ptr pMyQueue; + /* Thread handle. */ + pthread_t handleThread; + + /* Running flag. */ + bool isRunning; +}; +// } // namespace Wifi +// } // namespace OHOS +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/internal_message.cpp b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/internal_message.cpp new file mode 100644 index 000000000..35a26e90d --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/internal_message.cpp @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "internal_message.h" +// #include "securec.h" +#include "Log.h" + +#undef LOG_TAG +#define LOG_TAG "OHWIFI_INTERNAL_MESSAGE" + +// namespace OHOS { +// namespace Wifi { +void MessageBody::SaveIntData(int data) +{ + intArray_.push_back(data); + return; +} + +void MessageBody::SaveStringData(std::string data) +{ + stringArray_.push_back(data); + return; +} + +int MessageBody::GetIntData() +{ + if (intArray_.empty()) { + LogError("intArray is null.\n"); + return 0; + } + + int tmp = intArray_.front(); + intArray_.pop_front(); + return tmp; +} + +std::string MessageBody::GetStringData() +{ + std::string tmp; + if (stringArray_.empty()) { + LogError("stringArray is null.\n"); + return tmp; + } + + tmp = stringArray_.front(); + stringArray_.pop_front(); + return tmp; +} + +void MessageBody::ClearAllData() +{ + intArray_.clear(); + stringArray_.clear(); + return; +} + +void MessageBody::CopyMessageBody(const MessageBody &origBody) +{ + intArray_.assign(origBody.intArray_.begin(), origBody.intArray_.end()); + stringArray_.assign(origBody.stringArray_.begin(), origBody.stringArray_.end()); + + return; +} + +InternalMessage::InternalMessage() + : mMsgName(0), + mParam1(0), + mParam2(0), + pNextMsg(nullptr), + mHandleTime(0) +{} + +InternalMessage::~InternalMessage() +{ +} + +int InternalMessage::GetMessageName() const +{ + return mMsgName; +} + +int InternalMessage::GetParam1() const +{ + return mParam1; +} + +int InternalMessage::GetParam2() const +{ + return mParam2; +} + +int InternalMessage::GetIntFromMessage() +{ + return mMessageBody.GetIntData(); +} + +std::string InternalMessage::GetStringFromMessage() +{ + return mMessageBody.GetStringData(); +} + +const MessageBody &InternalMessage::GetMessageBody() const +{ + return mMessageBody; +} + +void InternalMessage::CopyMessageBody(const MessageBody &origBody) +{ + mMessageBody.CopyMessageBody(origBody); + return; +} + +InternalMessage *InternalMessage::GetNextMsg() const +{ + return pNextMsg; +} + +int64_t InternalMessage::GetHandleTime() const +{ + return mHandleTime; +} + +void InternalMessage::SetMessageName(int msgName) +{ + mMsgName = msgName; + return; +} + +void InternalMessage::SetParam1(int param1) +{ + mParam1 = param1; + return; +} + +void InternalMessage::SetParam2(int param2) +{ + mParam2 = param2; + return; +} + +void InternalMessage::ReleaseMessageObj() +{ + mMessageObj.reset(); + return; +} + +void InternalMessage::AddIntMessageBody(int data) +{ + mMessageBody.SaveIntData(data); + return; +} + +void InternalMessage::AddStringMessageBody(std::string data) +{ + mMessageBody.SaveStringData(data); + return; +} + +void InternalMessage::ClearMessageBody() +{ + mMessageBody.ClearAllData(); + return; +} + +void InternalMessage::SetNextMsg(InternalMessage *nextMsg) +{ + pNextMsg = nextMsg; + return; +} + +void InternalMessage::SetHandleTime(int64_t time) +{ + mHandleTime = time; + return; +} + +std::unique_ptr MessageManage::msgManage; + +MessageManage &MessageManage::GetInstance() +{ + if (msgManage.get() == nullptr) { + msgManage = std::make_unique(); + } + return *msgManage; +} + +MessageManage::MessageManage() : pMsgPool(nullptr), mMsgPoolSize(0) +{} + +MessageManage::~MessageManage() +{ + ReleasePool(); + return; +} + +InternalMessage *MessageManage::CreateMessage() +{ + { + std::unique_lock lock(mPoolMutex); + if (pMsgPool != nullptr) { + InternalMessage *m = pMsgPool; + pMsgPool = m->GetNextMsg(); + m->SetNextMsg(nullptr); + mMsgPoolSize--; + return m; + } + } + + auto pMessage = new (std::nothrow) InternalMessage(); + return pMessage; +} + +InternalMessage *MessageManage::CreateMessage(const InternalMessage *orig) +{ + InternalMessage *m = CreateMessage(); + if (m == nullptr) { + return nullptr; + } + + m->SetMessageName(orig->GetMessageName()); + m->SetParam1(orig->GetParam1()); + m->SetParam2(orig->GetParam2()); + m->SetMessageObj(orig->GetMessageObj()); + m->CopyMessageBody(orig->GetMessageBody()); + + return m; +} + +InternalMessage *MessageManage::CreateMessage(int messageName) +{ + InternalMessage *m = CreateMessage(); + if (m == nullptr) { + return nullptr; + } + + m->SetMessageName(messageName); + return m; +} + +InternalMessage *MessageManage::CreateMessage(int messageName, const std::shared_ptr &messageObj) +{ + InternalMessage *m = CreateMessage(); + if (m == nullptr) { + return nullptr; + } + + m->SetMessageName(messageName); + + m->SetMessageObj(messageObj); + return m; +} + +InternalMessage *MessageManage::CreateMessage(int messageName, int param1, int param2) +{ + InternalMessage *m = CreateMessage(); + if (m == nullptr) { + return nullptr; + } + + m->SetMessageName(messageName); + m->SetParam1(param1); + m->SetParam2(param2); + return m; +} + +InternalMessage *MessageManage::CreateMessage(int messageName, int param1, int param2, const std::shared_ptr &messageObj) +{ + InternalMessage *m = CreateMessage(); + if (m == nullptr) { + return nullptr; + } + + m->SetMessageName(messageName); + m->SetParam1(param1); + m->SetParam2(param2); + m->SetMessageObj(messageObj); + return m; +} + +void MessageManage::ReclaimMsg(InternalMessage *m) +{ + if (m == nullptr) { + return; + } + + m->SetMessageName(0); + m->SetParam1(0); + m->SetParam2(0); + m->ReleaseMessageObj(); + m->ClearMessageBody(); + + { + std::unique_lock lock(mPoolMutex); + if (mMsgPoolSize < MAX_MSG_NUM_IN_POOL) { + m->SetNextMsg(pMsgPool); + pMsgPool = m; + mMsgPoolSize++; + return; + } + } + + delete m; + m = nullptr; + return; +} + +void MessageManage::ReleasePool() +{ + std::unique_lock lock(mPoolMutex); + InternalMessage *current = pMsgPool; + InternalMessage *next = nullptr; + while (current != nullptr) { + next = current->GetNextMsg(); + delete current; + current = next; + } + + return; +} +// } // namespace Wifi +// } // namespace OHOS \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/internal_message.h b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/internal_message.h new file mode 100644 index 000000000..f00fbde54 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/internal_message.h @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_INTERNAL_MESSAGE_H +#define OHOS_INTERNAL_MESSAGE_H +#include "IStateMachineManager.h" +#include +#include +#include +#include +#include +// #include + +// namespace OHOS { +// namespace Wifi { +const int MAX_POOL_SIZE_INIT = 50; +class MessageBody { +public: + /** + * @Description : Save an Integer Data. + * + * @param data - Integer Data.[in] + */ + void SaveIntData(int data); + + /** + * @Description : Save a String Data. + * + * @param data - String Data.[in] + */ + void SaveStringData(std::string data); + + /** + * @Description : Get an Integer Data. + * + * @return int + */ + int GetIntData(); + + /** + * @Description : Get a String Data. + * + * @return std::string + */ + std::string GetStringData(); + + /** + * @Description : Clear all Data. + * + */ + void ClearAllData(); + + /** + * @Description : Copy a message body. + * + * @param origBody - Source Message Body.[in] + */ + void CopyMessageBody(const MessageBody &origBody); + +private: + /* Integer data. */ + std::list intArray_; + /* String data. */ + std::list stringArray_; +}; + +class InternalMessage : public VStateMachineMessage { +public: + /** + * @Description : Construct a new Internal Message object. + * + */ + InternalMessage(); + + /** + * @Description Destroy the Internal Message object. + * + */ + ~InternalMessage(); + + /** + * @Description : Get message name. + * + * @return int + */ + int GetMessageName() const override; + + /** + * @Description : Obtains the first parameter in the message body. + * + * @return int + */ + int GetParam1() const; + + /** + * @Description : Obtains the second parameter in the message body. + * + * @return int + */ + int GetParam2() const; + + /** + * @Description : Obtains Integer data from message. + * + * @return int + */ + int GetIntFromMessage(); + + /** + * @Description : Obtains Sting data from message. + * + * @return std::string + */ + std::string GetStringFromMessage(); + + /** + * @Description : Obtains message body. + * + * @return MessageBody& + */ + const MessageBody &GetMessageBody() const; + + /** + * @Description : Copy message body. + * + * @param origBody - Source Message Body.[in] + */ + void CopyMessageBody(const MessageBody &origBody); + + /** + * @Description : Get next message. + * + * @return InternalMessage* + */ + InternalMessage *GetNextMsg() const; + + /** + * @Description : Obtains time. + * + * @return int64_t + */ + int64_t GetHandleTime() const; + + /** + * @Description : Set message name. + * + * @param msgName - Message name.[in] + */ + void SetMessageName(int msgName); + + /** + * @Description : Set the first parameter in the message body. + * + * @param param1 - The first parameter.[in] + */ + void SetParam1(int param1); + + /** + * @Description : Set the second parameter in the message body. + * + * @param param2 - The second parameter.[in] + */ + void SetParam2(int param2); + + /** + * @DescriptionSet the Message Obj object - brief + * @tparam - T Custom type to be set + * @param messageObj - User-defined data to be set + */ + // template + // void SetMessageObj(const T &messageObj) + // { + // mMessageObj = messageObj; + // } + + /** + * @DescriptionSet the Message Obj object - brief + * @tparam - T Custom type to be set + * @param messageObj - User-defined data to be set + */ + // template + // void SetMessageObj(T &&messageObj) + // { + // mMessageObj = T(messageObj); + // } + + void SetMessageObj(const std::shared_ptr &messageObj) + { + mMessageObj = messageObj; + } + + /** + * @DescriptionGet the Message Obj object + * @tparam - T Custom type to be set + * @param messageObj - Gets data of an actual specific object. + * @return - bool true:success   false:failed   + */ + // template + // bool GetMessageObj(T &messageObj) const + // { + // messageObj = std::any_cast(mMessageObj); + // return true; + // } + bool GetMessageObj(std::shared_ptr &messageObj) const + { + // TODO: + // messageObj = std::any_cast(mMessageObj); + return true; + } + + // const std::any &GetMessageObj(void) const + // { + // return mMessageObj; + // } + const std::shared_ptr &GetMessageObj(void) const override + { + return mMessageObj; + } + + /** + * @Description : Release Message Object. + * + */ + void ReleaseMessageObj(); + + /** + * @Description : Add integer message body. + * + * @param data - Integer data.[in] + */ + void AddIntMessageBody(int data); + + /** + * @Description : Add string message body. + * + * @param data - String data.[in] + */ + void AddStringMessageBody(std::string data); + + /** + * @Description : Clear message body. + * + */ + void ClearMessageBody(); + + /** + * @Description : Sets next message. + * + * @param next - The next message.[in] + */ + void SetNextMsg(InternalMessage *nextMsg); + + /** + * @Description : Set the time. + * + * @param time - Time.[in] + */ + void SetHandleTime(int64_t time); + +private: + /* Message Name */ + int mMsgName; + /* Parameter 1 */ + int mParam1; + /* Parameter 2 */ + int mParam2; + /* any message obj. */ + // std::any mMessageObj; + std::shared_ptr mMessageObj; + /* Message bodies that cannot be directly copied */ + MessageBody mMessageBody; + /* Next message in the resource pool or message queue */ + InternalMessage *pNextMsg; + /* Message execution time */ + int64_t mHandleTime; +}; +class MessageManage { +public: + /** + * @Description : Obtains a single instance. + * + * @return MessageManage& + */ + static MessageManage &GetInstance(); + + /** + * @Description : Message obtaining function. + * + * @return InternalMessage* + */ + InternalMessage *CreateMessage(); + + /** + * @Description : Obtain original messages. + * + * @param orig - Original messages.[in] + * @return InternalMessage* + */ + InternalMessage *CreateMessage(const InternalMessage *orig); + + /** + * @Description : Obtains the message name. + * + * @param messageName - Message name.[in] + * @return InternalMessage* + */ + InternalMessage *CreateMessage(int messageName); + + /** + * @Description :Obtaining Message Information. + * + * @param messageName - Message name.[in] + * @param messageObj - Message pointer.[in] + * @return InternalMessage* + */ + InternalMessage *CreateMessage(int messageName, const std::shared_ptr &messageObj); + + /** + * @Description : Obtaining Message Information. + * + * @param messageName - Message name.[in] + * @param param1 - param1.[in] + * @param param2 - param2.[in] + * @return InternalMessage* + */ + InternalMessage *CreateMessage(int messageName, int param1, int param2); + + /** + * @Description : Obtaining Message Information. + * + * @param messageName - Message name.[in] + * @param param1 - param1.[in] + * @param param2 - param2.[in] + * @param messageObj - Message pointer.[in] + * @return InternalMessage* + */ + InternalMessage *CreateMessage(int messageName, int param1, int param2, const std::shared_ptr &messageObj); + + /** + * @Description :Recycle message. + * + * @param m - message.[in] + */ + void ReclaimMsg(InternalMessage *m); + + /** + * @Description : Release pool. + * + */ + + void ReleasePool(); + + /** + * @Description : Construct a new Message Manage object. + * + */ + MessageManage(); + + /** + * @Description : Destroy the Message Manage object. + * + */ + ~MessageManage(); + +private: + /* Maximum number of messages in the message resource pool */ + const int MAX_MSG_NUM_IN_POOL = 50; + /* Message resource pool */ + InternalMessage *pMsgPool; + /* Number of messages in the message resource pool */ + int mMsgPoolSize; + /* Mutex for operating the message resource pool */ + std::mutex mPoolMutex; + static std::unique_ptr msgManage; +}; +// } // namespace Wifi +// } // namespace OHOS +#endif diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/message_queue.cpp b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/message_queue.cpp new file mode 100644 index 000000000..e175d80f6 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/message_queue.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "message_queue.h" +#include +#include "Log.h" +// #include "wifi_errcode.h" + +#undef LOG_TAG +#define LOG_TAG "OHWIFI_MESSAGE_QUEUE" + +// namespace OHOS { +// namespace Wifi { +MessageQueue::MessageQueue() : pMessageQueue(nullptr), mIsBlocked(false), mNeedQuit(false) +{} + +MessageQueue::~MessageQueue() +{ + LogInfo("MessageQueue::~MessageQueue\n"); + /* Releasing Messages in a Queue */ + std::unique_lock lock(mMtxQueue); + InternalMessage *current = pMessageQueue; + InternalMessage *next = nullptr; + while (current != nullptr) { + next = current->GetNextMsg(); + delete current; + current = next; + } + + return; +} + +bool MessageQueue::AddMessageToQueue(InternalMessage *message, int64_t handleTime) +{ + if (message == nullptr) { + LogError("message is null.\n"); + return false; + } + + if (mNeedQuit) { + MessageManage::GetInstance().ReclaimMsg(message); + LogError("Already quit the message queue.\n"); + return false; + } + + message->SetHandleTime(handleTime); + bool needWake = false; + /* + * If the queue is empty, the current message needs to be executed + * immediately, or the execution time is earlier than the queue header, the + * message is placed in the queue header and is woken up when the queue is + * blocked. + */ + { + std::unique_lock lck(mMtxQueue); + InternalMessage *pTop = pMessageQueue; + if (pTop == nullptr || handleTime == 0 || handleTime < pTop->GetHandleTime()) { + message->SetNextMsg(pTop); + pMessageQueue = message; + needWake = mIsBlocked; + /* Inserts messages in the middle of the queue based on the execution time. */ + } else { + InternalMessage *pPrev = nullptr; + InternalMessage *pCurrent = pTop; + while (pCurrent != nullptr) { + pPrev = pCurrent; + pCurrent = pCurrent->GetNextMsg(); + if (pCurrent == nullptr || handleTime < pCurrent->GetHandleTime()) { + message->SetNextMsg(pCurrent); + pPrev->SetNextMsg(message); + break; + } + } + } + } + + /* Wake up the process. */ + if (needWake) { + std::unique_lock lck(mMtxBlock); + mCvQueue.notify_all(); + mIsBlocked = false; + } + + return true; +} + +bool MessageQueue::DeleteMessageFromQueue(int messageName) +{ + std::unique_lock lck(mMtxQueue); + + InternalMessage *pTop = pMessageQueue; + if (pTop == nullptr) { + return true; + } + + InternalMessage *pCurrent = pTop; + while (pCurrent != nullptr) { + InternalMessage *pPrev = pCurrent; + pCurrent = pCurrent->GetNextMsg(); + if ((pCurrent != nullptr) && (pCurrent->GetMessageName() == messageName)) { + InternalMessage *pNextMsg = pCurrent->GetNextMsg(); + pPrev->SetNextMsg(pNextMsg); + MessageManage::GetInstance().ReclaimMsg(pCurrent); + pCurrent = pNextMsg; + } + } + + if (pTop->GetMessageName() == messageName) { + pMessageQueue = pTop->GetNextMsg(); + MessageManage::GetInstance().ReclaimMsg(pTop); + } + + return true; +} + +InternalMessage *MessageQueue::GetNextMessage() +{ + // LogInfo("MessageQueue::GetNextMessage\n"); + int nextBlockTime = 0; + + while (!mNeedQuit) { + /* Obtains the current time, accurate to milliseconds. */ + struct timeval curTime = {0, 0}; + if (gettimeofday(&curTime, nullptr) != 0) { + LogError("gettimeofday failed.\n"); + return nullptr; + } + int64_t nowTime = static_cast(curTime.tv_sec) * TIME_USEC_1000 + curTime.tv_usec / TIME_USEC_1000; + + { + std::unique_lock lck(mMtxQueue); + InternalMessage *curMsg = pMessageQueue; + mIsBlocked = true; + if (curMsg != nullptr) { + if (nowTime < curMsg->GetHandleTime()) { + /* The execution time of the first message is not reached. + The remaining time is blocked here. */ + nextBlockTime = curMsg->GetHandleTime() - nowTime; + } else { + /* Return the first message. */ + mIsBlocked = false; + pMessageQueue = curMsg->GetNextMsg(); + curMsg->SetNextMsg(nullptr); + return curMsg; + } + } else { + /* If there's no message, check it every 30 seconds. */ + nextBlockTime = TIME_INTERVAL; + } + } + + std::unique_lock lck(mMtxBlock); + if (mIsBlocked && (!mNeedQuit)) { + if (mCvQueue.wait_for(lck, std::chrono::milliseconds(nextBlockTime)) == std::cv_status::timeout) { + // LogInfo("mCvQueue timeout.\n"); + } else { + // LogInfo("Wake up.\n"); + } + } + mIsBlocked = false; + } + + LogError("Already quit the message queue.\n"); + return nullptr; +} + +void MessageQueue::StopQueueLoop() +{ + mNeedQuit = true; + if (mIsBlocked) { + std::unique_lock lck(mMtxBlock); + mCvQueue.notify_all(); + mIsBlocked = false; + } + + return; +} +// } // namespace Wifi +// } // namespace OHOS \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/message_queue.h b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/message_queue.h new file mode 100644 index 000000000..290174ebe --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/message_queue.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MESSAGE_QUEUE_H +#define OHOS_MESSAGE_QUEUE_H + +#include +#include +#include +#include "internal_message.h" + +// namespace OHOS { +// namespace Wifi { +#define TIME_USEC_1000 1000 +#define TIME_INTERVAL 30000 +class MessageQueue { +public: + /** + * @Description : Construct a new Message Queue object. + * + */ + MessageQueue(); + + /** + * @Description : Destroy the Message Queue object. + * + */ + ~MessageQueue(); + + /** + * @Description : Inserting Messages into Queues. + * + * @param message - Message to be inserted.[in] + * @param handleTime - Message execution time.[in] + * @return true : success, false : failed. + */ + bool AddMessageToQueue(InternalMessage *message, int64_t handleTime); + + /** + * @Description : Delete messages from the queue. + * + * @param messageName - Name of the message to be deleted.[in] + * @return true : success, false : failed. + */ + bool DeleteMessageFromQueue(int messageName); + + /** + * @Description : Obtain messages from the queue for processing. + * If no message is found, the system blocks the messages. + * + */ + InternalMessage *GetNextMessage(); + + /** + * @Description : Obtain messages from the queue for processing. + * If no message is found, the system blocks the messages. + */ + void StopQueueLoop(); + +private: + /* Message Queuing */ + InternalMessage *pMessageQueue; + /* No messages to be executed, blocking */ + bool mIsBlocked; + /* Exit Loop */ + bool mNeedQuit; + /* Thread lock of operation queue */ + std::mutex mMtxQueue; + /* Blocked thread lock */ + std::mutex mMtxBlock; + /* blocking condition variable */ + std::condition_variable mCvQueue; +}; +// } // namespace Wifi +// } // namespace OHOS +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state.cpp b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state.cpp new file mode 100644 index 000000000..9a04c99f9 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IStateMachineManager.h" + +#undef LOG_TAG +#define LOG_TAG "OHWIFI_STATE" + +// namespace OHOS { +// namespace Wifi { +// State::State(const std::string &name) : mStateName(name) +// {} + +// State::~State() +// {} + +// std::string State::GetStateName() +// { +// return mStateName; +// } +// } // namespace Wifi +// } // namespace OHOS \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state.h b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state.h new file mode 100644 index 000000000..8bcf8d547 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_STATE_H +#define OHOS_STATE_H + +#include +#include "message_queue.h" + +// namespace OHOS { +// namespace Wifi { +// } // namespace Wifi +// } // namespace OHOS +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state_machine.cpp b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state_machine.cpp new file mode 100644 index 000000000..79ceac6b1 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state_machine.cpp @@ -0,0 +1,686 @@ +/* + * Copyright (C) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "state_machine.h" +#include "Log.h" + +#undef LOG_TAG +#define LOG_TAG "OHWIFI_STATE_MACHINE" + +// namespace OHOS { +// namespace Wifi { +static const int SM_INIT_CMD = -2; +StateMachine::StateMachine(const std::string &name) : pStateMachineHandler(nullptr), mStateName(name) +{} + +StateMachine::~StateMachine() +{ + LogInfo("StateMachine::~StateMachine\n"); + if (pStateMachineHandler != nullptr) { + delete pStateMachineHandler; + pStateMachineHandler = nullptr; + } +} + +bool StateMachine::InitialStateMachine() +{ + pStateMachineHandler = new (std::nothrow) StateMachineHandler(this); + if (pStateMachineHandler == nullptr) { + LogError("pStateMachineHandler alloc failed.\n"); + return false; + } + + if (!pStateMachineHandler->InitialSmHandler()) { + LogError("InitialStateMachineHandler failed.\n"); + return false; + } + + return true; +} + +void StateMachine::StartStateMachine() +{ + if (pStateMachineHandler == nullptr) { + LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n"); + return; + } + + pStateMachineHandler->BuildTreeComplete(); + return; +} + +void StateMachine::SetHandler(StateMachineHandler *handler) +{ + pStateMachineHandler = handler; +} + +void StateMachine::NotExecutedMessage(const InternalMessage *msg) +{ + if (msg == nullptr) { + return; + } + LogWarning("msg not handled msg:%d\n", msg->GetMessageName()); +} + +void StateMachine::StatePlus(State *state, State *upper) +{ + if (pStateMachineHandler == nullptr) { + LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n"); + return; + } + + pStateMachineHandler->StatePlus(state, upper); +} + +void StateMachine::StateDelete(State *state) +{ + if (pStateMachineHandler == nullptr) { + LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n"); + return; + } + + pStateMachineHandler->StateDelete(state); +} + +void StateMachine::SetFirstState(State *firstState) +{ + if (pStateMachineHandler == nullptr) { + LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n"); + return; + } + + pStateMachineHandler->SetFirstState(firstState); +} + +void StateMachine::SwitchState(State *targetState) +{ + if (pStateMachineHandler == nullptr) { + LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n"); + return; + } + + pStateMachineHandler->SwitchState(targetState); +} + +void StateMachine::DelayMessage(const InternalMessage *msg) +{ + if (pStateMachineHandler == nullptr) { + LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n"); + return; + } + + pStateMachineHandler->DelayMessage(msg); +} +void StateMachine::DelayMessage(VStateMachineMessage *msg) +{ + if (pStateMachineHandler == nullptr) { + LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n"); + return; + } + + pStateMachineHandler->DelayMessage((InternalMessage *)msg); +} + +void StateMachine::StopHandlerThread() +{ + if (pStateMachineHandler == nullptr) { + LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n"); + return; + } + + pStateMachineHandler->StopHandlerThread(); +} + +InternalMessage *StateMachine::CreateMessage() +{ + return MessageManage::GetInstance().CreateMessage(); +} + +InternalMessage *StateMachine::CreateMessage(const InternalMessage *orig) +{ + if (orig == nullptr) { + return nullptr; + } + return MessageManage::GetInstance().CreateMessage(orig); +} + +InternalMessage *StateMachine::CreateMessage(int msgName) +{ + return MessageManage::GetInstance().CreateMessage(msgName); +} + +InternalMessage *StateMachine::CreateMessage(int msgName, int param1) +{ + return MessageManage::GetInstance().CreateMessage(msgName, param1, 0); +} + +InternalMessage *StateMachine::CreateMessage(int msgName, int param1, int param2) +{ + return MessageManage::GetInstance().CreateMessage(msgName, param1, param2); +} + +InternalMessage *StateMachine::CreateMessage(int msgName, const std::shared_ptr &messageObj) +{ + return MessageManage::GetInstance().CreateMessage(msgName, messageObj); +} + +InternalMessage *StateMachine::CreateMessage(int msgName, int param1, int param2, const std::shared_ptr &messageObj) +{ + return MessageManage::GetInstance().CreateMessage(msgName, param1, param2, messageObj); +} + +void StateMachine::SendMessage(int msgName) +{ + pStateMachineHandler->SendMessage(CreateMessage(msgName)); + return; +} + +void StateMachine::SendMessage(int msgName, int param1) +{ + pStateMachineHandler->SendMessage(CreateMessage(msgName, param1)); + return; +} + +void StateMachine::SendMessage(int msgName, int param1, int param2) +{ + pStateMachineHandler->SendMessage(CreateMessage(msgName, param1, param2)); + return; +} + +void StateMachine::SendMessage(InternalMessage *msg) +{ + if (msg == nullptr) { + return; + } + pStateMachineHandler->SendMessage(msg); + return; +} + +void StateMachine::SendMessage(int msgName, const std::shared_ptr &messageObj) +{ + pStateMachineHandler->SendMessage(CreateMessage(msgName, messageObj)); + return; +} + +void StateMachine::SendMessage(int msgName, int param1, int param2, const std::shared_ptr &messageObj) +{ + pStateMachineHandler->SendMessage(CreateMessage(msgName, param1, param2, messageObj)); + return; +} + +void StateMachine::MessageExecutedLater(int msgName, int64_t delayTimeMs) +{ + pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName), delayTimeMs); + return; +} + +void StateMachine::MessageExecutedLater(int msgName, int param1, int64_t delayTimeMs) +{ + pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName, param1), delayTimeMs); + return; +} + +void StateMachine::MessageExecutedLater(int msgName, int param1, int param2, int64_t delayTimeMs) +{ + pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName, param1, param2), delayTimeMs); + return; +} + +void StateMachine::MessageExecutedLater(InternalMessage *msg, int64_t delayTimeMs) +{ + pStateMachineHandler->MessageExecutedLater(msg, delayTimeMs); + return; +} + +void StateMachine::MessageExecutedLater(int msgName, const std::shared_ptr &messageObj, int64_t delayTimeMs) +{ + pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName, messageObj), delayTimeMs); + return; +} + +void StateMachine::MessageExecutedLater( + int msgName, int param1, int param2, const std::shared_ptr &messageObj, int64_t delayTimeMs) +{ + pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName, param1, param2, messageObj), delayTimeMs); + return; +} + +void StateMachine::StartTimer(int timerName, int64_t interval) +{ + // LogInfo("Enter StateMachine::StartTimer, timerName is %d, interval is %d\n", timerName, interval); + MessageExecutedLater(timerName, interval); + return; +} + +void StateMachine::StopTimer(int timerName) +{ + // LogInfo("Enter StateMachine::StopTimer, timerName is %d.\n", timerName); + pStateMachineHandler->DeleteMessageFromQueue(timerName); + return; +} + +StateMachineHandler::StateMachineHandler(StateMachine *pStateMgr) +{ + mStateInfoMap.clear(); + mStateVector.clear(); + mStateVectorTopIndex = -1; + mSequenceStateVector.clear(); + mSequenceStateVectorCount = 0; + mDelayedMessages.clear(); + pStateMachine = pStateMgr; + pFirstState = nullptr; + pTargetState = nullptr; + mQuitFlag = false; + mBuildCompleteFlag = false; + mSwitchingStateFlag = false; + pCurrentMsg = nullptr; +} + +StateMachineHandler::~StateMachineHandler() +{ + LogInfo("StateMachineHandler::~StateMachineHandler\n"); + StopHandlerThread(); + ReleaseDelayedMessages(); + ClearWhenQuit(); + return; +} + +bool StateMachineHandler::InitialSmHandler() +{ + if (!InitialHandler()) { + return false; + } + return true; +} + +StateInfo *StateMachineHandler::StatePlus(State *state, State *upper) +{ + LogInfo("Enter StateMachineHandler::StatePlus function.\n"); + + StateInfo *upperStateInfo = nullptr; + StateInfoMap::iterator it = mStateInfoMap.begin(); + if (upper != nullptr) { + it = mStateInfoMap.find(upper->GetStateName()); + if (it != mStateInfoMap.end()) { + upperStateInfo = it->second; + } + if (upperStateInfo == nullptr) { + LogInfo("upperStateInfo is null, add upper first. upper->GetStateName():%s\n", + upper->GetStateName().c_str()); + /* Recursively add our upper as it's not been added yet. */ + StatePlus(upper, nullptr); + } else { + LogInfo("upperStateInfo is not null, go on.\n"); + } + } + + StateInfo *stateInfo = nullptr; + it = mStateInfoMap.find(state->GetStateName()); + if (it != mStateInfoMap.end()) { + stateInfo = it->second; + } + if (stateInfo == nullptr) { + stateInfo = new (std::nothrow) StateInfo(); + if (stateInfo == nullptr) { + LogError("failed to new StateInfo!\n"); + return nullptr; + } + mStateInfoMap.insert(StateInfoMap::value_type(state->GetStateName(), stateInfo)); + } + + /* Validate that we aren't adding the same state in two different hierarchies. */ + if (stateInfo->upperStateInfo != nullptr && stateInfo->upperStateInfo != upperStateInfo) { + LogError("The same state cannot be added to two different hierarchies!\n"); + } + + stateInfo->state = state; + stateInfo->upperStateInfo = upperStateInfo; + stateInfo->active = false; + + LogInfo("successfully added a new state!\n"); + + return stateInfo; +} + +void StateMachineHandler::StateDelete(State *state) +{ + StateInfoMap::iterator it = mStateInfoMap.find(state->GetStateName()); + StateInfo *stateInfo = nullptr; + if (it != mStateInfoMap.end()) { + stateInfo = it->second; + } + if (stateInfo == nullptr || stateInfo->active) { + return; + } + + it = mStateInfoMap.begin(); + while (it != mStateInfoMap.end()) { + if (it->second->upperStateInfo == stateInfo) { + return; + } + ++it; + } + + it = mStateInfoMap.find(state->GetStateName()); + if (it != mStateInfoMap.end()) { + delete it->second; + it->second = nullptr; + mStateInfoMap.erase(it); + } +} + +void StateMachineHandler::SetFirstState(State *firstState) +{ + pFirstState = firstState; +} + +void StateMachineHandler::BuildTreeComplete() +{ + /* Determines the maximum depth of the state hierarchy. */ + int maxDepth = 0; + StateInfoMap::iterator it = mStateInfoMap.begin(); + while (it != mStateInfoMap.end()) { + int depth = 0; + StateInfo *tempStateInfo = it->second; + while (tempStateInfo != nullptr) { + depth++; + tempStateInfo = tempStateInfo->upperStateInfo; + } + + if (maxDepth < depth) { + maxDepth = depth; + } + + ++it; + } + + LogInfo("StateMachineHandler::BuildTreeComplete, maxDepth:%d\n", maxDepth); + mStateVector.resize(maxDepth); + mSequenceStateVector.resize(maxDepth); + BuildStateInitVector(); + MessageExecutedAtTime(pStateMachine->CreateMessage(SM_INIT_CMD), 0); + return; +} + +void StateMachineHandler::BuildStateInitVector() +{ + LogInfo("StateMachineHandler::BuildStateInitVector\n"); + + if (pFirstState == nullptr) { + LogError("StateMachineHandler::BuildStateInitVector please set initial state first!\n"); + return; + } + + StateInfoMap::iterator it = mStateInfoMap.find(pFirstState->GetStateName()); + StateInfo *startStateInfo = nullptr; + if (it != mStateInfoMap.end()) { + startStateInfo = it->second; + } + + for (mSequenceStateVectorCount = 0; startStateInfo != nullptr; mSequenceStateVectorCount++) { + mSequenceStateVector[mSequenceStateVectorCount] = startStateInfo; + startStateInfo = startStateInfo->upperStateInfo; + } + + /* Clearing the StateVector. */ + mStateVectorTopIndex = -1; + MoveSequenceToStateVector(); +} + +StateInfo *StateMachineHandler::BuildSequenceStateVector(State *targetState) +{ + mSequenceStateVectorCount = 0; + StateInfoMap::iterator it = mStateInfoMap.find(targetState->GetStateName()); + StateInfo *curStateInfo = nullptr; + if (it != mStateInfoMap.end()) { + curStateInfo = it->second; + } + + if (curStateInfo == nullptr) { + return nullptr; + } + + do { + mSequenceStateVector[mSequenceStateVectorCount++] = curStateInfo; + curStateInfo = curStateInfo->upperStateInfo; + } while ((curStateInfo != nullptr) && (!curStateInfo->active)); + + return curStateInfo; +} + +void StateMachineHandler::PlaceDelayedMsgQueueTop() +{ + // LogInfo("Enter StateMachineHandler::PlaceDelayedMsgQueueTop.\n"); + + for (int i = mDelayedMessages.size() - 1; i >= 0; i--) { + InternalMessage *curMsg = mDelayedMessages[i]; + if (curMsg == nullptr) { + LogError("StateMachineHandler::PlaceDelayedMsgQueueTop: curMsg is null.\n"); + continue; + } + PlaceMessageTopOfQueue(curMsg); + } + mDelayedMessages.clear(); + + return; +} + +void StateMachineHandler::ReleaseDelayedMessages() +{ + for (int i = mDelayedMessages.size() - 1; i >= 0; i--) { + InternalMessage *curMsg = mDelayedMessages[i]; + if (curMsg != nullptr) { + delete curMsg; + curMsg = nullptr; + } + } + mDelayedMessages.clear(); + + return; +} + +int StateMachineHandler::MoveSequenceToStateVector() +{ + // LogInfo("StateMachineHandler::MoveSequenceToStateVector mSequenceStateVectorCount:%d\n", + // mSequenceStateVectorCount); + + int newIndex = mStateVectorTopIndex + 1; + int i = mSequenceStateVectorCount - 1; + int j = newIndex; + while (i >= 0) { + mStateVector[j] = mSequenceStateVector[i]; + j += 1; + i -= 1; + } + + mStateVectorTopIndex = j - 1; + return newIndex; +} + +void StateMachineHandler::SwitchState(State *targetState) +{ + pTargetState = static_cast(targetState); +} + +void StateMachineHandler::ClearWhenQuit() +{ + pStateMachine->SetHandler(nullptr); + pStateMachine = nullptr; + pCurrentMsg = nullptr; + mStateVector.clear(); + mSequenceStateVector.clear(); + mDelayedMessages.clear(); + pFirstState = nullptr; + pTargetState = nullptr; + mQuitFlag = true; + + StateInfoMap::iterator it = mStateInfoMap.begin(); + while (it != mStateInfoMap.end()) { + delete it->second; + it->second = nullptr; + it = mStateInfoMap.erase(it); + } + mStateInfoMap.clear(); +} + +void StateMachineHandler::PerformSwitchState(State *msgProcessedState, InternalMessage *msg) +{ + if (msgProcessedState == nullptr || msg == nullptr) { + // LogError("poniter is null.\n"); + } + + State *targetState = pTargetState; + if (targetState != nullptr) { + // LogInfo("StateMachineHandler::PerformSwitchState targetState name is: %s\n", + // targetState->GetStateName().c_str()); + while (true) { + StateInfo *commonStateInfo = BuildSequenceStateVector(targetState); + mSwitchingStateFlag = true; + CallTreeStateExits(commonStateInfo); + + int stateListEnteringIndex = MoveSequenceToStateVector(); + CallTreeStateEnters(stateListEnteringIndex); + + PlaceDelayedMsgQueueTop(); + + if (targetState != pTargetState) { + targetState = pTargetState; + } else { + break; + } + } + pTargetState = nullptr; + } + + return; +} + +void StateMachineHandler::ExecuteMessage(InternalMessage *msg) +{ + if (msg == nullptr) { + return; + } + if (!mQuitFlag) { + if (pStateMachine != nullptr && msg->GetMessageName() != SM_INIT_CMD) { + } + + pCurrentMsg = msg; + + State *msgProcessedState = nullptr; + if (mBuildCompleteFlag) { + // LogInfo("StateMachineHandler::ExecuteMessage ExecuteTreeStateMsg!\n"); + msgProcessedState = ExecuteTreeStateMsg(msg); + } else if (!mBuildCompleteFlag && msg->GetMessageName() == SM_INIT_CMD) { + // LogInfo("StateMachineHandler::ExecuteMessage msg: SM_INIT_CMD\n"); + mBuildCompleteFlag = true; + CallTreeStateEnters(0); + } else { + LogError("The start method not called!\n"); + } + + if (pStateMachine != nullptr) { + PerformSwitchState(msgProcessedState, msg); + } else { + LogError("poniter is null.\n"); + } + + if (pStateMachine != nullptr && msg->GetMessageName() != SM_INIT_CMD) { + } + } + + return; +} + +void StateMachineHandler::DelayMessage(const InternalMessage *msg) +{ + // LogInfo("Enter StateMachineHandler::DelayMessage.\n"); + if (msg == nullptr) { + return; + } + + InternalMessage *newMsg = pStateMachine->CreateMessage(msg); + if (newMsg == nullptr) { + LogError("StateMachineHandler::DelayMessage: newMsg is null.\n"); + return; + } + mDelayedMessages.push_back(newMsg); + return; +} + +State *StateMachineHandler::ExecuteTreeStateMsg(InternalMessage *msg) +{ + // LogInfo("StateMachineHandler::ExecuteTreeStateMsg mStateVectorTopIndex:%d\n", mStateVectorTopIndex); + if (msg == nullptr) { + return nullptr; + } + + StateInfo *curStateInfo = mStateVector[mStateVectorTopIndex]; + if (curStateInfo == nullptr) { + LogError("StateInfo is null.\n"); + return nullptr; + } + + if (curStateInfo->state) { + LOGI("State machine: %s execute Cmd:%d\n", + curStateInfo->state->GetStateName().c_str(), msg->GetMessageName()); + } +// TODO: + while (curStateInfo->state && (!curStateInfo->state->ExecuteStateMsg((VStateMachineMessage *)(msg)))) { + curStateInfo = curStateInfo->upperStateInfo; + + if (curStateInfo == nullptr) { + pStateMachine->NotExecutedMessage(msg); + break; + } + } + + return (curStateInfo != nullptr) ? curStateInfo->state : nullptr; +} + +void StateMachineHandler::CallTreeStateExits(StateInfo *commonStateInfo) +{ + while ((mStateVectorTopIndex >= 0) && (mStateVector[mStateVectorTopIndex] != commonStateInfo)) { + if (mStateVector[mStateVectorTopIndex] != nullptr) { + State *curState = mStateVector[mStateVectorTopIndex]->state; + if (curState != nullptr) { + curState->GoOutState(); + } + mStateVector[mStateVectorTopIndex]->active = false; + } + mStateVectorTopIndex -= 1; + } +} + +void StateMachineHandler::CallTreeStateEnters(int index) +{ + for (int i = index; i <= mStateVectorTopIndex; i++) { + if (index == mStateVectorTopIndex) { + /* Last enter state for transition. */ + mSwitchingStateFlag = false; + } + // LogInfo("StateMachineHandler::CallTreeStateEnters mStateVectorTopIndex:%d, i: %d\n", + // mStateVectorTopIndex, + // i); + if (mStateVector[i] != nullptr && mStateVector[i]->state != nullptr) { + mStateVector[i]->state->GoInState(); + mStateVector[i]->active = true; + } + } + /* ensure flag set to false if no methods called. */ + mSwitchingStateFlag = false; +} +// } // namespace Wifi +// } // namespace OHOS \ No newline at end of file diff --git a/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state_machine.h b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state_machine.h new file mode 100644 index 000000000..36b682262 --- /dev/null +++ b/code/application/sifarsdk/component/StateMachineManager/src/stateMachine/state_machine.h @@ -0,0 +1,518 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_STA_MACHINE_H +#define OHOS_STA_MACHINE_H + +#include +#include +#include +#include "handler.h" +#include "message_queue.h" +#include "IStateMachineManager.h" + +// namespace OHOS { +// namespace Wifi { +#define CMD_SET_OPERATIONAL_MODE 1 + +class StateMachineHandler; +class StateMachine : public VStateMachine +{ +public: + /** + * @Description : StateMachine Initialization Function + * + * @return true :success, false : failed. + */ + bool InitialStateMachine() override; + + /** + * @Description : Start StateMachine. + * + */ + void StartStateMachine() override; + + /** + * @Description : Set Handler. + * + * @param handler - StateMachineHandler instance.[in] + */ + void SetHandler(StateMachineHandler *handler); + + /** + * @Description : The Message is not handled. + * + * @param msg - Message object.[in] + */ + void NotExecutedMessage(const InternalMessage *msg); + + /** + * @Description Stop Handler Thread. + * + */ + void StopHandlerThread() override; + + /** + * @Description : Start the timer. + * + * @param timerName - Timer Name.[in] + * @param interval - Timer duration, in milliseconds.[in] + */ + virtual void StartTimer(int timerName, int64_t interval); + + /** + * @Description : Stop the timer. + * + * @param timerName - Timer Name.[in] + */ + virtual void StopTimer(int timerName) override; + + /** + * @Description : Construct internal messages. + * + * @return InternalMessage* : Pointer to the constructed internal message. + */ + InternalMessage *CreateMessage(); + + /** + * @Description : Construct an information message based on + * the original message. + * + * @param orig - Original message.[in] + * @return InternalMessage* : Pointer to the constructed internal message. + */ + InternalMessage *CreateMessage(const InternalMessage *orig); + + /** + * @Description : Construct internal messages. + * + * @param msgName - Message Name.[in] + * @return InternalMessage* : Pointer to the constructed internal message. + */ + InternalMessage *CreateMessage(int msgName); + + /** + * @Description : Construct internal messages. + * + * @param msgName - Message Name.[in] + * @param param1 - Message parameters.[in] + * @return InternalMessage* : Pointer to the constructed internal message. + */ + InternalMessage *CreateMessage(int msgName, int param1); + + /** + * @Description : Construct internal messages. + * + * @param msgName - Message Name.[in] + * @param param1 - Message parameters.[in] + * @param param2 - Message parameters.[in] + * @return InternalMessage* : Pointer to the constructed internal message. + */ + InternalMessage *CreateMessage(int msgName, int param1, int param2); + + /** + * @Description : Construct internal messages. + * + * @param msgName - Message Name.[in] + * @param messageObj - User-defined data + * @return InternalMessage* : Pointer to the constructed internal message. + */ + InternalMessage *CreateMessage(int msgName, const std::shared_ptr &messageObj); + + /** + * @Description : Constructs internal messages. + * + * @param msgName - Message name.[in] + * @param param1 - First Message parameter.[in] + * @param param2 - Second Message parameter.[in] + * @param messageObj - User-defined data + * @return InternalMessage* : Pointer to the constructed internal message. + */ + InternalMessage *CreateMessage(int msgName, int param1, int param2, const std::shared_ptr &messageObj); + + /** + * @Description : Constructs internal messages and places the + * messages in the message queue of the state machine. + * + * @param msgName - Message name.[in] + */ + virtual void SendMessage(int msgName) override; + + /** + * @Description : Constructs internal messages and places the messages + * in the message queue of the state machine. + * + * @param msgName - Message name.[in] + * @param param1 - Message parameter.[in] + */ + virtual void SendMessage(int msgName, int param1); + + /** + * @Description : Constructs internal messages and places the messages + * in the message queue of the state machine. + * + * @param msgName - Message name.[in] + * @param param1 - Message parameter.[in] + * @param param2 - Message parameter.[in] + */ + virtual void SendMessage(int msgName, int param1, int param2); + + /** + * @Description : Puts messages into the message queue of the state machine. + * + * @param msg - Message to be sent.[in] + */ + virtual void SendMessage(InternalMessage *msg); + + /** + * @Description : Puts messages into the message queue of the state machine. + * + * @param msgName - Message Name.[in] + * @param messageObj - User-defined data + */ + virtual void SendMessage(int msgName, const std::shared_ptr &messageObj) override; + + /** + * @Description : Puts messages into the message queue of the state machine. + * + * @param msgName - Message Name.[in] + * @param param1 - Message parameters.[in] + * @param param2 - Message parameters.[in] + * @param messageObj - User-defined data + */ + virtual void SendMessage(int msgName, int param1, int param2, const std::shared_ptr &messageObj); + + /** + * @Description Constructs internal messages and places them in the + * message queue of the state machine. The messages are processed + * after the specified delay time. + * + * @param msgName - Message Name.[in] + * @param delayTimeMs - Delay time, in milliseconds.[in] + */ + void MessageExecutedLater(int msgName, int64_t delayTimeMs); + + /** + * @Description : Constructs internal messages and places them in the + * message queue of the state machine. The messages are processed + * after the specified delay time. + * + * @param msgName - Message Name.[in] + * @param param1 - Message parameters.[in] + * @param delayTimeMs - Delay time, in milliseconds.[in] + */ + void MessageExecutedLater(int msgName, int param1, int64_t delayTimeMs); + + /** + * @Description : Constructs internal messages and places them in the + * message queue of the state machine. The messages are processed + * after the specified delay time. + * + * @param msgName - Message Name.[in] + * @param param1 - Message parameters.[in] + * @param param2 - Message parameters.[in] + * @param delayTimeMs - Delay time, in milliseconds.[in] + */ + void MessageExecutedLater(int msgName, int param1, int param2, int64_t delayTimeMs); + + /** + * @Description : Constructs internal messages and places them in the + * message queue of the state machine. The messages are processed + * after the specified delay time. + * + * @param msg - Message to be sent.[in] + * @param delayTimeMs - Delay time, in milliseconds.[in] + */ + void MessageExecutedLater(InternalMessage *msg, int64_t delayTimeMs); + + /** + * @Description : Constructs internal messages and places them in the + * message queue of the state machine. The messages are processed + * after the specified delay time. + * + * @param msgName - Message Name.[in] + * @param messageObj -User-defined data + * @param delayTimeMs - Delay time, in milliseconds.[in] + */ + void MessageExecutedLater(int msgName, const std::shared_ptr &messageObj, int64_t delayTimeMs) override; + + /** + * @Description : Constructs internal messages and places them in the + * message queue of the state machine. The messages are processed + * after the specified delay time. + * + * @param msgName - Message Name.[in] + * @param param1 - Message parameters.[in] + * @param param2 - Message parameters.[in] + * @param messageObj - User-defined data + * @param delayTimeMs - Delay time, in milliseconds.[in] + */ + void MessageExecutedLater(int msgName, int param1, int param2, const std::shared_ptr &messageObj, int64_t delayTimeMs); + + /** + * @Description : Construct a new State Machine:: State Machine object. + * + * @param name - State name.[in] + */ + explicit StateMachine(const std::string &name); + + /** + * @Description : Destroy the State Machine:: State Machine object. + * + */ + virtual ~StateMachine(); + +protected: + /** + * @Description : Add state. + * + * @param state - state.[in] + * @param upper - upper state.[in] + */ + void StatePlus(State *state, State *upper) override; + + /** + * @Description : Remove state. + * + * @param state - state.[in] + */ + void StateDelete(State *state); + + /** + * @Description : Set first state. + * + * @param firstState - First state.[in] + */ + void SetFirstState(State *firstState) override; + + /** + * @Description : Transition to orther state. + * + * @param targetState - state.[in] + */ + void SwitchState(State *targetState) override; + + /** + * @Description : Delay Message. + * + * @param msg - Message object.[in] + */ + void DelayMessage(const InternalMessage *msg); + void DelayMessage(VStateMachineMessage *msg) override; + +private: + StateMachineHandler *pStateMachineHandler; + std::string mStateName; +}; + +typedef struct StateInfo +{ + State *state; + StateInfo *upperStateInfo; + bool active; +} StateInfo; + +class StateMachineHandler : public Handler +{ +public: + using StateInfoMap = std::map; + using StateVector = std::vector; + using DelayedMessage = std::vector; + + /** + * @Description : Construct a new state machine Handler:: StateMachine Handler object. + * + * @param pStateMgr - Handler pointer.[in] + */ + explicit StateMachineHandler(StateMachine *pStateMgr); + + /** + * @Description : Destroy the StateMachine Handler:: StateMachine Handler object. + * + */ + ~StateMachineHandler(); + + /** + * @Description : StateMachineHandler Initialization Function. + * + * @return true : success, false : failed. + */ + bool InitialSmHandler(); + + /** + * @Description : Add a new state. + * + * @param state - State to be added.[in] + * @param upper - upper of state.[in] + * @return StateInfo* + */ + StateInfo *StatePlus(State *state, State *upper); + + /** + * @Description : Delete a state. + * + * @param state - State to be deleted.[in] + */ + void StateDelete(State *state); + + /** + * @Description : Sets the Initialization State. + * + * @param firstState - Initialization State.[in] + */ + void SetFirstState(State *firstState); + + /** + * @Description : State transition function. + * + * @param targetState - Destination State.[in] + */ + void SwitchState(State *targetState); + + /** + * @Description : Delay Message Processing Function. + * + * @param msg - Message body pointer.[in] + */ + void DelayMessage(const InternalMessage *msg); + // void DelayMessage(const std::shared_ptr &messageObj); + + /** + * @Description : The state machine is constructed. + * + */ + void BuildTreeComplete(); + +private: + /** + * @Description : Sets the initial state sequence. + * + */ + void BuildStateInitVector(); + + /** + * @Description : Writes the inactive upper states of targetState + * and targetState to the sequenceStateVector list. + * + * @param targetState - Target State Machine.[in] + * @return StateInfo* + */ + StateInfo *BuildSequenceStateVector(State *targetState); + + /** + * @Description : Move Delayed Message At Front Of Queue. + * + */ + void PlaceDelayedMsgQueueTop(); + + /** + * @Description : Release all messages in delayed Messages. + * + */ + void ReleaseDelayedMessages(); + + /** + * @Description : Fill the status in the sequential status + * list in reverse order. + * + * @return int + */ + int MoveSequenceToStateVector(); + + /** + * @Description : Invoke the ExecuteStateMsg interface of the current state + * to process messages sent to the state machine. The entry/exit of the + * state machine is also called, and the delayed messagei s put back + * into queue when transitioning to a new state. + * + * @param msg - Messages.[in] + */ + void ExecuteMessage(InternalMessage *msg) override; + + /** + * @Description : Clean up After Quitting. + * + */ + void ClearWhenQuit(); + + /** + * @Description : Performing Status Transitions. + * + * @param msgProcessedState - Message processing status.[in] + * @param msg - Messages.[in] + */ + void PerformSwitchState(State *msgProcessedState, InternalMessage *msg); + + /** + * @Description : Process messages. If the current state doesnot process it, + * the upper state processing is called, and so on. If all upper states + * are not processed, invoke the NotExecutedMessage method of the state machine. + * + * @param msg - Message body pointer.[in] + * @return State* + */ + State *ExecuteTreeStateMsg(InternalMessage *msg); + + /** + * @Description : Invoke GoOutState() for each state from the first + * state in the list to the public upper state. + * + * @param commonStateInfo - common upper state machine.[in] + */ + void CallTreeStateExits(StateInfo *commonStateInfo); + + /** + * @Description : Call the GoInState method from the start state + * index to the top of the state stack. + * + * @param index - Start state index of the + * state machine list. + */ + void CallTreeStateEnters(int index); + +private: + /* All state mappings of the state machine */ + StateInfoMap mStateInfoMap; + /* From child state to upper state list */ + StateVector mStateVector; + /* Top index of mStateVector */ + int mStateVectorTopIndex; + /* From upper state to child state list */ + StateVector mSequenceStateVector; + /* Top of mSequenceStateVector */ + int mSequenceStateVectorCount; + /* Delayed Message Queue */ + DelayedMessage mDelayedMessages; + /* State machine instance */ + StateMachine *pStateMachine; + /* Initial state */ + State *pFirstState; + /* Target Status */ + State *pTargetState; + /* StateMachine exit or not */ + bool mQuitFlag; + /* Whether the state machine has been built */ + bool mBuildCompleteFlag; + /* + * All State exit/enter calls are true before the + * last enter call in the target state. + */ + bool mSwitchingStateFlag; + /* Current Message */ + InternalMessage *pCurrentMsg; +}; +// } // namespace Wifi +// } // namespace OHOS +#endif \ No newline at end of file diff --git a/code/application/sifarsdk/component/SystemManager/CMakeLists.txt b/code/application/sifarsdk/component/SystemManager/CMakeLists.txt new file mode 100644 index 000000000..31fe89a71 --- /dev/null +++ b/code/application/sifarsdk/component/SystemManager/CMakeLists.txt @@ -0,0 +1,26 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME FileManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +# 这个模块暴露头文件过多,待梳理和优化 \ No newline at end of file diff --git a/code/application/sifarsdk/component/SystemManager/include/ISystemManager.h b/code/application/sifarsdk/component/SystemManager/include/ISystemManager.h new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/component/SystemManager/src/ISystemManager.cpp b/code/application/sifarsdk/component/SystemManager/src/ISystemManager.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/application/sifarsdk/component/SystemTime/CMakeLists.txt b/code/application/sifarsdk/component/SystemTime/CMakeLists.txt new file mode 100644 index 000000000..a6fee5950 --- /dev/null +++ b/code/application/sifarsdk/component/SystemTime/CMakeLists.txt @@ -0,0 +1,25 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/PeripheralManager/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME SystemTime) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) \ No newline at end of file diff --git a/code/application/sifarsdk/component/SystemTime/include/ISystemTime.h b/code/application/sifarsdk/component/SystemTime/include/ISystemTime.h new file mode 100644 index 000000000..83fffb4cb --- /dev/null +++ b/code/application/sifarsdk/component/SystemTime/include/ISystemTime.h @@ -0,0 +1,24 @@ +#ifndef I_SYSTEM_TIME_H +#define I_SYSTEM_TIME_H +#ifdef __cplusplus +extern "C" +{ +#endif + typedef struct SystemTime + { + unsigned short Year; + unsigned short Mon; + unsigned short Day; + unsigned short Hour; + unsigned short Min; + unsigned short Sec; + } SystemTime; + void SystemTimeInit(void); + void SystemTimeUnInit(void); + void SetSystemTime(const SystemTime time); + SystemTime GetSystemTime(void); + int CreateSystemTimeModule(void); +#ifdef __cplusplus +} +#endif +#endif // !I_SYSTEM_TIME_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/SystemTime/src/ISystemTime.cpp b/code/application/sifarsdk/component/SystemTime/src/ISystemTime.cpp new file mode 100644 index 000000000..20e51d5a1 --- /dev/null +++ b/code/application/sifarsdk/component/SystemTime/src/ISystemTime.cpp @@ -0,0 +1,19 @@ +#include "ISystemTime.h" +#include "ISystemTimeCpp.h" +#include "ISystemTime.h" +void SystemTimeInit(void) +{ + ISystemTimeCpp::GetInstance()->Init(); +} +void SystemTimeUnInit(void) +{ + ISystemTimeCpp::GetInstance()->UnInit(); +} +void SetSystemTime(const SystemTime time) +{ + ISystemTimeCpp::GetInstance()->SetSystemTime(time); +} +SystemTime GetSystemTime(void) +{ + return ISystemTimeCpp::GetInstance()->GetSystemTime(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/SystemTime/src/ISystemTimeCpp.cpp b/code/application/sifarsdk/component/SystemTime/src/ISystemTimeCpp.cpp new file mode 100644 index 000000000..2aea94b25 --- /dev/null +++ b/code/application/sifarsdk/component/SystemTime/src/ISystemTimeCpp.cpp @@ -0,0 +1,28 @@ +#include "ISystemTimeCpp.h" +#include "Log.h" +std::shared_ptr &ISystemTimeCpp::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/SystemTime/src/ISystemTimeCpp.h b/code/application/sifarsdk/component/SystemTime/src/ISystemTimeCpp.h new file mode 100644 index 000000000..5bbc4287d --- /dev/null +++ b/code/application/sifarsdk/component/SystemTime/src/ISystemTimeCpp.h @@ -0,0 +1,20 @@ +#ifndef I_SYSTEM_TIME_CPP_H +#define I_SYSTEM_TIME_CPP_H +#include "ISystemTime.h" +#include +class ISystemTimeCpp +{ +public: + ISystemTimeCpp() = default; + virtual ~ISystemTimeCpp() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual void Init(void) {} + virtual void UnInit(void) {} + virtual void SetSystemTime(const SystemTime &time) {} + virtual SystemTime GetSystemTime(void) + { + SystemTime time; + return time; + } +}; +#endif // !I_SYSTEM_TIME_CPP_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/SystemTime/src/SystemTimeCpp.cpp b/code/application/sifarsdk/component/SystemTime/src/SystemTimeCpp.cpp new file mode 100644 index 000000000..f06544790 --- /dev/null +++ b/code/application/sifarsdk/component/SystemTime/src/SystemTimeCpp.cpp @@ -0,0 +1,90 @@ +#include "SystemTimeCpp.h" +#include "Log.h" +#include +int CreateSystemTimeModule(void) +{ + std::shared_ptr impl = std::make_shared(); + if (impl) + { + ISystemTimeCpp::GetInstance(&impl); + return 0; + } + return -1; +} +SystemTimeCpp::SystemTimeCpp() +{ + mRtc = std::make_shared(); +} +void SystemTimeCpp::Init(void) +{ + std::shared_ptr rtc = std::make_shared(); + IPeripheralManager::GetInstance()->GetRtcTimeHandle(rtc); + mRtc = rtc; +} +void SystemTimeCpp::UnInit(void) +{ + std::shared_ptr rtc = std::make_shared(); +} +void SystemTimeCpp::SetSystemTime(const SystemTime &time) +{ + struct rtc_time rtctm; + + if (Check(time)) + { + rtctm.tm_year = time.Year - 1900; + rtctm.tm_mon = time.Mon - 1; + rtctm.tm_mday = time.Day; + rtctm.tm_hour = time.Hour; + rtctm.tm_min = time.Min; + rtctm.tm_sec = time.Sec; + mRtc->Set(rtctm); + } + else + { + LogWarning("Reset time because time check failed.\n"); + Reset(); + } +} +SystemTime SystemTimeCpp::GetSystemTime(void) +{ + struct rtc_time rtctm; + std::shared_ptr rtc = std::make_shared(); + IPeripheralManager::GetInstance()->GetRtcTimeHandle(rtc); + rtc->Get(rtctm); + SystemTime time; + time.Year = rtctm.tm_year + 1900; + time.Mon = rtctm.tm_mon + 1; + time.Day = rtctm.tm_mday; + time.Hour = rtctm.tm_hour; + time.Min = rtctm.tm_min; + time.Sec = rtctm.tm_sec; + return time; +} +bool SystemTimeCpp::Check(const SystemTime &time) +{ + LogInfo("%d-%d-%d %d:%d:%d\n", time.Year, time.Mon, time.Day, time.Hour, time.Min, time.Sec); + if ((time.Year >= 2021) && + (time.Year <= 2050) && + (time.Mon <= 12) && + (time.Day <= 31) && + (time.Hour < 24) && + (time.Min < 60) && + (time.Sec < 60)) + { + return true; + } + return false; +} +int SystemTimeCpp::Reset(void) +{ + int ret = -1; + struct rtc_time rtctm; + rtctm.tm_year = 2022 - 1900; + rtctm.tm_mon = 0; + rtctm.tm_mday = 1; + rtctm.tm_hour = 8; + rtctm.tm_min = 0; + rtctm.tm_sec = 0; + mRtc->Set(rtctm); + return ret; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/SystemTime/src/SystemTimeCpp.h b/code/application/sifarsdk/component/SystemTime/src/SystemTimeCpp.h new file mode 100644 index 000000000..446f503c7 --- /dev/null +++ b/code/application/sifarsdk/component/SystemTime/src/SystemTimeCpp.h @@ -0,0 +1,20 @@ +#ifndef SYSTEM_TIME_CPP_H +#define SYSTEM_TIME_CPP_H +#include "ISystemTimeCpp.h" +#include "IPeripheralManager.h" +class SystemTimeCpp : public ISystemTimeCpp +{ +public: + SystemTimeCpp(); + ~SystemTimeCpp() = default; + void Init(void) override; + void UnInit(void) override; + void SetSystemTime(const SystemTime &time) override; + SystemTime GetSystemTime(void) override; + bool Check(const SystemTime &time); + int Reset(void); + +private: + std::shared_ptr mRtc; +}; +#endif // !SYSTEM_TIME_CPP_H diff --git a/code/application/sifarsdk/component/UpgradeManager/CMakeLists.txt b/code/application/sifarsdk/component/UpgradeManager/CMakeLists.txt new file mode 100644 index 000000000..ad7258281 --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/CMakeLists.txt @@ -0,0 +1,28 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/HttpBase/include + ${COMPONENT_SOURCE_PATH}/FileManager/include + ${COMPONENT_SOURCE_PATH}/base64/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME UpgradeManager) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} FileManager HttpBase Log) \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/include/IUpgradeManager.h b/code/application/sifarsdk/component/UpgradeManager/include/IUpgradeManager.h new file mode 100644 index 000000000..66d376620 --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/include/IUpgradeManager.h @@ -0,0 +1,40 @@ +#ifndef I_UPGRADE_MANAGER_H +#define I_UPGRADE_MANAGER_H +#include "VReturnCode.h" +#include +enum class UpgradeResult +{ + SUCCEED = 0, + FAILED, + END +}; +class VUpgradeTask +{ +public: + VUpgradeTask() = default; + virtual ~VUpgradeTask() = default; + virtual const char *GetPackageUrl(void) { return nullptr; } + virtual const char *GetSavePath(void) { return nullptr; } + virtual const void GetSoftWareVersion(char *version, const unsigned int &length) {} + virtual void TaskResult(const UpgradeResult &resutl) {} +}; +class VUpgradeNetworkModuleTask +{ +public: + VUpgradeNetworkModuleTask() = default; + virtual ~VUpgradeNetworkModuleTask() = default; + virtual void TaskResult(const UpgradeResult &resutl) {} +}; +class IUpgradeManager +{ +public: + IUpgradeManager() = default; + virtual ~IUpgradeManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE Upgrade(std::shared_ptr &task) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE Upgrade(std::shared_ptr &task) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreateUpgradeManager(void); +#endif // !I_UPGRADE_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/src/IUpgradeManager.cpp b/code/application/sifarsdk/component/UpgradeManager/src/IUpgradeManager.cpp new file mode 100644 index 000000000..5e575d55c --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/IUpgradeManager.cpp @@ -0,0 +1,29 @@ +#include "IUpgradeManager.h" +#include "Log.h" +#include +std::shared_ptr &IUpgradeManager::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + static bool instanceChanging = false; + if (impl && false == instanceChanging) + { + instanceChanging = true; + //std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (instance.use_count() == 1) // bug? + { + LogInfo("Instance change succeed.\n"); + instance = *impl; + } + else + { + LogError("instance change failed, using by some one.\n"); + } + instanceChanging = false; + } + if (instanceChanging) + { + static auto tmporaryInstance = std::make_shared(); + return tmporaryInstance; + } + return instance; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/src/OtaServers.cpp b/code/application/sifarsdk/component/UpgradeManager/src/OtaServers.cpp new file mode 100644 index 000000000..ebd1371ba --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/OtaServers.cpp @@ -0,0 +1,562 @@ +#include "OtaServers.h" +#include "Log.h" +#include "FileManager.h" +#include "sf_base64.h" +#include "sf_md5.h" +#include +#include +#include +#include +#include +OtaServers::OtaServers(const std::string &hostName, std::shared_ptr &task) : HttpBase(hostName), mTask(task) +{ + memset(&stOtaAttrs, 0, sizeof(SF_OTA_ATTRS)); +} +const std::string OtaServers::GetHostName(const char *httpUrl) +{ + SINT32 s32ret = SF_SUCCESS; + char server_host[64] = {0}; + if (httpUrl == NULL) + { + LogError("download url is null\n!!!"); + return "nullptr host name"; + } + s32ret = sscanf(httpUrl, "%*[^//]//%[^/]", server_host); + if (s32ret <= 0) + { + LogError("String matching failed,please check download url!!!\n"); + return "nullptr host name"; + } + return server_host; +} +void OtaServers::Upgrade(void) +{ + SINT32 s32ret = SF_SUCCESS; + s32ret = Init(); + if (s32ret != SF_SUCCESS) + { + LogError("Init failed.\n"); + mTask->TaskResult(UpgradeResult::FAILED); + return; + } + s32ret = Download(); + if (s32ret != SF_SUCCESS) + { + LogError("Download failed.\n"); + mTask->TaskResult(UpgradeResult::FAILED); + return; + } + s32ret = sf_upgrade_ota_filecheck(); + if (s32ret != SF_SUCCESS) + { + LogError("sf_upgrade_ota_filecheck failed.\n"); + mTask->TaskResult(UpgradeResult::FAILED); + return; + } + s32ret = sf_upgrade_ota_reset(); + if (s32ret != SF_SUCCESS) + { + LogError("sf_upgrade_ota_reset failed.\n"); + mTask->TaskResult(UpgradeResult::FAILED); + return; + } + mTask->TaskResult(UpgradeResult::SUCCEED); +} +SINT32 OtaServers::Init(void) +{ + SINT32 s32ret = SF_SUCCESS; + UINT8 j = 0; + char filepath[64] = {0}; + const char *httpUrl = mTask->GetPackageUrl(); + if (httpUrl == NULL) + { + LogError("download url is null\n!!!"); + return SF_FAILURE; + } + s32ret = sscanf(httpUrl, "%*[^//]//%[^/]", stOtaAttrs.server_host); + if (s32ret <= 0) + { + LogError("String matching failed,please check download url!!!\n"); + return SF_FAILURE; + } + LogInfo("host = [%s]\n", stOtaAttrs.server_host); + + s32ret = sscanf((char *)httpUrl, "%*[^//]//%*[^/]/%s", stOtaAttrs.filepath); + if (s32ret <= 0) + { + LogError("String matching failed,please check download url!!!\n"); + return SF_FAILURE; + } + LogInfo("filepath = [%s]\n", stOtaAttrs.filepath); + while (j < 64) + { + if (stOtaAttrs.filepath[j] == '\5') + stOtaAttrs.filepath[j] = '\0'; + j++; + } + memset(filepath, '\0', 64); + strcpy(filepath, stOtaAttrs.filepath); + s32ret = sscanf(filepath, "%*[^/]/%s", stOtaAttrs.filename); + if (s32ret <= 0) + { + LogError("String matching failed,please check download url!!!\n"); + return SF_FAILURE; + } + LogInfo("filename = [%s]\n", stOtaAttrs.filename); + + if (sf_file_IsExsit(SF_OTA_UPGRADE_FILE_PATH) == SF_TRUE) + sf_file_remove(SF_OTA_UPGRADE_FILE_PATH); + if (sf_file_IsExsit(OTA_CFG_FILE_PATH) == SF_TRUE) + sf_file_remove(OTA_CFG_FILE_PATH); + if (sf_file_IsExsit(OTAFILE_PATH) == SF_TRUE) + sf_file_remove(OTAFILE_PATH); + + return SF_SUCCESS; +} +SINT32 OtaServers::Download(void) +{ + SINT32 s32ret = SF_SUCCESS; + char data_buff[BUFFER_SIZE] = {0}; + char cmd[512] = {0}; + HttpBase::Create(); + s32ret = upgrade_ota_addfileheader(); + s32ret = upgrade_ota_send(OTAFILE_PATH); + s32ret = upgrade_ota_firstrecv(data_buff, BUFFER_SIZE); + s32ret = upgrade_ota_dataparse(data_buff); + sprintf(data_buff, "%s/%s", OTA_UPGRADE_FATH_PREFIX, stOtaAttrs.filename); + s32ret = upgrade_ota_secondrecv(data_buff, BUFFER_SIZE); + HttpBase::Close(); + sprintf(cmd, "unzip %s/%s -d %s", OTA_UPGRADE_FATH_PREFIX, stOtaAttrs.filename, OTA_UPGRADE_FATH_PREFIX); + s32ret = system(cmd); + if (s32ret != SF_SUCCESS) + { + LogWarning("remount sd \n"); + // SF_MESSAGE_BUF_S stMessageBuf = {0}; // TODO: + // stMessageBuf.cmdId = 0x0113; + // stMessageBuf.arg1 = 0; + // sf_com_message_send_to_cardv(&stMessageBuf); + usleep(500000); + s32ret = system(cmd); + } + return s32ret; +} +SINT32 OtaServers::upgrade_ota_addfileheader(void) +{ + SINT16 fd = 0; + char httpstr[128] = {0}; + size_t length = 0; + + fd = open(OTAFILE_PATH, O_CREAT | O_RDWR, 0); + if (fd <= 0) + { + LogError("create file ota.txt failed\n"); + return SF_FAILURE; + } + LogInfo("\n"); + for (UINT8 i = 0; i < 4; i++) + { + memset(httpstr, '\0', 128); + switch (i) + { + case 0: + sprintf(httpstr, "GET /%s HTTP/1.1\r\n", stOtaAttrs.filepath); + break; + case 1: + sprintf(httpstr, "Host: %s\r\n", stOtaAttrs.server_host); + break; + case 2: + memcpy(httpstr, "Connection:close\r\n", strlen("Connection:close\r\n")); + break; + case 3: + memcpy(httpstr, "\r\n", strlen("\r\n")); + break; + } + LogInfo("%s", httpstr); + length = write(fd, httpstr, strlen(httpstr)); + if (length != strlen(httpstr)) + { + LogError("write failed.\n"); + } + } + sync(); + close(fd); + return SF_SUCCESS; +} +SINT32 OtaServers::upgrade_ota_send(const char *filename) +{ + SINT32 s32ret = SF_SUCCESS; + SINT32 fileFd = 0; + SINT32 tolFileSize = 0; + SINT32 readSize = 0; + + struct stat statBuf; + char *pBuf = NULL; + char *bufBak = NULL; + + fileFd = open(filename, O_RDONLY); + if (fileFd < 0) + { + LogError("open file error!\n"); + return SF_FAILURE; + } + + fstat(fileFd, &statBuf); + tolFileSize = statBuf.st_size; + + LogInfo("tolFileSize:%d\n", tolFileSize); + bufBak = (char *)((tolFileSize > 1024 * 1024 * 5) ? malloc(1024 * 1024 * 5) : malloc(tolFileSize)); + if (!bufBak) + { + LogError("malloc buf fail!\n"); + close(fileFd); + return SF_FAILURE; + } + + while (tolFileSize > 0) + { + pBuf = bufBak; + readSize = (tolFileSize >= 1024 * 1024 * 5) ? read(fileFd, pBuf, 1024 * 1024 * 5) : read(fileFd, pBuf, tolFileSize); + LogInfo("send file data, tolFileSize:%d, read size:%d\n", tolFileSize, readSize); + tolFileSize -= readSize; + + if (readSize > 0) + { + // s32ret = http_send_to_server(client, pBuf, readSize); + s32ret = HttpBase::Send(pBuf, readSize); + if (s32ret < 0) + { + LogError("Connection error (send returned %d)", s32ret); + free(bufBak); + close(fileFd); + return s32ret; + } + } + } + free(bufBak); + close(fileFd); + sf_file_remove(OTAFILE_PATH); + return SF_SUCCESS; +} +SINT32 OtaServers::upgrade_ota_firstrecv(char *data_buff, int length) +{ + SINT32 recv_byte = 0; + SINT32 respl = 0; + LogInfo("\n"); + while (respl < BUFFER_SIZE) + { + // recv_byte = http_recv_from_server(client, (data_buff + respl), 1); + recv_byte = HttpBase::Rece((data_buff + respl), 1); + LogInfo("%c", data_buff[respl]); + if (recv_byte <= 0) + return SF_FAILURE; + + respl += recv_byte; + data_buff[respl] = '\0'; + if (strstr(data_buff, "\r\n\r\n")) + break; + } + if (respl > BUFFER_SIZE) + return SF_FAILURE; + + return SF_SUCCESS; +} +SINT32 OtaServers::upgrade_ota_dataparse(char *buffer) +{ + SINT32 errcode = 0; + char *pbuff = NULL; + + pbuff = strstr(buffer, "HTTP/1.1"); + if (!pbuff) + return SF_FAILURE; + + errcode = atoi(pbuff + strlen("HTTP/1.1")); + LogInfo("errcode = %d\n", errcode); + if (errcode != 200) + return SF_FAILURE; + + pbuff = strstr(buffer, "Content-Length:"); + if (!pbuff) + return SF_FAILURE; + + stOtaAttrs.filesize = atoi(pbuff + 15); + LogInfo("filesize = %d\n", stOtaAttrs.filesize); + + return SF_SUCCESS; +} +SINT32 OtaServers::upgrade_ota_secondrecv(char *data, int length) +{ + SINT32 recv_byte = 0; + SINT32 respl = 0; + SINT32 loadpercent = 0; + SINT32 lenth = 0; + SINT32 fd = 0; + // char data_buff[BUFFER_SIZE] = {0}; + char *pdata_buff = 0; + char *bufBak = NULL; + size_t length2 = 0; + + fd = open(data, O_CREAT | O_RDWR, 0); + if (fd < 0) + { + LogError("create %s error\r\n", data); + return SF_FAILURE; + } + lenth = sizeof(char) * 1024 * 100; + bufBak = (char *)malloc(lenth); + LogInfo("reciving,please waiting................!!!\n"); + memset(bufBak, '\0', lenth); + pdata_buff = bufBak; + LogInfo("Current download progress: [ 0%%]"); + while ((recv_byte = HttpBase::Rece(pdata_buff, lenth)) > 0 && (respl < stOtaAttrs.filesize)) + { + length2 = write(fd, pdata_buff, recv_byte); + if (length2 != (size_t)recv_byte) // TODO: 强转不规范 + { + LogError("write failed.\n"); + } + respl += recv_byte; + memset(bufBak, '\0', lenth); + loadpercent = (respl * 100 / stOtaAttrs.filesize); + LogInfo("\b\b\b\b\b\b[%3d%%]", loadpercent); + + fflush(stdout); + pdata_buff = bufBak; + } + LogInfo("\n"); + free(bufBak); + LogInfo("revice finished....\n"); + close(fd); + + return SF_SUCCESS; +} +SINT32 OtaServers::sf_upgrade_ota_filecheck(void) +{ + SINT32 s32ret = SF_SUCCESS; + s32ret = upgrade_ota_cfgcheck(); + if (s32ret != SF_SUCCESS) + { + LogError("upgrade_ota_cfgcheck failed\n"); + return s32ret; + } + s32ret = upgrade_md5_check(); + if (s32ret != SF_SUCCESS) + { + LogError("upgrade_md5_check failed\n"); + return s32ret; + } + return SF_SUCCESS; +} +SINT32 OtaServers::upgrade_ota_cfgcheck(void) +{ + constexpr int BUF_LENGTH = 32; + UINT8 srcver[BUF_LENGTH + 1] = {0}; + UINT8 dstver[BUF_LENGTH + 1] = {0}; + size_t length = 0; + int fd = 0; + UINT8 mask; + UINT8 value; + UINT8 maskStr[8] = {0}; + UINT8 valueStr[8] = {0}; + UINT8 decodeSrc[33] = {0}; + char decodeDst[33] = {0}; + constexpr int VERSION_BUF_LENGTH = 24; + char localver[VERSION_BUF_LENGTH] = {0}; + + fd = open(OTA_CFG_FILE_PATH, O_RDONLY, 0); + if (fd <= 0) + { + LogError("open file[%s] failed!!!\n", OTA_CFG_FILE_PATH); + return SF_FAILURE; + } + + lseek(fd, 0x30, SEEK_SET); + length = read(fd, srcver, BUF_LENGTH); + if (length != BUF_LENGTH) + { + LogError("read failed.\n"); + } + + lseek(fd, 0x70, SEEK_SET); + length = read(fd, dstver, BUF_LENGTH); + if (length != BUF_LENGTH) + { + LogError("read failed.\n"); + } + + lseek(fd, 0xB0, SEEK_SET); + length = read(fd, &value, 1); + if (length != 1) + { + LogError("read failed.\n"); + } + + lseek(fd, 0xB8, SEEK_SET); + length = read(fd, &mask, 1); + if (length != 1) + { + LogError("read failed.\n"); + } + + close(fd); + LogInfo("src=%s\n", srcver); + LogInfo("dst=%s\n", dstver); + LogInfo("strValue=%x\n", value); + LogInfo("strMask=%x\n", mask); + + /*decode version*/ + sf_base64_decode((char *)srcver, (char *)decodeSrc); + sf_base64_decode((char *)dstver, (char *)decodeDst); + + LogInfo("decodeSrc=%s\n", decodeSrc); + LogInfo("decodeDst=%s\n", decodeDst); + + /*mask-vallue*/ + upgrade_ota_bitarray_get(valueStr, value); + upgrade_ota_bitarray_get(maskStr, mask); + + // sf_sys_software_version_get(localver); + mTask->GetSoftWareVersion(localver, VERSION_BUF_LENGTH); + + if ((maskStr[3] == 1) && (valueStr[3] == 1)) + { + return SF_SUCCESS; + } + else if ((maskStr[2] == 1) && (valueStr[2] == 1)) + { + return SF_SUCCESS; + } + else if ((maskStr[1] == 1) && (valueStr[1] == 1)) + { + if ((strncmp(localver, decodeDst, 2) == 0)) + { + if ((maskStr[0] == 1) && (valueStr[0] == 1)) + { + if ((strncmp(localver + 4, decodeDst + 4, 2) == 0)) + { + return SF_SUCCESS; + } + else + { + LogError("FEA is different !\n"); + return SF_FAILURE; + } + } + else + { + return SF_SUCCESS; + } + } + else + { + return SF_FAILURE; + } + } + else + { + if ((strstr((char *)decodeSrc, (char *)localver))) + { + return SF_SUCCESS; + } + else + { + return SF_FAILURE; + } + } +} +SINT32 OtaServers::upgrade_md5_check(void) +{ + int fd = 0; + constexpr int BUF_LENGTH = 16; + UINT8 srcCheckCode[BUF_LENGTH] = {0}; // md5 + UINT8 dstCheckCode[BUF_LENGTH] = {0}; // md5 + UINT32 filesize = 0; + SINT32 s32ret = SF_SUCCESS; + size_t length = 0; + fd = open(OTA_CFG_FILE_PATH, O_RDONLY, 0); + if (fd <= 0) + { + LogError("open file [%s] failed\n", OTA_CFG_FILE_PATH); + return SF_FAILURE; + } + + lseek(fd, 0x100, SEEK_SET); + length = read(fd, srcCheckCode, BUF_LENGTH); + if (length != BUF_LENGTH) + { + LogError("read failed.\n"); + } + close(fd); + + s32ret = sf_file_size_get(OTA_UPGRADE_FILE_PATH, &filesize); + LogInfo("file [%s] size is %d\r\n", OTA_UPGRADE_FILE_PATH, filesize); + s32ret = upgrade_md5_check_code_get(OTA_UPGRADE_FILE_PATH, dstCheckCode, 0, filesize); + + for (UINT8 i = 0; i < 16; i++) + { + if (srcCheckCode[i] != dstCheckCode[i]) + { + LogError("ERROR: BRN MD5 check error srcCheckCode[%d]=%d dstCheckCode[%d]=%d\n", i, srcCheckCode[i], i, dstCheckCode[i]); + return SF_FAILURE; + } + } + + return s32ret; +} +void OtaServers::upgrade_ota_bitarray_get(UINT8 str[], UINT8 value) +{ + UINT8 i = 0; + for (i = 0; i < 8; i++) + { + str[i] = (UINT8)(value & 1); + value = (UINT8)(value >> 1); + } +} +SINT32 OtaServers::upgrade_md5_check_code_get(const char *filename, UINT8 digest[], UINT32 offset, UINT32 size) +{ + MD5_CTX context; + UINT32 len = 0; + UINT32 flieSize = 0; + UINT8 buffer[1024] = {0}; + int fd = 0; + fd = open((char *)filename, O_RDONLY, 0); + if (fd <= 0) + { + LogError("read file %s failed\n", filename); + return SF_FAILURE; + } + + sf_md5_init(&context); + while (1) + { + len = read(fd, buffer, size > 1024 ? 1024 : size); + + if (len == 0) + break; + flieSize += len; + sf_md5_update(&context, buffer, len); + size = size - len; + } + + LogInfo("Check size=%d\n", flieSize); + + sf_md5_final(&context, digest); + close(fd); + return 0; +} +SINT32 OtaServers::sf_upgrade_ota_reset(void) +{ + char data_buff[BUFFER_SIZE] = {0}; + if (stOtaAttrs.filename == NULL) + { + LogError("souce filename is null\n"); + return SF_FAILURE; + } + sprintf(data_buff, "%s/%s", OTA_UPGRADE_FATH_PREFIX, stOtaAttrs.filename); + if (sf_file_IsExsit(data_buff) == SF_TRUE) + sf_file_remove(data_buff); + if (sf_file_IsExsit(OTA_CFG_FILE_PATH) == SF_TRUE) + sf_file_remove(OTA_CFG_FILE_PATH); + if (sf_file_IsExsit(OTAFILE_PATH) == SF_TRUE) + sf_file_remove(OTAFILE_PATH); + return SF_SUCCESS; +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/src/OtaServers.h b/code/application/sifarsdk/component/UpgradeManager/src/OtaServers.h new file mode 100644 index 000000000..ef938e60f --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/OtaServers.h @@ -0,0 +1,62 @@ +#ifndef OTA_SERVERS_H +#define OTA_SERVERS_H +#include "IUpgradeManager.h" +#include "HttpBase.h" +#include "SfTypeDefine.h" +// TODO: +constexpr int BUFFER_SIZE = 2048; +#define SF_SD_ROOT "/mnt/mmc/" +#define OTAFILE_PATH "/mnt/mmc/ota.txt" +#define OTA_UPGRADE_FILE_NAME "UpgradeSD.bin" +#define OTA_CFG_FILE_NAME "T110Upgrade.CFG" +#define OTA_BAK_FILE_NAME "backup.txt" + +#define OTA_UPGRADE_FATH_PREFIX "/mnt/mmc" +#define OTA_UPGRADE_FILE_PATH OTA_UPGRADE_FATH_PREFIX "/" OTA_UPGRADE_FILE_NAME +#define OTA_CFG_FILE_PATH OTA_UPGRADE_FATH_PREFIX "/" OTA_CFG_FILE_NAME + +#define SF_OTA_UPGRADE_FILE_PATH SF_SD_ROOT OTA_UPGRADE_FILE_NAME +#define SF_OTA_PARAM_BACKUP_FATH SF_SD_ROOT OTA_BAK_FILE_NAME +typedef struct sf_ota_attrs +{ + int server_type; + char server_url[128]; + char server_host[64]; + char filepath[64]; + char filename[64]; + int filesize; + char *host; + int socket; +} SF_OTA_ATTRS; +typedef struct sf_URL_s +{ + char url[160]; +} SF_URL_S; +class OtaServers : public HttpBase +{ +public: + OtaServers(const std::string &hostName, std::shared_ptr &task); + ~OtaServers() = default; + static const std::string GetHostName(const char *httpUrl); + void Upgrade(void); + +private: + SINT32 Init(void); + SINT32 Download(void); + SINT32 upgrade_ota_addfileheader(void); + SINT32 upgrade_ota_send(const char *filename); + SINT32 upgrade_ota_firstrecv(char *data_buff, int length); + SINT32 upgrade_ota_dataparse(char *buffer); + SINT32 upgrade_ota_secondrecv(char *data, int length); + SINT32 sf_upgrade_ota_filecheck(void); + SINT32 upgrade_ota_cfgcheck(void); + SINT32 upgrade_md5_check(void); + void upgrade_ota_bitarray_get(UINT8 str[], UINT8 value); + SINT32 upgrade_md5_check_code_get(const char *filename, UINT8 digest[], UINT32 offset, UINT32 size); + SINT32 sf_upgrade_ota_reset(void); + +private: + std::shared_ptr mTask; + SF_OTA_ATTRS stOtaAttrs; +}; +#endif // !OTA_SERVERS_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManager.cpp b/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManager.cpp new file mode 100644 index 000000000..51f42d0b1 --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManager.cpp @@ -0,0 +1,23 @@ +#include "UpgradeManager.h" +#include "OtaServers.h" +#include "IHal.h" +RETURN_CODE UpgradeManager::Upgrade(std::shared_ptr &task) +{ + std::string hostName = OtaServers::GetHostName(task->GetPackageUrl()); + OtaServers otaServers(hostName, task); + otaServers.Upgrade(); + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} +RETURN_CODE UpgradeManager::Upgrade(std::shared_ptr &task) +{ + NetWorkUpgradeResult result = IHal::GetInstance()->NetworkModuleUpgrade(); + if (NETWORK_MODULE_UPGRADE_RESULT::SUCCEED == result.mResult) + { + task->TaskResult(UpgradeResult::SUCCEED); + } + else + { + task->TaskResult(UpgradeResult::FAILED); + } + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManager.h b/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManager.h new file mode 100644 index 000000000..86d0a0973 --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManager.h @@ -0,0 +1,12 @@ +#ifndef UPGRADE_MANAGER_H +#define UPGRADE_MANAGER_H +#include "IUpgradeManager.h" +class UpgradeManager : public IUpgradeManager +{ +public: + UpgradeManager() = default; + ~UpgradeManager() = default; + RETURN_CODE Upgrade(std::shared_ptr &task) override; + RETURN_CODE Upgrade(std::shared_ptr &task) override; +}; +#endif // !UPGRADE_MANAGER_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManagerMakePtr.cpp b/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManagerMakePtr.cpp new file mode 100644 index 000000000..f6e98fd9d --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManagerMakePtr.cpp @@ -0,0 +1,34 @@ +#include "UpgradeManagerMakePtr.h" +#include "UpgradeManager.h" +#include "Log.h" +bool CreateUpgradeManager(void) +{ + auto instance = std::make_shared(); + RETURN_CODE code = UpgradeManagerMakePtr::GetInstance()->CreateUpgradeManager(instance); + if (code->IsCodeOK()) + { + LogInfo("Dual core manager instance is ok.\n"); + IUpgradeManager::GetInstance(&instance); + return true; + } + return false; +} +std::shared_ptr &UpgradeManagerMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) + { + /** + * @brief + * The non-thread-safe changing is only for gtest. + */ + instance = *impl; + } + return instance; +} +RETURN_CODE UpgradeManagerMakePtr::CreateUpgradeManager(std::shared_ptr &impl) +{ + auto tmp = std::make_shared(); + impl = tmp; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManagerMakePtr.h b/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManagerMakePtr.h new file mode 100644 index 000000000..6e6db560e --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/UpgradeManagerMakePtr.h @@ -0,0 +1,14 @@ +#ifndef UPGRADE_MANAGER_MAKE_PTR_H +#define UPGRADE_MANAGER_MAKE_PTR_H +#include "IUpgradeManager.h" +#include "VReturnCode.h" +#include +class UpgradeManagerMakePtr +{ +public: + UpgradeManagerMakePtr() = default; + virtual ~UpgradeManagerMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE CreateUpgradeManager(std::shared_ptr &impl); +}; +#endif // !UPGRADE_MANAGER_MAKE_PTR_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/UpgradeManager/src/sf_md5.c b/code/application/sifarsdk/component/UpgradeManager/src/sf_md5.c new file mode 100644 index 000000000..f8bc557cb --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/sf_md5.c @@ -0,0 +1,274 @@ +/************************************************************************** + * + * Copyright (c) 2009-2018 by SiFar Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * SiFar Technology, Inc. reserves the right to modify this software without notice. + * + * Author: HAC + * Ver: 1.0.0 2021.10.31 + * Description: creat + **************************************************************************/ +#include +#include +#include "sf_md5.h" + +/************************************************************************** + * C O N S T A N T S * + **************************************************************************/ + +/************************************************************************** + * M A C R O S * + **************************************************************************/ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +#define FF(a, b, c, d, x, s, ac) \ + { \ + (a) += F((b), (c), (d)) + (x) + (UINT32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + { \ + (a) += G((b), (c), (d)) + (x) + (UINT32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + { \ + (a) += H((b), (c), (d)) + (x) + (UINT32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + { \ + (a) += I((b), (c), (d)) + (x) + (UINT32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +/************************************************************************** + * D A T A T Y P E S * + **************************************************************************/ +typedef unsigned char *POINTER; +typedef unsigned int UINT32; +/************************************************************************** + * G L O B A L D A T A * + **************************************************************************/ +static unsigned char 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}; + +/************************************************************************** + * E X T E R N A L R E F E R E N C E S * + **************************************************************************/ + +/************************************************************************** + * F U N C T I O N D E C L A R A T I O N S * + **************************************************************************/ +static void Encode(unsigned char *output, UINT32 *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + { + output[j] = (unsigned char)(input[i] & 0xff); + output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +static void Decode(UINT32 *output, unsigned char *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT32)input[j]) | (((UINT32)input[j + 1]) << 8) | + (((UINT32)input[j + 2]) << 16) | (((UINT32)input[j + 3]) << 24); +} + +static void MD5_memcpy(POINTER output, POINTER input, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++) + + output[i] = input[i]; +} + +static void MD5_memset(POINTER output, int value, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} + +static void MD5Transform(UINT32 state[4], unsigned char block[64]) +{ + UINT32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode(x, block, 64); + + /* Round 1 */ + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + MD5_memset((POINTER)x, 0, sizeof(x)); +} + +void sf_md5_init(MD5_CTX *context) +{ + context->count[0] = context->count[1] = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +void sf_md5_update(MD5_CTX *context, unsigned char *input, unsigned int inputlen) +{ + unsigned int i, index, partLen; + + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + if ((context->count[0] += ((UINT32)inputlen << 3)) < ((UINT32)inputlen << 3)) + context->count[1]++; + + context->count[1] += ((UINT32)inputlen >> 29); + partLen = 64 - index; + + if (inputlen >= partLen) + { + MD5_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen); + MD5Transform(context->state, context->buffer); + + for (i = partLen; i + 63 < inputlen; i += 64) + MD5Transform(context->state, &input[i]); + + index = 0; + } + else + i = 0; + + MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputlen - i); +} + +void sf_md5_final(MD5_CTX *context, unsigned char digest[16]) +{ + unsigned char bits[8]; + unsigned int index, padLen; + + Encode(bits, context->count, 8); + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + sf_md5_update(context, PADDING, padLen); + sf_md5_update(context, bits, 8); + Encode(digest, context->state, 16); + MD5_memset((POINTER)context, 0, sizeof(*context)); +} diff --git a/code/application/sifarsdk/component/UpgradeManager/src/sf_md5.h b/code/application/sifarsdk/component/UpgradeManager/src/sf_md5.h new file mode 100644 index 000000000..63af26434 --- /dev/null +++ b/code/application/sifarsdk/component/UpgradeManager/src/sf_md5.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright (c) 2009-2018 by SiFar Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * SiFar Technology, Inc. reserves the right to modify this software without notice. + * + * Author: HAC + * Ver: 1.0.0 2021.10.31 + * Description: creat + **************************************************************************/ +#ifndef __SF_MD5_H__ +#define __SF_MD5_H__ +#if __cplusplus +extern "C" +{ +#endif + typedef struct + { + unsigned int state[4]; + unsigned int count[2]; + unsigned char buffer[64]; + } MD5_CTX; + + void sf_md5_init(MD5_CTX *context); + void sf_md5_update(MD5_CTX *context, unsigned char *input, unsigned int inputlen); + void sf_md5_final(MD5_CTX *context, unsigned char digest[16]); + +#if __cplusplus +} +#endif +#endif diff --git a/code/application/sifarsdk/component/base64/CMakeLists.txt b/code/application/sifarsdk/component/base64/CMakeLists.txt new file mode 100644 index 000000000..7b5b35e2c --- /dev/null +++ b/code/application/sifarsdk/component/base64/CMakeLists.txt @@ -0,0 +1,21 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME base64) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) \ No newline at end of file diff --git a/code/application/sifarsdk/component/base64/include/sf_base64.h b/code/application/sifarsdk/component/base64/include/sf_base64.h new file mode 100644 index 000000000..a9490c63e --- /dev/null +++ b/code/application/sifarsdk/component/base64/include/sf_base64.h @@ -0,0 +1,22 @@ +#ifndef _SF_BASE64_H_ +#define _SF_BASE64_H_ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int sf_base64_decode(const char * base64, char * bindata); + +char * sf_base64_encode(const char * bindata, char * base64, int binlength, int model); + +int URLEncode(const char* str, const int strSize, char* result, const int resultSize); + +#ifdef __cplusplus +#if __cplusplus + } +#endif +#endif + +#endif + diff --git a/code/application/sifarsdk/component/base64/src/sf_base64.c b/code/application/sifarsdk/component/base64/src/sf_base64.c new file mode 100644 index 000000000..a45dd6830 --- /dev/null +++ b/code/application/sifarsdk/component/base64/src/sf_base64.c @@ -0,0 +1,145 @@ + +#include +#include +#include + +#include "SfTypeDefine.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +static const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +int sf_base64_decode(const char * base64, char * bindata) +{ + int i, j; + U8 k; + U8 temp[4]; + for (i = 0, j = 0; base64[i] != '\0'; i += 4) + { + memset(temp, 0xFF, sizeof(temp)); + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i]) + temp[0] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 1]) + temp[1] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 2]) + temp[2] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 3]) + temp[3] = k; + } + + bindata[j++] = ((U8)(((U8)(temp[0] << 2)) & 0xFC)) | + ((U8)((U8)(temp[1] >> 4) & 0x03)); + if (base64[i + 2] == '=') + break; + + bindata[j++] = ((U8)(((U8)(temp[1] << 4)) & 0xF0)) | + ((U8)((U8)(temp[2] >> 2) & 0x0F)); + if (base64[i + 3] == '=') + break; + + bindata[j++] = ((U8)(((U8)(temp[2] << 6)) & 0xF0)) | + ((U8)(temp[3] & 0x3F)); + } + return j; +} + +char * sf_base64_encode(const char * bindata, char * base64, int binlength, int model) +{ + int i, j; + unsigned char current; + + for (i = 0, j = 0; i < binlength; i += 3) + { + current = (bindata[i] >> 2); + current &= (unsigned char)0x3F; + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i] << 4)) & ((unsigned char)0x30); + if (i + 1 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 1] >> 4)) & ((unsigned char)0x0F); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i + 1] << 2)) & ((unsigned char)0x3C); + if (i + 2 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 2] >> 6)) & ((unsigned char)0x03); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)bindata[i + 2]) & ((unsigned char)0x3F); + base64[j++] = base64char[(int)current]; + } + if(model) + { + base64[j++] = '\n'; + } + base64[j] = '\0'; + return base64; +} +int URLEncode(const char* str, const int strSize, char* result, const int resultSize) +{ + int i; + int j = 0;//for result index + char ch; + + if ((str == 0) || (result == 0) || (strSize <= 0) || (resultSize <= 0)) { + return 0; + } + + for (i = 0; (i= 'A') && (ch<='Z')) || + ((ch >= 'a') && (ch<='z')) || + ((ch >= '0') && (ch<='9'))) { + result[j++] = ch; + } + else if (ch == ' ') { + result[j++] = '+'; + } + else if (ch == '.' || ch == '-' || ch == '_' || ch == '*') { + result[j++] = ch; + } + else { + if (j + 3 < resultSize) { + sprintf(result + j, "%%%02X", (unsigned char)ch); + j += 3; + } + else { + return 0; + } + } + } + + result[j] = '\0'; + return j; +} + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/sifarsdk/component/cJSON/CMakeLists.txt b/code/application/sifarsdk/component/cJSON/CMakeLists.txt new file mode 100644 index 000000000..2bda4f82f --- /dev/null +++ b/code/application/sifarsdk/component/cJSON/CMakeLists.txt @@ -0,0 +1,21 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME cJSON) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) \ No newline at end of file diff --git a/code/application/sifarsdk/component/cJSON/include/cJSON.h b/code/application/sifarsdk/component/cJSON/include/cJSON.h new file mode 100644 index 000000000..ae4e60131 --- /dev/null +++ b/code/application/sifarsdk/component/cJSON/include/cJSON.h @@ -0,0 +1,276 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h +#include "SfTypeDefine.h" +#ifdef __cplusplus +extern "C" +{ +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 1 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + SINT32 valueSINT32; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type __stdcall +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall +#endif +#else /* !WIN32 */ +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check if the item is a string and return its valuestring */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(SINT32 num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/arrray that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateSINT32Array(const SINT32 *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + + +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const SINT32 number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valueSINT32 too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valueSINT32 = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(SINT32) cJSON_SetNumberHelper(cJSON *object, SINT32 number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (SINT32)number) : (number)) + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/component/cJSON/src/cJSON.c b/code/application/sifarsdk/component/cJSON/src/cJSON.c new file mode 100644 index 000000000..93571fa1b --- /dev/null +++ b/code/application/sifarsdk/component/cJSON/src/cJSON.c @@ -0,0 +1,2952 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef ENABLE_LOCALES +#include +#endif + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#define true ((cJSON_bool)1) +#define false ((cJSON_bool)0) + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { + if (!cJSON_IsString(item)) { + return NULL; + } + + return item->valuestring; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 1) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(*allocate)(size_t size); + void (*deallocate)(void *pointer); + void *(*reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ +static void *internal_malloc(size_t size) +{ + return malloc(size); +} +static void internal_free(void *pointer) +{ + free(pointer); +} +static void *internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + SINT32 number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + return false; /* parse_error */ + } + + item->valueSINT32 = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or SINT32 */ +CJSON_PUBLIC(SINT32) cJSON_SetNumberHelper(cJSON *object, SINT32 number) +{ + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } + + return object->valueSINT32 = number; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + if (newbuffer) + { + memcpy(newbuffer, p->buffer, p->offset + 1); + } + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + SINT32 d = item->valueSINT32; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26]; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + SINT32 test; + + if (output_buffer == NULL) + { + return false; + } + //printf("Json->num = %d\n", d); + /* This checks for NaN and Infinity */ + if ((d * 0) != 0) + { + length = sprintf((char*)number_buffer, "null"); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%d", d); + //printf("d length=%d\n",length); + //printf("json->numStr = _%s_\n", number_buffer); + #if 1 + /* Check whether the original SINT32 can be recovered */ + if ((sscanf((char*)number_buffer, "%d", &test) != 1) || ((SINT32)test != d)) + { + /* If not, print with 17 decimal places of precision */ + // printf("number_buffer error \n"); + length = sprintf((char*)number_buffer, "%d", d); + } + #endif + } + //printf("json->numStr = _%s_\n", number_buffer); + /* sprintf failed or buffer overrun occured */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = strlen((const char*)value) + sizeof(""); + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +#define cjson_min(a, b) ((a < b) ? a : b) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + buffer->buffer = NULL; + if (printed == NULL) { + goto fail; + } + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + } + + if (printed != NULL) + { + hooks->deallocate(printed); + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((len < 0) || (buf == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buf; + p.length = (size_t)len; + p.offset = 0; + p.noalloc = true; + p.format = fmt; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + if (!output_buffer->noalloc) + { + output_buffer->hooks.deallocate(output_buffer->buffer); + } + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { + goto fail; /* faile to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL)) + { + return false; + } + + child = array->child; + + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + } + else + { + /* append to the end */ + while (child->next) + { + child = child->next; + } + suffix_object(child, item); + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + if ((object == NULL) || (string == NULL) || (item == NULL)) + { + return false; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + if (constant_key) + { + item->string = (char*)cast_away_const(string); + item->type |= cJSON_StringIsConst; + } + else + { + //printf("string = %s,", string); + char *key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (key == NULL) + { + return false; + } + + item->string = key; + item->type &= ~cJSON_StringIsConst; + } + //printf("item num = %d\n", item->valueSINT32); + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return; + } + + add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return; + } + + add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const SINT32 number) +{ + + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + //printf("item add to object fail!\n"); + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL)) + { + return NULL; + } + + if (item->prev != NULL) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0) + { + return; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + add_item_to_array(array, newitem); + return; + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (parent->child == item) + { + parent->child = replacement; + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return; + } + + cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + replacement->type &= ~cJSON_StringIsConst; + + cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = b ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(SINT32 num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valueSINT32 = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((SINT32)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateSINT32Array(const SINT32 *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0;a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valueSINT32 = item->valueSINT32; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + unsigned char *into = (unsigned char*)json; + + if (json == NULL) + { + return; + } + + while (*json) + { + if (*json == ' ') + { + json++; + } + else if (*json == '\t') + { + /* Whitespace characters. */ + json++; + } + else if (*json == '\r') + { + json++; + } + else if (*json=='\n') + { + json++; + } + else if ((*json == '/') && (json[1] == '/')) + { + /* SINT32-slash comments, to end of line. */ + while (*json && (*json != '\n')) + { + json++; + } + } + else if ((*json == '/') && (json[1] == '*')) + { + /* multiline comments. */ + while (*json && !((*json == '*') && (json[1] == '/'))) + { + json++; + } + json += 2; + } + else if (*json == '\"') + { + /* string literals, which are \" sensitive. */ + *into++ = (unsigned char)*json++; + while (*json && (*json != '\"')) + { + if (*json == '\\') + { + *into++ = (unsigned char)*json++; + } + *into++ = (unsigned char)*json++; + } + *into++ = (unsigned char)*json++; + } + else + { + /* All other characters. */ + *into++ = (unsigned char)*json++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) + { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) + { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (a->type & 0xFF) + { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (a->valueSINT32 == b->valueSINT32) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); +} + +#ifdef __cplusplus +#if __cplusplus + } +#endif +#endif + diff --git a/code/application/sifarsdk/component/utils/CMakeLists.txt b/code/application/sifarsdk/component/utils/CMakeLists.txt new file mode 100644 index 000000000..cb7cae62b --- /dev/null +++ b/code/application/sifarsdk/component/utils/CMakeLists.txt @@ -0,0 +1,21 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${COMPONENT_SOURCE_PATH}/Common/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME utils) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) \ No newline at end of file diff --git a/code/application/sifarsdk/component/utils/include/linux_api.h b/code/application/sifarsdk/component/utils/include/linux_api.h new file mode 100755 index 000000000..31c9ade64 --- /dev/null +++ b/code/application/sifarsdk/component/utils/include/linux_api.h @@ -0,0 +1,22 @@ +#ifndef LINUX_API_H +#define LINUX_API_H +#include "SfTypeDefine.h" +#include +#include +#ifdef __cplusplus +extern "C" +{ +#endif + int fprintf_gpio(FILE *stream, const U32 pinNum); + int fprintf_dir(FILE *stream, const char *dir); + int linux_open(const char *pathname, int flags); + int linux_close(int fd); + int linux_fclose(FILE *stream); + size_t linux_fread(void *ptr, size_t size, size_t nmemb, FILE *stream); + int linux_fcntl(int fd, int cmd, int flag); + ssize_t linux_write(int fd, const void *buf, size_t count); + ssize_t linux_read(int fd, void *buf, size_t count); +#ifdef __cplusplus +} +#endif +#endif // !LINUX_API_H \ No newline at end of file diff --git a/code/application/sifarsdk/component/utils/include/mbedtls.h b/code/application/sifarsdk/component/utils/include/mbedtls.h new file mode 100644 index 000000000..8970d22d5 --- /dev/null +++ b/code/application/sifarsdk/component/utils/include/mbedtls.h @@ -0,0 +1,25923 @@ +/* + * MbedTLS Source Code Library Header + */ +#if 1//ME_COM_MBEDTLS +/* +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#endif +*/ +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_PLATFORM_EXIT_ALT +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define MBEDTLS_PLATFORM_PRINTF_ALT +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_MODE_CTR +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#define MBEDTLS_CIPHER_PADDING_PKCS7 +//#define MBEDTLS_CIPHER_PADDING_PKCS5 +#define MBEDTLS_AES_ROM_TABLES +#if 0 //modified by ljy 20220330 +/********* Start of file include/mbedtls/config.h ************/ + +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/mbedtls/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h and time(), gmtime() and the clock is correct. + * The time needs to be correct (not necesarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + */ +#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_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. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + */ +//#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 +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#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_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \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. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * 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 + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +#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/rsa_internal.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. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#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. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#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 up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#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 + * library/rsa_internal.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. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #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 + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#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 + + + +#endif /* MBEDTLS_CONFIG_H */ + + + + +#endif //lijiayong + + +/********* Start of file include/mbedtls/check_config.h ************/ + +/** + * \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_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ + !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) +#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ + + +/********* Start of file include/mbedtls/platform.h ************/ + +/** + * \file platform.h + * + * \brief The Mbed TLS platform abstraction layer. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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) + +#else + +#endif + +#if defined(MBEDTLS_HAVE_TIME) + +#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 /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The 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 This function allows configuring custom memory-management functions. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +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 This function allows configuring a custom \p fprintf function pointer. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 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 This function allows configuring a custom \c printf function + * pointer. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +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 This function allows configuring a custom \c snprintf function + * pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +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 This function allows configuring a custom \c exit function + * pointer. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +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 This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct { + char dummy; /**< Placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else + +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform initialization operations. + * + * \param ctx The Mbed TLS context. + * + * \return \c 0 on success. + * + * \note This function is intended to allow platform-specific initialization, + * and should be called before any other library functions. Its + * implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * Its use and whether it is necessary to call it is dependent on the + * platform. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \param ctx The Mbed TLS context. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * Its use and whether it is necessary to call it is dependent on the + * platform. + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ + + +/********* Start of file include/mbedtls/platform_time.h ************/ + +/** + * \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) + +#else + +#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 */ + + +/********* Start of file include/mbedtls/threading.h ************/ + +/** + * \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) + +#else + +#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 */ + + +/** + * \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 */ + + +/********* Start of file include/mbedtls/bignum.h ************/ + +/** + * \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) + +#else + +#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 temporarily result 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 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize one MPI (make internal references valid) + * This just makes it ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X One MPI to initialize. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: keep X's original value + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_copy( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mbedtls_mpi value + * \param Y Second mbedtls_mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param buf Buffer to write the string to + * \param buflen Length of buf + * \param olen Length of the string written, including final NUL byte + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with buflen = 0 to obtain the + * minimum required buffer size in *olen. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read MPI from a line in an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * MBEDTLS_ERR_MPI_XXX error code + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix 16. + * + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Unsigned subtraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed subtraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Signed subtraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The unsigned integer value to multiply with + * + * \note b is unsigned + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); + +/** + * \brief Division by mbedtls_mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination mbedtls_mpi_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or + * if E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * + * \note The bytes obtained from the PRNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1, + MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits + * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \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 */ + + +/********* Start of file include/mbedtls/net.h ************/ + +/** + * \file net.h + * + * \brief Deprecated header file that includes mbedtls/net_sockets.h + * + * \deprecated Superseded by 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) + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +/********* Start of file include/mbedtls/net_sockets.h ************/ + +/** + * \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) + +#else + +#endif + + + +#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 */ + + +/********* Start of file include/mbedtls/dhm.h ************/ + +/** + * \file dhm.h + * + * \brief Diffie-Hellman-Merkle key exchange. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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 + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/* + * DHM Error codes + */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters. */ +#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 or write of file failed. */ +#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The DHM context structure. + */ +typedef struct +{ + size_t len; /*!< The size of \p P in Bytes. */ + mbedtls_mpi P; /*!< The prime modulus. */ + mbedtls_mpi G; /*!< The generator. */ + mbedtls_mpi X; /*!< Our secret value. */ + mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi Vi; /*!< The blinding value. */ + mbedtls_mpi Vf; /*!< The unblinding value. */ + mbedtls_mpi pX; /*!< The previous \c X. */ +} +mbedtls_dhm_context; + +/** + * \brief This function initializes the DHM context. + * + * \param ctx The DHM context to initialize. + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief This function parses the ServerKeyExchange parameters. + * + * \param ctx The DHM context. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief This function sets up and writes the ServerKeyExchange + * parameters. + * + * \param ctx The DHM context. + * \param x_size The private value size in Bytes. + * \param olen The number of characters written. + * \param output The destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The destination buffer must be large enough to hold + * the reduced binary presentation of the modulus, the generator + * and the public key, each wrapped with a 2-byte length field. + * It is the responsibility of the caller to ensure that enough + * space is available. Refer to \c mbedtls_mpi_size to computing + * the byte-size of an MPI. + * + * \note This function assumes that \c ctx->P and \c ctx->G + * have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +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 Set prime modulus and generator + * + * \param ctx The DHM context. + * \param P The MPI holding DHM prime modulus. + * \param G The MPI holding DHM generator. + * + * \note This function can be used to set P, G + * in preparation for \c mbedtls_dhm_make_params. + * + * \return \c 0 if successful, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the public value G^Y of the peer. + * + * \param ctx The DHM context. + * \param input The input buffer. + * \param ilen The size of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function creates its own private value \c X and + * exports \c G^X. + * + * \param ctx The DHM context. + * \param x_size The private value size in Bytes. + * \param output The destination buffer. + * \param olen The length of the destination buffer. Must be at least + equal to ctx->len (the size of \c P). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The destination buffer will always be fully written + * so as to contain a big-endian presentation of G^X mod P. + * If it is larger than ctx->len, it will accordingly be + * padded with zero-bytes in the beginning. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +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 This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. + * + * \param ctx The DHM context. + * \param output The destination buffer. + * \param output_size The size of the destination buffer. Must be at least + * the size of ctx->len. + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function, for blinding purposes. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + * + * \note If non-NULL, \p f_rng is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our secret value \p X is re-used and omitted + * otherwise. Therefore, we recommend always passing a + * non-NULL \p 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 This function frees and clears the components of a DHM key. + * + * \param ctx The DHM context to free and clear. + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** \ingroup x509_module */ +/** + * \brief This function parses DHM parameters in PEM or DER format. + * + * \param dhm The DHM context to initialize. + * \param dhmin The input buffer. + * \param dhminlen The size of the buffer, including the terminating null + * Byte for PEM data. + * + * \return \c 0 on success, or a specific DHM or PEM error code + * on failure. + */ +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 This function loads and parses DHM parameters from a file. + * + * \param dhm The DHM context to load the parameters to. + * \param path The filename to read the DHM parameters from. + * + * \return \c 0 on success, or a specific DHM or PEM error code + * on failure. + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_DHM_ALT */ + +#endif /* MBEDTLS_DHM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The DMH checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_dhm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_constant_t) ( VAL ) ) +#else +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#endif /* ! MBEDTLS_DEPRECATED_WARNING */ + +/** + * \warning The origin of the primes in RFC 5114 is not documented and + * their use therefore constitutes a security risk! + * + * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are + * likely to be removed in a future version of the library without + * replacement. + */ + +/** + * The hexadecimal presentation of the prime underlying the + * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined + * in RFC-5114: Additional Diffie-Hellman Groups for Use with + * IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: + * Additional Diffie-Hellman Groups for Use with IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ + "81BC087F2A7065B384B890D3191F2BFA" ) + +/** + * The hexadecimal presentation of the prime underlying the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + * + * \deprecated The hex-encoded primes from RFC 3625 are deprecated and + * superseded by the corresponding macros providing them as + * binary constants. Their hex-encoded constants are likely + * to be removed in a future version of the library. + * + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 3072-bit MODP + * Group, as defined in RFC-3072: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 3072-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + +#endif /* dhm.h */ + + +/********* Start of file include/mbedtls/error.h ************/ + +/** + * \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 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * THREADING 3 0x001A-0x001E + * AES 4 0x0020-0x0022 0x0023-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 11 0x0042-0x0052 0x0043-0x0045 + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 + * SHA256 1 0x0037-0x0037 + * SHA512 1 0x0039-0x0039 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 9 (Started from top) + * MD 5 5 + * CIPHER 6 8 + * 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 */ + + +/********* Start of file include/mbedtls/md.h ************/ + + /** + * \file md.h + * + * \brief The generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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 + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#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. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Enumeration of supported message digests + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +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; + +/** + * The generic message-digest context. + */ +typedef struct { + /** Information about the associated message digest. */ + const mbedtls_md_info_t *md_info; + + /** The digest-specific context. */ + void *md_ctx; + + /** The HMAC part of the context. */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name, + * or NULL if not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type, + * or NULL if not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +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 This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It 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 The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \returns \c 0 on success, + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, + * #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 This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac
  • 0: HMAC is not used. Saves some memory.
  • + *
  • non-zero: HMAC is used with this context.
+ * + * \returns \c 0 on success, + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, or + * #MBEDTLS_ERR_MD_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success, + * #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 This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \returns \c 0 on success, #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \returns \c 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 This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \returns \c 0 on success, or #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 This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, or + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p 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 This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \returns \c 0 on success, or #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 This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \returns \c 0 on success, or #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 This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \returns \c 0 on success, or #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 */ + + +/********* Start of file include/mbedtls/md_internal.h ************/ + +/** + * \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) + +#else + +#endif + + + +#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 */ + int (*starts_func)( void *ctx ); + + /** Digest update function */ + int (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + int (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + int (*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 */ + int (*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 */ + + +/********* Start of file include/mbedtls/md5.h ************/ + +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests 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) + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +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 + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +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 + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret( 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 + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD5_ALT */ + +#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 + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ + + +/********* Start of file include/mbedtls/md2.h ************/ + +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * 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) + * + */ +#ifndef MBEDTLS_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD2 context structure + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +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 + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_init( mbedtls_md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +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 + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_starts_ret( 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 + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \param ctx MD2 context + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD2 context setup + * + * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 + * + * \param ctx MD2 context + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD2_ALT */ + +#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 + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD2( input buffer ) + * + * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md2.h */ + + +/********* Start of file include/mbedtls/md4.h ************/ + +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * 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) + * + */ +#ifndef MBEDTLS_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context structure + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +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 + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_init( mbedtls_md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +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 + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + */ +int mbedtls_md4_starts_ret( 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 + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD4 context setup + * + * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD4_ALT */ + +#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 + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD4( input buffer ) + * + * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md4.h */ + + +/********* Start of file include/mbedtls/rsa.h ************/ + +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem. + * + * For more information, see Public-Key Cryptography Standards (PKCS) + * #1 v1.5: RSA Encryption and Public-Key Cryptography Standards + * (PKCS) #1 v2.1: RSA Cryptography Specifications. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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) + +#else + +#endif + + + + +#if defined(MBEDTLS_THREADING_C) + +#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 validity check of the library. */ +#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. */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS-1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS-1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#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_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. + */ +typedef struct +{ + int ver; /*!< Always 0.*/ + size_t len; /*!< The size of \p N in Bytes. */ + + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ + + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ + + mbedtls_mpi DP; /*!< \p D % (P - 1) */ + mbedtls_mpi DQ; /*!< \p D % (Q - 1) */ + mbedtls_mpi QP; /*!< 1 / (Q % P) */ + + mbedtls_mpi RN; /*!< cached R^2 mod \p N */ + + mbedtls_mpi RP; /*!< cached R^2 mod \p P */ + mbedtls_mpi RQ; /*!< cached R^2 mod \p Q */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +/** + * \brief This function initializes 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 The RSA context to initialize. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of #mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The 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 is + * a default value, which can be overriden by calling specific + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overriden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overriden. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param P The first prime factor of \p N, or NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param D The private exponent, or NULL. + * \param E The public exponent, or NULL. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \return \c 0 on success, or a non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param N_len The Byte length of \p N, ignored if \p N == NULL. + * \param P The first prime factor of \p N, or NULL. + * \param P_len The Byte length of \p P, ignored if \p P == NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL. + * \param D The private exponent, or NULL. + * \param D_len The Byte length of \p D, ignored if \p D == NULL. + * \param E The public exponent, or NULL. + * \param E_len The Byte length of \p E, ignored if \p E == NULL. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \return \c 0 on success, or a non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success, or #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the + * attempted derivations failed. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus, or NULL. + * \param P The MPI to hold the first prime factor of \p N, or NULL. + * \param Q The MPI to hold the second prime factor of \p N, or NULL. + * \param D The MPI to hold the private exponent, or NULL. + * \param E The MPI to hold the public exponent, or NULL. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies, + * or a non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, or NULL. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, or + * NULL. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, or + NULL. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, or NULL. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, or NULL. + * \param E_len The size of the buffer for the public exponent. + * + * \note The length fields are ignored if the corresponding + * buffer pointers are NULL. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies, + * or a non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold D modulo P-1, or NULL. + * \param DQ The MPI to hold D modulo Q-1, or NULL. + * \param QP The MPI to hold modular inverse of Q modulo P, or NULL. + * + * \return \c 0 on success, non-zero error code otherwise. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The RSA context to be set. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \param ctx The RSA context used to hold the key. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent. For example, 65537. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + on failure. + */ +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 This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The RSA context to check. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \param ctx The RSA context to check. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code on + * failure. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The RSA context holding the public key. + * \param prv The RSA context holding the private key. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The RSA context. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \note The input and output buffers must be large + * enough. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for blinding. + * \param p_rng The RNG parameter. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The input and output buffers must be large + * enough. For example, 128 Bytes if RSA-1024 is used. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + */ +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 This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. + * + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1 + * encoding, and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The input and output buffers must be as large as the size + * of \p ctx->N. For example, 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 This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer must be as large as the size + * of \p ctx->N. For example, 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 This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1 + * encoding and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param label The buffer holding the custom label to use. + * \param label_len The length of the label. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 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 This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer used to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param label The buffer holding the custom label to use. + * \param label_len The length of the label. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p 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 This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 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 This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications 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 This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p 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 This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 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 This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in the RSA context. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p 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 This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in \p mgf1_hash_id. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the ciphertext. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p 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 This function copies the components of an RSA context. + * + * \param dst The destination context. + * \param src The source context. + * + * \return \c 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 This function frees the components of an RSA key. + * + * \param ctx The RSA Context to free. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_RSA_ALT */ + +#endif /* MBEDTLS_RSA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ + + +/********* Start of file include/mbedtls/rsa_internal.h ************/ + +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + */ +/* + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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 file declares some RSA-related helper functions useful when + * implementing the RSA interface. They are public and provided in a + * separate compilation unit in order to make it easy for designers of + * alternative RSA implementations to use them in their code, as it is + * conceived that the functionality they provide will be necessary + * for most complete implementations. + * + * End-users of Mbed TLS not intending to re-implement the RSA functionality + * are not expected to get into the need of making use of these functions directly, + * but instead should be able to use the functions declared in rsa.h. + * + * There are two classes of helper functions: + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters + * and generates some other, or CRT related parameters. + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters + * and check their validity. + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); +#ifdef __cplusplus +} +#endif + + +#endif /* rsa_internal.h */ + + +/********* Start of file include/mbedtls/asn1.h ************/ + +/** + * \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) + +#else + +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) + +#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 the DER encoded ASN.1 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 + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} 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 */ + + +/********* Start of file include/mbedtls/ecp.h ************/ + +/** + * \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 + + + +/* + * 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. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< ECP hardware accelerator failed. */ + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain parameters (curve, subgroup and generator) identifiers. + * + * Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only well-known domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, + MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ + MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ + MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ + MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ + MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ + MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ + MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ +} mbedtls_ecp_group_id; + +/** + * Number of supported curves (plus one for NONE). + * + * (Montgomery curves excluded for now.) + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/** + * Curve information for use by other modules + */ +typedef struct +{ + mbedtls_ecp_group_id grp_id; /*!< Internal identifier */ + uint16_t tls_id; /*!< TLS NamedCurve identifier */ + uint16_t bit_size; /*!< Curve size in bits */ + const char *name; /*!< Human-friendly name */ +} mbedtls_ecp_curve_info; + +/** + * \brief ECP point structure (jacobian coordinates) + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or Z == 1. (Other + * values of Z are used by internal functions only.) + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, X and Y are its standard (affine) coordinates. + */ +typedef struct +{ + mbedtls_mpi X; /*!< the point's X coordinate */ + mbedtls_mpi Y; /*!< the point's Y coordinate */ + mbedtls_mpi Z; /*!< the point's Z coordinate */ +} +mbedtls_ecp_point; + +/** + * \brief ECP group structure + * + * We consider two types of curves equations: + * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) + * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) + * In both cases, a generator G for a prime-order subgroup is fixed. In the + * short weierstrass, this subgroup is actually the whole curve, and its + * cardinal is denoted by N. + * + * In the case of Short Weierstrass curves, our code requires that N is an odd + * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.) + * + * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is + * the quantity actually used in the formulas. Also, nbits is not the size of N + * but the required size for private keys. + * + * If modp is NULL, reduction modulo P is done using a generic algorithm. + * Otherwise, it must point to a function that takes an mbedtls_mpi in the range + * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more + * than pbits, so that the integer may be efficiently brought in the 0..P-1 + * range by a few additions or substractions. It must return 0 on success and + * non-zero on failure. + */ +typedef struct +{ + mbedtls_ecp_group_id id; /*!< internal group identifier */ + mbedtls_mpi P; /*!< prime modulus of the base field */ + mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ + mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */ + mbedtls_ecp_point G; /*!< generator of the (sub)group used */ + mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */ + size_t pbits; /*!< number of bits in P */ + size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ + unsigned int h; /*!< internal: 1 if the constants are static */ + int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */ + void *t_data; /*!< unused */ + mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ + size_t T_size; /*!< number for pre-computed points */ +} +mbedtls_ecp_group; + +/** + * \brief ECP key pair structure + * + * A generic key pair that could be used for ECDSA, fixed ECDH, etc. + * + * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. + */ +typedef struct +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_MAX_BITS) +/** + * Maximum size of the groups (that is, of N and P) + */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ + +/** + * \brief Get the list of supported curves in order of preferrence + * (full information) + * + * \return A statically allocated array, the last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief Get the list of supported curves in order of preferrence + * (grp_id only) + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief Get curve information from an internal group identifier + * + * \param grp_id A MBEDTLS_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief Get curve information from a TLS NamedCurve value + * + * \param tls_id A MBEDTLS_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief Get curve information from a human-readable name + * + * \param name The name + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief Initialize a point (as zero) + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief Initialize a group (to something meaningless) + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief Initialize a key pair (as an invalid one) + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief Free the components of a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief Free the components of an ECP group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief Free the components of a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +/** + * \brief Copy the contents of point Q into P + * + * \param P Destination point + * \param Q Source point + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief Copy the contents of a group object + * + * \param dst Destination group + * \param src Source group + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); + +/** + * \brief Set a point to zero + * + * \param pt Destination point + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief Tell if a point is zero + * + * \param pt Point to test + * + * \return 1 if point is zero, 0 otherwise + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief Compare two points + * + * \note This assumes the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P First point to compare + * \param Q Second point to compare + * + * \return 0 if the points are equal, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief Import a non-zero point from two ASCII strings + * + * \param P Destination point + * \param radix Input numeric base + * \param x First affine coordinate as a null-terminated string + * \param y Second affine coordinate as a null-terminated string + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief Export a point into unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to export + * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro + * \param olen Length of the actual output + * \param buf Output buffer + * \param buflen Length of the output buffer + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief Import a point from unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to import + * \param buf Input buffer + * \param ilen Actual length of input + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * is not implemented. + * + * \note This function does NOT check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() for + * that. + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief Import a point from a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Destination point + * \param buf $(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after the ECPoint on exit + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief Export a point as a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Point to export + * \param format Export format + * \param olen length of data written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Set a group using well-known domain parameters + * + * \param grp Destination group + * \param id Index in the list of well-known domain parameters + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups + * + * \note Index should be a value of RFC 4492's enum NamedCurve, + * usually in the form of a MBEDTLS_ECP_DP_XXX macro. + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief Set a group from a TLS ECParameters record + * + * \param grp Destination group + * \param buf &(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after ECParameters on exit + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); + +/** + * \brief Write the TLS ECParameters record for a group + * + * \param grp ECP group used + * \param olen Number of bytes actually written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Multiplication by an integer: R = m * P + * (Not thread-safe to use same group in multiple threads) + * + * \note In order to prevent timing attacks, this function + * executes the exact same sequence of (base field) + * operations for any valid m. It avoids any if-branch or + * array index depending on the value of m. + * + * \note If f_rng is not NULL, it is used to randomize intermediate + * results in order to prevent potential timing attacks + * targeting these results. It is recommended to always + * provide a non-NULL f_rng (the overhead is negligible). + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply + * \param P Point to multiply + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey + * or P is not a valid pubkey, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Multiplication and addition of two points by integers: + * R = m * P + n * Q + * (Not thread-safe to use same group in multiple threads) + * + * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee + * a constant execution flow and timing. + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply P + * \param P Point to multiply by m + * \param n Integer by which to multiply Q + * \param Q Point to be multiplied by n + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey + * or P or Q is not a valid pubkey, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief Check that a point is a valid public key on this curve + * + * \param grp Curve/group the point should belong to + * \param pt Point to check + * + * \return 0 if point is a valid public key, + * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * + * \note This function only checks the point is non-zero, has valid + * coordinates and lies on the curve, but not that it is + * indeed a multiple of G. This is additional check is more + * expensive, isn't required by standards, and shouldn't be + * necessary if the group used has a small cofactor. In + * particular, it is useless for the NIST groups which all + * have a cofactor of 1. + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); + +/** + * \brief Check that an mbedtls_mpi is a valid private key for this curve + * + * \param grp Group used + * \param d Integer to check + * + * \return 0 if point is a valid private key, + * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); + +/** + * \brief Generate a keypair with configurable base point + * + * \param grp ECP group + * \param G Chosen base point + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Generate a keypair + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Generate a keypair + * + * \param grp_id ECP group identifier + * \param key Destination keypair + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check a public-private key pair + * + * \param pub Keypair structure holding a public key + * \param prv Keypair structure holding a private (plus public) key + * + * \return 0 if successful (keys are valid and match), or + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or + * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code. + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_ALT */ + +#endif /* ecp.h */ + + +/********* Start of file include/mbedtls/ecdsa.h ************/ + +/** + * \file ecdsa.h + * + * \brief The Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * ECDSA is defined in Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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 + + + + +/* + * 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 +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) + +/** + * \brief The ECDSA context structure. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version is usually preferred. + * + * \param grp The ECP group. + * \param r The first output integer. + * \param s The second output integer. + * \param d The private signing key. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + */ +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 This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \param grp The ECP group. + * \param r The first output integer. + * \param s The second output integer. + * \param d The private signing key. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param md_alg The MD algorithm used to hash the message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + * + * \see ecp.h + */ +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 This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \param grp The ECP group. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param Q The public key to use for verification. + * \param r The first integer of the signature. + * \param s The second integer of the signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + * + * \see ecp.h + */ +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 This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \param ctx The ECDSA context. + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The \p sig buffer must be at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + * + * \see ecp.h + */ +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 This function computes an ECDSA signature and writes it to a buffer, + * serialized as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS). + * + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) and + * Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in 2.0.0 + * + * \param ctx The ECDSA context. + * \param hash The Message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param md_alg The MD algorithm used to hash the message. + * + * \note The \p sig buffer must be at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if a + * 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + * + * \see ecp.h + */ +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 This function reads and verifies an ECDSA signature. + * + * \param ctx The ECDSA context. + * \param hash The message hash. + * \param hlen The size of the hash. + * \param sig The signature to read and verify. + * \param slen The size of \p sig. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \return \c 0 on success, + * #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 \p siglen, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + * + * \see ecp.h + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \param ctx The ECDSA context to store the keypair in. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX code on + * failure. + * + * \see ecp.h + */ +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 This function sets an ECDSA context from an EC key pair. + * + * \param ctx The ECDSA context to set. + * \param key The EC key to use. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX code on + * failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ + + +/********* Start of file include/mbedtls/ecjpake.h ************/ + +/** + * \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. + */ + + + + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +#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 ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ECJPAKE_ALT */ + +#endif /* MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* ecjpake.h */ + + +/********* Start of file include/mbedtls/pk.h ************/ + +/** + * \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) + +#else + +#endif + + + +#if defined(MBEDTLS_RSA_C) + +#endif + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#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. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ + +#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 */ + + +/********* Start of file include/mbedtls/pk_internal.h ************/ + +/** + * \file pk_internal.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) + +#else + +#endif + + + +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 */ + + +/********* Start of file include/mbedtls/x509.h ************/ + +/** + * \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) + +#else + +#endif + + + + +#if defined(MBEDTLS_RSA_C) + +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) + +#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param to mbedtls_x509_time to check + * + * \return 1 if the given time is in the past or an error occured, + * 0 otherwise. + */ +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param from mbedtls_x509_time to check + * + * \return 1 if the given time is in the future or an error occured, + * 0 otherwise. + */ +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_x509_self_test( int verbose ); + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ); +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ); +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ); +#endif +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ); +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t ); +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ); +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ); +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ); +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#define MBEDTLS_X509_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ + + +/********* Start of file include/mbedtls/x509_crl.h ************/ + +/** + * \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) + +#else + +#endif + + + +#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 */ + + +/********* Start of file include/mbedtls/x509_crt.h ************/ + +/** + * \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) + +#else + +#endif + + + + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct mbedtls_x509_crt +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ +} +mbedtls_x509_crt; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +typedef struct +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs (see note above) + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 (and flags set to 0) if the chain was verified and valid, + * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified + * but found to be invalid, in which case *flags will have one + * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX + * flags set, or another error (and flags set to 0xffffffff) + * in case of a fatal error encountered during the + * verification process. + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Verify the certificate signature according to profile + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED + * in which case *flags will have one or more + * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags + * set, + * or another error in case of a fatal error encountered + * during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c mbedtls_x509_crt_verify(). + */ +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extendedKeyUsage. + * + * \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 */ + + +/********* Start of file include/mbedtls/x509_csr.h ************/ + +/** + * \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) + +#else + +#endif + + + +#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 */ + + +/********* Start of file include/mbedtls/cipher.h ************/ + +/** + * \file cipher.h + * + * \brief The generic cipher wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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) + +#else + +#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. */ +#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. For example, because it was freed. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ + +#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 + +/** + * \brief An enumeration of supported ciphers. + * + * \warning ARC4 and DES are considered weak ciphers and their use + * constitutes a security risk. We recommend considering stronger + * ciphers instead. + */ +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; + +/** + * \brief An enumeration of supported (cipher, mode) pairs. + * + * \warning ARC4 and DES are considered weak ciphers and their use + * constitutes a security risk. We recommend considering stronger + * ciphers instead. + */ +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; + +/** Supported cipher modes. */ +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; + +/** Supported cipher padding types. */ +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; + +/** Type of operation. */ +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 calling cipher functions + * in a generic way. + */ +typedef struct { + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t type; + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t mode; + + /** The cipher key length, in bits. This is the + * 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 or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int iv_size; + + /** Flags to set. For example, if the cipher supports variable IV sizes or variable key sizes. */ + int flags; + + /** The block size, in Bytes. */ + unsigned int block_size; + + /** Struct for 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 key of the context has been + * initialized for. + */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific 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 input that has not been processed yet. */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + 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; + + /** The 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 This function retrieves the list of ciphers supported by the generic + * cipher module. + * + * \return A statically-allocated array of ciphers. The last entry + * is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves 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 \p cipher_name, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves 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 \p 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 This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id, 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 This function initializes a \p cipher_context as NONE. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + + +/** + * \brief This function initializes and fills the cipher-context + * structure with the appropriate values. It also clears + * the structure. + * + * \param ctx The context to initialize. May not be NULL. + * \param cipher_info The cipher to use. + * + * \return \c 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. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The size of the blocks of the cipher, or zero if \p ctx + * has not been initialized. + */ +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 This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The mode of operation, or #MBEDTLS_MODE_NONE if + * \p ctx has not been initialized. + */ +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 This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return
  • If no IV has been set: the recommended IV size. + * 0 for ciphers not using IV or nonce.
  • + *
  • If IV has already been set: the 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 This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The type of the cipher, or #MBEDTLS_CIPHER_NONE if + * \p ctx has not been initialized. + */ +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 This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The name of the cipher, or NULL if \p ctx has not + * been not initialized. + */ +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 This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The key length of the cipher in bits, or + * #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +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 This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or + * #MBEDTLS_DECRYPT, or #MBEDTLS_OPERATION_NONE if \p ctx + * has not been initialized. + */ +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 This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. May not be NULL. Must have + * been initialized using mbedtls_cipher_info_from_type() + * or mbedtls_cipher_info_from_string(). + * \param key The key to use. + * \param key_bitlen The key length to use, in bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \returns \c 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 This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. + * \param mode The padding mode. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the 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 This function sets the initialization vector (IV) + * or nonce. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * + * \note Some ciphers do not 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 This function resets the cipher state. + * + * \param ctx The generic cipher context. + * + * \returns \c 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 This function adds additional data for AEAD ciphers. + * Only supported with GCM. Must be called + * exactly once, after mbedtls_cipher_reset(). + * + * \param ctx The generic cipher context. + * \param ad The additional data to use. + * \param ad_len the Length of \p ad. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \param ctx The generic cipher context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. Must be able to hold at + * least \p ilen + block_size. Must not be the same buffer + * as input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * + * \returns \c 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 \p ilen as 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 The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. + * \param output The buffer to write data to. Needs block_size available. + * \param olen The length of the data written to the \p output buffer. + * + * \returns \c 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 + * on failure for any other reason. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. + * \param tag The buffer to write the tag to. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. Must be able to hold at + * least \p ilen + block_size. Must not be the same buffer + * as input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \returns \c 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 on + * failure for any other reason. + */ +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 The generic autenticated encryption (AEAD) function. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to authenticate. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * Must be able to hold at least \p ilen. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * \param tag The buffer for the authentication tag. + * \param tag_len The desired length of the authentication tag. + * + * \returns \c 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 The generic autenticated decryption (AEAD) function. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to be authenticated. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * Must be able to hold at least \p ilen. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * \param tag The buffer holding the authentication tag. + * \param tag_len The length of the authentication tag. + * + * \returns \c 0 on success, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic, + * or a cipher-specific error code on failure for any other reason. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, 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 */ + + +/********* Start of file include/mbedtls/cipher_internal.h ************/ + +/** + * \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) + +#else + +#endif + + + +#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 */ + + +/********* Start of file include/mbedtls/ssl_ciphersuites.h ************/ + +/** + * \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 + + + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 +#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 +#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A +#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#endif + +/* Key exchanges allowing client certificate requests */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED +#endif + +/* Key exchanges involving server signature in ServerKeyExchange */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED +#endif + +/* Key exchanges using ECDH */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED +#endif + +/* Key exchanges that don't involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED +#endif + +/* Key exchanges that involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED +#endif + +/* Key exchanges using a PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#endif + +/* Key exchanges using DHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED +#endif + +/* Key exchanges using ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#endif + +typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; + +#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ +#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct mbedtls_ssl_ciphersuite_t +{ + int id; + const char * name; + + mbedtls_cipher_type_t cipher; + mbedtls_md_type_t mac; + mbedtls_key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +const int *mbedtls_ssl_list_ciphersuites( void ); + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); +#endif + +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ + + +/********* Start of file include/mbedtls/ecdh.h ************/ + +/** + * \file ecdh.h + * + * \brief The Elliptic Curve Diffie-Hellman (ECDH) protocol APIs. + * + * ECDH is an anonymous key agreement protocol allowing two parties to + * establish a shared secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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 + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the source of the imported EC key: + *
  • Our key.
  • + *
  • The key of the peer.
+ */ +typedef enum +{ + MBEDTLS_ECDH_OURS, + MBEDTLS_ECDH_THEIRS, +} mbedtls_ecdh_side; + +/** + * \brief The ECDH context structure. + */ +typedef struct +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ + int point_format; /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point Vi; /*!< The blinding value. */ + mbedtls_ecp_point Vf; /*!< The unblinding value. */ + mbedtls_mpi _d; /*!< The previous \p d. */ +} +mbedtls_ecdh_context; + +/** + * \brief This function generates an ECDH keypair on an elliptic + * curve. + * + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). + * + * \param grp The ECP group. + * \param d The destination MPI (private key). + * \param Q The destination point (public key). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + */ +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 This function computes the shared secret. + * + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). + * + * \param grp The ECP group. + * \param z The destination MPI (shared secret). + * \param Q The public key from another party. + * \param d Our secret exponent (private key). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks. For more information, see mbedtls_ecp_mul(). + */ +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 This function initializes an ECDH context. + * + * \param ctx The ECDH context to initialize. + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function generates a public key and a TLS + * ServerKeyExchange payload. + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context. + * \param olen The number of characters written. + * \param buf The destination buffer. + * \param blen The length of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note This function assumes that the ECP group (grp) of the + * \p ctx context has already been properly set, + * for example, using mbedtls_ecp_group_load(). + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +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 This function parses and processes a TLS ServerKeyExhange + * payload. + * + * This is the first function used by a TLS client for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context. + * \param buf The pointer to the start of the input buffer. + * \param end The address for one Byte past the end of the buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ); + +/** + * \brief This function sets up an ECDH context from an EC key. + * + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \param ctx The ECDH context to set up. + * \param key The EC key to use. + * \param side Defines the source of the key: + *
  • 1: Our key.
  • +
  • 0: The key of the peer.
+ * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief This function generates a public key and a TLS + * ClientKeyExchange payload. + * + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. + * + * \param ctx The ECDH context. + * \param olen The number of Bytes written. + * \param buf The destination buffer. + * \param blen The size of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +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 This function parses and processes a TLS ClientKeyExchange + * payload. + * + * This is the second function used by a TLS server for ECDH(E) + * ciphersuites. + * + * \param ctx The ECDH context. + * \param buf The start of the input buffer. + * \param blen The length of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief This function derives and exports the shared secret. + * + * This is the last function used by both TLS client + * and servers. + * + * \param ctx The ECDH context. + * \param olen The number of Bytes written. + * \param buf The destination buffer. + * \param blen The length of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks. For more information, see mbedtls_ecp_mul(). + */ +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 */ + + +/********* Start of file include/mbedtls/sha1.h ************/ + +/** + * \file sha1.h + * + * \brief The SHA-1 cryptographic hash function. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +/** + * \brief This function initializes a SHA-1 context. + * + * \param ctx The SHA-1 context to initialize. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \param ctx The SHA-1 context to clear. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \param dst The destination context. + * \param src The context to clone. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \param ctx The context to initialize. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only) + * + * \param ctx SHA-1 context + * \param data The data block being processed. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief SHA-1 context setup + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0 + * + * \param ctx The SHA-1 context to be initialized. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param data The data block being processed. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA1_ALT */ + +#endif /* MBEDTLS_SHA1_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = SHA-1( input buffer ) + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief The SHA-1 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ + + +/********* Start of file include/mbedtls/sha256.h ************/ + +/** + * \file sha256.h + * + * \brief The SHA-224 and SHA-256 cryptographic hash function. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use. +
  • 0: Use SHA-256.
  • +
  • 1: Use SHA-224.
*/ +} +mbedtls_sha256_context; + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. + * \param src The context to clone. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to initialize. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return \c 0 on success. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. + * \param output The SHA-224 or SHA-256 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. + * \param data The buffer holding one block of data. + * + * \return \c 0 on success. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to initialize. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to initialize. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. + * \param output The SHA-224or SHA-256 checksum result. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. + * \param data The buffer holding one block of data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA256_ALT */ + +#endif /* MBEDTLS_SHA256_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-224 or SHA-256 checksum result. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The SHA-224 or SHA-256 checksum result. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ + + +/********* Start of file include/mbedtls/sha512.h ************/ + +/** + * \file sha512.h + * + * \brief The SHA-384 and SHA-512 cryptographic hash function. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). + */ +typedef struct +{ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ + int is384; /*!< Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
*/ +} +mbedtls_sha512_context; + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. + * \param src The context to clone. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to initialize. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. This function is for + * internal use only. + * + * \param ctx The SHA-512 context. + * \param output The SHA-384 or SHA-512 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * + * \param ctx The SHA-512 context. + * \param data The buffer holding one block of data. + * + * \return \c 0 on success. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to initialize. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param output The SHA-384 or SHA-512 checksum result. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param data The buffer holding one block of data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA512_ALT */ + +#endif /* MBEDTLS_SHA512_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-384 or SHA-512 checksum result. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The SHA-384 or SHA-512 checksum result. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ + + +/********* Start of file include/mbedtls/aes.h ************/ + +/** + * \file aes.h + * + * \brief The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + */ +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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) + +#else + +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0023-0x0025 */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The AES context-type definition. + */ +typedef struct +{ + 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. +
*/ +} +mbedtls_aes_context; + +/** + * \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. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * \param key The encryption key. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success or #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + * on failure. + */ +int mbedtls_aes_setkey_enc( mbedtls_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. + * \param key The decryption key. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success, or #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_dec( mbedtls_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. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_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. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + */ +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 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. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the AES block size of 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. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success, or #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +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 This function performs an AES-CFB128 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. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \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 must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +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 This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the 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 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. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +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 This function performs an AES-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must keep the maximum use of your counter in mind. + * + * \param ctx The AES context to use for encryption or decryption. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer 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. This is + * overwritten by the function. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +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. This is only + * exposed to allow overriding it using + * \c MBEDTLS_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 mbedtls_internal_aes_encrypt( mbedtls_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 MBEDTLS_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 mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0. + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0. + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_AES_ALT */ + +#endif /* MBEDTLS_AES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aes_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ + + +/********* Start of file include/mbedtls/aesni.h ************/ + +/** + * \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 + + + +#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 */ + + +/********* Start of file include/mbedtls/arc4.h ************/ + +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers 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) + * + */ +#ifndef MBEDTLS_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * + */ +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 + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +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 + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +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 + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +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 */ + +#endif /* MBEDTLS_ARC4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ + + +/********* Start of file include/mbedtls/base64.h ************/ + +/** + * \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 */ + + +/********* Start of file include/mbedtls/bn_mul.h ************/ + +/** + * \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 + + + +#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 */ + + +/********* Start of file include/mbedtls/camellia.h ************/ + +/** + * \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) + +#else + +#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. */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ + +#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 */ + +#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 */ + + +/********* Start of file include/mbedtls/ctr_drbg.h ************/ + +/** + * \file ctr_drbg.h + * + * \brief CTR_DRBG is based on AES-256, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic + * Random Bit Generators. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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 + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */ +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (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 using 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 +/**< The 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 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer. */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct +{ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation. */ + int reseed_interval; /*!< The reseed interval. */ + + mbedtls_aes_context aes_ctx; /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *p_entropy; /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * 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 The CTR_DRBG context to seed. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + length of the buffer. + * \param p_entropy The entropy context. + * \param custom Personalization data, that is device-specific + identifiers. Can be NULL. + * \param len The length of the personalization data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +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 This function clears CTR_CRBG context data. + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The 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 This function sets the amount of entropy grabbed on each + * seed or reseed. The default value is + * #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be NULL. + * \param len The length of the additional data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + * + * \note If \p 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 Bytes are silently discarded. + */ +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * \note The function automatically reseeds if the reseed counter is exceeded. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * \param additional Additional data to update. Can be NULL. + * \param add_len The length of the additional data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +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 This function uses CTR_DRBG to generate random data. + * + * \note The function automatically reseeds if the reseed counter is exceeded. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success, + * #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 on failure. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +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 */ + + +/********* Start of file include/mbedtls/des.h ************/ + +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * 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) + * + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#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_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_DES_ALT */ + +#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 */ + + +/********* Start of file include/mbedtls/entropy.h ************/ + +/** + * \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) + +#else + +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) + +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR + +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#if defined(MBEDTLS_HAVEGE_C) + +#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 +{ + int accumulator_started; +#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 */ + + +/********* Start of file include/mbedtls/entropy_poll.h ************/ + +/** + * \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) + +#else + +#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 */ + + +/********* Start of file include/mbedtls/havege.h ************/ + +/** + * \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 */ + + +/********* Start of file include/mbedtls/memory_buffer_alloc.h ************/ + +/** + * \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) + +#else + +#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 */ + + +/********* Start of file include/mbedtls/padlock.h ************/ + +/** + * \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 + + + +#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 */ + + +/********* Start of file include/mbedtls/timing.h ************/ + +/** + * \file timing.h + * + * \brief Portable interface to timeouts and 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) + +#else + +#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. + * + * \note This value starts at an unspecified origin and + * may wrap around. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +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 + * (must be >=0) + * + * \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. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +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 */ + +#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 */ + + +/********* Start of file include/mbedtls/xtea.h ************/ + +/** + * \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) + +#else + +#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. */ +#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ + +#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 */ + +#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 */ + + +/********* Start of file include/mbedtls/ssl.h ************/ + +/** + * \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) + +#else + +#endif + + + + + + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + + +#endif + +#if defined(MBEDTLS_DHM_C) + +#endif + +#if defined(MBEDTLS_ECDH_C) + +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and will be removed in the next major revision of the library" +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and cannot be used if MBEDTLS_DEPRECATED_REMOVED is set" +#endif + + +#endif + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +/* + * SSL Error codes + */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ + +/* + * Various constants + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 +#define MBEDTLS_SSL_IS_FALLBACK 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 +#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 + +#define MBEDTLS_SSL_ARC4_ENABLED 0 +#define MBEDTLS_SSL_ARC4_DISABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) +#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Maxium fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +/* \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 +#else +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 + +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret +{ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum +{ + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +} +mbedtls_ssl_states; + +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send fewer bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \return The callback must return the number of bytes received, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in ssl_internal.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) +typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; +#endif + +/* + * This structure is used for storing current session data. + */ +struct mbedtls_ssl_session +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t id_len; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t verify_result; /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif +}; + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config +{ + /* Group items by size (largest first) to minimize padding overhead */ + + /* + * Pointers + */ + + const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ + + /** Callback for printing debug output */ + void (*f_dbg)(void *, int, const char *, int, const char *); + void *p_dbg; /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + int (*f_get_cache)(void *, mbedtls_ssl_session *); + /** Callback to store a session into the cache */ + int (*f_set_cache)(void *, const mbedtls_ssl_session *); + void *p_cache; /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /** Callback to retrieve PSK key from identity */ + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a cookie for ClientHello veirifcation */ + int (*f_cookie_write)( void *, unsigned char **, unsigned char *, + const unsigned char *, size_t ); + /** Callback to verify validity of a ClientHello cookie */ + int (*f_cookie_check)( void *, const unsigned char *, size_t, + const unsigned char *, size_t ); + void *p_cookie; /*!< context for the cookie callbacks */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a session ticket */ + int (*f_ticket_write)( void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, uint32_t * ); + /** Callback to parse a session ticket into a session structure */ + int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *p_ticket; /*!< context for the ticket callbacks */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + /** Callback to export key block and master secret */ + int (*f_export_keys)( void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t ); + void *p_export_keys; /*!< context for key export callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ + mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ + mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + const int *sig_hashes; /*!< allowed signature hashes */ +#endif + +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ + mbedtls_mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< pre-shared key */ + size_t psk_len; /*!< length of the pre-shared key */ + unsigned char *psk_identity; /*!< identity for PSK negotiation */ + size_t psk_identity_len;/*!< length of identity */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char **alpn_list; /*!< ordered list of protocols */ +#endif + + /* + * Numerical settings (int then char) + */ + + uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t hs_timeout_min; /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t hs_timeout_max; /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned int badmac_limit; /*!< limit of records with a bad MAC */ +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ +#endif + + unsigned char max_major_ver; /*!< max. major version used */ + unsigned char max_minor_ver; /*!< max. minor version used */ + unsigned char min_major_ver; /*!< min. major version used */ + unsigned char min_minor_ver; /*!< min. minor version used */ + + /* + * Flags (bitfields) + */ + + unsigned int endpoint : 1; /*!< 0: client, 1: server */ + unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ + unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_ARC4_C) + unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites? */ +#endif +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned int mfl_code : 3; /*!< desired fragment length */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + unsigned int anti_replay : 1; /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + unsigned int cbc_record_splitting : 1; /*!< do cbc record splitting */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + unsigned int disable_renegotiation : 1; /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + unsigned int trunc_hmac : 1; /*!< negotiate truncated hmac? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + unsigned int session_tickets : 1; /*!< use session tickets? */ +#endif +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) + unsigned int fallback : 1; /*!< is this a fallback? */ +#endif +#if defined(MBEDTLS_SSL_SRV_C) + unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in + Certificate Request messages? */ +#endif +}; + + +struct mbedtls_ssl_context +{ + const mbedtls_ssl_config *conf; /*!< configuration information */ + + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_status; /*!< Initial, in progress, pending? */ + int renego_records_seen; /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ +#endif + + int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned badmac_seen; /*!< records with a bad MAC received */ +#endif + + mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ + mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *f_recv_timeout; + /*!< Callback for network receive with timeout */ + + void *p_bio; /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *session_in; /*!< current session data (in) */ + mbedtls_ssl_session *session_out; /*!< current session data (out) */ + mbedtls_ssl_session *session; /*!< negotiated session data */ + mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform; /*!< negotiated transform params */ + mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Timers + */ + void *p_timer; /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ + mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_buf; /*!< input buffer */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *in_hdr; /*!< start of record header */ + unsigned char *in_len; /*!< two-bytes message length field */ + unsigned char *in_iv; /*!< ivlen-byte IV */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t in_epoch; /*!< DTLS epoch for incoming records */ + size_t next_record_offset; /*!< offset of the next record in datagram + (equal to in_left if none) */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint64_t in_window_top; /*!< last validated record seq_num */ + uint64_t in_window; /*!< bitmask for replay detection */ +#endif + + size_t in_hslen; /*!< current handshake message length, + including the handshake header */ + int nb_zero; /*!< # of 0-length encrypted messages */ + + int keep_current_message; /*!< drop or reuse current message + on next call to record layer? */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_buf; /*!< output buffer */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< start of record header */ + unsigned char *out_len; /*!< two-bytes message length field */ + unsigned char *out_iv; /*!< ivlen-byte IV */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ + +#if defined(MBEDTLS_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + signed char split_done; /*!< current record already splitted? */ +#endif + + /* + * PKI layer + */ + int client_auth; /*!< flag for client auth. */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *hostname; /*!< expected peer CN for verification + (and SNI if available) */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_chosen; /*!< negotiated protocol */ +#endif + + /* + * Information for DTLS hello verify + */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + unsigned char *cli_id; /*!< transport-level ID of the client */ + size_t cli_id_len; /*!< length of cli_id */ +#endif + + /* + * Secure renegotiation + */ + /* needed to know when to send extension on server */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif + void *appData; +}; + +#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 The conf structure will be accessed during the session. + * It must not be modified or freed as long as the session + * is active. + * + * \warning This function must be called exactly once per context. + * Calling mbedtls_ssl_setup again is not supported, even + * if no session is active. + * + * \param ssl SSL context + * \param conf SSL configuration to use + * + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if + * memory allocation failed + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or + * MBEDTLS_ERR_SSL_COMPRESSION_FAILED + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param conf SSL configuration + * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); + +/** + * \brief Set the transport type (TLS or DTLS). + * Default: TLS + * + * \note For DTLS, you must either provide a recv callback that + * doesn't block, or one that handles timeouts, see + * \c mbedtls_ssl_set_bio(). You also need to provide timer + * callbacks with \c mbedtls_ssl_set_timer_cb(). + * + * \param conf SSL configuration + * \param transport transport type: + * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. + */ +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); + +/** + * \brief Set the certificate verification mode + * Default: NONE on server, REQUIRED on client + * + * \param conf SSL configuration + * \param authmode can be: + * + * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked + * (default on server) + * (insecure on client) + * + * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * mbedtls_ssl_get_verify_result() can be called after the + * handshake is complete. + * + * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * (default on client) + * + * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. + * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the verify callback is called for each + * certificate in the chain. For implementation + * information, please see \c mbedtls_x509_crt_verify() + * + * \param conf SSL configuration + * \param f_vrfy verification function + * \param p_vrfy verification parameter + */ +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param conf SSL configuration + * \param f_rng RNG function + * \param p_rng RNG parameter + */ +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * The callback has the following argument: + * void * opaque context for the callback + * int debug level + * const char * file name + * int line number + * const char * message + * + * \param conf SSL configuration + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO callbacks for write, read and + * read-with-timeout. + * + * \param ssl SSL context + * \param p_bio parameter (context) shared by BIO callbacks + * \param f_send write callback + * \param f_recv read callback + * \param f_recv_timeout blocking read callback with timeout. + * + * \note One of f_recv or f_recv_timeout can be NULL, in which case + * the other is used. If both are non-NULL, f_recv_timeout is + * used and f_recv is ignored (as if it were NULL). + * + * \note The two most common use cases are: + * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL + * - blocking I/O, f_recv == NULL, f_recv_timout != NULL + * + * \note For DTLS, you need to provide either a non-NULL + * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_sent_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the conventions those callbacks must follow. + * + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \c mbedtls_net_recv_timeout() that are suitable to be used + * here. + */ +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ); + +/** + * \brief Set the timeout period for mbedtls_ssl_read() + * (Default: no timeout.) + * + * \param conf SSL configuration context + * \param timeout Timeout value in milliseconds. + * Use 0 for no timeout (default). + * + * \note With blocking I/O, this will only work if a non-NULL + * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). + * With non-blocking I/O, this will only work if timer + * callbacks were set with \c mbedtls_ssl_set_timer_cb(). + * + * \note With non-blocking I/O, you may also skip this function + * altogether and handle timeouts at the application layer. + */ +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) + * + * \param ssl SSL context + * \param p_timer parameter (context) shared by timer callbacks + * \param f_set_timer set timer callback + * \param f_get_timer get timer callback. Must return: + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must follow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \note See also the "DTLS tutorial" article in our knowledge base. + * https://tls.mbed.org/kb/how-to/dtls-tutorial + */ +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ); + +/** + * \brief Callback type: generate and write session ticket + * + * \note This describes what a callback implementation should do. + * This callback should generate an encrypted and + * authenticated ticket for the session and write it to the + * output buffer. Here, ticket means the opaque ticket part + * of the NewSessionTicket structure of RFC 5077. + * + * \param p_ticket Context for the callback + * \param session SSL session to be written in the ticket + * \param start Start of the output buffer + * \param end End of the output buffer + * \param tlen On exit, holds the length written + * \param lifetime On exit, holds the lifetime of the ticket in seconds + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *lifetime ); + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Callback type: Export key block and master secret + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback + * \param ms Pointer to master secret (fixed length: 48 bytes) + * \param kb Pointer to key block, see RFC 5246 section 6.3 + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length + * \param keylen Key length + * \param ivlen IV length + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_export_keys_t( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: parse and load session ticket + * + * \note This describes what a callback implementation should do. + * This callback should parse a session ticket as generated + * by the corresponding mbedtls_ssl_ticket_write_t function, + * and, if the ticket is authentic and valid, load the + * session. + * + * \note The implementation is allowed to modify the first len + * bytes of the input buffer, eg to use it as a temporary + * area for the decrypted ticket contents. + * + * \param p_ticket Context for the callback + * \param session SSL session to be loaded + * \param buf Start of the buffer containing the ticket + * \param len Length of the ticket. + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or + * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or + * any other non-zero code for other failures. + */ +typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Configure SSL session ticket callbacks (server only). + * (Default: none.) + * + * \note On server, session tickets are enabled by providing + * non-NULL callbacks. + * + * \note On client, use \c mbedtls_ssl_conf_session_tickets(). + * + * \param conf SSL configuration context + * \param f_ticket_write Callback for writing a ticket + * \param f_ticket_parse Callback for parsing a ticket + * \param p_ticket Context shared by the two callbacks + */ +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Configure key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_t. + * + * \param conf SSL configuration context + * \param f_export_keys Callback for exporting keys + * \param p_export_keys Context for the callback + */ +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: generate a cookie + * + * \param ctx Context for the callback + * \param p Buffer to write to, + * must be updated to point right after the cookie + * \param end Pointer to one past the end of the output buffer + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 on success, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_write_t( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen ); + +/** + * \brief Callback type: verify a cookie + * + * \param ctx Context for the callback + * \param cookie Cookie to verify + * \param clen Length of cookie + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 if cookie is valid, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_check_t( void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Register callbacks for DTLS cookies + * (Server only. DTLS only.) + * + * Default: dummy callbacks that fail, in order to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * + * \note See comments on \c mbedtls_ssl_handshake() about handling + * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected + * on the first handshake attempt when this is enabled. + * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * + * \param conf SSL configuration + * \param f_cookie_write Cookie write callback + * \param f_cookie_check Cookie check callback + * \param p_cookie Context for both callbacks + */ +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ); + +/** + * \brief Set client's transport-level identification info. + * (Server only. DTLS only.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. + */ +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ); + +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enabled. + * + * \param conf SSL configuration + * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. + * + * \warning Disabling this is a security risk unless the application + * protocol handles duplicated packets in a safe way. You + * should not disable this without careful consideration. + * However, if your application already detects duplicated + * packets and needs information about them to adjust its + * transmission strategy, then you'll want to disable this. + */ +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param conf SSL configuration + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker ot inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/** + * \brief Set retransmit timeout values for the DTLS handshake. + * (DTLS only, no effect on TLS.) + * + * \param conf SSL configuration + * \param min Initial timeout value in milliseconds. + * Default: 1000 (1 second). + * \param max Maximum timeout value in milliseconds. + * Default: 60000 (60 seconds). + * + * \note Default values are from RFC 6347 section 4.2.4.1. + * + * \note The 'min' value should typically be slightly above the + * expected round-trip time to your peer, plus whatever time + * it takes for the peer to process the message. For example, + * if your RTT is about 600ms and you peer needs up to 1s to + * do the cryptographic operations in the handshake, then you + * should set 'min' slightly above 1600. Lower values of 'min' + * might cause spurious resends which waste network resources, + * while larger value of 'min' will increase overall latency + * on unreliable network links. + * + * \note The more unreliable your network connection is, the larger + * your max / min ratio needs to be in order to achieve + * reliable handshakes. + * + * \note Messages are retransmitted up to log2(ceil(max/min)) times. + * For example, if min = 1s and max = 5s, the retransmit plan + * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> + * resend ... 5s -> give up and return a timeout error. + */ +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, mbedtls_ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const mbedtls_ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the mbedtls_ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param conf SSL configuration + * \param p_cache parmater (context) for both callbacks + * \param f_get_cache session get callback + * \param f_set_cache session set callback + */ +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_get_session() + */ +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version-specific lists) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * Note: The server uses its own preferences + * over the preference of the client unless + * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ); + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 + * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + */ +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the X.509 security profile used for verification + * + * \note The restrictions are enforced for all certificates in the + * chain. However, signatures in the handshake are not covered + * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). + * + * \param conf SSL configuration + * \param profile Profile to use + */ +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ); + +/** + * \brief Set the data required to verify peer certificate + * + * \param conf SSL configuration + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note On server, this function can be called multiple times to + * provision more than one cert/key pair (eg one ECDSA, one + * RSA with SHA-256, one RSA with SHA-1). An adequate + * certificate will be selected according to the client's + * advertised capabilities. In case mutliple certificates are + * adequate, preference is given to the one set by the first + * call to this function, then second, etc. + * + * \note On client, only the first call has any effect. That is, + * only one client certificate can be provisioned. The + * server's preferences in its CertficateRequest message will + * be ignored and our only cert will be sent regardless of + * whether it matches those preferences - the server can then + * decide what it wants to do with it. + * + * \param conf SSL configuration + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +/** + * \brief Set the Pre Shared Key (PSK) and the expected identity name + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note Currently clients can only register one pre-shared key. + * In other words, the servers' identity hint is ignored. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature but + * feedback is welcomed. + * + * \param conf SSL configuration + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * \param psk_identity pointer to the pre-shared key identity + * \param psk_identity_len identity key length + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + + +/** + * \brief Set the Pre Shared Key (PSK) for the current handshake + * + * \note This should only be called inside the PSK callback, + * ie the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \param ssl SSL context + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ); + +/** + * \brief Set the PSK callback (server-side only). + * + * If set, the PSK callback is called for each + * handshake where a PSK ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: (void *parameter, + * mbedtls_ssl_context *ssl, const unsigned char *psk_identity, + * size_t identity_len) + * If a valid PSK identity is found, the callback should use + * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the + * correct PSK and return 0. + * Any other return value will result in a denied PSK identity. + * + * \note If you set a PSK callback using this function, then you + * don't need to set a PSK key and identity using + * \c mbedtls_ssl_conf_psk(). + * + * \param conf SSL configuration + * \param f_psk PSK identity function + * \param p_psk PSK identity parameter + */ +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \deprecated Superseded by \c mbedtls_ssl_conf_dh_param_bin. + * + * \return 0 if successful + */ +MBEDTLS_DEPRECATED int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, + const char *dhm_P, + const char *dhm_G ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the Diffie-Hellman public P and G values + * from big-endian binary presentations. + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form + * \param P_len Length of DHM modulus + * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form + * \param G_len Length of DHM generator + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ); + +/** + * \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 or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, + * too, if that extension is enabled. (client-side only) + * + * \param ssl SSL context + * \param hostname the server hostname, may be NULL to clear hostname + + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. + * + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * too long input hostname. + * + * Hostname set to the one provided on success (cleared + * when NULL). On allocation failure hostname is cleared. + * On too long input failure, old hostname is unchanged. + */ +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set own certificate and key for the current handshake + * + * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); + +/** + * \brief Set the data required to verify peer certificate for the + * current handshake + * + * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or + * MBEDTLS_SSL_VERIFY_REQUIRED + */ +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, mbedtls_ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback must set the + * certificate(s) and key(s) to use with \c + * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), + * and may optionally adjust the CA and associated CRL with \c + * mbedtls_ssl_set_hs_ca_chain() as well as the client + * authentication mode with \c mbedtls_ssl_set_hs_authmode(), + * then must return 0. If no matching name is found, the + * callback must either set a default cert, or + * return non-zero to abort the handshake at this point. + * + * \param conf SSL configuration + * \param f_sni verification function + * \param p_sni verification parameter + */ +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/** + * \brief Set the EC J-PAKE password for current handshake. + * + * \note An internal copy is made, and destroyed as soon as the + * handshake is completed, or when the SSL context is reset or + * freed. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret) + * \param pw_len length of pw in bytes + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ); +#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param conf SSL configuration + * \param protos Pointer to a NULL-terminated list of supported protocols, + * in decreasing preference order. The pointer to the list is + * recorded by the library for later reference as required, so + * the lifetime of the table must be atleast as long as the + * lifetime of the SSL configuration structure. + * + * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. + */ +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ALPN */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * + * \note This ignores ciphersuites from higher versions. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: TLS 1.0) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the fallback flag (client-side only). + * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). + * + * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback + * connection, that is a connection with max_version set to a + * lower value than the value you're willing to use. Such + * fallback connections are not recommended but are sometimes + * necessary to interoperate with buggy (version-intolerant) + * servers. + * + * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for + * non-fallback connections! This would appear to work for a + * while, then cause failures when the server is upgraded to + * support a newer TLS version. + * + * \param conf SSL configuration + * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK + */ +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); +#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: MBEDTLS_SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED + */ +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED + */ +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_ARC4_C) +/** + * \brief Disable or enable support for RC4 + * (Default: MBEDTLS_SSL_ARC4_DISABLED) + * + * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 + * for security reasons. Use at your own risk. + * + * \note This function is deprecated and will likely be removed in + * a future version of the library. + * RC4 is disabled by default at compile time and needs to be + * actively enabled for use with legacy systems. + * + * \param conf SSL configuration + * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED + */ +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate + * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * + * \param conf SSL configuration + * \param mfl_code Code for maximum fragment length (allowed values: + * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, + * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) + * + * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + */ +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC + * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + * + * \param conf SSL configuration + * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or + * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + */ +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +/** + * \brief Enable / Disable 1/n-1 record splitting + * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) + * + * \note Only affects SSLv3 and TLS 1.0, not higher versions. + * Does not affect non-CBC ciphersuites in any version. + * + * \param conf SSL configuration + * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or + * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED + */ +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Enable / Disable session tickets (client only). + * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) + * + * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). + * + * \param conf SSL configuration + * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or + * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) + */ +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) + * + * \warning It is recommended to always disable renegotation unless you + * know you need it and you know what you're doing. In the + * past, there have been several issues associated with + * renegotiation or a poor understanding of its properties. + * + * \note Server-side, enabling renegotiation also makes the server + * susceptible to a resource DoS by a malicious client. + * + * \param conf SSL configuration + * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or + * MBEDTLS_SSL_RENEGOTIATION_DISABLED) + */ +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) + * + * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param conf SSL configuration + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) + */ +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enforce renegotiation requests. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \note With DTLS and server-initiated renegotiation, the + * HelloRequest is retransmited every time mbedtls_ssl_read() times + * out or receives Application Data, until: + * - max_records records have beens seen, if it is >= 0, or + * - the number of retransmits that would happen during an + * actual handshake has been reached. + * Please remember the request might be lost a few times + * if you consider setting max_records to a really low value. + * + * \warning On client, the grace period can only happen during + * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during mbedtls_ssl_read(). + * + * \param conf SSL configuration + * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^48 - 1) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or ingoing) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * + * \param conf SSL configuration + * \param period The threshold value: a big-endian 64-bit number. + */ +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Return the number of data bytes available to read + * + * \param ssl SSL context + * + * \return how many bytes are available in the read buffer + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl SSL context + * + * \return 0 if successful, + * -1 if result is not available (eg because the handshake was + * aborted too early), or + * a combination of BADCERT_xxx and BADCRL_xxx flags, see + * x509.h + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes, or + * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is + * enabled, which makes expansion much less predictable + */ +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes). + * This is the value negotiated with peer if any, + * or the locally configured value. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \param ssl SSL context + * + * \return Current maximum fragment length. + */ +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection + * + * Note: Can be NULL in case no certificate was sent during + * the handshake. Different calls for the same connection can + * return the same or different pointers for the same + * certificate and even a different certificate altogether. + * The peer cert CAN change in a single connection if + * renegotiation is performed. + * + * \param ssl SSL context + * + * \return the current peer certificate + */ +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * \warning Currently, peer certificate is lost in the operation. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_set_session() + */ +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or + * a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * \note The state of the context (ssl->state) will be at + * the next state after execution of this function. Do not + * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \param ssl SSL context + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * a specific SSL error code. + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to mbedtls_ssl_read() if honored by + * client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any mbedtls_ssl_handshake() return + * value. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return the number of bytes read, or + * 0 for EOF, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or + * another negative error code. + * + * \note If this function returns something other than a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * (which can only happen server-side), it means that a client + * is initiating a new connection using the same source port. + * You can either treat that as a connection close and wait + * for the client to resend a ClientHello, or directly + * continue with \c mbedtls_ssl_handshake() with the same + * context (as it has beeen reset internally). Either way, you + * should make sure this is seen by the application as a new + * connection: application state, if any, should be reset, and + * most importantly the identity of the client must be checked + * again. WARNING: not validating the identity of the client + * again, or not transmitting the new identity to the + * application layer, would allow authentication bypass! + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Try to write exactly 'len' application data bytes + * + * \warning This function will do partial writes in some cases. If the + * return value is non-negative but less than length, the + * function must be called again with updated arguments: + * buf + ret, len - ret (if ret is the return value) until + * it returns a value equal to the last 'len' argument. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return the number of bytes actually written (may be less than len), + * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, + * or another negative error code. + * + * \note If this function returns something other than a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * it must be called later with the *same* arguments, + * until it returns a positive value. + * + * \note If the requested length is greater than the maximum + * fragment length (either the built-in limit or the one set + * or negotiated with the peer), then: + * - with TLS, less bytes than requested are written. + * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. + * \c mbedtls_ssl_get_max_frag_len() may be used to query the + * active maximum fragment length. + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); + +/** + * \brief Initialize an SSL configuration context + * Just makes the context ready for + * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). + * + * \note You need to call mbedtls_ssl_config_defaults() unless you + * manually set all of the relevent fields yourself. + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); + +/** + * \brief Load reasonnable default SSL configuration values. + * (You need to call mbedtls_ssl_config_init() first.) + * + * \param conf SSL configuration context + * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS + * \param preset a MBEDTLS_SSL_PRESET_XXX value + * + * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. + * + * \return 0 if successful, or + * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ); + +/** + * \brief Free an SSL configuration context + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \param session SSL session + */ +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ + + +/********* Start of file include/mbedtls/ssl_cookie.h ************/ + +/** + * \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 + + + +#if defined(MBEDTLS_THREADING_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. + * \{ + */ +#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 */ + + +/********* Start of file include/mbedtls/ssl_internal.h ************/ + +/** + * \file ssl_internal.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 + + + + +#if defined(MBEDTLS_MD5_C) + +#endif + +#if defined(MBEDTLS_SHA1_C) + +#endif + +#if defined(MBEDTLS_SHA256_C) + +#endif + +#if defined(MBEDTLS_SHA512_C) + +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + +#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 */ + +#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +/* 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_PAYLOAD_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ + + MBEDTLS_SSL_COMPRESSION_ADD \ + + MBEDTLS_MAX_IV_LENGTH \ + + MBEDTLS_SSL_MAC_ADD \ + + MBEDTLS_SSL_PADDING_ADD \ + ) + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 +#error Bad configuration - record content too large. +#endif + +#if MBEDTLS_SSL_PAYLOAD_LEN > 16384 + 2048 +#error Bad configuration - protected record payload too large. +#endif + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#define MBEDTLS_SSL_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_PAYLOAD_LEN ) ) + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Abstraction for a grid of allowed signature-hash-algorithm pairs. + */ +struct mbedtls_ssl_sig_hash_set_t +{ + /* At the moment, we only need to remember a single suitable + * hash algorithm per signature algorithm. As long as that's + * the case - and we don't need a general lookup function - + * we can implement the sig-hash-set as a map from signatures + * to hash algorithms. */ + mbedtls_md_type_t rsa; + mbedtls_md_type_t ecdsa; +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ +#endif +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + int sni_authmode; /*!< authmode from SNI callback */ + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie + Srv: unused */ + unsigned char verify_cookie_len; /*!< Cli: cookie length + Srv: flag for sending a cookie */ + + unsigned char *hs_msg; /*!< Reassembled handshake message */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + unsigned char retransmit_state; /*!< Retransmission state */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter + for resending messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Checksum contexts + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_context fin_md5; + mbedtls_sha1_context fin_sha1; +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_context fin_sha256; +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_context fin_sha512; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(mbedtls_ssl_context *, unsigned char *); + void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + int (*tls_prf)(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ + int max_major_ver; /*!< max. major version client*/ + int max_minor_ver; /*!< max. minor version client*/ + int cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + int new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + int extended_ms; /*!< use Extended Master Secret? */ +#endif +}; + +/* + * This structure contains a full set of runtime transform parameters + * either in negotiation or active. + */ +struct mbedtls_ssl_transform +{ + /* + * Session specific crypto layer + */ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + /*!< Chosen cipersuite_info */ + unsigned int keylen; /*!< symmetric key length (bytes) */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC length */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ + + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ + + /* + * Session specific compression layer + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif +}; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct mbedtls_ssl_key_cert +{ + mbedtls_x509_crt *cert; /*!< cert */ + mbedtls_pk_context *key; /*!< private key */ + mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +struct mbedtls_ssl_flight_item +{ + unsigned char *p; /*!< message, including handshake headers */ + size_t len; /*!< length of p */ + unsigned char type; /*!< type of the message: handshake or CCS */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ); +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ); +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ); + +/* Setup an empty signature-hash set */ +static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) +{ + mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param handshake SSL handshake context + */ +void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); + +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); + +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl SSL context to use + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); + +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); +#endif + +#if defined(MBEDTLS_PK_C) +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); +unsigned char mbedtls_ssl_hash_from_md_alg( int md ); +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); + +#if defined(MBEDTLS_ECP_C) +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->key ); +} + +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ); +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ); + +static inline size_t mbedtls_ssl_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 13 ); +#else + ((void) ssl); +#endif + return( 5 ); +} + +static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 12 ); +#else + ((void) ssl); +#endif + return( 4 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +#endif + +/* Visible for testing purposes only */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); +#endif + +/* constant-time buffer comparison */ +static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ); +#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) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_internal.h */ + + +/********* Start of file include/mbedtls/ssl_cache.h ************/ + +/** + * \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 + + + +#if defined(MBEDTLS_THREADING_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_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 */ + + +/********* Start of file include/mbedtls/ssl_ticket.h ************/ + +/** + * \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. + */ + + + + +#if defined(MBEDTLS_THREADING_C) + +#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 */ + + +/********* Start of file include/mbedtls/debug.h ************/ + +/** + * \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) + +#else + +#endif + + + +#if defined(MBEDTLS_ECP_C) + +#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 */ + + + +/********* Start of file include/mbedtls/blowfish.h ************/ + +/** + * \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) + +#else + +#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_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ +#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 */ + +#endif /* MBEDTLS_BLOWFISH_ALT */ + +#endif /* blowfish.h */ + + +/********* Start of file include/mbedtls/ccm.h ************/ + +/** + * \file ccm.h + * + * \brief CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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 + + + +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ + +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} +mbedtls_ccm_context; + +/** + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). + * + * \param ctx The CCM context to initialize. + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The CCM context to initialize. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. + * \param keybits The key size in bits. This must be acceptable by the cipher. + * + * \return \c 0 on success, 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 This function releases and clears the specified CCM context + * and underlying cipher sub-context. + * + * \param ctx The CCM context to clear. + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief This function encrypts a buffer using CCM. + * + * \param ctx The CCM context to use for encryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \return \c 0 on success. + */ +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 This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector. + * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag in Bytes. + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return 0 if successful and authenticated, or + * #MBEDTLS_ERR_CCM_AUTH_FAILED if the 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 ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_CCM_ALT */ + +#endif /* MBEDTLS_CCM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The CCM checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ + + +/********* Start of file include/mbedtls/gcm.h ************/ + +/** + * \file gcm.h + * + * \brief Galois/Counter Mode (GCM) for 128-bit block ciphers, as defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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 + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ +#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#if !defined(MBEDTLS_GCM_ALT) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The GCM context structure. + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint64_t len; /*!< The total length of the encrypted data. */ + uint64_t add_len; /*!< The total length of the additional data. */ + unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ + unsigned char y[16]; /*!< The Y working value. */ + unsigned char buf[16]; /*!< The buf working value. */ + int mode; /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +/** + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). + * + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief This function associates a GCM context with a + * cipher algorithm and a key. + * + * \param ctx The GCM context to initialize. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success, 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 This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the input buffer. + * For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context to use for encryption or decryption. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. + * + * \return \c 0 on success. + */ +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 This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag. + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * + * \return 0 if successful and authenticated, or + * #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 This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data, or NULL if \p add_len is 0. + * \param add_len The length of the additional data. If 0, \p add is NULL. + * + * \return \c 0 on success. + */ +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 This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * ` The function expects input to be a multiple of 16 + * Bytes. Only the last call before calling + * mbedtls_gcm_finish() can be less than 16 Bytes. + * + * \note For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * + * \return \c 0 on success, or #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. + * \param tag The buffer for holding the tag. + * \param tag_len The length of the tag to generate. Must be at least four. + * + * \return \c 0 on success, or #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief This function clears a GCM context and the underlying + * cipher sub-context. + * + * \param ctx The GCM context to clear. + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#else /* !MBEDTLS_GCM_ALT */ + +#endif /* !MBEDTLS_GCM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The GCM checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_gcm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + + +#endif /* gcm.h */ + + +/********* Start of file include/mbedtls/pem.h ************/ + +/** + * \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 */ + + +/********* Start of file include/mbedtls/asn1write.h ************/ + +/** + * \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 + + + +#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 */ + + +/********* Start of file include/mbedtls/hmac_drbg.h ************/ + +/** + * \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 + + + +#if defined(MBEDTLS_THREADING_C) + +#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 */ + + +/********* Start of file include/mbedtls/pkcs12.h ************/ + +/** + * \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 + +#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 */ + + +/********* Start of file include/mbedtls/pkcs11.h ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_PKCS11_C) + + + +#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 */ + + +/********* Start of file include/mbedtls/pkcs5.h ************/ + +/** + * \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 +#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 */ + + +/********* Start of file include/mbedtls/oid.h ************/ + +/** + * \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) + +#else + +#endif + + + + +#include + +#if defined(MBEDTLS_CIPHER_C) + +#endif + +#if defined(MBEDTLS_MD_C) + +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + +#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 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * 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 ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#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 */ + + +/********* Start of file include/mbedtls/ripemd160.h ************/ + +/** + * \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) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ + +#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 + * + * \return 0 if successful + */ +int mbedtls_ripemd160_starts_ret( 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 + * + * \return 0 if successful + */ +int mbedtls_ripemd160_update_ret( 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 + * + * \return 0 if successful + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief RIPEMD-160 context setup + * + * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( + mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( + mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( + mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( + mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_RIPEMD160_ALT */ + +#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 + * + * \return 0 if successful + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \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 */ + + +/********* Start of file include/mbedtls/version.h ************/ + +/** + * \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) + +#else + +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 8 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x02080000 +#define MBEDTLS_VERSION_STRING "2.8.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.8.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 */ + +#endif /* ME_COM_MBEDTLS */ diff --git a/code/application/sifarsdk/component/utils/include/sf_aes.h b/code/application/sifarsdk/component/utils/include/sf_aes.h new file mode 100644 index 000000000..8d1b1821d --- /dev/null +++ b/code/application/sifarsdk/component/utils/include/sf_aes.h @@ -0,0 +1,14 @@ +#ifndef __SF_AES_H +#define __SF_AES_H +#include "SfTypeDefine.h" +#if __cplusplus +extern "C" +{ +#endif + UINT32 sf_cipher(UINT32 aesType, UINT8 operation, UINT8 *input, UINT8 *output, UINT8 srcl); + void sf_cipher_test(void); + void sf_cipher_test1(void); +#if __cplusplus +} +#endif +#endif diff --git a/code/application/sifarsdk/component/utils/include/sf_qrutils.h b/code/application/sifarsdk/component/utils/include/sf_qrutils.h new file mode 100644 index 000000000..55318ddda --- /dev/null +++ b/code/application/sifarsdk/component/utils/include/sf_qrutils.h @@ -0,0 +1,14 @@ + +#ifndef __SF_QRUTILS_H +#define __SF_QRUTILS_H +#if __cplusplus +extern "C" +{ +#endif + char *nfc_qrencrypt(char *content); + char *nfc_qrdecrypt(char *content); +#if __cplusplus +} +#endif + +#endif diff --git a/code/application/sifarsdk/component/utils/src/linux_api.c b/code/application/sifarsdk/component/utils/src/linux_api.c new file mode 100644 index 000000000..d02848437 --- /dev/null +++ b/code/application/sifarsdk/component/utils/src/linux_api.c @@ -0,0 +1,40 @@ +#include "linux_api.h" +#include +#include +#include +int fprintf_gpio(FILE *stream, const U32 pinNum) +{ + return fprintf(stream, "%d", pinNum); +} +int fprintf_dir(FILE *stream, const char *dir) +{ + return fprintf(stream, dir); +} +int linux_open(const char *pathname, int flags) +{ + return open(pathname, flags); +} +int linux_close(int fd) +{ + return close(fd); +} +int linux_fclose(FILE *stream) +{ + return fclose(stream); +} +size_t linux_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + return fread(ptr, size, nmemb, stream); +} +int linux_fcntl(int fd, int cmd, int flag) +{ + return fcntl(fd, cmd, flag); +} +ssize_t linux_write(int fd, const void *buf, size_t count) +{ + return write(fd, buf, count); +} +ssize_t linux_read(int fd, void *buf, size_t count) +{ + return read(fd, buf, count); +} \ No newline at end of file diff --git a/code/application/sifarsdk/component/utils/src/mbedtls.c b/code/application/sifarsdk/component/utils/src/mbedtls.c new file mode 100644 index 000000000..4105e305b --- /dev/null +++ b/code/application/sifarsdk/component/utils/src/mbedtls.c @@ -0,0 +1,66851 @@ +/* + * MbedTLS Source Code Library Source + */ + +#include "mbedtls.h" + + +#if 1//ME_COM_MBEDTLS + + +/********* Start of file library/aes.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_AES_C) + +#include + + +#if defined(MBEDTLS_PADLOCK_C) + +#endif +#if defined(MBEDTLS_AESNI_C) + +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); + } +} + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + + } +#endif + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free( &cty ); + + return( ret ); +} +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +} + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_encrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_DECRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_decrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_ENCRYPT ) + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); + else + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + unsigned char ov[17]; + + while( length-- ) + { + memcpy( ov, iv, 16 ); + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + if( mode == MBEDTLS_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == MBEDTLS_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#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; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-ECB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_ecb_dec[u]; + } + else + { + ret = mbedtls_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 + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + ret = mbedtls_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 ) + 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; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CBC-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_cbc_dec[u]; + } + else + { + ret = mbedtls_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 + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + if( mode == MBEDTLS_AES_ENCRYPT ) + { + unsigned char tmp[16]; + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + ret = mbedtls_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 ) + 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; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_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 + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_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 = mbedtls_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 ) + 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; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CTR-128 (%s): ", + ( mode == 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; + if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) + goto exit; + + len = aes_test_ctr_len[u]; + + if( mode == MBEDTLS_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 = mbedtls_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 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "failed\n" ); + + mbedtls_aes_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/aesni.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_AESNI_C) + + + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/arc4.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ARC4_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/asn1parse.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + + + +#include + +#if defined(MBEDTLS_BIGNUM_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/asn1write.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ASN1_WRITE_C) + + + +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/base64.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_BASE64_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( ( i + 1 ) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + uint32_t j, x; + unsigned char *p; + + /* First pass: check for validity and get output length */ + for( i = n = j = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + x = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + ++x; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( x != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' && ++j > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); + n -= j; + + if( dst == NULL || dlen < n ) + { + *olen = n; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' || *src == ' ' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *olen = p - dst; + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int mbedtls_base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + mbedtls_printf( " Base64 encoding test: " ); + + src = base64_test_dec; + + if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n Base64 decoding test: " ); + + src = base64_test_enc; + + if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BASE64_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/bignum.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_BIGNUM_C) + + + + +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#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; +} + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + + /* Actually resize up in this case */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret; + size_t i; + + if( X == Y ) + return( 0 ); + + if( Y->p == NULL ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + for( i = 0; i < Y->n; i++ ) + X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; + + for( ; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) +{ + int ret; + mbedtls_mpi_uint r; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + + if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + /* + * Round up the buffer length to an even value to ensure that there is + * enough room for hexadecimal values that can be represented in an odd + * number of digits. + */ + n += 3 + ( ( n + 1 ) & 1 ); + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + *p++ = '-'; + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t i, j; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = buflen, j = 0; i > 0; 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 && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * 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: + mbedtls_zeroize( buf, sizeof( buf ) ); + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, n, s; + mbedtls_mpi W, R, T, A, RR; + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + i = mbedtls_mpi_bitlen( X ); + /* + * HAC, table 4.4 + */ + n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : + ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : + ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); + + for( i = 0; i < n; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) + { + j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); + } + A.p[0] |= 3; + + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); + } + + if (count++ > 30) { + return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi XX; + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); +} + +/* + * Prime number generation + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t k, n; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + + k = mbedtls_mpi_bitlen( X ); + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); + + mbedtls_mpi_set_bit( X, nbits-1, 1 ); + + X->p[0] |= 1; + + if( dh_flag == 0 ) + { + while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); + } + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && + ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + { + break; + } + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/blowfish.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + + + +#include + +#if !defined(MBEDTLS_BLOWFISH_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/camellia.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ccm.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_CCM_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_CCM_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#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 ); +} + +#endif /* !MBEDTLS_CCM_ALT */ + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/certs.c ************/ + +/* + * 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) + +#else + +#endif + + + +#if defined(MBEDTLS_CERTS_C) + +#if defined(MBEDTLS_ECDSA_C) +#define TEST_CA_CRT_EC \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n" \ +"ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n" \ +"aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n" \ +"JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n" \ +"NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n" \ +"AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n" \ +"CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n" \ +"t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n" \ +"uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ +"-----END CERTIFICATE-----\r\n" +const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; +const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); + +const char mbedtls_test_ca_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" +"\r\n" +"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" +"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" +"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" +"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_ca_key_ec_len = sizeof( mbedtls_test_ca_key_ec ); + +const char mbedtls_test_ca_pwd_ec[] = "PolarSSLTest"; +const size_t mbedtls_test_ca_pwd_ec_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; + +const char mbedtls_test_srv_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" +"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" +"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" +"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" +"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" +"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" +"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" +"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" +"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); + +const char mbedtls_test_srv_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" +"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" +"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); + +const char mbedtls_test_cli_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n" +"WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n" +"9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n" +"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n" +"IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n" +"CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n" +"lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" +"LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); + +const char mbedtls_test_cli_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" +"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" +"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_RSA_C) + +#if defined(MBEDTLS_SHA256_C) +#define TEST_CA_CRT_RSA_SHA256 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTcwNTA0MTY1NzAxWhcNMjcwNTA1MTY1NzAxWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/MGMGA1UdIwRcMFqA\r\n" \ +"FLRa5KWz3tJS9rnVppUP6z68x/3/oT+kPTA7MQswCQYDVQQGEwJOTDERMA8GA1UE\r\n" \ +"CgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0GCAQAwDAYDVR0T\r\n" \ +"BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAHK/HHrTZMnnVMpde1io+voAtql7j\r\n" \ +"4sRhLrjD7o3THtwRbDa2diCvpq0Sq23Ng2LMYoXsOxoL/RQK3iN7UKxV3MKPEr0w\r\n" \ +"XQS+kKQqiT2bsfrjnWMVHZtUOMpm6FNqcdGm/Rss3vKda2lcKl8kUnq/ylc1+QbB\r\n" \ +"G6A6tUvQcr2ZyWfVg+mM5XkhTrOOXus2OLikb4WwEtJTJRNE0f+yPODSUz0/vT57\r\n" \ +"ApH0CnB80bYJshYHPHHymOtleAB8KSYtqm75g/YNobjnjB6cm4HkW3OZRVIl6fYY\r\n" \ +"n20NRVA1Vjs6GAROr4NqW4k/+LofY9y0LLDE+p0oIEKXIsIvhPr39swxSA==\r\n" \ +"-----END CERTIFICATE-----\r\n" + +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA256; +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +#define TEST_CA_CRT_RSA_SOME + +static const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; + +#endif + +#if !defined(TEST_CA_CRT_RSA_SOME) || defined(MBEDTLS_SHA1_C) +#define TEST_CA_CRT_RSA_SHA1 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" \ +"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" \ +"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" \ +"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" \ +"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" \ +"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" \ +"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" \ +"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ +"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ +"-----END CERTIFICATE-----\r\n" + +#if !defined (TEST_CA_CRT_RSA_SOME) +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA1; +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +#endif + +static const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; + +#endif + +const char mbedtls_test_ca_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" +"\r\n" +"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" +"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" +"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" +"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" +"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" +"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" +"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" +"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" +"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" +"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" +"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" +"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" +"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" +"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" +"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" +"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" +"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" +"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" +"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" +"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" +"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" +"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" +"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" +"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" +"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); + +const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; +const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; + +const char mbedtls_test_srv_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" +"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" +"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" +"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" +"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" +"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" +"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" +"zhuYwjVuX6JHG0c=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); + +const char mbedtls_test_srv_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" +"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" +"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" +"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" +"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" +"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" +"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" +"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" +"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" +"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" +"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" +"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" +"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" +"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" +"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" +"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" +"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" +"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" +"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" +"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" +"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" +"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" +"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" +"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" +"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); + +const char mbedtls_test_cli_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDhTCCAm2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTcwNTA1MTMwNzU5WhcNMjcwNTA2MTMwNzU5WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" +"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" +"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" +"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" +"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" +"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" +"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" +"o4GSMIGPMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITBjBgNVHSMEXDBa\r\n" +"gBS0WuSls97SUva51aaVD+s+vMf9/6E/pD0wOzELMAkGA1UEBhMCTkwxETAPBgNV\r\n" +"BAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xhclNTTCBUZXN0IENBggEAMAkGA1Ud\r\n" +"EwQCMAAwDQYJKoZIhvcNAQELBQADggEBAC7yO786NvcHpK8UovKIG9cB32oSQQom\r\n" +"LoR0eHDRzdqEkoq7yGZufHFiRAAzbMqJfogRtxlrWAeB4y/jGaMBV25IbFOIcH2W\r\n" +"iCEaMMbG+VQLKNvuC63kmw/Zewc9ThM6Pa1Hcy0axT0faf1B/U01j0FIcw/6mTfK\r\n" +"D8w48OIwc1yr0JtutCVjig5DC0yznGMt32RyseOLcUe+lfq005v2PAiCozr5X8rE\r\n" +"ofGZpiM2NqRPePgYy+Vc75Zk28xkRQq1ncprgQb3S4vTsZdScpM9hLf+eMlrgqlj\r\n" +"c5PLSkXBeLE5+fedkyfTaLxxQlgCpuoOhKBm04/R1pWNzUHyqagjO9Q=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); + +const char mbedtls_test_cli_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" +"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" +"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" +"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" +"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" +"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" +"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" +"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" +"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" +"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" +"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" +"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" +"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" +"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" +"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" +"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" +"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" +"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" +"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" +"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" +"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" +"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" +"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" +"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" +"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_cli_key_rsa_len = sizeof( mbedtls_test_cli_key_rsa ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all available CA certificates */ +const char mbedtls_test_cas_pem[] = +#ifdef TEST_CA_CRT_RSA_SHA1 + TEST_CA_CRT_RSA_SHA1 +#endif +#ifdef TEST_CA_CRT_RSA_SHA256 + TEST_CA_CRT_RSA_SHA256 +#endif +#ifdef TEST_CA_CRT_EC + TEST_CA_CRT_EC +#endif + ""; +const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); +#endif + +/* List of all available CA certificates */ +const char * mbedtls_test_cas[] = { +#if defined(TEST_CA_CRT_RSA_SHA1) + mbedtls_test_ca_crt_rsa_sha1, +#endif +#if defined(TEST_CA_CRT_RSA_SHA256) + mbedtls_test_ca_crt_rsa_sha256, +#endif +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec, +#endif + NULL +}; +const size_t mbedtls_test_cas_len[] = { +#if defined(TEST_CA_CRT_RSA_SHA1) + sizeof( mbedtls_test_ca_crt_rsa_sha1 ), +#endif +#if defined(TEST_CA_CRT_RSA_SHA256) + sizeof( mbedtls_test_ca_crt_rsa_sha256 ), +#endif +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec ), +#endif + 0 +}; + +#if defined(MBEDTLS_RSA_C) +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; /* SHA1 or SHA256 */ +const char *mbedtls_test_ca_key = mbedtls_test_ca_key_rsa; +const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_rsa; +const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_rsa; +const char *mbedtls_test_srv_key = mbedtls_test_srv_key_rsa; +const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_rsa; +const char *mbedtls_test_cli_key = mbedtls_test_cli_key_rsa; +const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_rsa ); +const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_rsa ); +const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_rsa ); +const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_rsa ); +const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_rsa ); +const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_rsa ); +#else /* ! MBEDTLS_RSA_C, so MBEDTLS_ECDSA_C */ +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_ec; +const char *mbedtls_test_ca_key = mbedtls_test_ca_key_ec; +const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_ec; +const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_ec; +const char *mbedtls_test_srv_key = mbedtls_test_srv_key_ec; +const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_ec; +const char *mbedtls_test_cli_key = mbedtls_test_cli_key_ec; +const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_ec ); +const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_ec ); +const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; +const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_ec ); +const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_ec ); +const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_ec ); +const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_ec ); +#endif /* MBEDTLS_RSA_C */ + +#endif /* MBEDTLS_CERTS_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/cipher.c ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_CIPHER_C) + + + + +#include +#include + +#if defined(MBEDTLS_GCM_C) + +#endif + +#if defined(MBEDTLS_CCM_C) + +#endif + +#if defined(MBEDTLS_CMAC_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) +{ + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + } + + if( MBEDTLS_DECRYPT == operation ) + return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ) +{ + size_t actual_iv_size; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ); + } + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret; + size_t block_size = 0; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + *olen = ilen; + return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ); + } +#endif + + if ( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen < block_size - ctx->unprocessed_len ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + if( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + copy_len = ilen % block_size; + if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) + copy_len = block_size; + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0x80; + *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] * ( 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/cipher_wrap.c ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_CIPHER_C) + + + +#if defined(MBEDTLS_AES_C) + +#endif + +#if defined(MBEDTLS_ARC4_C) + +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + +#endif + +#if defined(MBEDTLS_DES_C) + +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + +#endif + +#if defined(MBEDTLS_GCM_C) + +#endif + +#if defined(MBEDTLS_CCM_C) + +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#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 ) +{ + //#define mbedtls_calloc calloc ////modified by ljy 20220330 + mbedtls_aes_context *aes = calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + //#define mbedtls_calloc free ////modified by ljy 20220330 + + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/cmac.c ************/ + +/** + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The + * CMAC Mode for Authentication + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf + * + * - RFC 4493 - The AES-CMAC Algorithm + * https://tools.ietf.org/html/rfc4493 + * + * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message + * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) + * Algorithm for the Internet Key Exchange Protocol (IKE) + * https://tools.ietf.org/html/rfc4615 + * + * Additional test vectors: ISO/IEC 9797-1 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_CMAC_C) + + + +#include + + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#if defined(MBEDTLS_SELF_TEST) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Multiplication by u in the Galois field of GF(2^n) + * + * As explained in NIST SP 800-38B, this can be computed: + * + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ R_n + * with R_64 = 0x1B and R_128 = 0x87 + * + * Input and output MUST NOT point to the same buffer + * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. + */ +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize ) +{ + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i; + + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) + { + R_n = R_128; + } + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) + { + R_n = R_64; + } + else + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + for( i = (int)blocksize - 1; i >= 0; i-- ) + { + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; + } + + /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 + * using bit operations to avoid branches */ + + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( input[0] >> 7 ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + output[ blocksize - 1 ] ^= R_n & mask; + + return( 0 ); +} + +/* + * Generate subkeys + * + * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm + */ +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) +{ + int ret; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + size_t olen, block_size; + + mbedtls_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; + + /* Calculate Ek(0) */ + if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) + goto exit; + + /* + * Generate K1 and K2 + */ + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) + goto exit; + + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_zeroize( L, sizeof( L ) ); + + return( ret ); +} +#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ + +#if !defined(MBEDTLS_CMAC_ALT) +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) +{ + size_t idx; + + for( idx = 0; idx < block_size; idx++ ) + output[ idx ] = input1[ idx ] ^ input2[ idx ]; +} + +/* + * Create padded last block from (partial) last block. + * + * We can't use the padding option from the cipher layer, as it only works for + * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. + */ +static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], + size_t padded_block_len, + const unsigned char *last_block, + size_t last_block_len ) +{ + size_t j; + + for( j = 0; j < padded_block_len; j++ ) + { + if( j < last_block_len ) + padded_block[j] = last_block[j]; + else if( j == last_block_len ) + padded_block[j] = 0x80; + else + padded_block[j] = 0x00; + } +} + +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ) +{ + mbedtls_cipher_type_t type; + mbedtls_cmac_context_t *cmac_ctx; + int retval; + + if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + + return 0; +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + int ret = 0; + size_t n, j, olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; + + /* Is there data still to process from the last call, that's greater in + * size than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen > block_size - cmac_ctx->unprocessed_len ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; + cmac_ctx->unprocessed_len = 0; + } + + /* n is the number of blocks including any final partial block */ + n = ( ilen + block_size - 1 ) / block_size; + + /* Iterate across the input data in block sized chunks, excluding any + * final partial or complete block */ + for( j = 1; j < n; j++ ) + { + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + } + + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state, *last_block; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + int ret; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || + output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = cmac_ctx->state; + + mbedtls_zeroize( K1, sizeof( K1 ) ); + mbedtls_zeroize( K2, sizeof( K2 ) ); + cmac_generate_subkeys( ctx, K1, K2 ); + + last_block = cmac_ctx->unprocessed_block; + + /* Calculate last block */ + if( cmac_ctx->unprocessed_len < block_size ) + { + cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); + cmac_xor_block( M_last, M_last, K2, block_size ); + } + else + { + /* Last block is complete block */ + cmac_xor_block( M_last, last_block, K1, block_size ); + } + + + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + memcpy( output, state, block_size ); + +exit: + /* Wipe the generated keys on the stack, and any other transients to avoid + * side channel leakage */ + mbedtls_zeroize( K1, sizeof( K1 ) ); + mbedtls_zeroize( K2, sizeof( K2 ) ); + + cmac_ctx->unprocessed_len = 0; + mbedtls_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + + mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + return( ret ); +} + +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) +{ + mbedtls_cmac_context_t* cmac_ctx; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); + + return( 0 ); +} + +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_cipher_context_t ctx; + int ret; + + if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_finish( &ctx, output ); + +exit: + mbedtls_cipher_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +/* + * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char *output ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; + + if( key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) + { + /* Use key as is */ + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); + } + else + { + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); + + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); + +exit: + mbedtls_zeroize( int_key, sizeof( int_key ) ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* !MBEDTLS_CMAC_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * CMAC test data for SP800-38B + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf + * + * AES-CMAC-PRF-128 test data from RFC 4615 + * https://tools.ietf.org/html/rfc4615#page-4 + */ + +#define NB_CMAC_TESTS_PER_KEY 4 +#define NB_PRF_TESTS 3 + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) +/* All CMAC test inputs are truncated from the same 64 byte buffer. */ +static const unsigned char test_message[] = { + /* PT */ + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* Truncation point of message for AES CMAC tests */ +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + /* Mlen */ + 0, + 16, + 20, + 64 +}; + +/* CMAC-AES128 Test Data */ +static const unsigned char aes_128_key[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde + }, + { + /* K2 */ + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b + } +}; +static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }, + { + /* Example #2 */ + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }, + { + /* Example #3 */ + 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, + 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde + }, + { + /* Example #4 */ + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + } +}; + +/* CMAC-AES192 Test Data */ +static const unsigned char aes_192_key[24] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; +static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 + }, + { + /* K2 */ + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c + } +}; +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }, + { + /* Example #2 */ + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }, + { + /* Example #3 */ + 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, + 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 + }, + { + /* Example #4 */ + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + } +}; + +/* CMAC-AES256 Test Data */ +static const unsigned char aes_256_key[32] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; +static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f + }, + { + /* K2 */ + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 + } +}; +static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }, + { + /* Example #2 */ + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }, + { + /* Example #3 */ + 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, + 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 + }, + { + /* Example #4 */ + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + } +}; +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) +/* Truncation point of message for 3DES CMAC tests */ +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 20, + 32 +}; + +/* CMAC-TDES (Generation) - 2 Key Test Data */ +static const unsigned char des3_2key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, + /* Key3 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef +}; +static const unsigned char des3_2key_subkeys[2][8] = { + { + /* K1 */ + 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 + }, + { + /* K2 */ + 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 + } +}; +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 + }, + { + /* Sample #2 */ + 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b + }, + { + /* Sample #3 */ + 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 + }, + { + /* Sample #4 */ + 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb + } +}; + +/* CMAC-TDES (Generation) - 3 Key Test Data */ +static const unsigned char des3_3key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, + /* Key3 */ + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 +}; +static const unsigned char des3_3key_subkeys[2][8] = { + { + /* K1 */ + 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 + }, + { + /* K2 */ + 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b + } +}; +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 + }, + { + /* Sample #2 */ + 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 + }, + { + /* Sample #3 */ + 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 + }, + { + /* Sample #4 */ + 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 + } +}; + +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* AES AES-CMAC-PRF-128 Test Data */ +static const unsigned char PRFK[] = { + /* Key */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xed, 0xcb +}; + +/* Sizes in bytes */ +static const size_t PRFKlen[NB_PRF_TESTS] = { + 18, + 16, + 10 +}; + +/* Message */ +static const unsigned char PRFM[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char PRFT[NB_PRF_TESTS][16] = { + { + 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, + 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a + }, + { + 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, + 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d + }, + { + 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, + 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d + } +}; +#endif /* MBEDTLS_AES_C */ + +static int cmac_test_subkeys( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* subkeys, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + int i, ret; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_cipher_free( &ctx ); + } + + goto exit; + +cleanup: + mbedtls_cipher_free( &ctx ); + +exit: + return( ret ); +} + +static int cmac_test_wth_cipher( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* expected_result, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret; + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); + + if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, + message_lengths[i], output ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + +exit: + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) +{ + int i; + int ret; + unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); + if( ret != 0 || + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) + { + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +int mbedtls_cmac_self_test( int verbose ) +{ + int ret; + +#if defined(MBEDTLS_AES_C) + /* AES-128 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 128", + aes_128_key, + 128, + (const unsigned char*)aes_128_subkeys, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*)aes_128_expected_result, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-192 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 192", + aes_192_key, + 192, + (const unsigned char*)aes_192_subkeys, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*)aes_192_expected_result, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-256 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 256", + aes_256_key, + 256, + (const unsigned char*)aes_256_subkeys, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*)aes_256_expected_result, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) + /* 3DES 2 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 2 key", + des3_2key_key, + 192, + (const unsigned char*)des3_2key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_2key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* 3DES 3 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 3 key", + des3_3key_key, + 192, + (const unsigned char*)des3_3key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_3key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_AES_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CMAC_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ctr_drbg.c ************/ + +/* + * 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 publication. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + + + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 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 + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + 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 ret = 0; + + 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; + + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + + /* + * 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; + + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 ) + { + goto exit; + } + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) + { + goto exit; + } + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } +exit: + mbedtls_aes_free( &aes_ctx ); + /* + * tidy up the stack + */ + mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_zeroize( chain, sizeof( chain ) ); + if( 0 != ret ) + { + /* + * wipe partial seed from memory + */ + mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + } + + return( ret ); +} + +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; + int ret = 0; + + 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 + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) + { + return( ret ); + } + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + 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; + int ret; + + if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + + /* + * Gather entropy_len bytes of entropy to seed state + */ + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, + ctx->entropy_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len; + + /* + * Add additional data + */ + if( additional && len ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* + * Reduce to 384 bits + */ + if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) + { + return( ret ); + } + + /* + * Update state + */ + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + { + return( ret ); + } + 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 ) + { + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + { + return( ret ); + } + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + { + return( ret ); + } + } + + 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 + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) + { + return( ret ); + } + + 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; + } + + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + { + return( ret ); + } + + 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; + else + ret = 0; + +exit: + mbedtls_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + int ret = 0; + 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 ) + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + else + mbedtls_ctr_drbg_update( ctx, buf, n ); + + fclose( f ); + + mbedtls_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/debug.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time_t time_t +#define mbedtls_snprintf snprintf +#endif + + + +#include +#include +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define DEBUG_BUF_SIZE 512 + +static int debug_threshold = 0; + +void mbedtls_debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +/* + * All calls to f_dbg must be made via this function + */ +static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *str ) +{ + /* + * If in a threaded environment, we need a thread identifier. + * Since there is no portable way to get one, use the address of the ssl + * context instead, as it shouldn't be shared between threads. + */ +#if defined(MBEDTLS_THREADING_C) + char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ + mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); +#else + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); +#endif +} + +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) +{ + va_list argp; + char str[DEBUG_BUF_SIZE]; + int ret; + + if( NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold ) + return; + + va_start( argp, format ); +#if defined(_WIN32) +#if defined(_TRUNCATE) && !defined(__MINGW32__) + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/des.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_DES_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/dhm.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_DHM_C) + + + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_DHM_ALT) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 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 + * + * This means that we need to return an error if + * public_param < 2 or 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 = 0; + + 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 = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + +cleanup: + mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); + return( ret ); +} + +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ) +{ + int ret; + + if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) + return( ret ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + ctx->len = mbedtls_mpi_size( &ctx->P ); + + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + size_t n1, n2, n3; + unsigned char *p; + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * Generate X as large as possible ( < P ) + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + /* + * Calculate GX = G^X mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + /* + * export P, G, GX + */ +#define DHM_MPI_EXPORT( X, n ) \ + do { \ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ + p + 2, \ + ( n ) ) ); \ + *p++ = (unsigned char)( ( n ) >> 8 ); \ + *p++ = (unsigned char)( ( n ) ); \ + p += ( n ); \ + } while( 0 ) + + 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 ); +} + +/* + * Set prime modulus and generator + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ) +{ + int ret; + + if( ctx == NULL || P == NULL || G == NULL ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) + { + return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->P ); + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret; + + if( ctx == NULL || ilen < 1 || ilen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + + if( ctx == NULL || olen < 1 || olen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * generate X and calculate GX = G^X mod P + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Use the blinding method and optimisation suggested in section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int dhm_update_blinding( mbedtls_dhm_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count; + + /* + * Don't use any blinding the first time a particular X is used, + * but remember it to use blinding next time. + */ + if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); + + return( 0 ); + } + + /* + * Ok, we need blinding. Can we re-use existing values? + * If yes, just update them by squaring them. + */ + if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + return( 0 ); + } + + /* + * We need to generate blinding values from scratch + */ + + /* Vi = random( 2, P-1 ) */ + count = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); + + /* Vf = Vi^-X mod P */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + return( ret ); +} + +/* + * Derive and export the shared secret (G^Y)^X mod P + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi GYb; + + if( ctx == NULL || output_size < ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mbedtls_mpi_init( &GYb ); + + /* Blind peer's value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); + + /* Do modular exponentiation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + } + + *olen = mbedtls_mpi_size( &ctx->K ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mbedtls_mpi_free( &GYb ); + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) +{ + mbedtls_mpi_free( &ctx->pX ); mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); + mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); +} + +#if defined(MBEDTLS_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret; + size_t len; + unsigned char *p, *end; +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN DH PARAMETERS-----", + "-----END DH PARAMETERS-----", + dhmin, NULL, 0, &dhminlen ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + dhminlen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* MBEDTLS_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * privateValueLength INTEGER OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + if( p != end ) + { + /* This might be the optional privateValueLength. + * If so, we can cleanly discard it */ + mbedtls_mpi rec; + mbedtls_mpi_init( &rec ); + ret = mbedtls_asn1_get_mpi( &p, end, &rec ); + mbedtls_mpi_free( &rec ); + if ( ret != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + if ( p != end ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto exit; + } + } + + ret = 0; + + dhm->len = mbedtls_mpi_size( &dhm->P ); + +exit: +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + if( ret != 0 ) + mbedtls_dhm_free( dhm ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_zeroize( *buf, *n + 1 ); + 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 */ +#endif /* MBEDTLS_DHM_ALT */ + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecdh.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ECDH_C) + + + +#include + +#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) +/* + * 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 ); +} +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ + +#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) +/* + * 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 ); +} +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +/* + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecdsa.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ECDSA_C) + + + + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + +#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 ); +} + +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/* + * 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 ); + + /* Make sure d is in range 1..n-1 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + 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 ); +} +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +#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 */ + +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * 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 ); +} +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + +/* + * 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 ); +} + +#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) +/* + * 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 ) ); +} +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ + +/* + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecjpake.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ECJPAKE_C) + + + +#include + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +/* + * 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 + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecp.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ECP_C) + + + + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define ECP_SHORTWEIERSTRASS +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define ECP_MONTGOMERY +#endif + +/* + * Curve types: internal for now, might be exposed later + */ +typedef enum +{ + ECP_TYPE_NONE = 0, + ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} ecp_curve_type; + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. This provides the default order for the SSL module. + * + * Reminder: update profiles in x509_crt.c when adding a new curves! + */ +static const mbedtls_ecp_curve_info ecp_supported_curves[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif + { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( strcmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( ECP_TYPE_MONTGOMERY ); + else + return( ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_init( &pt->X ); + mbedtls_mpi_init( &pt->Y ); + mbedtls_mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) +{ + if( grp == NULL ) + return; + + memset( grp, 0, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Initialize (the components of) a key pair + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_init( &key->grp ); + mbedtls_mpi_init( &key->d ); + mbedtls_ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_free( &( pt->X ) ); + mbedtls_mpi_free( &( pt->Y ) ); + mbedtls_mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mbedtls_mpi_free( &grp->P ); + mbedtls_mpi_free( &grp->A ); + mbedtls_mpi_free( &grp->B ); + mbedtls_ecp_point_free( &grp->G ); + mbedtls_mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + + mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_free( &key->grp ); + mbedtls_mpi_free( &key->d ); + mbedtls_ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) +{ + return mbedtls_ecp_group_load( dst, src->id ); +} + +/* + * Set point to zero + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) +{ + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Compare two points lazyly + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3) + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = 0; + size_t plen; + + if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && + format != MBEDTLS_ECP_PF_COMPRESSED ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Common case: P == 0 + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == MBEDTLS_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + } + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret; + size_t plen; + + if( ilen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( mbedtls_ecp_set_zero( pt ) ); + else + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( buf[0] != 0x04 ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret; + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const mbedtls_ecp_curve_info *curve_info; + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + return mbedtls_ecp_group_load( grp, curve_info->grp_id ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_ecp_curve_info *curve_info; + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + buf[0] = curve_info->tls_id >> 8; + buf[1] = curve_info->tls_id & 0xFF; + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. + * See the documentation of struct mbedtls_ecp_group. + * + * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) +{ + int ret; + + if( grp->modp == NULL ) + return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || + mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + MBEDTLS_MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); + + while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi + */ +#if defined(MBEDTLS_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ + while( 0 ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) ) + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with coutermeasueres against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi Zi, ZZi; + + if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_jac( grp, pt ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); + + /* + * Y = Y / Z^3 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); + + /* + * Z = 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + + return( ret ); +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ) +{ + int ret; + size_t i; + mbedtls_mpi *c, u, Zi, ZZi; + + if( t_len < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len); + } +#endif + + if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < t_len; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); + MOD_MUL( c[i] ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); + + for( i = t_len - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); + } + + /* + * proceed as in normalize() + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + for( i = 0; i < t_len; i++ ) + mbedtls_mpi_free( &c[i] ); + mbedtls_free( c ); + + return( ret ); +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *Q, + unsigned char inv ) +{ + int ret; + unsigned char nonzero; + mbedtls_mpi mQY; + + mbedtls_mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mbedtls_mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . + * + * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR + * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. + * + * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + */ +static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ + int ret; + mbedtls_mpi M, S, T, U; + +#if defined(MBEDTLS_SELF_TEST) + dbl_count++; +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_double_jac( grp, R, P ); + } +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); + } + } + + /* S = 4.X.Y^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); + + /* U = 8.Y^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + /* T = M^2 - 2.S */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + + /* S = M(S - T) - U */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); + + /* U = 2.Y.Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); + +cleanup: + mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); + + return( ret ); +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + +#if defined(MBEDTLS_SELF_TEST) + add_count++; +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_add_mixed( grp, R, P, Q ); + } +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); + + /* Special cases (2) and (3) */ + if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = mbedtls_ecp_set_zero( R ); + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + + return( ret ); +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l, ll; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ); + } +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + /* Z = l * Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); + + /* X = l^2 * X */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); + + /* Y = l^3 * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); + +cleanup: + mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); + + return( ret ); +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 +#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries. + * + * Also, for the sake of compactness, only the seven low-order bits of x[i] + * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in + * the paper): it is set if and only if if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_fixed( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the comb method + * + * If i = i_{w-1} ... i_1 is the binary representation of i, then + * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P + * + * T must be able to hold 2^{w - 1} elements + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + */ +static int ecp_precompute_comb( const mbedtls_ecp_group *grp, + mbedtls_ecp_point T[], const mbedtls_ecp_point *P, + unsigned char w, size_t d ) +{ + int ret; + unsigned char i, k; + size_t j; + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); + + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + cur = T + i; + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + for( j = 0; j < d; j++ ) + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + + TT[k++] = cur; + } + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + j = i; + while( j-- ) + { + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + TT[k++] = &T[i + j]; + } + } + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + +cleanup: + + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + */ +static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char t_len, + unsigned char i ) +{ + int ret; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < t_len; j++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char t_len, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point Txi; + size_t i; + + mbedtls_ecp_point_init( &Txi ); + + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + + while( i-- != 0 ) + { + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + + mbedtls_ecp_point_free( &Txi ); + + return( ret ); +} + +/* + * Multiplication using the comb method, + * for curves in short Weierstrass form + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char w, m_is_odd, p_eq_g, pre_len, i; + size_t d; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *T; + mbedtls_mpi M, mm; + + mbedtls_mpi_init( &M ); + mbedtls_mpi_init( &mm ); + + /* we need N to be odd to trnaform m in an odd number, check now */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); + if( p_eq_g ) + w++; +#else + p_eq_g = 0; +#endif + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ + if( w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; + if( w >= grp->nbits ) + w = 2; + + /* Other sizes that depend on w */ + pre_len = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* + * Prepare precomputed points: if P == G we want to + * use grp->T if already initialized, or initialize it. + */ + T = p_eq_g ? grp->T : NULL; + + if( T == NULL ) + { + T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); + if( T == NULL ) + { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); + + if( p_eq_g ) + { + grp->T = T; + grp->T_size = pre_len; + } + } + + /* + * Make sure M is odd (M = m or M = N - m, since N is odd) + * using the fact that m * P = - (N - m) * P + */ + m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + + /* + * Go for comb multiplication, R = M * P + */ + ecp_comb_fixed( k, d, w, &M ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); + + /* + * Now get m * P from M * P and normalize it + */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + + if( T != NULL && ! 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; + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_mxz( grp, P ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); + } +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); + +cleanup: + mbedtls_mpi_free( &l ); + + return( ret ); +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + const mbedtls_mpi *d ) +{ + int ret; + mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ); + } +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); + mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); + +cleanup: + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); + mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); + + return( ret ); +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t i; + unsigned char b; + mbedtls_ecp_point RP; + mbedtls_mpi PX; + + mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); + + /* Save PX and read from P before writing to R, in case P == R */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); + mbedtls_mpi_free( &R->Y ); + + /* RP.X might be sligtly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ + if( f_rng != NULL ) + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mbedtls_mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); + + return( ret ); +} + +#endif /* ECP_MONTGOMERY */ + +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + + /* Common sanity checks */ + if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || + ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) + { + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ); + +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng ); + +#endif +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +cleanup: + + if ( is_grp_capable ) + { + mbedtls_internal_ecp_free( grp ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + return( ret ); +} + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || + mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || + mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); + + if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + +cleanup: + + mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); + + return( ret ); +} +#endif /* ECP_SHORTWEIERSTRASS */ + +/* + * R = m * P with shortcuts for m == 1 and m == -1 + * NOT constant-time - ONLY for short Weierstrass! + */ +static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *P ) +{ + int ret; + + if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + } + else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + } + +cleanup: + return( ret ); +} + +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_ecp_point mP; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + + if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) + { + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable ) + { + mbedtls_internal_ecp_free( grp ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + mbedtls_ecp_point_free( &mP ); + + return( ret ); +} + + +#if defined(ECP_MONTGOMERY) +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); +} +#endif /* ECP_MONTGOMERY */ + +/* + * Check that a point is valid as a public key + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mbedtls_mpi is valid as a private key + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) +{ +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* see [Curve25519] page 5 */ + if( mbedtls_mpi_get_bit( d, 0 ) != 0 || + mbedtls_mpi_get_bit( d, 1 ) != 0 || + mbedtls_mpi_get_bit( d, 2 ) != 0 || + mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* ECP_SHORTWEIERSTRASS */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* [M225] page 5 */ + size_t b; + + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + } while( mbedtls_mpi_bitlen( d ) == 0); + + /* Make sure the most significant bit is nbits */ + b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ + if( b > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); + + /* Make sure the last three bits are unset */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } + else +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* SEC1 3.2.1: Generate d such that 1 <= n < N */ + int count = 0; + + /* + * 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( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); + + /* + * Each try has at worst a probability 1/2 of failing (the msb has + * a probability 1/2 of being 0, and then the result will be < N), + * so after 30 tries failure probability is a most 2**(-30). + * + * For most curves, 1 try is enough with overwhelming probability, + * since N starts with a lot of 1s in binary, but some curves + * such as secp224k1 are actually very close to the worst case. + */ + if( ++count > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); + } + else +#endif /* ECP_SHORTWEIERSTRASS */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +cleanup: + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); +} + +/* + * Generate key pair, wrapper for conventional base point + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +/* + * Check a public-private key pair + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) +{ + int ret; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + + if( pub->grp.id == MBEDTLS_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + mbedtls_ecp_point_init( &Q ); + mbedtls_ecp_group_init( &grp ); + + /* mbedtls_ecp_mul() needs a non-const group... */ + mbedtls_ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); + + if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &Q ); + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Checkup routine + */ +int mbedtls_ecp_self_test( int verbose ) +{ + int ret; + size_t i; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, P; + mbedtls_mpi m; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + /* exponents especially adapted for secp192r1 */ + const char *exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &P ); + mbedtls_mpi_init( &m ); + + /* Use secp192r1 if available, or any available curve */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); +#else + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); + + /* Do a dummy multiplication first to trigger precomputation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret < 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &P ); + mbedtls_mpi_free( &m ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecp_curves.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ECP_C) + + + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) a << 0 ) | \ + ( (mbedtls_mpi_uint) b << 8 ) | \ + ( (mbedtls_mpi_uint) c << 16 ) | \ + ( (mbedtls_mpi_uint) d << 24 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_4( a, b, c, d ), \ + BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) a << 0 ) | \ + ( (mbedtls_mpi_uint) b << 8 ) | \ + ( (mbedtls_mpi_uint) c << 16 ) | \ + ( (mbedtls_mpi_uint) d << 24 ) | \ + ( (mbedtls_mpi_uint) e << 32 ) | \ + ( (mbedtls_mpi_uint) f << 40 ) | \ + ( (mbedtls_mpi_uint) g << 48 ) | \ + ( (mbedtls_mpi_uint) h << 56 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in mbedtls_mpi_uint */ + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + */ +static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( mbedtls_mpi_uint ); + X->p = (mbedtls_mpi_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mbedtls_mpi *X ) +{ + static mbedtls_mpi_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + grp->h = 1; + + return( 0 ); +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mbedtls_mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mbedtls_mpi * ); +#endif + +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( mbedtls_ecp_group *grp ) +{ + int ret; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); + + /* P = 2^255 - 19 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionaly not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) +{ + mbedtls_ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + + default: + mbedtls_ecp_group_free( grp ); + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) +#define A( i ) N->p + i * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi_uint c = 0; + mbedtls_mpi_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (mbedtls_mpi_uint) cur; \ + } + +#endif /* sizeof( mbedtls_mpi_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +/* + * Helpers for the main 'loop' + * (see fix_negative for the motivation of C) + */ +#define INIT( b ) \ + int ret; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = b; \ + mbedtls_mpi C; \ + mbedtls_mpi_uint Cp[ b / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ + \ + C.s = 1; \ + C.n = b / 8 / sizeof( mbedtls_mpi_uint) + 1; \ + C.p = Cp; \ + memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ + \ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, b * 2 / 8 / sizeof( mbedtls_mpi_uint ) ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) fix_negative( N, c, &C, bits ); + +/* + * If the result is negative, we get it in the form + * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' + */ +static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) +{ + int ret; + + /* C = - c * 2^(bits + 32) */ +#if !defined(MBEDTLS_HAVE_INT64) + ((void) bits); +#else + if( bits == 224 ) + C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; + else +#endif + C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; + + /* N = - ( C - N ) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); + N->s = -1; + +cleanup: + + return( ret ); +} + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mbedtls_mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mbedtls_mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mbedtls_mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + M.n = P255_WIDTH + 1; + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, mbedtls_mpi_uint mask ) +{ + int ret; + size_t i; + mbedtls_mpi M, R; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(MBEDTLS_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/entropy.c ************/ + +/* + * 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) + +#else + +#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 + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_HAVEGE_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + ctx->accumulator_started = 0; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_init( &ctx->accumulator ); +#else + mbedtls_sha256_init( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + +#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 ); + ctx->initial_entropy_run = 0; +#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 +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_free( &ctx->accumulator ); +#else + mbedtls_sha256_free( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + ctx->initial_entropy_run = 0; +#endif + ctx->source_count = 0; + mbedtls_zeroize( ctx->source, sizeof( ctx->source ) ); + ctx->accumulator_started = 0; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ) +{ + int idx, ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + idx = ctx->source_count; + if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) + { + ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + ctx->source[idx].f_source = f_source; + ctx->source[idx].p_source = p_source; + ctx->source[idx].threshold = threshold; + ctx->source[idx].strong = strong; + + ctx->source_count++; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + int ret = 0; + + if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#else + if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#endif + p = tmp; + use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + + /* + * Start the accumulator if this has not already happened. Note that + * it is sufficient to start the accumulator here only because all calls to + * gather entropy eventually execute this code. + */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); +#else + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); +#endif + +cleanup: + mbedtls_zeroize( tmp, sizeof( tmp ) ); + + return( ret ); +} + +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 ) + { + goto cleanup; + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + if( ( ret = entropy_update( ctx, (unsigned char) i, + buf, olen ) ) != 0 ) + return( ret ); + ctx->source[i].size += olen; + } + } + + if( have_one_strong == 0 ) + ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * 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) + /* + * Note that at this stage it is assumed that the accumulator was started + * in a previous call to entropy_update(). If this is not guaranteed, the + * code below will fail. + */ + if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha512_free( &ctx->accumulator ); + mbedtls_sha512_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-512 on entropy + */ + if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha256_free( &ctx->accumulator ); + mbedtls_sha256_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-256 on entropy + */ + if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#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: + mbedtls_zeroize( buf, sizeof( buf ) ); + +#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_BLOCK_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 ); + ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + return( ret ); +} +#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: + mbedtls_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = 0; + 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 ) + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = mbedtls_entropy_update_manual( ctx, buf, n ); + + fclose( f ); + + mbedtls_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/entropy_poll.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ENTROPY_C) + + + + +#if defined(MBEDTLS_TIMING_C) +#include + +#endif +#if defined(MBEDTLS_HAVEGE_C) + +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/error.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#define mbedtls_snprintf snprintf +#define mbedtls_time_t time_t +#endif + +#if defined(MBEDTLS_ERROR_C) + +#include + +#if defined(MBEDTLS_AES_C) + +#endif + +#if defined(MBEDTLS_ARC4_C) + +#endif + +#if defined(MBEDTLS_BASE64_C) + +#endif + +#if defined(MBEDTLS_BIGNUM_C) + +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + +#endif + +#if defined(MBEDTLS_CCM_C) + +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#endif + +#if defined(MBEDTLS_CMAC_C) + +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + +#endif + +#if defined(MBEDTLS_DES_C) + +#endif + +#if defined(MBEDTLS_DHM_C) + +#endif + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_ENTROPY_C) + +#endif + +#if defined(MBEDTLS_GCM_C) + +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + +#endif + +#if defined(MBEDTLS_MD_C) + +#endif + +#if defined(MBEDTLS_MD2_C) + +#endif + +#if defined(MBEDTLS_MD4_C) + +#endif + +#if defined(MBEDTLS_MD5_C) + +#endif + +#if defined(MBEDTLS_NET_C) + +#endif + +#if defined(MBEDTLS_OID_C) + +#endif + +#if defined(MBEDTLS_PADLOCK_C) + +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#endif + +#if defined(MBEDTLS_PK_C) + +#endif + +#if defined(MBEDTLS_PKCS12_C) + +#endif + +#if defined(MBEDTLS_PKCS5_C) + +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + +#endif + +#if defined(MBEDTLS_RSA_C) + +#endif + +#if defined(MBEDTLS_SHA1_C) + +#endif + +#if defined(MBEDTLS_SHA256_C) + +#endif + +#if defined(MBEDTLS_SHA512_C) + +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#endif + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + +#endif + +#if defined(MBEDTLS_XTEA_C) + +#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" ); + 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. For example, because it was freed" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Cipher hardware accelerator failed" ); +#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" ); + 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 or write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - DHM hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Setting the modulus and generator 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" ); + if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - ECP hardware accelerator failed" ); +#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" ); + if( use_ret == -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - MD hardware accelerator 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" ); + if( use_ret == -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - PK hardware accelerator failed" ); +#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 validity check of the library" ); + 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" ); + if( use_ret == -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION) ) + mbedtls_snprintf( buf, buflen, "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); + if( use_ret == -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - RSA hardware accelerator failed" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) + mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) + mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) + mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) + mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); + if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) + { + mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); + return; + } + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) + mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) + mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) + mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) + mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) + mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) + mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) + mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) + mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) + mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) + mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) + mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) + mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) + mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) + mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) + mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); + if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); + if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); + if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed" ); +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + // END generated code + + if( strlen( buf ) == 0 ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Low level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_AES_C) + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" ); + if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "AES - AES hardware accelerator failed" ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + if( use_ret == -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" ); +#endif /* MBEDTLS_ARC4_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_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" ); + 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" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Camellia hardware accelerator failed" ); +#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 the function" ); + if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CMAC_C) + if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" ); +#endif /* MBEDTLS_CMAC_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 - The requested random buffer length is too big" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The input (entropy + additional data) is too large" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read or 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" ); + if( use_ret == -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DES - DES hardware accelerator failed" ); +#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_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - GCM hardware accelerator 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_MD2_C) + if( use_ret == -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD2 - MD2 hardware accelerator failed" ); +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + if( use_ret == -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD4 - MD4 hardware accelerator failed" ); +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + if( use_ret == -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD5 - MD5 hardware accelerator failed" ); +#endif /* MBEDTLS_MD5_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_RIPEMD160_C) + if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA512_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" ); + if( use_ret == -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "XTEA - XTEA hardware accelerator failed" ); +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/gcm.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_GCM_C) + + + +#include + +#if defined(MBEDTLS_AESNI_C) + +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_GCM_ALT) + +/* + * 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 */ +/* zeroize was here */ + +/* + * Initialize a context + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); +} + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( mbedtls_gcm_context *ctx ) +{ + int ret, i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char h[16]; + size_t olen = 0; + + memset( h, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); + + /* pack h as two 64-bits ints, big-endian */ + GET_UINT32_BE( hi, h, 0 ); + GET_UINT32_BE( lo, h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + GET_UINT32_BE( hi, h, 8 ); + GET_UINT32_BE( lo, h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) + return( 0 ); +#endif + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for( i = 4; i > 0; i >>= 1 ) + { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for( i = 2; i <= 8; i *= 2 ) + { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for( j = 1; j < i; j++ ) + { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return( 0 ); +} + +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = +{ + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { + unsigned char h[16]; + + PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); + PUT_UINT32_BE( ctx->HH[8], h, 4 ); + PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); + PUT_UINT32_BE( ctx->HL[8], h, 12 ); + + mbedtls_aesni_gcm_mult( output, x, h ); + return; + } +#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ + + lo = x[15] & 0xf; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + for( i = 15; i >= 0; i-- ) + { + lo = x[i] & 0xf; + hi = x[i] >> 4; + + if( i != 15 ) + { + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + } + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + PUT_UINT32_BE( zh >> 32, output, 0 ); + PUT_UINT32_BE( zh, output, 4 ); + PUT_UINT32_BE( zl >> 32, output, 8 ); + PUT_UINT32_BE( zl, output, 12 ); +} + +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ) +{ + int ret; + unsigned char work_buf[16]; + size_t i; + const unsigned char *p; + size_t use_len, olen = 0; + + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + /* IV is not allowed to be zero length */ + if( iv_len == 0 || + ( (uint64_t) iv_len ) >> 61 != 0 || + ( (uint64_t) add_len ) >> 61 != 0 ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + memset( ctx->y, 0x00, sizeof(ctx->y) ); + memset( ctx->buf, 0x00, sizeof(ctx->buf) ); + + ctx->mode = mode; + ctx->len = 0; + ctx->add_len = 0; + + if( iv_len == 12 ) + { + memcpy( ctx->y, iv, iv_len ); + ctx->y[15] = 1; + } + else + { + memset( work_buf, 0x00, 16 ); + PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); + + p = iv; + while( iv_len > 0 ) + { + use_len = ( iv_len < 16 ) ? iv_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->y[i] ^= p[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + + iv_len -= use_len; + p += use_len; + } + + for( i = 0; i < 16; i++ ) + ctx->y[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + } + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + ctx->add_len = add_len; + p = add; + while( add_len > 0 ) + { + use_len = ( add_len < 16 ) ? add_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->buf[i] ^= p[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + add_len -= use_len; + p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char ectr[16]; + size_t i; + const unsigned char *p; + unsigned char *out_p = output; + size_t use_len, olen = 0; + + if( output > input && (size_t) ( output - input ) < length ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if( ctx->len + length < ctx->len || + (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + ctx->len += length; + + p = input; + while( length > 0 ) + { + use_len = ( length < 16 ) ? length : 16; + + for( i = 16; i > 12; i-- ) + if( ++ctx->y[i - 1] != 0 ) + break; + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == MBEDTLS_GCM_DECRYPT ) + ctx->buf[i] ^= p[i]; + out_p[i] = ectr[i] ^ p[i]; + if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) + ctx->buf[i] ^= out_p[i]; + } + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + length -= use_len; + p += use_len; + out_p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ) +{ + unsigned char work_buf[16]; + size_t i; + uint64_t orig_len = ctx->len * 8; + uint64_t orig_add_len = ctx->add_len * 8; + + if( tag_len > 16 || tag_len < 4 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + memcpy( tag, ctx->base_ectr, tag_len ); + + if( orig_len || orig_add_len ) + { + memset( work_buf, 0x00, 16 ); + + PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); + PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); + PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); + PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); + + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + for( i = 0; i < tag_len; i++ ) + tag[i] ^= ctx->buf[i]; + } + + return( 0 ); +} + +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret; + + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_zeroize( output, length ); + return( MBEDTLS_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); +} + +#endif /* !MBEDTLS_GCM_ALT */ + +#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; + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 ) + { + mbedtls_printf( "skipped\n" ); + break; + } + else if( ret != 0 ) + { + goto exit; + } + + 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 ) + goto exit; + + if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + 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 ) + goto exit; + + if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + 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 ) + goto exit; + + 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 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + 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 ) + goto exit; + + 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 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], + buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + ret = 0; + +exit: + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + mbedtls_gcm_free( &ctx ); + } + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_GCM_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/havege.c ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_HAVEGE_C) + + + + +#include + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* ------------------------------------------------------------------------ + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/hmac_drbg.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + + + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 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 ); + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = 0; + 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 ) + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + else + mbedtls_hmac_drbg_update( ctx, buf, n ); + + fclose( f ); + + mbedtls_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md.c ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_MD_C) + + + + +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 ); + + return( ctx->md_info->starts_func( ctx->md_ctx ) ); +} + +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 ); + + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); +} + +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 ); + + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); +} + +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 ); + + return( md_info->digest_func( input, ilen, output ) ); +} + +#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; + + if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 ) + goto cleanup; + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 ) + goto cleanup; + + if( ferror( f ) != 0 ) + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + else + ret = md_info->finish_func( ctx.md_ctx, output ); + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + 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 ) +{ + int ret; + 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 ) + { + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 ) + goto cleanup; + + 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] ); + } + + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_zeroize( sum, sizeof( sum ) ); + + return( ret ); +} + +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 ); + + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret; + 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; + + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret; + 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; + + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + return( ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ); +} + +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 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +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 ); + + return( ctx->md_info->process_func( ctx->md_ctx, data ) ); +} + +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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md2.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_MD2_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +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 + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ) +{ + memset( ctx->cksum, 0, 16 ); + memset( ctx->state, 0, 46 ); + memset( ctx->buffer, 0, 16 ); + ctx->left = 0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_starts( mbedtls_md2_context *ctx ) +{ + mbedtls_md2_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD2_PROCESS_ALT) +int mbedtls_internal_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]; + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_process( mbedtls_md2_context *ctx ) +{ + mbedtls_internal_md2_process( ctx ); +} +#endif +#endif /* !MBEDTLS_MD2_PROCESS_ALT */ + +/* + * MD2 process buffer + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + + while( ilen > 0 ) + { + if( ilen > 16 - ctx->left ) + fill = 16 - ctx->left; + else + fill = ilen; + + memcpy( ctx->buffer + ctx->left, input, fill ); + + ctx->left += fill; + input += fill; + ilen -= fill; + + if( ctx->left == 16 ) + { + ctx->left = 0; + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + } + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md2_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD2 final digest + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + int ret; + size_t i; + unsigned char x; + + x = (unsigned char)( 16 - ctx->left ); + + for( i = ctx->left; i < 16; i++ ) + ctx->buffer[i] = x; + + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( ctx->buffer, ctx->cksum, 16 ); + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( output, ctx->state, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md2_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD2_ALT */ + +/* + * output = MD2( input buffer ) + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md2_context ctx; + + mbedtls_md2_init( &ctx ); + + if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md2_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md2_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1319 test vectors + */ +static const unsigned char md2_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md2_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +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, ret = 0; + unsigned char md2sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD2 test #%d: ", i + 1 ); + + ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD2_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md4.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_MD4_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 + */ +int mbedtls_md4_starts_ret( 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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_starts( mbedtls_md4_context *ctx ) +{ + mbedtls_md4_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD4_PROCESS_ALT) +int mbedtls_internal_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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md4_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD4_PROCESS_ALT */ + +/* + * MD4 process buffer + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + 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 ); + + if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md4_update_ret( ctx, input, ilen ); +} +#endif + +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 + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + int ret; + 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 ); + + ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); + if( ret != 0 ) + return( ret ); + + if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + + 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 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md4_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD4_ALT */ + +/* + * output = MD4( input buffer ) + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md4_context ctx; + + mbedtls_md4_init( &ctx ); + + if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md4_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md4_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1320 test vectors + */ +static const unsigned char md4_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md4_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +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, ret = 0; + unsigned char md4sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD4 test #%d: ", i + 1 ); + + ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD4_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md5.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_MD5_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 + */ +int mbedtls_md5_starts_ret( 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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + mbedtls_md5_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md5_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + 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 ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update_ret( ctx, input, ilen ); +} +#endif + +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 + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret; + 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 ); + + if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + 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 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md5_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + + if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md5_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md5_ret( input, ilen, output ); +} +#endif + +#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 size_t 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, ret = 0; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md_wrap.c ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_MD_C) + + + +#if defined(MBEDTLS_MD2_C) + +#endif + +#if defined(MBEDTLS_MD4_C) + +#endif + +#if defined(MBEDTLS_MD5_C) + +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + +#endif + +#if defined(MBEDTLS_SHA1_C) + +#endif + +#if defined(MBEDTLS_SHA256_C) + +#endif + +#if defined(MBEDTLS_SHA512_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_MD2_C) + +static int md2_starts_wrap( void *ctx ) +{ + return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) ); +} + +static int md2_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) ); +} + +static int md2_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md2_finish_ret( (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 int md2_process_wrap( void *ctx, const unsigned char *data ) +{ + ((void) data); + + return( mbedtls_internal_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_ret, + md2_ctx_alloc, + md2_ctx_free, + md2_clone_wrap, + md2_process_wrap, +}; + +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + +static int md4_starts_wrap( void *ctx ) +{ + return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) ); +} + +static int md4_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) ); +} + +static int md4_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md4_finish_ret( (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 int md4_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_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_ret, + md4_ctx_alloc, + md4_ctx_free, + md4_clone_wrap, + md4_process_wrap, +}; + +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + +static int md5_starts_wrap( void *ctx ) +{ + return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) ); +} + +static int md5_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) ); +} + +static int md5_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md5_finish_ret( (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 int md5_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_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_ret, + md5_ctx_alloc, + md5_ctx_free, + md5_clone_wrap, + md5_process_wrap, +}; + +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + +static int ripemd160_starts_wrap( void *ctx ) +{ + return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) ); +} + +static int ripemd160_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx, + input, ilen ) ); +} + +static int ripemd160_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_ripemd160_finish_ret( (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 int ripemd160_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_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_ret, + ripemd160_ctx_alloc, + ripemd160_ctx_free, + ripemd160_clone_wrap, + ripemd160_process_wrap, +}; + +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + +static int sha1_starts_wrap( void *ctx ) +{ + return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) ); +} + +static int sha1_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx, + input, ilen ) ); +} + +static int sha1_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha1_finish_ret( (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 int sha1_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_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_ret, + 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 int sha224_starts_wrap( void *ctx ) +{ + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) ); +} + +static int sha224_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx, + input, ilen ) ); +} + +static int sha224_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx, + output ) ); +} + +static int sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha256_ret( 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 int sha224_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_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 int sha256_starts_wrap( void *ctx ) +{ + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) ); +} + +static int sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha256_ret( 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 int sha384_starts_wrap( void *ctx ) +{ + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) ); +} + +static int sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx, + input, ilen ) ); +} + +static int sha384_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx, + output ) ); +} + +static int sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha512_ret( 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 int sha384_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_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 int sha512_starts_wrap( void *ctx ) +{ + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) ); +} + +static int sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha512_ret( 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/memory_buffer_alloc.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + + +/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C + is dependent upon MBEDTLS_PLATFORM_C */ + + +#include + +#if defined(MBEDTLS_MEMORY_BACKTRACE) +#include +#endif + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#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( void ) +{ + 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( void ) +{ + memory_header *prv = heap.first, *cur; + + if( prv == NULL || verify_header( prv ) != 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 ); + } + + cur = heap.first->next; + + 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 || size == 0 || len / n != size ) + return( NULL ); + else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + 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( void ) +{ + return verify_chain(); +} + +#if defined(MBEDTLS_MEMORY_DEBUG) +void mbedtls_memory_buffer_alloc_status( void ) +{ + 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 ) ); + +#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( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return; + else 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; + } + + memset( buf, 0, len ); + + 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( void ) +{ +#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( void ) +{ + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/net_sockets.c ************/ + +/* + * 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) + +#else + +#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) + +#else +#include +#endif + + + +#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 functions use socklen_t, so cast only for MSVC */ +#if defined(_MSC_VER) +#define MSVC_INT_CAST (int) +#else +#define MSVC_INT_CAST +#endif + +#include + +#include + +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int n, ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if( proto == MBEDTLS_NET_PROTO_TCP ) + { + if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* Bind was successful */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + int err = errno; + + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) + { + errno = err; + return( 0 ); + } + + switch( errno = err ) + { +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/oid.c ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_OID_C) + + + + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + +#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) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/padlock.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_PADLOCK_C) + + + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pem.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + + + + + + + + +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +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 int 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; + int ret; + + mbedtls_md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + goto exit; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + +exit: + mbedtls_md5_free( &md5_ctx ); + mbedtls_zeroize( md5sum, 16 ); + + return( ret ); +} + +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static int 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]; + int ret; + + mbedtls_des_init( &des_ctx ); + + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); + +exit: + mbedtls_des_free( &des_ctx ); + mbedtls_zeroize( des_key, 8 ); + + return( ret ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static int 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]; + int ret; + + mbedtls_des3_init( &des3_ctx ); + + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); + +exit: + mbedtls_des3_free( &des3_ctx ); + mbedtls_zeroize( des3_key, 24 ); + + return( ret ); +} +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static int 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]; + int ret; + + mbedtls_aes_init( &aes_ctx ); + + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); + +exit: + mbedtls_aes_free( &aes_ctx ); + mbedtls_zeroize( aes_key, keylen ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ + + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); + + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) + { + mbedtls_zeroize( buf, len ); + 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_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } + + ret = 0; + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + ret = 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 ) + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } + + /* + * 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_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_zeroize( buf, len ); + 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 ) +{ + if( ctx->buf != NULL ) + mbedtls_zeroize( ctx->buf, ctx->buflen ); + 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 = NULL, *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( use_len != 0 && + ( ( 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pk.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_PK_C) + + + +#if defined(MBEDTLS_RSA_C) + +#endif +#if defined(MBEDTLS_ECP_C) + +#endif +#if defined(MBEDTLS_ECDSA_C) + +#endif + +#include +#include + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 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 SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + NULL, NULL, MBEDTLS_RSA_PUBLIC, + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } + + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + +/* + * Decrypt message + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) +{ + if( pub == NULL || pub->pk_info == NULL || + prv == NULL || prv->pk_info == NULL || + prv->pk_info->check_pair_func == NULL ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#endif /* MBEDTLS_PK_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pk_wrap.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_PK_C) + + +/* Even if RSA not activated, for the sake of RSA-alt */ + + +#include + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#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 ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} + +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; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + if( sig_len > rsa_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 ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + + return( mbedtls_rsa_pkcs1_sign( rsa, 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 ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( rsa, 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 ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#else + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +} + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkcs11.c ************/ + +/** + * \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) + */ + + + +#if defined(MBEDTLS_PKCS11_C) + + + + + +#if defined(MBEDTLS_PLATFORM_C) + +#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) */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkcs12.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_PKCS12_C) + + + + + +#include + +#if defined(MBEDTLS_ARC4_C) + +#endif + +#if defined(MBEDTLS_DES_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkcs5.c ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_PKCS5_C) + + + + + + +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#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_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkparse.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_PK_PARSE_C) + + + + + +#include + +#if defined(MBEDTLS_RSA_C) + +#endif +#if defined(MBEDTLS_ECP_C) + +#endif +#if defined(MBEDTLS_ECDSA_C) + +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif +#if defined(MBEDTLS_PKCS5_C) + +#endif +#if defined(MBEDTLS_PKCS12_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_FS_IO) || \ + defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#endif + +#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. + */ +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_zeroize( *buf, *n ); + 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; + + if ( end - *p < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* 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 ); + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + + if( *p != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + 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, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init( &T ); + + 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, &version ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( version != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, p, len ) ) != 0 ) + goto cleanup; + p += len; + + /* Import D */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + p, len, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import P */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import Q */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Complete the RSA private key */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ) + goto cleanup; + + /* Check optional parameters */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; + + if( p != end ) + { + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ; + } + +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret; + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + + mbedtls_rsa_free( rsa ); + } + + return( ret ); +} +#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 + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * + */ +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 PrivateKeyInfo 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 + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + 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 + + p = key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivateKeyInfo 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 ); + + buf = p; + + /* + * Decrypt EncryptedData with appropriate PBE + */ +#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 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + 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 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + + 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) + { + unsigned char *key_copy; + + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen ); + + mbedtls_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); + } + + if( ret == 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) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + key, keylen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + else + { + return( 0 ); + } + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + else + { + return( 0 ); + } + +#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_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#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 PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* 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 PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + mbedtls_pem_free( &pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#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( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkwrite.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_PK_WRITE_C) + + + + + +#include + +#if defined(MBEDTLS_RSA_C) + +#endif +#if defined(MBEDTLS_ECP_C) + +#endif +#if defined(MBEDTLS_ECDSA_C) + +#endif +#if defined(MBEDTLS_PEM_WRITE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#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_mpi T; + + mbedtls_mpi_init( &T ); + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + +end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + 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_mpi T; /* Temporary holding the exported parameters */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init( &T ); + + /* Export QP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DQ */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export Q */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export P */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export D */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/platform.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + + + +#if defined(MBEDTLS_ENTROPY_NV_SEED) && \ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#endif + +#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) && !defined(__MINGW32__) + 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 ); + mbedtls_zeroize( buf, buf_len ); + return( -1 ); + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#endif /* MBEDTLS_PLATFORM_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ripemd160.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) + +/* + * 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 */ +/* zeroize was here */ + +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 + */ +int mbedtls_ripemd160_starts_ret( 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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + mbedtls_ripemd160_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +int mbedtls_internal_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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_ripemd160_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + 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 ); + + if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update_ret( ctx, input, ilen ); +} +#endif + +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 + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + int ret; + 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 ); + + ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 ); + if( ret != 0 ) + return( ret ); + + 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 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + mbedtls_ripemd160_finish_ret( ctx, output ); +} +#endif + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + +/* + * output = RIPEMD-160( input buffer ) + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret; + mbedtls_ripemd160_context ctx; + + mbedtls_ripemd160_init( &ctx ); + + if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_ripemd160_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_ripemd160_ret( input, ilen, output ); +} +#endif + +#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 +static const unsigned char ripemd160_test_str[TESTS][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" }, +}; + +static const size_t ripemd160_test_strlen[TESTS] = +{ + 0, 1, 3, 14, 26, 56, 62, 80 +}; + +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, ret = 0; + 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 ); + + ret = mbedtls_ripemd160_ret( ripemd160_test_str[i], + ripemd160_test_strlen[i], output ); + if( ret != 0 ) + goto fail; + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RIPEMD160_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/rsa.c ************/ + +/* + * The RSA public-key cryptosystem + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_RSA_C) + + + + + +#include + +#if defined(MBEDTLS_PKCS1_V21) + +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_RSA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* constant-time buffer comparison */ +static inline int mbedtls_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 ); +} + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret; + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + + const int have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + const int have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + const int have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + const int n_missing = have_P && have_Q && have_D && have_E; + const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + const int d_missing = have_P && have_Q && !have_D && have_E; + const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + const int is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + + /* Check if key is private or public */ + const int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret; + + /* Check if key is private or public */ + int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret; + + /* Check if key is private or public */ + int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif + + return( 0 ); +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ) +{ + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + mbedtls_rsa_set_padding( ctx, padding, hash_id ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) +{ + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + +#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 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( &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 ); + + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + } + while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + + /* + * 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 ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); + +cleanup: + + 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( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + 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 for the consistency of all fields in an RSA private key context + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif + + 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; + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); + + /* Blinding value: Vi = Vf^(-e) mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + if( rsa_check_context( ctx, 1 /* private key checks */, + f_rng != NULL /* blinding y/n */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + + 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; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#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 ) ); + } + + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + + 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( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + 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 int 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; + int ret = 0; + + 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; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#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 */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + 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 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret; + unsigned char *p = output; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + // We don't check p_rng because it won't be dereferenced here + if( f_rng == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == MBEDTLS_RSA_PUBLIC ) + { + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = MBEDTLS_RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + memcpy( p, input, ilen ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + /* + * Parameters sanity checks + */ + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + int ret; + size_t ilen, pad_count = 0, i; + unsigned char *p, bad, pad_done = 0; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + p = buf; + bad = 0; + + /* + * Check and get padding len in "constant-time" + */ + bad |= *p++; /* First byte must be 0 */ + + /* This test does not depend on secret data */ + if( mode == MBEDTLS_RSA_PRIVATE ) + { + bad |= *p++ ^ MBEDTLS_RSA_CRYPT; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + else + { + bad |= *p++ ^ MBEDTLS_RSA_SIGN; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ( p[i] != 0xFF ); + pad_count += ( pad_done == 0 ); + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + + bad |= ( pad_count < 8 ); + + if( bad ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[MBEDTLS_MD_MAX_SIZE]; + unsigned int slen, hlen, offset = 0; + int ret; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + slen = hlen; + + if( olen < hlen + slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( sig, 0, olen ); + + /* Generate salt of length slen */ + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen * 2 - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + mbedtls_zeroize( salt, sizeof( salt ) ); + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + 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 + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw 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 ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *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++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * 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 ) +{ + int ret; + unsigned char *sig_try = NULL, *verif = NULL; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* + * Call respective RSA primitive + */ + + if( mode == MBEDTLS_RSA_PUBLIC ) + { + /* Skip verification on a public key operation */ + return( mbedtls_rsa_public( ctx, sig, sig ) ); + } + + /* Private key operation + * + * 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 ) ); + + if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 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 *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, 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 ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * 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 = 0; + const size_t sig_len = ctx->len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, encoded ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#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 ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + 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->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + 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->RN ); mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + + + +/* + * 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 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_mpi K; + + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); + + 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" ); + + ret = 1; + goto cleanup; + } + + 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" ); + + ret = 1; + goto cleanup; + } + + 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" ); + + ret = 1; + goto cleanup; + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + 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" ); + + ret = 1; + goto cleanup; + } + + 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" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/rsa_internal.c ************/ + +/* + * Helper functions for the RSA module + * + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See 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) + +#else + +#endif + +#if defined(MBEDTLS_RSA_C) + + + + + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 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 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime( P, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/sha1.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SHA1_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 + */ +int mbedtls_sha1_starts_ret( 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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + 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 ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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 + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + 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 ); + + if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + 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 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_sha1_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t 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 ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto fail; + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) + goto fail; + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/sha256.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SHA256_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 + */ +int mbedtls_sha256_starts_ret( 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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + +#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; \ +} + +int mbedtls_internal_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]; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + 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 ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char sha256_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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 + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + 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 ); + + if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + 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 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + int ret; + mbedtls_sha256_context ctx; + + mbedtls_sha256_init( &ctx ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha256_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + mbedtls_sha256_ret( input, ilen, output, is224 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t 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 ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha256_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + + } + else + { + ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 ) + goto fail; + + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/sha512.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SHA512_C) + + + +#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) + +#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 */ +/* zeroize was here */ + +/* + * 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 + */ +int mbedtls_sha512_starts_ret( 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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +#define K KK +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) +}; + +int mbedtls_internal_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; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + unsigned int left; + + if( ilen == 0 ) + return( 0 ); + + 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 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char sha512_padding[128] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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 + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + int ret; + size_t last, padn; + uint64_t high, low; + unsigned char msglen[16]; + + 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 ); + + if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 ) + return( ret ); + + 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 ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + int ret; + mbedtls_sha512_context ctx; + + mbedtls_sha512_init( &ctx ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + mbedtls_sha512_ret( input, ilen, output, is384 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t 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 ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha512_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 ) + goto fail; + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_cache.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SSL_CACHE_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +#include + +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); + + cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &cache->mutex ); +#endif +} + +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ); +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *entry; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - entry->timestamp ) > cache->timeout ) + continue; +#endif + + if( session->ciphersuite != entry->session.ciphersuite || + session->compression != entry->session.compression || + session->id_len != entry->session.id_len ) + continue; + + if( memcmp( session->id, entry->session.id, + entry->session.id_len ) != 0 ) + continue; + + memcpy( session->master, entry->session.master, 48 ); + + session->verify_result = entry->session.verify_result; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Restore peer certificate (without rest of the original chain) + */ + if( entry->peer_cert.p != NULL ) + { + if( ( session->peer_cert = mbedtls_calloc( 1, + sizeof(mbedtls_x509_crt) ) ) == NULL ) + { + ret = 1; + goto exit; + } + + mbedtls_x509_crt_init( session->peer_cert ); + if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, + entry->peer_cert.len ) != 0 ) + { + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + ret = 1; + goto exit; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = 0; + goto exit; + } + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; + mbedtls_ssl_cache_entry *old = NULL; +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *prv; + int count = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + count++; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + cur->timestamp = t; + break; /* expired, reuse this slot, update timestamp */ + } +#endif + + if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + +#if defined(MBEDTLS_HAVE_TIME) + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } +#endif + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { +#if defined(MBEDTLS_HAVE_TIME) + /* + * Reuse oldest entry if max_entries reached + */ + if( count >= cache->max_entries ) + { + if( old == NULL ) + { + ret = 1; + goto exit; + } + + cur = old; + } +#else /* MBEDTLS_HAVE_TIME */ + /* + * Reuse first entry in chain if max_entries reached, + * but move to last place + */ + if( count >= cache->max_entries ) + { + if( cache->chain == NULL ) + { + ret = 1; + goto exit; + } + + cur = cache->chain; + cache->chain = cur->next; + cur->next = NULL; + prv->next = cur; + } +#endif /* MBEDTLS_HAVE_TIME */ + else + { + /* + * max_entries not reached, create new entry + */ + cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); + if( cur == NULL ) + { + ret = 1; + goto exit; + } + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur->timestamp = t; +#endif + } + + memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + mbedtls_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); + } + + /* + * Store peer certificate + */ + if( session->peer_cert != NULL ) + { + cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len ); + if( cur->peer_cert.p == NULL ) + { + ret = 1; + goto exit; + } + + memcpy( cur->peer_cert.p, session->peer_cert->raw.p, + session->peer_cert->raw.len ); + cur->peer_cert.len = session->peer_cert->raw.len; + + cur->session.peer_cert = NULL; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +#if defined(MBEDTLS_HAVE_TIME) +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* MBEDTLS_HAVE_TIME */ + +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) +{ + mbedtls_ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + mbedtls_ssl_session_free( &prv->session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_free( prv->peer_cert.p ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + mbedtls_free( prv ); + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &cache->mutex ); +#endif + cache->chain = NULL; +} + +#endif /* MBEDTLS_SSL_CACHE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_ciphersuites.c ************/ + +/** + * \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) + +#else + +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#endif + + + + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except rc4, weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK + * 2. By key length and cipher: + * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(MBEDTLS_SSL_CIPHERSUITES) + MBEDTLS_SSL_CIPHERSUITES, +#else + /* All AES-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All AES-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All remaining >= 128-bit ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + + /* The PSK ephemeral suites */ + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, + + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The ECJPAKE suite */ + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + + /* All AES-256 suites */ + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All AES-128 suites */ + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All remaining >= 128-bit suites */ + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + + /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, + + MBEDTLS_TLS_RSA_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_WITH_NULL_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_PSK_WITH_NULL_SHA, + +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + 0 +}; + +static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ + + { 0, "", + MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(MBEDTLS_SSL_CIPHERSUITES) +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 ) +#else + if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL ) +#endif + *(q++) = *p; + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +} +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( MBEDTLS_PK_ECKEY ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_TLS_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_cli.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + + + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#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; + } + + /* + * Sect. 3, RFC 6066 (TLS Extensions Definitions) + * + * In order to provide any of the server names, clients MAY include an + * extension of type "server_name" in the (extended) client hello. The + * "extension_data" field of this extension SHALL contain + * "ServerNameList" where: + * + * 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 cli_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; + + /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the + * initial ClientHello, in which case also adding the renegotiation + * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); + + if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Secure renegotiation + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; + *p++ = ssl->verify_data_len & 0xFF; + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t sig_alg_len = 0; + const int *md; +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + } + + if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ + sig_alg_len = 0; + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; +#endif + } + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); + + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); + + *olen = 6 + sig_alg_len; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *grp_id; +#else + ((void) ssl); +#endif + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); + +#if defined(MBEDTLS_ECP_C) + for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) +#else + for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) +#endif + { +#if defined(MBEDTLS_ECP_C) + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); +#endif + if( info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) ); + return; + } + + elliptic_curve_len += 2; + } + + if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + elliptic_curve_len = 0; + +#if defined(MBEDTLS_ECP_C) + for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) +#else + for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) +#endif + { +#if defined(MBEDTLS_ECP_C) + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); +#endif + elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; + elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; + } + + if( elliptic_curve_len == 0 ) + return; + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); + + *olen = 6 + elliptic_curve_len; +} + +static void cli_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 cli_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 cli_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 cli_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 cli_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 cli_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 cli_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] ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) ); + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); + *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 ); + +#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 + + /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added + * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + cli_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; + + cli_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) + cli_ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + cli_ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + cli_ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + cli_ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + cli_ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + cli_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 cli_ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + mbedtls_ssl_safer_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x00 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int cli_ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->conf->mfl_code ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int cli_ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int cli_ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int cli_ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int cli_ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( ssl->transform_negotiate->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + /* If we got here, we no longer need our cached extension */ + mbedtls_free( ssl->handshake->ecjpake_cache ); + ssl->handshake->ecjpake_cache = NULL; + ssl->handshake->ecjpake_cache_len = 0; + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +static int cli_ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, name_len; + const char **p; + + /* If we didn't send it, the server shouldn't send it */ + if( ssl->conf->alpn_list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + name_len = buf[2]; + if( name_len != list_len - 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->conf->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Parse HelloVerifyRequest. Only called after verifying the HS type. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + int major_ver, minor_ver; + unsigned char cookie_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); + p += 2; + + /* + * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) + * even is lower than our min version. + */ + if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || + major_ver > ssl->conf->max_major_ver || + minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + cookie_len = *p++; + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); + + if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "cookie length does not match incoming message size" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + mbedtls_free( ssl->handshake->verify_cookie ); + + ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->verify_cookie, p, cookie_len ); + ssl->handshake->verify_cookie_len = cookie_len; + + /* Start over at ClientHello */ + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_reset_checksum( ssl ); + + mbedtls_ssl_recv_flight_completed( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret, i; + size_t n; + size_t ext_len; + unsigned char *buf, *ext; + unsigned char comp; +#if defined(MBEDTLS_ZLIB_SUPPORT) + int accept_comp; +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const mbedtls_ssl_ciphersuite_t *suite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + buf = ssl->in_msg; + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_records_seen++; + + if( ssl->conf->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by server" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); + + ssl->keep_current_message = 1; + return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + return( ssl_parse_hello_verify_request( ssl ) ); + } + else + { + /* We made it through the verification process */ + mbedtls_free( ssl->handshake->verify_cookie ); + ssl->handshake->verify_cookie = NULL; + ssl->handshake->verify_cookie_len = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || + buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * 0 . 1 server_version + * 2 . 33 random (maybe including 4 bytes of Unix time) + * 34 . 34 session_id length = n + * 35 . 34+n session_id + * 35+n . 36+n cipher_suite + * 37+n . 37+n compression_method + * + * 38+n . 39+n extensions length (optional) + * 40+n . .. extensions + */ + buf += mbedtls_ssl_hs_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf + 0 ); + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver || + ssl->major_ver > ssl->conf->max_major_ver || + ssl->minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - " + " min: [%d:%d], server: [%d:%d], max: [%d:%d]", + ssl->conf->min_major_ver, ssl->conf->min_minor_ver, + ssl->major_ver, ssl->minor_ver, + ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", + ( (uint32_t) buf[2] << 24 ) | + ( (uint32_t) buf[3] << 16 ) | + ( (uint32_t) buf[4] << 8 ) | + ( (uint32_t) buf[5] ) ) ); + + memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); + + n = buf[34]; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); + + if( n > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) + { + ext_len = ( ( buf[38 + n] << 8 ) + | ( buf[39 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) + { + ext_len = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* ciphersuite (used later) */ + i = ( buf[35 + n] << 8 ) | buf[36 + n]; + + /* + * Read and check compression + */ + comp = buf[37 + n]; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + accept_comp = 0; + else +#endif + accept_comp = 1; + + if( comp != MBEDTLS_SSL_COMPRESS_NULL && + ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) +#else /* MBEDTLS_ZLIB_SUPPORT */ + if( comp != MBEDTLS_SSL_COMPRESS_NULL ) +#endif/* MBEDTLS_ZLIB_SUPPORT */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * Initialize update checksum functions + */ + ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); + + if( ssl->transform_negotiate->ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->handshake->resume == 0 || n == 0 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->id_len != n || + memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->id_len = n; + memcpy( ssl->session_negotiate->id, buf + 35, n ); + } + else + { + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); + + suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); + if( suite_info == NULL +#if defined(MBEDTLS_ARC4_C) + || ( ssl->conf->arc4_disabled && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + + i = 0; + while( 1 ) + { + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + if( comp != MBEDTLS_SSL_COMPRESS_NULL +#if defined(MBEDTLS_ZLIB_SUPPORT) + && comp != MBEDTLS_SSL_COMPRESS_DEFLATE +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 40 + n; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + if( ( ret = cli_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 = cli_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 = cli_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 = cli_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 = cli_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 = cli_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 = cli_ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_ALPN */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); + return( ret ); + } + + if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d", + ssl->handshake->dhm_ctx.len * 8, + ssl->conf->dhm_min_bitlen ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + + curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t len; + ((void) ssl); + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + if( (*p) > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " + "(psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + len = (*p)[0] << 8 | (*p)[1]; + *p += 2; + + if( (*p) > end - len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " + "(psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Note: we currently ignore the PKS identity hint, as we only allow one + * PSK to be provisionned on the client. This could be changed later if + * someone needs that feature. + */ + *p += len; + ret = 0; + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret; + size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + + if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * Now write it out, encrypted + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); + ssl->out_msg[offset+1] = (unsigned char)( *olen ); + *olen += 2; + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end, + mbedtls_md_type_t *md_alg, + mbedtls_pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = MBEDTLS_MD_NONE; + *pk_alg = MBEDTLS_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported " + "HashAlgorithm %d", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported " + "SignatureAlgorithm %d", (*p)[1] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Check if the hash is acceptable + */ + if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm %d that was not offered", + *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int cli_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 = NULL, *end = NULL; + + 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 = cli_ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "cli_ssl_get_ecdh_params_from_cert", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server + * doesn't use a psk_identity_hint + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* Current message is probably either + * CertificateRequest or ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key exchange message must " + "not be skipped" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } /* FALLTROUGH */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t sig_len, hashlen; + unsigned char hash[64]; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + size_t params_len = p - params; + + /* + * Handle the digitally-signed structure + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + + /* Default hash for ECDSA is SHA-1 */ + if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + + if( p > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( p != end - sig_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params, + params_len ); + if( ret != 0 ) + return( ret ); + } + 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 ) + { + /* Info from md_alg will be used instead */ + hashlen = 0; + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params, + params_len, md_alg ); + if( ret != 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 ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * Verify signature + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len ) ) != 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + +exit: + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + size_t n = 0; + size_t cert_type_len = 0, dn_len = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->state++; + ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", + ssl->client_auth ? "a" : "no" ) ); + + if( ssl->client_auth == 0 ) + { + /* Current message is probably the ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + /* + * struct { + * ClientCertificateType certificate_types<1..2^8-1>; + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only + * DistinguishedName certificate_authorities<0..2^16-1>; + * } CertificateRequest; + * + * Since we only support a single certificate on clients, let's just + * ignore all the information that's supposed to help us pick a + * certificate. + * + * We could check that our certificate matches the request, and bail out + * if it doesn't, but it's simpler to just send the certificate anyway, + * and give the server the opportunity to decide if it should terminate + * the connection when it doesn't like our certificate. + * + * Same goes for the hash in TLS 1.2's signature_algorithms: at this + * point we only have one hash available (see comments in + * write_certificate_verify), so let's just use what we have. + * + * However, we still minimally parse the message to check it is at least + * superficially sane. + */ + buf = ssl->in_msg; + + /* certificate_types */ + cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; + n = cert_type_len; + + if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + + /* supported_signature_algorithms */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); +#if defined(MBEDTLS_DEBUG_C) + unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + size_t i; + + for( i = 0; i < sig_alg_len; i += 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d" + ",%d", sig_alg[i], sig_alg[i + 1] ) ); + } +#endif + + n += 2 + sig_alg_len; + + if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* certificate_authorities */ + dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); + + n += dn_len; + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ + +static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || + ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + /* + * DHM key exchange -- send G^X mod P + */ + n = ssl->handshake->dhm_ctx.len; + + ssl->out_msg[4] = (unsigned char)( n >> 8 ); + ssl->out_msg[5] = (unsigned char)( n ); + i = 6; + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + i = 4; + + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &n, + &ssl->out_msg[i], 1000, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + i = 4; + n = ssl->conf->psk_identity_len; + + if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " + "SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len ); + i += ssl->conf->psk_identity_len; + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + n = 0; + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + n = ssl->handshake->dhm_ctx.len; + + if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" + " or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * ClientECDiffieHellmanPublic public; + */ + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, + &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + i = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + i = 4; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen = i + n; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + size_t n = 0, offset = 0; + unsigned char hash[48]; + unsigned char *hash_start = hash; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + unsigned int hashlen; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make an RSA signature of the handshake digests + */ + ssl->handshake->calc_verify( ssl, hash ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(handshake_messages); + * + * sha_hash + * SHA(handshake_messages); + */ + hashlen = 36; + md_alg = MBEDTLS_MD_NONE; + + /* + * For ECDSA, default hash is SHA-1 only + */ + if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and SHA224 + * in order to satisfy 'weird' needs from the server side. + */ + if( ssl->transform_negotiate->ciphersuite_info->mac == + MBEDTLS_MD_SHA384 ) + { + md_alg = MBEDTLS_MD_SHA384; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; + } + else + { + md_alg = MBEDTLS_MD_SHA256; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; + } + ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, &n, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + + ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); + ssl->out_msg[5 + offset] = (unsigned char)( n ); + + ssl->out_msglen = 6 + n + offset; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + const unsigned char *msg; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 3 ticket_lifetime_hint + * 4 . 5 ticket_len (n) + * 6 . 5+n ticket content + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + + lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); + + ticket_len = ( msg[4] << 8 ) | ( msg[5] ); + + if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); + + /* We're not waiting for a NewSessionTicket message any more */ + ssl->handshake->new_session_ticket = 0; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + /* + * Zero-length ticket means the server changed his mind and doesn't want + * to send a ticket after all, so just forget it + */ + if( ticket_len == 0 ) + return( 0 ); + + mbedtls_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + mbedtls_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ticket, msg + 6, ticket_len ); + + ssl->session_negotiate->ticket = ticket; + ssl->session_negotiate->ticket_len = ticket_len; + ssl->session_negotiate->ticket_lifetime = lifetime; + + /* + * RFC 5077 section 3.4: + * "If the client receives a session ticket from the server, then it + * discards any Session ID that was sent in the ServerHello." + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->id_len = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } +#endif + + /* Change state now, so that it is right in mbedtls_ssl_read_record(), used + * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && + ssl->handshake->new_session_ticket != 0 ) + { + ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: + ret = ssl_parse_new_session_ticket( ssl ); + break; +#endif + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_cookie.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + + +#include + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is + * available. Try SHA-256 first, 512 wastes resources since we need to stay + * with max 32 bytes of cookie for DTLS 1.0 + */ +#if defined(MBEDTLS_SHA256_C) +#define COOKIE_MD MBEDTLS_MD_SHA224 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA512_C) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA1_C) +#define COOKIE_MD MBEDTLS_MD_SHA1 +#define COOKIE_MD_OUTLEN 20 +#define COOKIE_HMAC_LEN 20 +#else +#error "DTLS hello verify needs SHA-1 or SHA-2" +#endif + +/* + * Cookies are formed of a 4-bytes timestamp (or serial number) and + * an HMAC of timestemp and client ID. + */ +#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) + +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_init( &ctx->hmac_ctx ); +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) +{ + ctx->timeout = delay; +} + +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_free( &ctx->hmac_ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); +} + +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char key[COOKIE_MD_OUTLEN]; + + if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) + return( ret ); + + ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); + if( ret != 0 ) + return( ret ); + + mbedtls_zeroize( key, sizeof( key ) ); + + return( 0 ); +} + +/* + * Generate the HMAC part of a cookie + */ +static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, + const unsigned char time[4], + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char hmac_out[COOKIE_MD_OUTLEN]; + + if( (size_t)( end - *p ) < COOKIE_HMAC_LEN ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || + mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); + *p += COOKIE_HMAC_LEN; + + return( 0 ); +} + +/* + * Generate cookie for DTLS ClientHello verification + */ +int mbedtls_ssl_cookie_write( void *p_ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + int ret; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long t; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( (size_t)( end - *p ) < COOKIE_LEN ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_HAVE_TIME) + t = (unsigned long) mbedtls_time( NULL ); +#else + t = ctx->serial++; +#endif + + (*p)[0] = (unsigned char)( t >> 24 ); + (*p)[1] = (unsigned char)( t >> 16 ); + (*p)[2] = (unsigned char)( t >> 8 ); + (*p)[3] = (unsigned char)( t ); + *p += 4; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, + p, end, cli_id, cli_id_len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Check a cookie + */ +int mbedtls_ssl_cookie_check( void *p_ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char ref_hmac[COOKIE_HMAC_LEN]; + int ret = 0; + unsigned char *p = ref_hmac; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long cur_time, cookie_time; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cookie_len != COOKIE_LEN ) + return( -1 ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, + &p, p + sizeof( ref_hmac ), + cli_id, cli_id_len ) != 0 ) + ret = -1; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + if( ret != 0 ) + return( ret ); + + if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) + return( -1 ); + +#if defined(MBEDTLS_HAVE_TIME) + cur_time = (unsigned long) mbedtls_time( NULL ); +#else + cur_time = ctx->serial; +#endif + + cookie_time = ( (unsigned long) cookie[0] << 24 ) | + ( (unsigned long) cookie[1] << 16 ) | + ( (unsigned long) cookie[2] << 8 ) | + ( (unsigned long) cookie[3] ); + + if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) + return( -1 ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_COOKIE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_srv.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + + + +#include + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ) +{ + if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + mbedtls_free( ssl->cli_id ); + + if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->cli_id, info, ilen ); + ssl->cli_id_len = ilen; + + return( 0 ); +} + +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ) +{ + conf->f_cookie_write = f_cookie_write; + conf->f_cookie_check = f_cookie_check; + conf->p_cookie = p_cookie; +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( servername_list_size > 0 ) + { + hostname_len = ( ( p[1] << 8 ) | p[2] ); + if( hostname_len + 3 > servername_list_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl->conf->f_sni( ssl->conf->p_sni, + ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len || + buf[0] != ssl->verify_data_len || + mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* + * Status of the implementation of signature-algorithms extension: + * + * Currently, we are only considering the signature-algorithm extension + * to pick a ciphersuite which allows us to send the ServerKeyExchange + * message with a signature-hash combination that the user allows. + * + * We do *not* check whether all certificates in our certificate + * chain are signed with an allowed signature-hash pair. + * This needs to be done at a later stage. + * + */ +static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t sig_alg_list_size; + + const unsigned char *p; + const unsigned char *end = buf + len; + + mbedtls_md_type_t md_cur; + mbedtls_pk_type_t sig_cur; + + sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( sig_alg_list_size + 2 != len || + sig_alg_list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Currently we only guarantee signing the ServerKeyExchange message according + * to the constraints specified in this extension (see above), so it suffices + * to remember only one suitable hash for each possible signature algorithm. + * + * This will change when we also consider certificate signatures, + * in which case we will need to remember the whole signature-hash + * pair list from the extension. + */ + + for( p = buf + 2; p < end; p += 2 ) + { + /* Silently ignore unknown signature or hash algorithms. */ + + if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" + " unknown sig alg encoding %d", p[1] ) ); + continue; + } + + /* Check if we support the hash the user proposes */ + md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); + if( md_cur == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " unknown hash alg encoding %d", p[0] ) ); + continue; + } + + if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) + { + mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " match sig %d and hash %d", + sig_cur, md_cur ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " + "hash alg %d not supported", md_cur ) ); + } + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const mbedtls_ecp_curve_info *curve_info, **curves; + + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Should never happen unless client duplicates the extension */ + if( ssl->handshake->curves != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Don't allow our peer to make us allocate too much memory, + * and leave room for a final 0 */ + our_size = list_size / 2 + 1; + if( our_size > MBEDTLS_ECP_DP_MAX ) + our_size = MBEDTLS_ECP_DP_MAX; + + if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); + + if( curve_info != NULL ) + { + *curves++ = curve_info; + our_size--; + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( ret ); + } + + /* Only mark the extension as OK when we're sure it is */ + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret; + mbedtls_ssl_session session; + + mbedtls_ssl_session_init( &session ); + + if( ssl->conf->f_ticket_parse == NULL || + ssl->conf->f_ticket_write == NULL ) + { + return( 0 ); + } + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); + + if( len == 0 ) + return( 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, + buf, len ) ) != 0 ) + { + mbedtls_ssl_session_free( &session ); + + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); + else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); + else + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); + + return( 0 ); + } + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform them we're accepting the ticket (RFC 5077 section 3.4) + */ + session.id_len = ssl->session_negotiate->id_len; + memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); + + mbedtls_ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); + + ssl->handshake->resume = 1; + + /* Don't send a new ticket after all, this one is OK */ + ssl->handshake->new_session_ticket = 0; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, cur_len, ours_len; + const unsigned char *theirs, *start, *end; + const char **ours; + + /* If ALPN not configured, just ignore the extension */ + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Validate peer's list (lengths) + */ + start = buf + 2; + end = buf + len; + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + /* Current identifier must fit in list */ + if( cur_len > (size_t)( end - theirs ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + /* + * Use our order of preference + */ + for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) + { + ours_len = strlen( *ours ); + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + if( cur_len == ours_len && + memcmp( theirs, *ours, cur_len ) == 0 ) + { + ssl->alpn_chosen = *ours; + return( 0 ); + } + } + } + + /* If we get there, no match was found */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise + */ +#if defined(MBEDTLS_ECDSA_C) +static int ssl_check_key_curve( mbedtls_pk_context *pk, + const mbedtls_ecp_curve_info **curves ) +{ + const mbedtls_ecp_curve_info **crv = curves; + mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 0 ); + crv++; + } + + return( -1 ); +} +#endif /* MBEDTLS_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +static int ssl_pick_cert( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) +{ + mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; + mbedtls_pk_type_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + uint32_t flags; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->conf->key_cert; + + if( pk_alg == MBEDTLS_PK_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); + + if( list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); + return( -1 ); + } + + for( cur = list; cur != NULL; cur = cur->next ) + { + MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", + cur->cert ); + + if( ! mbedtls_pk_can_do( cur->key, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); + continue; + } + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + * + * It also allows the user to provision different certificates for + * different uses based on keyUsage, eg if they want to avoid signing + * and decrypting with the same RSA key. + */ + if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, + MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " + "(extended) key usage extension" ) ); + continue; + } + +#if defined(MBEDTLS_ECDSA_C) + if( pk_alg == MBEDTLS_PK_ECDSA && + ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); + continue; + } +#endif + + /* + * Try to select a SHA-1 certificate for pre-1.2 clients, but still + * present them a SHA-higher cert rather than failing if it's the only + * one we got that satisfies the other conditions. + */ + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && + cur->cert->sig_md != MBEDTLS_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " + "sha-2 with pre-TLS 1.2 client" ) ); + continue; + } + } + + /* If we get there, we got a winner */ + break; + } + + if( cur == NULL ) + cur = fallback; + + /* Do not update ssl->handshake->key_cert unless there is a match */ + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", + ssl->handshake->key_cert->cert ); + return( 0 ); + } + + return( -1 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, + const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) +{ + const mbedtls_ssl_ciphersuite_t *suite_info; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_pk_type_t sig_type; +#endif + + suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) ); + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 0 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " + "not configured or ext missing" ) ); + return( 0 ); + } +#endif + + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no common elliptic curve" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl->conf->f_psk == NULL && + ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || + ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); + if( sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %d", sig_type ) ); + return( 0 ); + } + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no suitable certificate" ) ); + return( 0 ); + } +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len, chal_len; + unsigned char *buf, *p; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + buf = ssl->in_hdr; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", + buf[2] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", + ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", + buf[3], buf[4] ) ); + + /* + * SSLv2 Client Hello + * + * Record layer: + * 0 . 1 message length + * + * SSL layer: + * 2 . 2 message type + * 3 . 4 protocol version + */ + if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || + buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; + + if( n < 17 || n > 512 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) + ? buf[4] : ssl->conf->max_minor_ver; + + if( ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + ssl->handshake->max_major_ver = buf[3]; + ssl->handshake->max_minor_ver = buf[4]; + + if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->handshake->update_checksum( ssl, buf + 2, n ); + + buf = ssl->in_msg; + n = ssl->in_left - 5; + + /* + * 0 . 1 ciphersuitelist length + * 2 . 3 session id length + * 4 . 5 challenge length + * 6 . .. ciphersuitelist + * .. . .. session id + * .. . .. challenge + */ + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + ciph_len = ( buf[0] << 8 ) | buf[1]; + sess_len = ( buf[2] << 8 ) | buf[3]; + chal_len = ( buf[4] << 8 ) | buf[5]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", + ciph_len, sess_len, chal_len ) ); + + /* + * Make sure each parameter length is valid + */ + if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( sess_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( chal_len < 8 || chal_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( n != 6 + ciph_len + sess_len + chal_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 6, ciph_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 6 + ciph_len, sess_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", + buf + 6 + ciph_len + sess_len, chal_len ); + + p = buf + 6 + ciph_len; + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); + + p += sess_len; + memset( ssl->handshake->randbytes, 0, 64 ); + memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) +#endif + { + if( p[0] != 0 || + p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite_v2; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite_v2: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + + /* + * SSLv2 Client Hello relevant renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->in_left = 0; + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +/* This function doesn't alert on errors that happen early during + ClientHello parsing because they might indicate that the client is + not talking SSL/TLS at all and would not understand our alert. */ +static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + size_t i, j; + size_t ciph_offset, comp_offset, ext_offset; + size_t msg_len, ciph_len, sess_len, comp_len, ext_len; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + size_t cookie_offset, cookie_len; +#endif + unsigned char *buf, *p, *ext; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int major, minor; + + /* If there is no signature-algorithm extension present, + * we need to fall back to the default values for allowed + * signature-hash pairs. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + int sig_hash_alg_ext_present = 0; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +read_record_header: +#endif + /* + * If renegotiating, then the input was read with mbedtls_ssl_read_record(), + * otherwise read it ourselves manually in order to support SSLv2 + * ClientHello, which doesn't use the same record layer format. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_hdr; + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) +#endif + if( ( buf[0] & 0x80 ) != 0 ) + return( ssl_parse_client_hello_v2( ssl ) ); +#endif + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); + + /* + * SSLv3/TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 11 DTLS: epoch + record sequence number + * 3 . 4 message length + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", + buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", + ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", + buf[1], buf[2] ) ); + + mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); + + /* According to RFC 5246 Appendix E.1, the version here is typically + * "{03,00}, the lowest version number supported by the client, [or] the + * value of ClientHello.client_version", so the only meaningful check here + * is the major version shouldn't be less than 3 */ + if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* For DTLS if this is the initial handshake, remember the client sequence + * number to use it in our next message (RFC 6347 4.2.1) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + /* Epoch should be 0 for initial handshakes */ + if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); + ssl->next_record_offset = 0; + ssl->in_left = 0; + goto read_record_header; + } + + /* No MAC to check yet, so we can update right now */ + mbedtls_ssl_dtls_replay_update( ssl ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Set by mbedtls_ssl_read_record() */ + msg_len = ssl->in_hslen; + } + else +#endif + { + if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + } + + buf = ssl->in_msg; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); + + ssl->handshake->update_checksum( ssl, buf, msg_len ); + + /* + * Handshake layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 DTLS only: message seqence number + * 6 . 8 DTLS only: fragment offset + * 9 . 11 DTLS only: fragment length + */ + if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + + /* We don't support fragmentation of ClientHello (yet?) */ + if( buf[1] != 0 || + msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* + * Copy the client's handshake message_seq on initial handshakes, + * check sequence number on renego. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* This couldn't be done in ssl_prepare_handshake_record() */ + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + + if( cli_msg_seq != ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " + "%d (expected %d)", cli_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->in_msg_seq++; + } + else +#endif + { + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + ssl->handshake->out_msg_seq = cli_msg_seq; + ssl->handshake->in_msg_seq = cli_msg_seq + 1; + } + + /* + * For now we don't support fragmentation, so make sure + * fragment_offset == 0 and fragment_length == length + */ + if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || + memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + buf += mbedtls_ssl_hs_hdr_len( ssl ); + msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * ClientHello layer: + * 0 . 1 protocol version + * 2 . 33 random bytes (starting with 4 bytes of Unix time) + * 34 . 35 session id length (1 byte) + * 35 . 34+x session id + * 35+x . 35+x DTLS only: cookie length (1 byte) + * 36+x . .. DTLS only: cookie + * .. . .. ciphersuite list length (2 bytes) + * .. . .. ciphersuite list + * .. . .. compression alg. list length (1 byte) + * .. . .. compression alg. list + * .. . .. extensions length (2 bytes, optional) + * .. . .. extensions (optional) + */ + + /* + * Minimal length (with everything empty and extensions ommitted) is + * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can + * read at least up to session id length without worrying. + */ + if( msg_len < 38 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check and save the protocol version + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); + + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf ); + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->conf->max_major_ver ) + { + ssl->major_ver = ssl->conf->max_major_ver; + ssl->minor_ver = ssl->conf->max_minor_ver; + } + else if( ssl->minor_ver > ssl->conf->max_minor_ver ) + ssl->minor_ver = ssl->conf->max_minor_ver; + + /* + * Save client random (inc. Unix time) + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); + + memcpy( ssl->handshake->randbytes, buf + 2, 32 ); + + /* + * Check the session ID length and save session ID + */ + sess_len = buf[34]; + + if( sess_len > sizeof( ssl->session_negotiate->id ) || + sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); + + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 35, + ssl->session_negotiate->id_len ); + + /* + * Check the cookie length and content + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + cookie_offset = 35 + sess_len; + cookie_len = buf[cookie_offset]; + + if( cookie_offset + 1 + cookie_len + 2 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + buf + cookie_offset + 1, cookie_len ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->f_cookie_check != NULL +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + buf + cookie_offset + 1, cookie_len, + ssl->cli_id, ssl->cli_id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); + ssl->handshake->verify_cookie_len = 1; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); + ssl->handshake->verify_cookie_len = 0; + } + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + /* We know we didn't send a cookie, so it should be empty */ + if( cookie_len != 0 ) + { + /* This may be an attacker's probe, so don't send an alert */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); + } + + /* + * Check the ciphersuitelist length (will be parsed later) + */ + ciph_offset = cookie_offset + 1 + cookie_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + ciph_offset = 35 + sess_len; + + ciph_len = ( buf[ciph_offset + 0] << 8 ) + | ( buf[ciph_offset + 1] ); + + if( ciph_len < 2 || + ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ + ( ciph_len % 2 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + ciph_offset + 2, ciph_len ); + + /* + * Check the compression algorithms length and pick one + */ + comp_offset = ciph_offset + 2 + ciph_len; + + comp_len = buf[comp_offset]; + + if( comp_len < 1 || + comp_len > 16 || + comp_len + comp_offset + 1 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", + buf + comp_offset + 1, comp_len ); + + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#if defined(MBEDTLS_ZLIB_SUPPORT) + for( i = 0; i < comp_len; ++i ) + { + if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; + break; + } + } +#endif + + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#endif + + /* Do not parse the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + /* + * Check the extension length + */ + ext_offset = comp_offset + 1 + comp_len; + if( msg_len > ext_offset ) + { + if( msg_len < ext_offset + 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ext_len = ( buf[ext_offset + 0] << 8 ) + | ( buf[ext_offset + 1] ); + + if( ( ext_len > 0 && ext_len < 4 ) || + msg_len != ext_offset + 2 + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else + ext_len = 0; + + ext = buf + ext_offset + 2; + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); + + while( ext_len != 0 ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->conf->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + + sig_hash_alg_ext_present = 1; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); + + ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); + + ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + + /* + * Try to fall back to default hash SHA1 if the client + * hasn't provided any preferred signature-hash combinations. + */ + if( sig_hash_alg_ext_present == 0 ) + { + mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; + + if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) + md_default = MBEDTLS_MD_NONE; + + mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions + * and certificate from the SNI callback triggered by the SNI extension.) + */ + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) +#endif + { + if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + /* Debugging-only output for testsuite */ +#if defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); + if( sig_alg != MBEDTLS_PK_NONE ) + { + mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " + "%d - should not happen", sig_alg ) ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const mbedtls_ssl_ciphersuite_t *suite = NULL; + const mbedtls_cipher_info_t *cipher = NULL; + + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + /* + * RFC 7366: "If a server receives an encrypt-then-MAC request extension + * from a client and then selects a stream or Authenticated Encryption + * with Associated Data (AEAD) ciphersuite, it MUST NOT send an + * encrypt-then-MAC response extension back to the client." + */ + if( ( suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ) ) == NULL || + ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || + cipher->mode != MBEDTLS_MODE_CBC ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + *p++ = 0x00; + *p++ = 0x01; + *p++ = 0x00; + } + + *olen = p - buf; +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly computation if not needed */ + if( ssl->transform_negotiate->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN ) +static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); + + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + *olen = 7 + strlen( ssl->alpn_chosen ); + + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); + + memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *p = ssl->out_msg + 4; + unsigned char *cookie_len_byte; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + + /* The RFC is not clear on this point, but sending the actual negotiated + * version looks like the most interoperable thing to do. */ + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + p += 2; + + /* If we get here, f_cookie_check is not null */ + if( ssl->conf->f_cookie_write == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Skip length byte until we know the length */ + cookie_len_byte = p++; + + if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN, + ssl->cli_id, ssl->cli_id_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); + return( ret ); + } + + *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); + + ssl->out_msglen = p - ssl->out_msg; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + + ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + int ret; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie_len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ssl_write_hello_verify_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + /* + * Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). + * If not, try looking up session ID in our cache. + */ + if( ssl->handshake->resume == 0 && +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE && +#endif + ssl->session_negotiate->id_len != 0 && + ssl->conf->f_get_cache != NULL && + ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); + ssl->handshake->resume = 1; + } + + if( ssl->handshake->resume == 0 ) + { + /* + * New session, create a new session id, + * unless we're about to issue a session ticket + */ + ssl->state++; + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->id_len = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->id_len = n = 32; + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->id_len; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions + */ + *p++ = (unsigned char) ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); + *p++ = (unsigned char)( ssl->session_negotiate->compression ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + ssl->session_negotiate->compression ) ); + + /* Do not write the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; + + ret = mbedtls_ssl_write_record( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + size_t dn_size, total_dn_size; /* excluding length bytes */ + size_t ct_len, sa_len; /* including length bytes */ + unsigned char *buf, *p; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const mbedtls_x509_crt *crt; + int authmode; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; + else +#endif + authmode = ssl->conf->authmode; + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + buf = ssl->out_msg; + p = buf + 4; + + /* + * Supported certificate types + * + * ClientCertificateType certificate_types<1..2^8-1>; + * enum { (255) } ClientCertificateType; + */ + ct_len = 0; + +#if defined(MBEDTLS_RSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Add signature_algorithms for verify (TLS 1.2) + * + * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * enum { (255) } HashAlgorithm; + * enum { (255) } SignatureAlgorithm; + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + const int *cur; + + /* + * Supported signature algorithms + */ + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + { + unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); + + if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) + continue; + +#if defined(MBEDTLS_RSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif + } + + p[0] = (unsigned char)( sa_len >> 8 ); + p[1] = (unsigned char)( sa_len ); + sa_len += 2; + p += sa_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; + + total_dn_size = 0; + + if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; + + while( crt != NULL && crt->version != 0 ) + { + dn_size = crt->subject_raw.len; + + if( end < p || + (size_t)( end - p ) < dn_size || + (size_t)( end - p ) < 2 + dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; + ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); + ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); + + ret = mbedtls_ssl_write_record( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, + mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), + MBEDTLS_ECDH_OURS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t n = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) + unsigned char *p = ssl->out_msg + 4; + size_t len; +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + unsigned char *dig_signed = p; + size_t dig_signed_len = 0; +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + + /* + * + * Part 1: Extract static ECDH parameters and abort + * if ServerKeyExchange not needed. + * + */ + + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ssl_get_ecdh_params_from_cert( ssl ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */ + + /* + * + * Part 2: Provide key exchange parameters for chosen ciphersuite. + * + */ + + /* + * - ECJPAKE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + p += len; + n += len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + + /* + * For (EC)DHE key exchanges with PSK, parameters are prefixed by support + * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, + * we use empty support identity hints here. + **/ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + *(p++) = 0x00; + *(p++) = 0x00; + + n += 2; + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + + /* + * - DHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) + { + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx, + &ssl->conf->dhm_P, + &ssl->conf->dhm_G ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret ); + return( ret ); + } + + if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = p; + dig_signed_len = len; +#endif + + p += len; + n += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED */ + + /* + * - ECDHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const mbedtls_ecp_curve_info **curve = NULL; + const mbedtls_ecp_group_id *gid; + + /* Match our preference list against the offered curves */ + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->grp_id == *gid ) + goto curve_matching_done; + +curve_matching_done: + if( curve == NULL || *curve == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, + (*curve)->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, + p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = p; + dig_signed_len = len; +#endif + + p += len; + n += len; + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ + + /* + * + * Part 3: For key exchanges involving the server signing the + * exchange parameters, compute and add the signature here. + * + */ +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t signature_len = 0; + unsigned int hashlen = 0; + unsigned char hash[64]; + + /* + * 3.1: Choose hash algorithm: + * A: For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. + * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 + * (RFC 4492, Sec. 5.4) + * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) + */ + + mbedtls_md_type_t md_alg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t sig_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* A: For TLS 1.2, obey signature-hash-algorithm extension + * (RFC 5246, Sec. 7.4.1.4.1). */ + if( sig_alg == MBEDTLS_PK_NONE || + ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + /* (... because we choose a cipher suite + * only if there is a matching hash.) */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + /* B: Default hash SHA1 */ + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + { + /* C: MD5 + SHA1 */ + md_alg = MBEDTLS_MD_NONE; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); + + /* + * 3.2: Compute the hash to be signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, + dig_signed, + dig_signed_len ); + if( ret != 0 ) + return( ret ); + } + 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 ) + { + /* Info from md_alg will be used instead */ + hashlen = 0; + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, + dig_signed, + dig_signed_len, + md_alg ); + if( ret != 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 ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + + /* + * 3.3: Compute and add the signature + */ + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * For TLS 1.2, we need to specify signature and hash algorithm + * explicitly through a prefix to the signature. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * struct { + * SignatureAndHashAlgorithm algorithm; + * opaque signature<0..2^16-1>; + * } DigitallySigned; + * + */ + + *(p++) = mbedtls_ssl_hash_from_md_alg( md_alg ); + *(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg ); + + n += 2; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, + p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( signature_len >> 8 ); + *(p++) = (unsigned char)( signature_len ); + n += 2; + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); + + n += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + /* Done with actual work; add header and send. */ + + ssl->out_msglen = 4 + n; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + + return( 0 ); +} + +static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + *p += n; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Decrypt the premaster using own private RSA key + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( *p++ != ( ( len >> 8 ) & 0xFF ) || + *p++ != ( ( len ) & 0xFF ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + } +#endif + + if( p + len != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* + * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding + * must not cause the connection to end immediately; instead, send a + * bad_record_mac later in the handshake. + * Also, avoid data-dependant branches here to protect against + * timing-based variants. + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, + peer_pms, &peer_pmslen, + sizeof( peer_pms ), + ssl->conf->f_rng, ssl->conf->p_rng ); + + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( diff != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); +#endif + + if( sizeof( ssl->handshake->premaster ) < pms_offset || + sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->handshake->pmslen = 48; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + for( i = 0; i < ssl->handshake->pmslen; i++ ) + pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + size_t n; + + if( ssl->conf->f_psk == NULL && + ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || + ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( end - *p < 2 ) + { + 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 || n > (size_t) ( end - *p ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->conf->f_psk != NULL ) + { + if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + else + { + /* Identity is not a big secret since clients send it in the clear, + * but treat it carefully anyway, just in case */ + if( n != ssl->conf->psk_identity_len || + mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) + { + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); + return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char *p, *end; + + ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t pk_alg; +#endif + mbedtls_md_type_t md_alg; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || + ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + /* Read the message without adding it to the checksum */ + do { + + if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + return( ret ); + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + ssl->state++; + + /* Process the message contents */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * struct { + * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only + * opaque signature<0..2^16-1>; + * } DigitallySigned; + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + md_alg = MBEDTLS_MD_NONE; + hashlen = 36; + + /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ + if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Hash + */ + md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); + + if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + +#if !defined(MBEDTLS_MD_SHA1) + if( MBEDTLS_MD_SHA1 == md_alg ) + hash_start += 16; +#endif + + /* Info from md_alg will be used instead */ + hashlen = 0; + + i++; + + /* + * Signature + */ + if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i++; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; + i += 2; + + if( i + sig_len != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* Calculate hash and verify signature */ + ssl->handshake->calc_verify( ssl, hash ); + + if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash_start, hashlen, + ssl->in_msg + i, sig_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + + mbedtls_ssl_update_handshake_status( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t tlen; + uint32_t lifetime; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 4 . 7 ticket_lifetime_hint (0 = unspecified) + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + + if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, + ssl->session_negotiate, + ssl->out_msg + 10, + ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN, + &tlen, &lifetime ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); + tlen = 0; + } + + ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; + ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; + ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; + ssl->out_msg[7] = ( lifetime ) & 0xFF; + + ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); + + ssl->out_msglen = 10 + tlen; + + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +#endif + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_ticket.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +#include + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_tls.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + + + +#include + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* 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 ) +{ + int ret = 0; + 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 ); + + if( ( ret = mbedtls_sha1_starts_ret( &sha1 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, padding, 1 + i ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, random, rlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_finish_ret( &sha1, sha1sum ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_starts_ret( &md5 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, sha1sum, 20 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5, dstbuf + i * 16 ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_zeroize( padding, sizeof( padding ) ); + mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( ret ); +} +#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 mac_key_len; + 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; + mac_key_len = 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 */ + mac_key_len = mbedtls_md_get_size( md_info ); + transform->maclen = mac_key_len; + +#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; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + /* Fall back to old, non-compliant version of the truncated + * HMAC implementation which also truncates the key + * (Mbed TLS versions from 1.3 to 2.6.0) */ + mac_key_len = transform->maclen; +#endif + } +#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 + mac_key_len * 2; + key2 = keyblk + mac_key_len * 2 + transform->keylen; + + mac_enc = keyblk; + mac_dec = keyblk + mac_key_len; + + /* + * 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 + mac_key_len * 2 + transform->keylen; + key2 = keyblk + mac_key_len * 2; + + mac_enc = keyblk + mac_key_len; + 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( mac_key_len > sizeof transform->mac_enc ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( transform->mac_enc, mac_enc, mac_key_len ); + memcpy( transform->mac_dec, mac_dec, mac_key_len ); + } + 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, mac_key_len ); + mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); + } + 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, + mac_key_len ) ) != 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, + mac_key_len, 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_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_1, 48 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_2, 48 ); + mbedtls_md5_update_ret( &md5, hash, 16 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_1, 40 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_2, 40 ); + mbedtls_sha1_update_ret( &sha1, hash + 16, 20 ); + mbedtls_sha1_finish_ret( &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_ret( &md5, hash ); + mbedtls_sha1_finish_ret( &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_ret( &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_ret( &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 + */ +#define SSL_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ +static void ssl_mac( mbedtls_md_context_t *md_ctx, + const unsigned char *secret, + const unsigned char *buf, size_t len, + const unsigned char *ctr, int type, + unsigned char out[SSL_MAC_MAX_BYTES] ) +{ + 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, out ); + + 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, out, md_size ); + mbedtls_md_finish( md_ctx, out ); +} +#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 ); + + if( ssl->out_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", + (unsigned) ssl->out_msglen, + MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * 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 ) + { + unsigned char mac[SSL_MAC_MAX_BYTES]; + + 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, + mac ); + + memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); + } + 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 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + 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, mac ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); + } + 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 ); +} + +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 mac_expect[MBEDTLS_SSL_MAC_ADD]; + 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, mac_expect ); + 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, "expected mac", mac_expect, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, mac_expect, + 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 mac_expect[MBEDTLS_SSL_MAC_ADD]; + + 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 ); + +#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, + mac_expect ); + } + 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, mac_expect ); + /* 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, "expected mac", mac_expect, ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect, + 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 */ + if( MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen < 8 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " + "size %u, maximum %u", + (unsigned) ( ssl->in_hslen - 4 ), + (unsigned) ( MBEDTLS_SSL_MAX_CONTENT_LEN - 12 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); + ssl->out_msglen += 8; + len += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; + ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* We don't fragment, so frag_offset = 0 and frag_len = len */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); + } + + /* Save handshake and CCS messages for resending */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING && + ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || + ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_write != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); + + ret = mbedtls_ssl_hw_record_write( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + } + + ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], + ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Reassemble fragmented DTLS handshake messages. + * + * Use a temporary buffer for reassembly, divided in two parts: + * - the first holds the reassembled message (including handshake header), + * - the second holds a bitmask indicating which parts of the message + * (excluding headers) have been received so far. + */ +static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) +{ + unsigned char *msg, *bitmask; + size_t frag_len, frag_off; + size_t msg_len = ssl->in_hslen - 12; /* Without headers */ + + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * For first fragment, check size and allocate buffer + */ + if( ssl->handshake->hs_msg == NULL ) + { + size_t alloc_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* The bitmask needs one bit per byte of message excluding header */ + alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); + + ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); + if( ssl->handshake->hs_msg == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); + memset( ssl->handshake->hs_msg + 6, 0, 3 ); + memcpy( ssl->handshake->hs_msg + 9, + ssl->handshake->hs_msg + 1, 3 ); + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + + msg = ssl->handshake->hs_msg + 12; + bitmask = msg + msg_len; + + /* + * Check and copy current fragment + */ + frag_off = ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8]; + frag_len = ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11]; + + if( frag_off + frag_len > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", + frag_off, frag_len, msg_len ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( frag_len + 12 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", + frag_len, ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + ssl_bitmask_set( bitmask, frag_off, frag_len ); + + /* + * Do we have the complete message by now? + * If yes, finalize it, else ask to read the next record. + */ + if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); + + if( frag_len + 12 < ssl->in_msglen ) + { + /* + * We'got more handshake messages in the same record. + * This case is not handled now because no know implementation does + * that and it's hard to test, so we prefer to fail cleanly for now. + */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( ssl->in_left > ssl->next_record_offset ) + { + /* + * We've got more data in the buffer after the current record, + * that we don't want to overwrite. Move it before writing the + * reassembled message, and adjust in_left and next_record_offset. + */ + unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; + unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; + size_t remain_len = ssl->in_left - ssl->next_record_offset; + + /* First compute and check new lengths */ + ssl->next_record_offset = new_remain - ssl->in_hdr; + ssl->in_left = ssl->next_record_offset + remain_len; + + if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - + (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + memmove( new_remain, cur_remain, remain_len ); + } + + memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); + + mbedtls_free( ssl->handshake->hs_msg ); + ssl->handshake->hs_msg = NULL; + + MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", + ssl->in_msg, ssl->in_hslen ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ( + ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + /* ssl->handshake is NULL when receiving ClientHello for renego */ + if( ssl->handshake != NULL && + recv_msg_seq != ssl->handshake->in_msg_seq ) + { + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %d, start_of_flight = %d", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %d, expected = %d", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Reassemble if current message is fragmented or reassembly is + * already in progress */ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 || + ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + + if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); + return( ret ); + } + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->handshake != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + ssl->handshake->in_msg_seq++; + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* Forward declaration */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + if( f_cookie_write == NULL || f_cookie_check == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); + obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); + obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); + + obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); + obuf[12] = (unsigned char)( ( *olen - 13 ) ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * mbedtls_ssl_read_record() will ignore the record if anything else than + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function + * cannot not return 0. + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t len; + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + ssl->conf->p_cookie, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + /* Don't check write errors as we can't do anything here. + * If the error is permanent we'll catch it later, + * if it's not, then hopefully it'll work next time. */ + (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); + } + + if( ret == 0 ) + { + /* Got a valid cookie, partially reset context */ + if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +/* + * ContentType type; + * ProtocolVersion version; + * uint16 epoch; // DTLS only + * uint48 sequence_number; // DTLS only + * uint16 length; + * + * Return 0 if header looks sane (and, for DTLS, the record is expected) + * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. + * + * With DTLS, mbedtls_ssl_read_record() will: + * 1. proceed with the record if this function returns 0 + * 2. drop only the current record if this function returns UNEXPECTED_RECORD + * 3. return CLIENT_RECONNECT if this function return that value + * 4. drop the whole datagram if this function returns anything else. + * Point 2 is needed when the peer is resending, and we have already received + * the first record from a datagram but are still waiting for the others. + */ +static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) +{ + int major_ver, minor_ver; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); + + ssl->in_msgtype = ssl->in_hdr[0]; + ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->in_msgtype, + major_ver, minor_ver, ssl->in_msglen ) ); + + /* Check record type */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msgtype != MBEDTLS_SSL_MSG_ALERT && + ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* Silently ignore invalid DTLS records as recommended by RFC 6347 + * Section 4.1.2.7 */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check version */ + if( major_ver != ssl->major_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check length against the size of our buffer */ + if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN + - (size_t)( ssl->in_msg - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check length against bounds of the current transform and version */ + if( ssl->transform_in == NULL ) + { + if( ssl->in_msglen < 1 || + ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + else + { + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * TLS encrypted messages can have up to 256 bytes of padding + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && + ssl->in_msglen > ssl->transform_in->minlen + + MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif + } + + /* + * DTLS-related tests done last, because most of them may result in + * silently dropping the record (but not the whole datagram), and we only + * want to consider that after ensuring that the "basic" fields (type, + * version, length) are sane. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; + + /* Drop unexpected ChangeCipherSpec messages */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + /* Check epoch (and sequence number) with DTLS */ + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " + "expected %d, received %d", + ssl->in_epoch, rec_epoch ) ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + rec_epoch == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + /* Replay detection only works for the current epoch */ + if( rec_epoch == ssl->in_epoch && + mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + +/* + * If applicable, decrypt (and decompress) record content + */ +static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) +{ + int ret, done = 0; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", + ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_read != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); + + ret = mbedtls_ssl_hw_record_read( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", + ssl->in_msg, ssl->in_msglen ); + + if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + mbedtls_ssl_dtls_replay_update( ssl ); + } +#endif + + return( 0 ); +} + +static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); + +/* + * Read a record. + * + * Silently ignore non-fatal alert (and for DTLS, invalid records as well, + * RFC 6347 4.1.2.7) and continue reading until a valid record is found. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + if( ssl->keep_current_message == 0 ) + { + do { + + if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + return( ret ); + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + return( ret ); + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= reuse previously read message" ) ); + ssl->keep_current_message = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) +{ + int ret; + + /* + * Step A + * + * Consume last content-layer message and potentially + * update in_msglen which keeps track of the contents' + * consumption state. + * + * (1) Handshake messages: + * Remove last handshake message, move content + * and adapt in_msglen. + * + * (2) Alert messages: + * Consume whole record content, in_msglen = 0. + * + * NOTE: This needs to be fixed, since like for + * handshake messages it is allowed to have + * multiple alerts witin a single record. + * Internal reference IOTSSL-1321. + * + * (3) Change cipher spec: + * Consume whole record content, in_msglen = 0. + * + * (4) Application data: + * Don't do anything - the record layer provides + * the application data as a stream transport + * and consumes through mbedtls_ssl_read only. + * + */ + + /* Case (1): Handshake messages */ + if( ssl->in_hslen != 0 ) + { + /* Hard assertion to be sure that no application data + * is in flight, as corrupting ssl->in_msglen during + * ssl->in_offt != NULL is fatal. */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Get next Handshake message in the current record + */ + + /* Notes: + * (1) in_hslen is *NOT* necessarily the size of the + * current handshake content: If DTLS handshake + * fragmentation is used, that's the fragment + * size instead. Using the total handshake message + * size here is FAULTY and should be changed at + * some point. Internal reference IOTSSL-1414. + * (2) While it doesn't seem to cause problems, one + * has to be very careful not to assume that in_hslen + * is always <= in_msglen in a sensible communication. + * Again, it's wrong for DTLS handshake fragmentation. + * The following check is therefore mandatory, and + * should not be treated as a silently corrected assertion. + * Additionally, ssl->in_hslen might be arbitrarily out of + * bounds after handling a DTLS message with an unexpected + * sequence number, see mbedtls_ssl_prepare_handshake_record. + */ + if( ssl->in_hslen < ssl->in_msglen ) + { + ssl->in_msglen -= ssl->in_hslen; + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + } + else + { + ssl->in_msglen = 0; + } + + ssl->in_hslen = 0; + } + /* Case (4): Application data */ + else if( ssl->in_offt != NULL ) + { + return( 0 ); + } + /* Everything else (CCS & Alerts) */ + else + { + ssl->in_msglen = 0; + } + + /* + * Step B + * + * Fetch and decode new record if current one is fully consumed. + * + */ + + if( ssl->in_msglen > 0 ) + { + /* There's something left to be processed in the current record. */ + return( 0 ); + } + + /* Need to fetch a new record */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +read_record_header: +#endif + + /* Current record either fully processed or to be discarded. */ + + if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + if( ( ret = ssl_parse_record_header( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) + { + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) + { + /* Skip unexpected record (but not whole datagram) */ + ssl->next_record_offset = ssl->in_msglen + + mbedtls_ssl_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " + "(header)" ) ); + } + else + { + /* Skip invalid record and the rest of the datagram */ + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " + "(header)" ) ); + } + + /* Get next record */ + goto read_record_header; + } +#endif + return( ret ); + } + + /* + * Read and optionally decrypt the message contents + */ + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + + if( ( ret = ssl_prepare_record_content( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Silently discard invalid records */ + if( ret == MBEDTLS_ERR_SSL_INVALID_RECORD || + ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + /* Except when waiting for Finished as a bad mac here + * probably means something went wrong in the handshake + * (eg wrong psk used, mitm downgrade attempt, etc.) */ + if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || + ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) + { +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( ssl->conf->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->conf->badmac_limit ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif + + /* As above, invalid records cause + * dismissal of the whole datagram. */ + + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); + goto read_record_header; + } + + return( ret ); + } + else +#endif + { + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + } + + /* + * When we sent the last flight of the handshake, we MUST respond to a + * retransmit of the peer's previous flight with a retransmit. (In + * practice, only the Finished message will make it, other messages + * including CCS use the old transform so they're dropped as invalid.) + * + * If the record we received is not a handshake message, however, it + * means the peer received our last flight so we can clean up + * handshake info. + * + * This check needs to be done before prepare_handshake() due to an edge + * case: if the client immediately requests renegotiation, this + * finishes the current handshake first, avoiding the new ClientHello + * being mistaken for an ancient message in the current handshake. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + else + { + ssl_handshake_wrapup_free_hs_transform( ssl ); + } + } +#endif + + return( 0 ); +} + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) +{ + int ret; + + /* + * Handle particular types of records + */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) + { + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify and no_renegotiation + */ + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled when trying to parse ServerHello */ + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled in mbedtls_ssl_parse_certificate() */ + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + + /* Silently ignore: fetch new message */ + return MBEDTLS_ERR_SSL_NON_FATAL; + } + + return( 0 ); +} + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +/* No certificate support -> dummy functions */ +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +#else +/* Some certificate support -> implement write and parse */ + +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( mbedtls_ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->out_msglen = 2; + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", + i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + + ssl->out_msg[i ] = (unsigned char)( n >> 16 ); + ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); + ssl->out_msg[i + 2] = (unsigned char)( n ); + + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); + ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); + ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); + + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) +write_msg: +#endif + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + int authmode = ssl->conf->authmode; + uint8_t alert; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; +#endif + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + return( 0 ); + else + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + return( 0 ); + else + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_SRV_C */ + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || + ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + + if( ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* In case we tried to reuse a session but it failed */ + if( ssl->session_negotiate->peer_cert != NULL ) + { + mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); + mbedtls_free( ssl->session_negotiate->peer_cert ); + } + + if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, + sizeof( mbedtls_x509_crt ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + sizeof( mbedtls_x509_crt ) ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); + + i += 3; + + while( i < ssl->in_hslen ) + { + if( ssl->in_msg[i] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, + ssl->in_msg + i, n ); + switch( ret ) + { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + crt_parse_der_failed: + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); + + /* + * On client, make sure the server cert doesn't change during renego to + * avoid "triple handshake" attack: https://secure-resumption.com/ + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->session->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + if( ssl->session->peer_cert->raw.len != + ssl->session_negotiate->peer_cert->raw.len || + memcmp( ssl->session->peer_cert->raw.p, + ssl->session_negotiate->peer_cert->raw.p, + ssl->session->peer_cert->raw.len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + if( authmode != MBEDTLS_SSL_VERIFY_NONE ) + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + /* + * Main check: verify certificate + */ + ret = mbedtls_x509_crt_verify_with_profile( + ssl->session_negotiate->peer_cert, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_ECP_C) + { + const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && + mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) + { + ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + } +#endif /* MBEDTLS_ECP_C */ + + if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, + ciphersuite_info, + ! ssl->conf->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * ssl_parse_certificate even if verification was optional. */ + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) + { + ret = 0; + } + + if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if( ret != 0 ) + { + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) + alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) + alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; + else + alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert ); + } + +#if defined(MBEDTLS_DEBUG_C) + if( ssl->session_negotiate->verify_result != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x", + ssl->session_negotiate->verify_result ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); + } +#endif /* MBEDTLS_DEBUG_C */ + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); + } + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + ssl_dtls_replay_reset( ssl ); +#endif + + /* Increment epoch */ + if( ++ssl->in_epoch == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->in_ctr, 0, 8 ); + + /* + * Set the in_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - + ssl->transform_negotiate->fixed_ivlen; + } + else + ssl->in_msg = ssl->in_iv; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_starts_ret( &ssl->handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &ssl->handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_starts_ret( &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_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_update_ret( &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_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &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_ret( &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_ret( &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_ret( &md5, (const unsigned char *) sender, 4 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_finish_ret( &md5, md5sum ); + + mbedtls_sha1_update_ret( &sha1, (const unsigned char *) sender, 4 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf, 40 ); + mbedtls_sha1_finish_ret( &sha1, sha1sum ); + + memset( padbuf, 0x5C, 48 ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_update_ret( &md5, md5sum, 16 ); + mbedtls_md5_finish_ret( &md5, buf ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf , 40 ); + mbedtls_sha1_update_ret( &sha1, sha1sum, 20 ); + mbedtls_sha1_finish_ret( &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_ret( &md5, padbuf ); + mbedtls_sha1_finish_ret( &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_ret( &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_ret( &sha512, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_sha512_free( &sha512 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); + + /* + * Free our handshake params + */ + mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + + /* + * Free the previous transform and swith in the current one + */ + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); +} + +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } +#endif + + /* + * Free the previous session and switch in the current one + */ + if( ssl->session ) + { +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif + + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->conf->f_set_cache != NULL && + ssl->session->id_len != 0 && + resume == 0 ) + { + if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->flight != NULL ) + { + /* Cancel handshake timer */ + ssl_set_timer( ssl, 0 ); + + /* Keep last flight around in case we need to resend it: + * we need the handshake and transform structures for that */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); + } + else +#endif + ssl_handshake_wrapup_free_hs_transform( ssl ); + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) +{ + int ret, hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + /* + * Set the out_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - + ssl->transform_negotiate->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; + + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); + + /* + * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites + * may define some other value. Currently (early 2016), no defined + * ciphersuite does this (and this is unlikely to change as activity has + * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. + */ + hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); +#endif + + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned char i; + + /* Remember current epoch settings for resending */ + ssl->handshake->alt_transform_out = ssl->transform_out; + memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 ); + + /* Set sequence_number to zero */ + memset( ssl->out_ctr + 2, 0, 6 ); + + /* Increment epoch */ + for( i = 2; i > 0; i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->out_ctr, 0, 8 ); + + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define SSL_MAX_HASH_LEN 36 +#else +#define SSL_MAX_HASH_LEN 12 +#endif + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned int hash_len; + unsigned char buf[SSL_MAX_HASH_LEN]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* There is currently no ciphersuite using another length with TLS 1.2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + hash_len = 36; + else +#endif + hash_len = 12; + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + + if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), + buf, hash_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); +#endif + + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif + } + else + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + + return( 0 ); +} + +static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_init( &handshake->fin_md5 ); + mbedtls_sha1_init( &handshake->fin_sha1 ); + mbedtls_md5_starts_ret( &handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &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_ret( &handshake->fin_sha256, 0 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_init( &handshake->fin_sha512 ); + mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; +#endif +} + +static void ssl_transform_init( mbedtls_ssl_transform *transform ) +{ + memset( transform, 0, sizeof(mbedtls_ssl_transform) ); + + mbedtls_cipher_init( &transform->cipher_ctx_enc ); + mbedtls_cipher_init( &transform->cipher_ctx_dec ); + + mbedtls_md_init( &transform->md_ctx_enc ); + mbedtls_md_init( &transform->md_ctx_dec ); +} + +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) +{ + memset( session, 0, sizeof(mbedtls_ssl_session) ); +} + +static int ssl_handshake_init( mbedtls_ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + mbedtls_ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + mbedtls_ssl_handshake_free( ssl->handshake ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); + } + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Initialize structures */ + mbedtls_ssl_session_init( ssl->session_negotiate ); + ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->handshake->alt_transform_out = ssl->transform_out; + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + + ssl_set_timer( ssl, 0 ); + } +#endif + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/* Dummy cookie callbacks for defaults */ +static int ssl_cookie_write_dummy( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +static int ssl_cookie_check_dummy( void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +/* + * Initialize an SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) +{ + memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Setup an SSL context + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ) +{ + int ret; + const size_t len = MBEDTLS_SSL_BUFFER_LEN; + + ssl->conf = conf; + + /* + * Prepare base structures + */ + if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || + ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); + mbedtls_free( ssl->in_buf ); + ssl->in_buf = NULL; + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->out_ctr = ssl->out_buf + 3; + ssl->out_len = ssl->out_buf + 11; + ssl->out_iv = ssl->out_buf + 13; + ssl->out_msg = ssl->out_buf + 13; + + ssl->in_hdr = ssl->in_buf; + ssl->in_ctr = ssl->in_buf + 3; + ssl->in_len = ssl->in_buf + 11; + ssl->in_iv = ssl->in_buf + 13; + ssl->in_msg = ssl->in_buf + 13; + } + else +#endif + { + ssl->out_ctr = ssl->out_buf; + ssl->out_hdr = ssl->out_buf + 8; + ssl->out_len = ssl->out_buf + 11; + ssl->out_iv = ssl->out_buf + 13; + ssl->out_msg = ssl->out_buf + 13; + + ssl->in_ctr = ssl->in_buf; + ssl->in_hdr = ssl->in_buf + 8; + ssl->in_len = ssl->in_buf + 11; + ssl->in_iv = ssl->in_buf + 13; + ssl->in_msg = ssl->in_buf + 13; + } + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) + */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) +{ + int ret; + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + + /* Cancel any possibly running timer */ + ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); + memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; + + ssl->in_offt = NULL; + + ssl->in_msg = ssl->in_buf + 13; + ssl->in_msgtype = 0; + ssl->in_msglen = 0; + if( partial == 0 ) + ssl->in_left = 0; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + ssl_dtls_replay_reset( ssl ); +#endif + + ssl->in_hslen = 0; + ssl->nb_zero = 0; + + ssl->keep_current_message = 0; + + ssl->out_msg = ssl->out_buf + 13; + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) + ssl->split_done = 0; +#endif + + ssl->transform_in = NULL; + ssl->transform_out = NULL; + + memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + if( partial == 0 ) + memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_reset != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); + if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + ssl->transform = NULL; + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(MBEDTLS_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + if( partial == 0 ) + { + mbedtls_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + return( ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * SSL set accessors + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) +{ + conf->endpoint = endpoint; +} + +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) +{ + conf->transport = transport; +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) +{ + conf->anti_replay = mode; +} +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) +{ + conf->badmac_limit = limit; +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) +{ + conf->hs_timeout_min = min; + conf->hs_timeout_max = max; +} +#endif + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) +{ + conf->authmode = authmode; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + conf->f_vrfy = f_vrfy; + conf->p_vrfy = p_vrfy; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + conf->f_rng = f_rng; + conf->p_rng = p_rng; +} + +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ) +{ + conf->f_dbg = f_dbg; + conf->p_dbg = p_dbg; +} + +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ) +{ + ssl->p_bio = p_bio; + ssl->f_send = f_send; + ssl->f_recv = f_recv; + ssl->f_recv_timeout = f_recv_timeout; +} + +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) +{ + conf->read_timeout = timeout; +} + +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ) +{ + ssl->p_timer = p_timer; + ssl->f_set_timer = f_set_timer; + ssl->f_get_timer = f_get_timer; + + /* Make sure we start with no timer running */ + ssl_set_timer( ssl, 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ) +{ + conf->p_cache = p_cache; + conf->f_get_cache = f_get_cache; + conf->f_set_cache = f_set_cache; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) +{ + int ret; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ) +{ + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; +} + +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ) +{ + if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) + return; + + if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + conf->ciphersuite_list[minor] = ciphersuites; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ) +{ + conf->cert_profile = profile; +} + +/* Append a new keycert entry to a (possibly empty) list */ +static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, + mbedtls_x509_crt *cert, + mbedtls_pk_context *key ) +{ + mbedtls_ssl_key_cert *new; + + new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + new->cert = cert; + new->key = key; + new->next = NULL; + + /* Update head is the list was null, else add to the end */ + if( *head == NULL ) + { + *head = new; + } + else + { + mbedtls_ssl_key_cert *cur = *head; + while( cur->next != NULL ) + cur = cur->next; + cur->next = new; + } + + return( 0 ); +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + conf->ca_chain = ca_chain; + conf->ca_crl = ca_crl; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, + own_cert, pk_key ) ); +} + +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + ssl->handshake->sni_ca_chain = ca_chain; + ssl->handshake->sni_ca_crl = ca_crl; +} + +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ) +{ + ssl->handshake->sni_authmode = authmode; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Set EC J-PAKE password for current handshake + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + mbedtls_ecjpake_role role; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + role = MBEDTLS_ECJPAKE_SERVER; + else + role = MBEDTLS_ECJPAKE_CLIENT; + + return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, + role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + pw, pw_len ) ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + if( psk == NULL || psk_identity == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* Identity len will be encoded on two bytes */ + if( ( psk_identity_len >> 16 ) != 0 || + psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( conf->psk != NULL ) + { + mbedtls_zeroize( conf->psk, conf->psk_len ); + + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + if( conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } + + 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_zeroize( ssl->handshake->psk, ssl->handshake->psk_len ); + mbedtls_free( ssl->handshake->psk ); + ssl->handshake->psk_len = 0; + } + + 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) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +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 ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ) +{ + int ret; + + if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 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 /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#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 /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; + + /* Check if new hostname is valid before + * making any change to current one */ + if( hostname != NULL ) + { + hostname_len = strlen( hostname ); + + if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ + + if( ssl->hostname != NULL ) + { + mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } + + /* Passing NULL as hostname shall clear the old one */ + + if( hostname == NULL ) + { + ssl->hostname = NULL; + } + else + { + 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 /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + conf->f_sni = f_sni; + conf->p_sni = p_sni; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) +{ + size_t cur_len, tot_len; + const char **p; + + /* + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. + */ + tot_len = 0; + for( p = protos; *p != NULL; p++ ) + { + cur_len = strlen( *p ); + tot_len += cur_len; + + if( cur_len == 0 || cur_len > 255 || tot_len > 65535 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->alpn_list = protos; + + return( 0 ); +} + +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->max_major_ver = major; + conf->max_minor_ver = minor; +} + +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->min_major_ver = major; + conf->min_minor_ver = minor; +} + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) +{ + conf->fallback = fallback; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) +{ + conf->encrypt_then_mac = etm; +} +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) +{ + conf->extended_ms = ems; +} +#endif + +#if defined(MBEDTLS_ARC4_C) +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) +{ + conf->arc4_disabled = arc4; +} +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) +{ + if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || + mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) +{ + conf->trunc_hmac = truncate; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) +{ + conf->cbc_record_splitting = split; +} +#endif + +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) +{ + conf->allow_legacy_renegotiation = allow_legacy; +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) +{ + conf->disable_renegotiation = renegotiation; +} + +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) +{ + conf->renego_max_records = max_records; +} + +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ) +{ + memcpy( conf->renego_period, period, 8 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) +{ + conf->session_tickets = use_tickets; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ) +{ + conf->f_ticket_write = f_ticket_write; + conf->f_ticket_parse = f_ticket_parse; + conf->p_ticket = p_ticket; +} +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ) +{ + conf->f_export_keys = f_export_keys; + conf->p_export_keys = p_export_keys; +} +#endif + +/* + * SSL get accessors + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) +{ + if( ssl->session != NULL ) + return( ssl->session->verify_result ); + + if( ssl->session_negotiate != NULL ) + return( ssl->session_negotiate->verify_result ); + + return( 0xFFFFFFFF ); +} + +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "DTLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "DTLSv1.2" ); + + default: + return( "unknown (DTLS)" ); + } + } +#endif + + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_0: + return( "SSLv3.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_1: + return( "TLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "TLSv1.1" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + return( "unknown" ); + } +} + +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +{ + size_t transform_expansion; + const mbedtls_ssl_transform *transform = ssl->transform_out; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + if( transform == NULL ) + return( (int) mbedtls_ssl_hdr_len( ssl ) ); + + switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + { + case MBEDTLS_MODE_GCM: + case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_STREAM: + transform_expansion = transform->minlen; + break; + + case MBEDTLS_MODE_CBC: + transform_expansion = transform->maclen + + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len; + + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = mfl_code_to_length[ssl->conf->mfl_code]; + + /* + * Check if a smaller max length was negotiated + */ + if( ssl->session_out != NULL && + mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) + { + max_len = mfl_code_to_length[ssl->session_out->mfl_code]; + } + + return max_len; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return( ssl->session->peer_cert ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst ) +{ + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ssl_session_copy( dst, ssl->session ) ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +/* + * Perform a single step of the SSL handshake + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ret = mbedtls_ssl_handshake_client_step( ssl ); +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ret = mbedtls_ssl_handshake_server_step( ssl ); +#endif + + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. + */ +static int ssl_start_renegotiation( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; + } +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return( ret ); +} + +/* + * Check record counters and renegotiate if they're above the limit. + */ +static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) +{ + size_t ep_len = ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + out_ctr_cmp = memcmp( ssl->out_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + { + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); + return( mbedtls_ssl_renegotiate( ssl ) ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret; + size_t n; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + if( ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } + } +#endif + + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ret = ssl_check_ctr_renegotiate( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + /* + * TODO + * + * The logic should be streamlined here: + * + * Instead of + * + * - Manually checking whether ssl->in_offt is NULL + * - Fetching a new record if yes + * - Setting ssl->in_offt if one finds an application record + * - Resetting keep_current_message after handling the application data + * + * one should + * + * - Adapt read_record to set ssl->in_offt automatically + * when a new application data record is processed. + * - Always call mbedtls_ssl_read_record here. + * + * This way, the logic of ssl_read would be much clearer: + * + * (1) Always call record layer and see what kind of record is on + * and have it ready for consumption (in particular, in_offt + * properly set for application data records). + * (2) If it's application data (either freshly fetched + * or something already being partially processed), + * serve the read request from it. + * (3) If it's something different from application data, + * handle it accordingly, e.g. potentially start a + * renegotiation. + * + * This will also remove the need to manually reset + * ssl->keep_current_message = 0 below. + * + */ + + if( ssl->in_offt == NULL ) + { + /* Start timer if not already running */ + if( ssl->f_get_timer != NULL && + ssl->f_get_timer( ssl->p_timer ) == -1 ) + { + ssl_set_timer( ssl, ssl->conf->read_timeout ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) + { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = ssl_start_renegotiation( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* SSLv3 does not have a "no_renegotiation" warning, so + we send a fatal alert and abort the connection. */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->renego_max_records >= 0 ) + { + if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + + /* We're going to return something now, cancel timer, + * except if handshake (renegotiation) is in progress */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* If we requested renego but received AppData, resend HelloRequest. + * Do it now, after setting in_offt, to avoid taking this branch + * again if ssl_write_hello_request() returns WANT_WRITE */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + if( ssl->in_msglen == 0 ) + { + /* all bytes consumed */ + ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } + else + { + /* more data available */ + ssl->in_offt += n; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer, + * taking care of max fragment length and buffer size + */ +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); +#else + size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + 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; + } + + 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 whether we already did the split or not. + */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +static int ssl_write_split( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; + + if( ssl->conf->cbc_record_splitting == + MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || + len <= 1 || + ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || + mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) + != MBEDTLS_MODE_CBC ) + { + return( ssl_write_real( ssl, buf, len ) ); + } + + if( ssl->split_done == 0 ) + { + if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 1; + } + + if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 0; + + return( ret + 1 ); +} +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + mbedtls_cipher_free( &transform->cipher_ctx_enc ); + mbedtls_cipher_free( &transform->cipher_ctx_dec ); + + mbedtls_md_free( &transform->md_ctx_enc ); + mbedtls_md_free( &transform->md_ctx_dec ); + + mbedtls_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) +{ + mbedtls_ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) +{ + if( handshake == NULL ) + return; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_free( &handshake->fin_md5 ); + mbedtls_sha1_free( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_free( &handshake->fin_sha256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_free( &handshake->fin_sha512 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_free( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( handshake->ecjpake_cache ); + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + /* explicit void pointer cast for buggy MS compiler */ + mbedtls_free( (void *) handshake->curves ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( handshake->psk != NULL ) + { + mbedtls_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_free( handshake->psk ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_free( handshake->verify_cookie ); + mbedtls_free( handshake->hs_msg ); + ssl_flight_free( handshake->flight ); +#endif + + mbedtls_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) ); +} + +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( session->peer_cert != NULL ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + } +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( session->ticket ); +#endif + + mbedtls_zeroize( session, sizeof( mbedtls_ssl_session ) ); +} + +/* + * Free an SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_buf != NULL ) + { + mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->out_buf ); + } + + if( ssl->in_buf != NULL ) + { + mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->in_buf ); + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->compress_buf != NULL ) + { + mbedtls_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->compress_buf ); + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + + if( ssl->handshake ) + { + mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + mbedtls_ssl_session_free( ssl->session_negotiate ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ssl->hostname != NULL ) + { + mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_finish != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); + mbedtls_ssl_hw_record_finish( ssl ); + } +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + mbedtls_free( ssl->cli_id ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + mbedtls_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Initialze mbedtls_ssl_config + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) +{ + memset( conf, 0, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_preset_default_hashes[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif + +static int ssl_preset_suiteb_ciphersuites[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + 0 +}; + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_preset_suiteb_hashes[] = { + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_NONE +}; +#endif + +#if defined(MBEDTLS_ECP_C) +static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { + MBEDTLS_ECP_DP_SECP256R1, + MBEDTLS_ECP_DP_SECP384R1, + MBEDTLS_ECP_DP_NONE +}; +#endif + +/* + * Load default in mbedtls_ssl_config + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ) +{ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + int ret; +#endif + + /* Use the functions here so that they are covered in tests, + * but otherwise access member directly for efficiency */ + mbedtls_ssl_conf_endpoint( conf, endpoint ); + mbedtls_ssl_conf_transport( conf, transport ); + + /* + * Things that are common to all presets + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; +#endif + } +#endif + +#if defined(MBEDTLS_ARC4_C) + conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + conf->f_cookie_write = ssl_cookie_write_dummy; + conf->f_cookie_check = ssl_cookie_check_dummy; +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; + conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset( conf->renego_period, 0x00, 2 ); + memset( conf->renego_period + 2, 0xFF, 6 ); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + const unsigned char dhm_p[] = + MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; + const unsigned char dhm_g[] = + MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + + if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf, + dhm_p, sizeof( dhm_p ), + dhm_g, sizeof( dhm_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_MIN_MAJOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ? + MBEDTLS_SSL_MIN_MAJOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; + conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ? + MBEDTLS_SSL_MIN_MINOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; +#endif + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + mbedtls_ssl_list_ciphersuites(); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + conf->sig_hashes = ssl_preset_default_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = mbedtls_ecp_grp_id_list(); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + conf->dhm_min_bitlen = 1024; +#endif + } + + return( 0 ); +} + +/* + * Free mbedtls_ssl_config + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) +{ +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( conf->psk != NULL ) + { + mbedtls_zeroize( conf->psk, conf->psk_len ); + mbedtls_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk ); + mbedtls_free( conf->psk_identity ); + conf->psk_len = 0; + conf->psk_identity_len = 0; + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_key_cert_free( conf->key_cert ); +#endif + + mbedtls_zeroize( conf, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_PK_C) && \ + ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) +/* + * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX + */ +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) + return( MBEDTLS_SSL_SIG_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) + return( MBEDTLS_SSL_SIG_ECDSA ); +#endif + return( MBEDTLS_SSL_SIG_ANON ); +} + +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) +{ + switch( type ) { + case MBEDTLS_PK_RSA: + return( MBEDTLS_SSL_SIG_RSA ); + case MBEDTLS_PK_ECDSA: + case MBEDTLS_PK_ECKEY: + return( MBEDTLS_SSL_SIG_ECDSA ); + default: + return( MBEDTLS_SSL_SIG_ANON ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + return( MBEDTLS_PK_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_SSL_SIG_ECDSA: + return( MBEDTLS_PK_ECDSA ); +#endif + default: + return( MBEDTLS_PK_NONE ); + } +} +#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + return( set->rsa ); + case MBEDTLS_PK_ECDSA: + return( set->ecdsa ); + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + if( set->rsa == MBEDTLS_MD_NONE ) + set->rsa = md_alg; + break; + + case MBEDTLS_PK_ECDSA: + if( set->ecdsa == MBEDTLS_MD_NONE ) + set->ecdsa = md_alg; + break; + + default: + break; + } +} + +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ) +{ + set->rsa = md_alg; + set->ecdsa = md_alg; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/* + * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX + */ +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + return( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA224: + return( MBEDTLS_MD_SHA224 ); + case MBEDTLS_SSL_HASH_SHA256: + return( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + return( MBEDTLS_MD_SHA384 ); + case MBEDTLS_SSL_HASH_SHA512: + return( MBEDTLS_MD_SHA512 ); +#endif + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* + * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX + */ +unsigned char mbedtls_ssl_hash_from_md_alg( int md ) +{ + switch( md ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( MBEDTLS_SSL_HASH_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( MBEDTLS_SSL_HASH_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( MBEDTLS_SSL_HASH_SHA224 ); + case MBEDTLS_MD_SHA256: + return( MBEDTLS_SSL_HASH_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( MBEDTLS_SSL_HASH_SHA384 ); + case MBEDTLS_MD_SHA512: + return( MBEDTLS_SSL_HASH_SHA512 ); +#endif + default: + return( MBEDTLS_SSL_HASH_NONE ); + } +} + +#if defined(MBEDTLS_ECP_C) +/* + * Check if a curve proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_group_id *gid; + + if( ssl->conf->curve_list == NULL ) + return( -1 ); + + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + if( *gid == grp_id ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Check if a hash proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ) +{ + const int *cur; + + if( ssl->conf->sig_hashes == NULL ) + return( -1 ); + + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + if( *cur == (int) md ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ) +{ + int ret = 0; +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + int usage = 0; +#endif +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + const char *ext_oid; + size_t ext_len; +#endif + +#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ + !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + ((void) cert); + ((void) cert_endpoint); + ((void) flags); +#endif + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + break; + + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + break; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + usage = MBEDTLS_X509_KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case MBEDTLS_KEY_EXCHANGE_NONE: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + } + + if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; + ret = -1; + } +#else + ((void) ciphersuite); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); + } + else + { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); + } + + if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; + ret = -1; + } +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + + return( ret ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Convert version numbers to/from wire format + * and, for DTLS, to/from TLS equivalent. + * + * For TLS this is the identity. + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: + * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + */ +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) + --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + + ver[0] = (unsigned char)( 255 - ( major - 2 ) ); + ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); + } + else +#else + ((void) transport); +#endif + { + ver[0] = (unsigned char) major; + ver[1] = (unsigned char) minor; + } +} + +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + *major = 255 - ver[0] + 2; + *minor = 255 - ver[1] + 1; + + if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) + ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + } + else +#else + ((void) transport); +#endif + { + *major = ver[0]; + *minor = ver[1]; + } +} + +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + + switch( md ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + ssl->handshake->calc_verify = ssl_calc_verify_tls; + break; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + } + + return 0; +#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ + (void) ssl; + (void) md; + + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ) +{ + int ret = 0; + 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); + */ + if( ( ret = mbedtls_md5_starts_ret( &mbedtls_md5 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_finish_ret( &mbedtls_md5, output ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ret", ret ); + goto exit; + } + + if( ( ret = mbedtls_sha1_starts_ret( &mbedtls_sha1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, data, + data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_finish_ret( &mbedtls_sha1, + output + 16 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ret", ret ); + goto exit; + } + +exit: + mbedtls_md5_free( &mbedtls_md5 ); + mbedtls_sha1_free( &mbedtls_sha1 ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); + +} +#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) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + int ret = 0; + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + + mbedtls_md_init( &ctx ); + + /* + * 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 ); + goto exit; + } + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_finish( &ctx, output ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); + goto exit; + } + +exit: + mbedtls_md_free( &ctx ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#endif /* MBEDTLS_SSL_TLS_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/threading.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_THREADING_C) + + + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return; + + mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; +} + +static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || !mutex->is_valid ) + return; + + (void) pthread_mutex_destroy( &mutex->mutex ); + mutex->is_valid = 0; +} + +static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; + +/* + * With phtreads we can statically initialize mutexes + */ +#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } + +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_THREADING_ALT) +static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); +} +static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return; +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; + +/* + * Set functions pointers and initialize global mutexes + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) +{ + mbedtls_mutex_init = mutex_init; + mbedtls_mutex_free = mutex_free; + mbedtls_mutex_lock = mutex_lock; + mbedtls_mutex_unlock = mutex_unlock; + + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; + +#endif /* MBEDTLS_THREADING_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/timing.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_TIMING_C) + + + +#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 ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + QueryPerformanceCounter( &t->start ); + return( 0 ); + } + else + { + unsigned long delta; + LARGE_INTEGER now, hfreq; + QueryPerformanceCounter( &now ); + QueryPerformanceFrequency( &hfreq ); + delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul + / hfreq.QuadPart ); + 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; + + if( seconds == 0 ) + { + /* No need to create a thread for this simple case. + * Also, this shorcut is more reliable at least on MinGW32 */ + mbedtls_timing_alarmed = 1; + return; + } + + 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 ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + gettimeofday( &t->start, NULL ); + return( 0 ); + } + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.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 ); + if( seconds == 0 ) + { + /* alarm(0) cancelled any previous pending alarm, but the + handler won't fire, so raise the flag straight away. */ + mbedtls_timing_alarmed = 1; + } +} + +#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 at line %d\n", __LINE__ ); \ + mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ + cycles, ratio, millisecs, secs, hardfail, \ + (unsigned long) a, (unsigned long) b ); \ + mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ + mbedtls_timing_get_timer( &hires, 0 ), \ + mbedtls_timing_get_timer( &ctx.timer, 0 ), \ + mbedtls_timing_get_delay( &ctx ) ); \ + } \ + 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 = 0, ratio = 0; + unsigned long millisecs = 0, secs = 0; + int hardfail = 0; + struct mbedtls_timing_hr_time hires; + uint32_t a = 0, b = 0; + 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): " ); + + { + secs = 1; + + (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 ) + FAIL; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); + + { + a = 800; + b = 400; + mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */ + + busy_msleep( a - a / 4 ); /* T = a - a/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; + + busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b ); /* T = a + b + 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. + */ + +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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/version.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_VERSION_C) + + +#include + +unsigned int mbedtls_version_get_number( void ) +{ + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/version_features.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_VERSION_C) + + + +#include + +static const char *features[] = { +#if defined(MBEDTLS_VERSION_FEATURES) +#if defined(MBEDTLS_HAVE_ASM) + "MBEDTLS_HAVE_ASM", +#endif /* MBEDTLS_HAVE_ASM */ +#if defined(MBEDTLS_NO_UDBL_DIVISION) + "MBEDTLS_NO_UDBL_DIVISION", +#endif /* MBEDTLS_NO_UDBL_DIVISION */ +#if defined(MBEDTLS_HAVE_SSE2) + "MBEDTLS_HAVE_SSE2", +#endif /* MBEDTLS_HAVE_SSE2 */ +#if defined(MBEDTLS_HAVE_TIME) + "MBEDTLS_HAVE_TIME", +#endif /* MBEDTLS_HAVE_TIME */ +#if defined(MBEDTLS_HAVE_TIME_DATE) + "MBEDTLS_HAVE_TIME_DATE", +#endif /* MBEDTLS_HAVE_TIME_DATE */ +#if defined(MBEDTLS_PLATFORM_MEMORY) + "MBEDTLS_PLATFORM_MEMORY", +#endif /* MBEDTLS_PLATFORM_MEMORY */ +#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) + "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) + "MBEDTLS_PLATFORM_EXIT_ALT", +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) + "MBEDTLS_PLATFORM_TIME_ALT", +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) + "MBEDTLS_PLATFORM_FPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) + "MBEDTLS_PLATFORM_PRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) + "MBEDTLS_PLATFORM_SNPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) + "MBEDTLS_PLATFORM_NV_SEED_ALT", +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ +#if defined(MBEDTLS_DEPRECATED_WARNING) + "MBEDTLS_DEPRECATED_WARNING", +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#if defined(MBEDTLS_DEPRECATED_REMOVED) + "MBEDTLS_DEPRECATED_REMOVED", +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_TIMING_ALT) + "MBEDTLS_TIMING_ALT", +#endif /* MBEDTLS_TIMING_ALT */ +#if defined(MBEDTLS_AES_ALT) + "MBEDTLS_AES_ALT", +#endif /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_ARC4_ALT) + "MBEDTLS_ARC4_ALT", +#endif /* MBEDTLS_ARC4_ALT */ +#if defined(MBEDTLS_BLOWFISH_ALT) + "MBEDTLS_BLOWFISH_ALT", +#endif /* MBEDTLS_BLOWFISH_ALT */ +#if defined(MBEDTLS_CAMELLIA_ALT) + "MBEDTLS_CAMELLIA_ALT", +#endif /* MBEDTLS_CAMELLIA_ALT */ +#if defined(MBEDTLS_CCM_ALT) + "MBEDTLS_CCM_ALT", +#endif /* MBEDTLS_CCM_ALT */ +#if defined(MBEDTLS_CMAC_ALT) + "MBEDTLS_CMAC_ALT", +#endif /* MBEDTLS_CMAC_ALT */ +#if defined(MBEDTLS_DES_ALT) + "MBEDTLS_DES_ALT", +#endif /* MBEDTLS_DES_ALT */ +#if defined(MBEDTLS_DHM_ALT) + "MBEDTLS_DHM_ALT", +#endif /* MBEDTLS_DHM_ALT */ +#if defined(MBEDTLS_ECJPAKE_ALT) + "MBEDTLS_ECJPAKE_ALT", +#endif /* MBEDTLS_ECJPAKE_ALT */ +#if defined(MBEDTLS_GCM_ALT) + "MBEDTLS_GCM_ALT", +#endif /* MBEDTLS_GCM_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_RSA_ALT) + "MBEDTLS_RSA_ALT", +#endif /* MBEDTLS_RSA_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_XTEA_ALT) + "MBEDTLS_XTEA_ALT", +#endif /* MBEDTLS_XTEA_ALT */ +#if defined(MBEDTLS_ECP_ALT) + "MBEDTLS_ECP_ALT", +#endif /* MBEDTLS_ECP_ALT */ +#if defined(MBEDTLS_MD2_PROCESS_ALT) + "MBEDTLS_MD2_PROCESS_ALT", +#endif /* MBEDTLS_MD2_PROCESS_ALT */ +#if defined(MBEDTLS_MD4_PROCESS_ALT) + "MBEDTLS_MD4_PROCESS_ALT", +#endif /* MBEDTLS_MD4_PROCESS_ALT */ +#if defined(MBEDTLS_MD5_PROCESS_ALT) + "MBEDTLS_MD5_PROCESS_ALT", +#endif /* MBEDTLS_MD5_PROCESS_ALT */ +#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) + "MBEDTLS_RIPEMD160_PROCESS_ALT", +#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ +#if defined(MBEDTLS_SHA1_PROCESS_ALT) + "MBEDTLS_SHA1_PROCESS_ALT", +#endif /* MBEDTLS_SHA1_PROCESS_ALT */ +#if defined(MBEDTLS_SHA256_PROCESS_ALT) + "MBEDTLS_SHA256_PROCESS_ALT", +#endif /* MBEDTLS_SHA256_PROCESS_ALT */ +#if defined(MBEDTLS_SHA512_PROCESS_ALT) + "MBEDTLS_SHA512_PROCESS_ALT", +#endif /* MBEDTLS_SHA512_PROCESS_ALT */ +#if defined(MBEDTLS_DES_SETKEY_ALT) + "MBEDTLS_DES_SETKEY_ALT", +#endif /* MBEDTLS_DES_SETKEY_ALT */ +#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) + "MBEDTLS_DES_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) + "MBEDTLS_DES3_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) + "MBEDTLS_AES_SETKEY_ENC_ALT", +#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ +#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) + "MBEDTLS_AES_SETKEY_DEC_ALT", +#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ +#if defined(MBEDTLS_AES_ENCRYPT_ALT) + "MBEDTLS_AES_ENCRYPT_ALT", +#endif /* MBEDTLS_AES_ENCRYPT_ALT */ +#if defined(MBEDTLS_AES_DECRYPT_ALT) + "MBEDTLS_AES_DECRYPT_ALT", +#endif /* MBEDTLS_AES_DECRYPT_ALT */ +#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) + "MBEDTLS_ECDH_GEN_PUBLIC_ALT", +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ +#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) + "MBEDTLS_ECDH_COMPUTE_SHARED_ALT", +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + "MBEDTLS_ECDSA_VERIFY_ALT", +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + "MBEDTLS_ECDSA_SIGN_ALT", +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#if defined(MBEDTLS_ECDSA_GENKEY_ALT) + "MBEDTLS_ECDSA_GENKEY_ALT", +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + "MBEDTLS_ECP_INTERNAL_ALT", +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + "MBEDTLS_ECP_ADD_MIXED_ALT", +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + "MBEDTLS_ECP_DOUBLE_JAC_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + "MBEDTLS_TEST_NULL_ENTROPY", +#endif /* MBEDTLS_TEST_NULL_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + "MBEDTLS_ENTROPY_HARDWARE_ALT", +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#if defined(MBEDTLS_AES_ROM_TABLES) + "MBEDTLS_AES_ROM_TABLES", +#endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + "MBEDTLS_CAMELLIA_SMALL_MEMORY", +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + "MBEDTLS_CIPHER_MODE_CBC", +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_CFB) + "MBEDTLS_CIPHER_MODE_CFB", +#endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_CTR) + "MBEDTLS_CIPHER_MODE_CTR", +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + "MBEDTLS_CIPHER_NULL_CIPHER", +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + "MBEDTLS_CIPHER_PADDING_PKCS7", +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + "MBEDTLS_CIPHER_PADDING_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) + "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + "MBEDTLS_ECP_DP_SECP192R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + "MBEDTLS_ECP_DP_SECP224R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + "MBEDTLS_ECP_DP_SECP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + "MBEDTLS_ECP_DP_SECP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + "MBEDTLS_ECP_DP_SECP521R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + "MBEDTLS_ECP_DP_SECP192K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + "MBEDTLS_ECP_DP_SECP224K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + "MBEDTLS_ECP_DP_SECP256K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + "MBEDTLS_ECP_DP_BP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + "MBEDTLS_ECP_DP_BP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + "MBEDTLS_ECP_DP_BP512R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + "MBEDTLS_ECP_DP_CURVE25519_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_NIST_OPTIM) + "MBEDTLS_ECP_NIST_OPTIM", +#endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + "MBEDTLS_ECDSA_DETERMINISTIC", +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + "MBEDTLS_PK_PARSE_EC_EXTENDED", +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + "MBEDTLS_ERROR_STRERROR_DUMMY", +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ +#if defined(MBEDTLS_GENPRIME) + "MBEDTLS_GENPRIME", +#endif /* MBEDTLS_GENPRIME */ +#if defined(MBEDTLS_FS_IO) + "MBEDTLS_FS_IO", +#endif /* MBEDTLS_FS_IO */ +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) + "MBEDTLS_NO_PLATFORM_ENTROPY", +#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) + "MBEDTLS_ENTROPY_FORCE_SHA256", +#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) + "MBEDTLS_ENTROPY_NV_SEED", +#endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if defined(MBEDTLS_MEMORY_DEBUG) + "MBEDTLS_MEMORY_DEBUG", +#endif /* MBEDTLS_MEMORY_DEBUG */ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + "MBEDTLS_MEMORY_BACKTRACE", +#endif /* MBEDTLS_MEMORY_BACKTRACE */ +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + "MBEDTLS_PK_RSA_ALT_SUPPORT", +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ +#if defined(MBEDTLS_PKCS1_V15) + "MBEDTLS_PKCS1_V15", +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + "MBEDTLS_PKCS1_V21", +#endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_RSA_NO_CRT) + "MBEDTLS_RSA_NO_CRT", +#endif /* MBEDTLS_RSA_NO_CRT */ +#if defined(MBEDTLS_SELF_TEST) + "MBEDTLS_SELF_TEST", +#endif /* MBEDTLS_SELF_TEST */ +#if defined(MBEDTLS_SHA256_SMALLER) + "MBEDTLS_SHA256_SMALLER", +#endif /* MBEDTLS_SHA256_SMALLER */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + "MBEDTLS_SSL_ALL_ALERT_MESSAGES", +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_DEBUG_ALL) + "MBEDTLS_SSL_DEBUG_ALL", +#endif /* MBEDTLS_SSL_DEBUG_ALL */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + "MBEDTLS_SSL_ENCRYPT_THEN_MAC", +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + "MBEDTLS_SSL_FALLBACK_SCSV", +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + "MBEDTLS_SSL_HW_RECORD_ACCEL", +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + "MBEDTLS_SSL_CBC_RECORD_SPLITTING", +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + "MBEDTLS_SSL_RENEGOTIATION", +#endif /* MBEDTLS_SSL_RENEGOTIATION */ +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", +#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + "MBEDTLS_SSL_PROTO_SSL3", +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) + "MBEDTLS_SSL_PROTO_TLS1", +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) + "MBEDTLS_SSL_PROTO_TLS1_1", +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + "MBEDTLS_SSL_PROTO_TLS1_2", +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + "MBEDTLS_SSL_PROTO_DTLS", +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_ALPN) + "MBEDTLS_SSL_ALPN", +#endif /* MBEDTLS_SSL_ALPN */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + "MBEDTLS_SSL_DTLS_ANTI_REPLAY", +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + "MBEDTLS_SSL_DTLS_HELLO_VERIFY", +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + "MBEDTLS_SSL_SESSION_TICKETS", +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + "MBEDTLS_SSL_EXPORT_KEYS", +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + "MBEDTLS_SSL_SERVER_NAME_INDICATION", +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + "MBEDTLS_SSL_TRUNCATED_HMAC", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_X509_USE_C) + + + + + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#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) + +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) +#include +#include +#include +#endif +#endif + +#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) paramaters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ) +{ + int ret; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + + MBEDTLS_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + val->p = *p; + *p += val->len; + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ + *res = 0; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + *res *= 10; + *res += ( *(*p)++ - '0' ); + } + + return( 0 ); +} + +static int x509_date_is_valid(const mbedtls_x509_time *t ) +{ + int ret = MBEDTLS_ERR_X509_INVALID_DATE; + int month_len; + + CHECK_RANGE( 0, 9999, t->year ); + CHECK_RANGE( 0, 23, t->hour ); + CHECK_RANGE( 0, 59, t->min ); + CHECK_RANGE( 0, 59, t->sec ); + + switch( t->mon ) + { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + month_len = 31; + break; + case 4: case 6: case 9: case 11: + month_len = 30; + break; + case 2: + if( ( !( t->year % 4 ) && t->year % 100 ) || + !( t->year % 400 ) ) + month_len = 29; + else + month_len = 28; + break; + default: + return( ret ); + } + CHECK_RANGE( 1, month_len, t->day ); + + return( 0 ); +} + +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *tm ) +{ + int ret; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &tm->year ) ); + if ( 2 == yearlen ) + { + if ( tm->year < 50 ) + tm->year += 100; + + tm->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &tm->mon ) ); + CHECK( x509_parse_int( p, 2, &tm->day ) ); + CHECK( x509_parse_int( p, 2, &tm->hour ) ); + CHECK( x509_parse_int( p, 2, &tm->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( tm ) ); + + return ( 0 ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *tm ) +{ + int ret; + size_t len, year_len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + + if( tag == MBEDTLS_ASN1_UTC_TIME ) + year_len = 2; + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + year_len = 4; + else + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + return x509_parse_time( p, len, year_len, tm ); +} + +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) +{ + int ret; + size_t len; + int tag_type; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag_type = **p; + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); + + sig->tag = tag_type; + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret; + + if( *sig_opts != NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + mbedtls_pk_rsassa_pss_options *pss_opts; + + pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + ret = mbedtls_x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + mbedtls_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed!) + */ +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ) +{ + int ret; + size_t len; + + if( *p == end ) + return( 0 ); + + ext->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) + return( ret ); + + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + * + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( end != *p + len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) +{ + int ret; + size_t i, n; + unsigned char c, merge = 0; + const mbedtls_x509_name *name; + const char *short_name = NULL; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = mbedtls_snprintf( p, n, "%s=", short_name ); + else + ret = mbedtls_snprintf( p, n, "\?\?=" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + for( i = 0; i < name->val.len; i++ ) + { + if( i >= sizeof( s ) - 1 ) + break; + + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; + } + s[i] = '\0'; + ret = mbedtls_snprintf( p, n, "%s", s ); + MBEDTLS_X509_SAFE_SNPRINTF; + + merge = name->next_merged; + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) +{ + int ret; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + if( nr != serial->len ) + { + ret = mbedtls_snprintf( p, n, "...." ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ) +{ + int ret; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = mbedtls_snprintf( p, n, "???" ); + else + ret = mbedtls_snprintf( p, n, "%s", desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_pk_rsassa_pss_options *pss_opts; + const mbedtls_md_info_t *md_info, *mgf_md_info; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + md_info = mbedtls_md_info_from_type( md_alg ); + mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? mbedtls_md_get_name( md_info ) : "???", + mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", + pss_opts->expected_salt_len ); + MBEDTLS_X509_SAFE_SNPRINTF; + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) +{ + char *p = buf; + size_t n = buf_size; + int ret; + + ret = mbedtls_snprintf( p, n, "%s key size", name ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( 0 ); +} + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/* + * Set the time structure to the current time. + * Return 0 on success, non-zero on failure. + */ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + SYSTEMTIME st; + + GetSystemTime( &st ); + + now->year = st.wYear; + now->mon = st.wMonth; + now->day = st.wDay; + now->hour = st.wHour; + now->min = st.wMinute; + now->sec = st.wSecond; + + return( 0 ); +} +#else +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + struct tm *lt; + mbedtls_time_t tt; + int ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + tt = mbedtls_time( NULL ); + lt = gmtime( &tt ); + + if( lt == NULL ) + ret = -1; + else + { + now->year = lt->tm_year + 1900; + now->mon = lt->tm_mon + 1; + now->day = lt->tm_mday; + now->hour = lt->tm_hour; + now->min = lt->tm_min; + now->sec = lt->tm_sec; + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( &now, to ) ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( from, &now ) ); +} + +#else /* MBEDTLS_HAVE_TIME_DATE */ + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#if defined(MBEDTLS_SELF_TEST) + + + + +/* + * Checkup routine + */ +int mbedtls_x509_self_test( int verbose ) +{ +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) + int ret; + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + + if( verbose != 0 ) + mbedtls_printf( " X.509 certificate load: " ); + + mbedtls_x509_crt_init( &clicert ); + + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + mbedtls_x509_crt_init( &cacert ); + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, + mbedtls_test_ca_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n X.509 signature verify: "); + + ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n"); + + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &clicert ); + + return( 0 ); +#else + ((void) verbose); + return( 0 ); +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_X509_USE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509_create.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_X509_CREATE_C) + + + + + +#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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509_crl.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + + + + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 + * + * We currently don't parse any extension's content, but we do check that the + * list of extensions is well-formed and abort on critical extensions (that + * are unsupported as we don't support any extension so far) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + 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 ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + int is_critical = 0; + const unsigned char *end_ext_data; + size_t len; + + /* Get enclosing 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 ); + + end_ext_data = *p + len; + + /* Get OID (currently ignored) */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + *p += len; + + /* 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 ); + + /* Ignore data so far and just check its length */ + *p += len; + if( *p != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Abort on (unsupported) critical extensions */ + if( is_critical ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + 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 = NULL, *end = NULL; + 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( buflen == 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + p = mbedtls_calloc( 1, buflen ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crl->raw.p = p; + crl->raw.len = buflen; + + end = p + buflen; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->version < 0 || crl->version > 1 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crl->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && + ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid.len != sig_oid2.len || + memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret; + size_t use_len; + mbedtls_pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + do + { + mbedtls_pem_init( &pem ); + + // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated + // string + if( buflen == 0 || buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + is_pem = 1; + + buflen -= use_len; + buf += use_len; + + if( ( ret = mbedtls_x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + } + else if( is_pem ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + + mbedtls_pem_free( &pem ); + } + /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. + * And a valid CRL cannot be less than 1 byte anyway. */ + while( is_pem && buflen > 1 ); + + if( is_pem ) + return( 0 ); + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crl_parse( chain, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ) +{ + int ret; + size_t n; + char *p; + const mbedtls_x509_crl_entry *entry; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = &crl->entry; + + ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%sserial number: ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = entry->next; + } + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) +{ + memset( crl, 0, sizeof(mbedtls_x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) +{ + mbedtls_x509_crl *crl_cur = crl; + mbedtls_x509_crl *crl_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + if( crl_prv != crl ) + mbedtls_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509_crt.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + + + + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) + +#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 */ +/* zeroize was here */ + +/* + * Default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) + /* Allow SHA-1 (weak, but still safe in controlled environments) */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | +#endif + /* Only SHA-2 hashes */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 2048, +}; + +/* + * Next-default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), +#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_TAG_CLASS_MASK ) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + /* Skip everything but DNS name */ + if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) + { + *p += tag_len; + continue; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt ) +{ + int ret; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get extension ID */ + extn_oid.tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.p = *p; + *p += extn_oid.len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } +#endif + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + default: + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf, + size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + // Use the original buffer until we figure out actual length + p = (unsigned char*) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len > (size_t) ( end - p ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + crt_end = p + len; + + // Create and populate a new buffer for the raw field + crt->raw.len = crt_end - buf; + crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, crt->raw.len ); + + // Direct pointers to the new buffer + p += crt->raw.len - len; + end = crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, + &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->version < 0 || crt->version > 2 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crt->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) +#endif + { + ret = x509_get_crt_ext( &p, end, crt ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid.len != sig_oid2.len || + memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ) +{ + int ret; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( crt->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + prev = crt; + mbedtls_x509_crt_init( crt->next ); + crt = crt->next; + } + + if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + mbedtls_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if( buflen != 0 && buf[buflen - 1] == '\0' && + strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if( buf_format == MBEDTLS_X509_FORMAT_DER ) + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if( buf_format == MBEDTLS_X509_FORMAT_PEM ) + { + int ret; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while( buflen > 1 ) + { + size_t use_len; + mbedtls_pem_init( &pem ); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + else + break; + + ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + mbedtls_pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crt_parse( chain, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, + MAX_PATH - 3 ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, (int) len - 1, + NULL, NULL ); + if( w_ret == 0 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + w_ret = mbedtls_x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + +cleanup: + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) + { + closedir( dir ); + return( ret ); + } +#endif /* MBEDTLS_THREADING_C */ + + while( ( entry = readdir( dir ) ) != NULL ) + { + snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, + "%s/%s", path, entry->d_name ); + + if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) + { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } + else if( stat( entry_name, &sb ) == -1 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + +cleanup: + closedir( dir ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; +#endif /* MBEDTLS_THREADING_C */ + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const mbedtls_x509_sequence *subject_alt_name ) +{ + size_t i; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + const char *sep = ""; + size_t sep_len = 0; + + while( cur != NULL ) + { + if( cur->buf.len + sep_len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + n -= cur->buf.len + sep_len; + for( i = 0; i < sep_len; i++ ) + *p++ = sep[i]; + for( i = 0; i < cur->buf.len; i++ ) + *p++ = cur->buf.p[i]; + + sep = ", "; + sep_len = 2; + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & type ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & code ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned int key_usage ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); + KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage ) +{ + int ret; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "%sserial number : ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &crt->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) + { + ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( crt->max_pathlen > 0 ) + { + ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) + { + ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, + { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, + { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, + { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, + { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, + { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { 0, NULL } +}; + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + int ret; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) + return( 0 ); + + usage_must = usage & ~may_mask; + + if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + usage_may = usage & may_mask; + + if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) + return( 0 ); + } + + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + if( mbedtls_x509_time_is_past( &cur->revocation_date ) ) + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation is no CRL for the given CA is present. + */ +static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + crl_list->issuer_raw.len != ca->subject_raw.len || + memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, + crl_list->issuer_raw.len ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + + if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + + md_info = mbedtls_md_info_from_type( crl_list->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); + + if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 ) + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + + if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) + flags |= MBEDTLS_X509_BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) + { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return( flags ); +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( 0 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + * bottom means child is the end entity cert + */ +static int x509_crt_check_parent( const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top, int bottom ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + return( -1 ); + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + /* Exception: self-signed end-entity certs that are locally trusted. */ + if( top && bottom && + child->raw.len == parent->raw.len && + memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) + { + need_ca_bit = 0; + } + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +static int x509_crt_verify_top( + mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + int path_cnt, int self_cnt, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + uint32_t ca_flags = 0; + int check_path_cnt; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_x509_crt *future_past_ca = NULL; + + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* + * Child is the top of the chain. Check against the trust_ca list. + */ + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown', no need to try any CA + */ + trust_ca = NULL; + } + else + mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); + + for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) + { + if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) + continue; + + check_path_cnt = path_cnt + 1; + + /* + * Reduce check_path_cnt to check against if top of the chain is + * the same as the trusted CA + */ + if( child->subject_raw.len == trust_ca->subject_raw.len && + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) == 0 ) + { + check_path_cnt--; + } + + /* Self signed certificates do not count towards the limit */ + if( trust_ca->max_pathlen > 0 && + trust_ca->max_pathlen < check_path_cnt - self_cnt ) + { + continue; + } + + if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) != 0 ) + { + continue; + } + + if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) || + mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) + { + if ( future_past_ca == NULL ) + future_past_ca = trust_ca; + + continue; + } + + break; + } + + if( trust_ca != NULL || ( trust_ca = future_past_ca ) != NULL ) + { + /* + * Top of chain is signed by a trusted CA + */ + *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + } + + /* + * If top of chain is not the same as the trusted CA send a verify request + * to the callback for any issues with validity and CRL presence for the + * trusted CA certificate. + */ + if( trust_ca != NULL && + ( child->subject_raw.len != trust_ca->subject_raw.len || + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) != 0 ) ) + { +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the chain's top crt */ + *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); +#else + ((void) ca_crl); +#endif + + if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ) + ca_flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) + ca_flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( NULL != f_vrfy ) + { + if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, + &ca_flags ) ) != 0 ) + { + return( ret ); + } + } + } + + /* Call callback on top cert */ + if( NULL != f_vrfy ) + { + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) + return( ret ); + } + + *flags |= ca_flags; + + return( 0 ); +} + +static int x509_crt_verify_child( + mbedtls_x509_crt *child, mbedtls_x509_crt *parent, + mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + int path_cnt, int self_cnt, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + uint32_t parent_flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + mbedtls_x509_crt *grandparent; + const mbedtls_md_info_t *md_info; + + /* Counting intermediate self signed certificates */ + if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + self_cnt++; + + /* path_cnt is 0 for the first intermediate CA */ + if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately as the goal is to avoid unbounded recursion */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + } + else + { + mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); + + if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + } + } + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile ); +#endif + + /* Look for a grandparent in trusted CAs */ + for( grandparent = trust_ca; + grandparent != NULL; + grandparent = grandparent->next ) + { + if( x509_crt_check_parent( parent, grandparent, + 0, path_cnt == 0 ) == 0 ) + break; + } + + if( grandparent != NULL ) + { + ret = x509_crt_verify_top( parent, grandparent, ca_crl, profile, + path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + /* Look for a grandparent upwards the chain */ + for( grandparent = parent->next; + grandparent != NULL; + grandparent = grandparent->next ) + { + /* +2 because the current step is not yet accounted for + * and because max_pathlen is one higher than it should be. + * Also self signed certificates do not count to the limit. */ + if( grandparent->max_pathlen > 0 && + grandparent->max_pathlen < 2 + path_cnt - self_cnt ) + { + continue; + } + + if( x509_crt_check_parent( parent, grandparent, + 0, path_cnt == 0 ) == 0 ) + break; + } + + /* Is our parent part of the chain or at the top? */ + if( grandparent != NULL ) + { + ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, + profile, path_cnt + 1, self_cnt, &parent_flags, + f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, + path_cnt + 1, self_cnt, &parent_flags, + f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + } + + /* child is verified to be a child of the parent, call verify callback */ + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) + return( ret ); + + *flags |= parent_flags; + + return( 0 ); +} + +/* + * Verify the certificate validity + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, + &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); +} + + +/* + * Verify the certificate validity, with profile + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + size_t cn_len; + int ret; + int pathlen = 0, selfsigned = 0; + mbedtls_x509_crt *parent; + mbedtls_x509_name *name; + mbedtls_x509_sequence *cur = NULL; + mbedtls_pk_type_t pk_type; + + *flags = 0; + + if( profile == NULL ) + { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; + } + + if( cn != NULL ) + { + name = &crt->subject; + cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + cur = &crt->subject_alt_names; + + while( cur != NULL ) + { + if( cur->buf.len == cn_len && + x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 ) + break; + + if( cur->buf.len > 2 && + memcmp( cur->buf.p, "*.", 2 ) == 0 && + x509_check_wildcard( cn, &cur->buf ) == 0 ) + { + break; + } + + cur = cur->next; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + while( name != NULL ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 ) + { + if( name->val.len == cn_len && + x509_memcasecmp( name->val.p, cn, cn_len ) == 0 ) + break; + + if( name->val.len > 2 && + memcmp( name->val.p, "*.", 2 ) == 0 && + x509_check_wildcard( cn, &name->val ) == 0 ) + break; + } + + name = name->next; + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + } + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type( &crt->pk ); + + if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + /* Look for a parent in trusted CAs */ + for( parent = trust_ca; parent != NULL; parent = parent->next ) + { + if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) + break; + } + + if( parent != NULL ) + { + ret = x509_crt_verify_top( crt, parent, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + goto exit; + } + else + { + /* Look for a parent upwards the chain */ + for( parent = crt->next; parent != NULL; parent = parent->next ) + if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) + break; + + /* Are we part of the chain or at the top? */ + if( parent != NULL ) + { + ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + goto exit; + } + else + { + ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + goto exit; + } + } + +exit: + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + + if( ret != 0 ) + { + *flags = (uint32_t) -1; + return( ret ); + } + + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) +{ + memset( crt, 0, sizeof(mbedtls_x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_sequence *seq_cur; + mbedtls_x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + mbedtls_pk_free( &cert_cur->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL ) + { + mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + if( cert_prv != crt ) + mbedtls_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509_csr.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + + + + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + mbedtls_x509_buf sig_params; + + memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + mbedtls_x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = mbedtls_calloc( 1, len = buflen ); + + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( csr->version != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + csr->version++; + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + * + * The list of possible attributes is open-ended, though RFC 2985 + * (PKCS#9) defines a few in section 5.4. We currently don't support any, + * so we just ignore them. This is a safe thing to do as the worst thing + * that could happen is that we issue a certificate that does not match + * the requester's expectations - this cannot cause a violation of our + * signature policies. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret; + size_t use_len; + mbedtls_pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) + return( ret ); + + mbedtls_pem_free( &pem ); + return( 0 ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load a CSR into the structure + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_csr_parse( csr, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &csr->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CSR + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) +{ + memset( csr, 0, sizeof(mbedtls_x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if( csr == NULL ) + return; + + mbedtls_pk_free( &csr->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + mbedtls_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_free( csr->raw.p ); + } + + mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) ); +} + +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509write_crt.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + + + + + + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) + +#endif /* MBEDTLS_PEM_WRITE_C */ + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +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 ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + 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 ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof( buf ) - len, len ); +} +#endif /* MBEDTLS_SHA1_C */ + +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ) +{ + unsigned char buf[4], ku; + unsigned char *c; + int ret; + + /* We currently only support 7 bits, from 0x80 to 0x02 */ + if( ( key_usage & ~0xfe ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + + c = buf + 4; + ku = (unsigned char) key_usage; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *t, size_t size ) +{ + int ret; + size_t len = 0; + + /* + * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t + 2, + size - 2 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t, + size ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char tmp_buf[2048]; + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed in tmp_buf + */ + c = tmp_buf + sizeof( tmp_buf ); + + /* Signature algorithm needed in TBS, and later for actual signature */ + + /* There's no direct way of extracting a signature algorithm + * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ + if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + 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 + */ + + /* Only for v3 */ + if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) + { + 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) } + */ + + /* Can be omitted for v1 */ + if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) + { + 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 + */ + if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, + len, hash ) ) != 0 ) + { + return( ret ); + } + + 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509write_csr.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + + + + + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +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 ); + + if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/xtea.c ************/ + +/* + * 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) + +#else + +#endif + +#if defined(MBEDTLS_XTEA_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#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 */ +/* zeroize was here */ + +/* + * 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 */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + +#endif /* ME_COM_MBEDTLS */ diff --git a/code/application/sifarsdk/component/utils/src/sf_aes.c b/code/application/sifarsdk/component/utils/src/sf_aes.c new file mode 100644 index 000000000..678558e83 --- /dev/null +++ b/code/application/sifarsdk/component/utils/src/sf_aes.c @@ -0,0 +1,133 @@ + + +#if 1 +#include +#include +#include "mbedtls.h" +#include "sf_aes.h" + +/* + # padding with pkcs7 AES_128_CBC Encrypt + ptx = "CBC has been the most commonly used mode of operation." + key = 06a9214036b8a15b512e03d534120006 + iv = 3dafba429d9eb430b422da802c9fac41 + ctx = 4DDF9012D7B3898745A1ED9860EB0FA2 + FD2BBD80D27190D72A2F240C8F372A27 + 63746296DDC2BFCE7C252B6CD7DD4BA8 + 577E096DBD8024C8B4C5A1160CA2D3F9 +*/ + +#define mbedtls_printf printf + +UINT32 i = 0; + +// UINT8 *inputData = (UINT8 *)"CBC has been the most commonly used mode of operation."; + +// UINT8 key[16] = "000000000000000"; +// UINT8 iv[16] = "000000000000000"; + +UINT8 key[16] = { + 'S', 'T', '1', 'Y', 'C', 'S', 'Y', 'R', 'Y', 'O', '0', '1', 'Y', '0', '0', 'S'}; + +UINT8 iv[16] = { + 'S', 'T', '1', 'Y', 'C', 'S', 'Y', 'R', 'Y', 'O', '0', '1', 'Y', '0', '1', 'S'}; + +static void dump_buf(UINT8 *info, UINT8 *buf, UINT32 len) +{ + mbedtls_printf("%s", info); + for (i = 0; i < len; i++) + { + mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n\t" : " ", + buf[i], i == len - 1 ? "\n" : ""); + } + mbedtls_printf("\n"); +} + +/*********************************************** +aesType:MBEDTLS_CIPHER_AES_128_CBC +operation:MBEDTLS_ENCRYPT/MBEDTLS_DECRYPT +***********************************************/ +UINT32 sf_cipher(UINT32 aesType, UINT8 operation, UINT8 *input, UINT8 *output, UINT8 srcl) +{ + size_t len; + size_t olen = 0; + int ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *info; + + // mbedtls_platform_set_printf(printf); + // mbedtls_printf("sf_cipher len %d", srcl); + + mbedtls_cipher_init(&ctx); + info = mbedtls_cipher_info_from_type(aesType); + if (info == NULL) + { + mbedtls_printf("mbedtls_cipher_info_from_type error"); + } + ret = mbedtls_cipher_setup(&ctx, info); + // mbedtls_printf("\n mbedtls_cipher_setup %d\n", ret); + + // mbedtls_printf("\n cipher info setup, name: %s, block size: %d\n", + // mbedtls_cipher_get_name(&ctx), + // mbedtls_cipher_get_block_size(&ctx)); + + mbedtls_cipher_setkey(&ctx, key, sizeof(key) * 8, operation); + mbedtls_cipher_set_iv(&ctx, iv, sizeof(iv)); + // mbedtls_cipher_update(&ctx, input, strlen((char *)input), output, &len); + mbedtls_cipher_update(&ctx, input, srcl, output, &len); + olen += len; + + mbedtls_cipher_finish(&ctx, output + len, &len); + olen += len; + + // dump_buf((UINT8 *)"\n cipher aes encrypt:", output, olen); + + mbedtls_cipher_free(&ctx); + return olen; +} + +#if 0 +void sf_cipher_test(void) +{ + UINT8 outputData[64] = {0}; + UINT8 inputData[64] = {0}; + sf_cipher(MBEDTLS_CIPHER_AES_128_CBC,MBEDTLS_ENCRYPT,inputData,outputData); + sf_cipher(MBEDTLS_CIPHER_AES_128_CTR,MBEDTLS_ENCRYPT,inputData,outputData); + + +} +#else +void sf_cipher_test(void) // use cbc way, the output is integer multiple of 16 bytes of input +{ + UINT8 outputData[128] = {0}; + UINT8 inputData[128] = "abc"; //"CBC has been the most commonly used mode of operation."; + sf_cipher(MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_ENCRYPT, inputData, outputData, strlen((char *)inputData)); + + mbedtls_printf("cbc test\r\n"); + mbedtls_printf("after encode %s", outputData); + + memset(inputData, 0x00, sizeof(inputData)); + sf_cipher(MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_DECRYPT, outputData, inputData, strlen((char *)outputData)); + + printf("after decode %s", inputData); + // sf_cipher(MBEDTLS_CIPHER_AES_128_CTR,MBEDTLS_ENCRYPT,inputData,outputData); +} + +void sf_cipher_test1(void) // use ctr way, the output is as large as the input +{ + UINT8 outputData[128] = {0}; + UINT8 inputData[128] = "1111111111111111"; //"CBC has been the most commonly used mode of operation."; + sf_cipher(MBEDTLS_CIPHER_AES_128_CTR, MBEDTLS_ENCRYPT, inputData, outputData, strlen((char *)inputData)); + + mbedtls_printf("ctr test\r\n"); + mbedtls_printf("after encode %s", outputData); + + memset(inputData, 0x00, sizeof(inputData)); + sf_cipher(MBEDTLS_CIPHER_AES_128_CTR, MBEDTLS_DECRYPT, outputData, inputData, strlen((char *)outputData)); + + printf("after decode %s", inputData); + // sf_cipher(MBEDTLS_CIPHER_AES_128_CTR,MBEDTLS_ENCRYPT,inputData,outputData); +} + +#endif +#endif diff --git a/code/application/sifarsdk/component/utils/src/sf_qrutils.c b/code/application/sifarsdk/component/utils/src/sf_qrutils.c new file mode 100644 index 000000000..4368b9a62 --- /dev/null +++ b/code/application/sifarsdk/component/utils/src/sf_qrutils.c @@ -0,0 +1,222 @@ + + +#include +#include +#include + +#ifndef MAX_PATH +#define MAX_PATH 256 +#endif + +static char *base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static char *base64_encode(const unsigned char *bindata, char *base64, int binlength, int model) +{ + int i, j; + unsigned char current; + + for (i = 0, j = 0; i < binlength; i += 3) + { + current = (bindata[i] >> 2); + current &= (unsigned char)0x3F; + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i] << 4)) & ((unsigned char)0x30); + if (i + 1 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 1] >> 4)) & ((unsigned char)0x0F); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i + 1] << 2)) & ((unsigned char)0x3C); + if (i + 2 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 2] >> 6)) & ((unsigned char)0x03); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)bindata[i + 2]) & ((unsigned char)0x3F); + base64[j++] = base64char[(int)current]; + } + if (model) + { + base64[j++] = '\n'; + } + base64[j] = '\0'; + return base64; +} + +static int base64_decode(const char *base64, unsigned char *bindata) +{ + int i, j; + unsigned char k; + unsigned char temp[4]; + for (i = 0, j = 0; base64[i] != '\0'; i += 4) + { + memset(temp, 0xFF, sizeof(temp)); + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i]) + temp[0] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 1]) + temp[1] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 2]) + temp[2] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 3]) + temp[3] = k; + } + + bindata[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2)) & 0xFC)) | + ((unsigned char)((unsigned char)(temp[1] >> 4) & 0x03)); + if (base64[i + 2] == '=') + break; + + bindata[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4)) & 0xF0)) | + ((unsigned char)((unsigned char)(temp[2] >> 2) & 0x0F)); + if (base64[i + 3] == '=') + break; + + bindata[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6)) & 0xF0)) | + ((unsigned char)(temp[3] & 0x3F)); + } + return j; +} + +static int URLEncode(const char *str, const int strSize, char *result, const int resultSize) +{ + int i; + int j = 0; // for result index + char ch; + + if ((str == 0) || (result == 0) || (strSize <= 0) || (resultSize <= 0)) + { + return 0; + } + + for (i = 0; (i < strSize) && (j < resultSize); ++i) + { + ch = str[i]; + if (((ch >= 'A') && (ch <= 'Z')) || + ((ch >= 'a') && (ch <= 'z')) || + ((ch >= '0') && (ch <= '9'))) + { + result[j++] = ch; + } + else if (ch == ' ') + { + result[j++] = '+'; + } + else if (ch == '.' || ch == '-' || ch == '_' || ch == '*') + { + result[j++] = ch; + } + else + { + if (j + 3 < resultSize) + { + sprintf(result + j, "%%%02X", (unsigned char)ch); + j += 3; + } + else + { + return 0; + } + } + } + + result[j] = '\0'; + return j; +} + +static void urldecode(char *p) +{ + // register i = 0; + volatile int i = 0; + while (*(p + i)) + { + if ((*p = *(p + i)) == '%') + { + *p = *(p + i + 1) >= 'A' ? ((*(p + i + 1) & 0XDF) - 'A') + 10 : (*(p + i + 1) - '0'); + *p = (*p) * 16; + *p += *(p + i + 2) >= 'A' ? ((*(p + i + 2) & 0XDF) - 'A') + 10 : (*(p + i + 2) - '0'); + i += 2; + } + else if (*(p + i) == '+') + { + *p = ' '; + } + p++; + } + *p = '\0'; +} + +static void strConv(char *p) +{ + int i; + int len = strlen(p); + char temp; + + for (i = 0; i < len;) + { + temp = *(p + i); + if (*(p + i + 1) != '\0') + { + *(p + i) = *(p + i + 1); + *(p + i + 1) = temp; + } + i += 2; + } +} + +char *nfc_qrencrypt(char *content) +{ + char encodeStr[512] = {0}; + + char encodeUrlStr[512] = {0}; + + base64_encode((unsigned char *)content, encodeStr, strlen(content), 0); + + strConv(encodeStr); + + URLEncode(encodeStr, strlen(encodeStr), encodeUrlStr, 256); + + strcpy(content, encodeUrlStr); + + return content; +} + +char *nfc_qrdecrypt(char *content) +{ + + char decodeStr[512] = {0}; + + char decodeUrlStr[512] = {0}; + + strcpy(decodeUrlStr, content); + + urldecode(decodeUrlStr); + + strConv(decodeUrlStr); + + base64_decode(decodeUrlStr, (unsigned char *)decodeStr); + + strcpy(content, decodeStr); + + return content; +} diff --git a/code/application/sifarsdk/customization/CMakeLists.txt b/code/application/sifarsdk/customization/CMakeLists.txt new file mode 100644 index 000000000..3f914dab5 --- /dev/null +++ b/code/application/sifarsdk/customization/CMakeLists.txt @@ -0,0 +1,6 @@ + +# cmake_minimum_required(VERSION 2.8.0) +add_subdirectory(application/main) +add_subdirectory(application/StateManager) + + diff --git a/code/application/sifarsdk/customization/README.md b/code/application/sifarsdk/customization/README.md new file mode 100644 index 000000000..1ed168f91 --- /dev/null +++ b/code/application/sifarsdk/customization/README.md @@ -0,0 +1,2 @@ +# 客制化目录 +   这里只演示如何基于SifarSDK公版版本,不修改公版版本源码基础上,衍生出一个全新的客制化版本,实际创建客制化版本时,可按需进行源码目录管理即可。 \ No newline at end of file diff --git a/code/application/sifarsdk/customization/application/StateManager/CMakeLists.txt b/code/application/sifarsdk/customization/application/StateManager/CMakeLists.txt new file mode 100644 index 000000000..10a34a259 --- /dev/null +++ b/code/application/sifarsdk/customization/application/StateManager/CMakeLists.txt @@ -0,0 +1,28 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./ + ${APPLICATION_SOURCE_PATH}/StateManager/include + ${APPLICATION_SOURCE_PATH}/StateManager/src + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/StateMachineManager/include + ${HAL_SOURCE_PATH}/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) + +set(TARGET_NAME StateManagerCustomization) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} StateManager ReturnCode Log) + diff --git a/code/application/sifarsdk/customization/application/StateManager/DefaultStateCustomization.cpp b/code/application/sifarsdk/customization/application/StateManager/DefaultStateCustomization.cpp new file mode 100644 index 000000000..85e4540be --- /dev/null +++ b/code/application/sifarsdk/customization/application/StateManager/DefaultStateCustomization.cpp @@ -0,0 +1,5 @@ +#include "DefaultStateCustomization.h" +bool DefaultStateCustomization::ExecuteStateMsg(VStateMachineMessage *msg) +{ + return true; +} \ No newline at end of file diff --git a/code/application/sifarsdk/customization/application/StateManager/DefaultStateCustomization.h b/code/application/sifarsdk/customization/application/StateManager/DefaultStateCustomization.h new file mode 100644 index 000000000..47e749263 --- /dev/null +++ b/code/application/sifarsdk/customization/application/StateManager/DefaultStateCustomization.h @@ -0,0 +1,11 @@ +#ifndef DEFAULT_STATE_CUSTOMIZATION +#define DEFAULT_STATE_CUSTOMIZATION +#include "DefaultState.h" +class DefaultStateCustomization : public DefaultState +{ +public: + DefaultStateCustomization() = default; + virtual ~DefaultStateCustomization() = default; + bool ExecuteStateMsg(VStateMachineMessage *msg) override; +}; +#endif // !DEFAULT_STATE_CUSTOMIZATION \ No newline at end of file diff --git a/code/application/sifarsdk/customization/application/StateManager/MakePtrCustomization.cpp b/code/application/sifarsdk/customization/application/StateManager/MakePtrCustomization.cpp new file mode 100644 index 000000000..a527627af --- /dev/null +++ b/code/application/sifarsdk/customization/application/StateManager/MakePtrCustomization.cpp @@ -0,0 +1,6 @@ +#include "MakePtrCustomization.h" +#include "DefaultStateCustomization.h" +std::shared_ptr MakePtrCustomization::CreateDefaultState() +{ + return std::make_shared(); +} \ No newline at end of file diff --git a/code/application/sifarsdk/customization/application/StateManager/MakePtrCustomization.h b/code/application/sifarsdk/customization/application/StateManager/MakePtrCustomization.h new file mode 100644 index 000000000..e0e6a401b --- /dev/null +++ b/code/application/sifarsdk/customization/application/StateManager/MakePtrCustomization.h @@ -0,0 +1,11 @@ +#ifndef MAKE_PTR_CUSTOMIZATION +#define MAKE_PTR_CUSTOMIZATION +#include "StateManagerMakePtr.h" +class MakePtrCustomization : public StateManagerMakePtr +{ +public: + MakePtrCustomization() = default; + virtual ~MakePtrCustomization() = default; + std::shared_ptr CreateDefaultState() override; +}; +#endif // !MAKE_PTR_CUSTOMIZATION \ No newline at end of file diff --git a/code/application/sifarsdk/customization/application/main/CMakeLists.txt b/code/application/sifarsdk/customization/application/main/CMakeLists.txt new file mode 100644 index 000000000..8104104c4 --- /dev/null +++ b/code/application/sifarsdk/customization/application/main/CMakeLists.txt @@ -0,0 +1,30 @@ + +include(${CMAKE_SOURCE_DIR}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./ + ${APPLICATION_SOURCE_PATH}/main + ${APPLICATION_SOURCE_PATH}/StateManager/include + ${APPLICATION_SOURCE_PATH}/StateManager/src + ${COMPONENT_SOURCE_PATH}/ReturnCode/include + ${COMPONENT_SOURCE_PATH}/Log/include + ${COMPONENT_SOURCE_PATH}/StateMachineManager/include + # ${HAL_SOURCE_PATH}/include + ${PROJECT_ROOT_PATH}/customization/application/StateManager +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./ SRC_FILES) + +set(TARGET_NAME mainCustomization) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) + +target_link_libraries(${TARGET_NAME} StateManager ReturnCode Log) + diff --git a/code/application/sifarsdk/customization/application/main/MainThreadCustomization.cpp b/code/application/sifarsdk/customization/application/main/MainThreadCustomization.cpp new file mode 100644 index 000000000..38808f42e --- /dev/null +++ b/code/application/sifarsdk/customization/application/main/MainThreadCustomization.cpp @@ -0,0 +1,12 @@ +#include "MainThreadCustomization.h" +#include "MakePtrCustomization.h" +static std::shared_ptr CreateCustomizationModule(void) +{ + std::shared_ptr customization = std::shared_ptr(); + return customization; +} +void MainThreadCustomization::CustomizationInit(void) +{ + std::shared_ptr customization = std::make_shared(); + StateManagerMakePtr::GetInstance(&customization); +} \ No newline at end of file diff --git a/code/application/sifarsdk/customization/application/main/MainThreadCustomization.h b/code/application/sifarsdk/customization/application/main/MainThreadCustomization.h new file mode 100644 index 000000000..5744be42c --- /dev/null +++ b/code/application/sifarsdk/customization/application/main/MainThreadCustomization.h @@ -0,0 +1,11 @@ +#ifndef MAIN_THREAD_CUSTOMIZATION +#define MAIN_THREAD_CUSTOMIZATION +#include "MainThread.h" +class MainThreadCustomization : public MainThread +{ +public: + MainThreadCustomization() = default; + virtual ~MainThreadCustomization() = default; + void CustomizationInit(void) override; +}; +#endif // MAIN_THREAD_CUSTOMIZATION \ No newline at end of file diff --git a/code/application/sifarsdk/customization/component/PeripheralManager/PeripheralManagerCustomization.cpp b/code/application/sifarsdk/customization/component/PeripheralManager/PeripheralManagerCustomization.cpp new file mode 100644 index 000000000..c93c4f4bd --- /dev/null +++ b/code/application/sifarsdk/customization/component/PeripheralManager/PeripheralManagerCustomization.cpp @@ -0,0 +1,11 @@ +#include "PeripheralManagerCustomization.h" +#include "IHalCommonCustomization.h" +RETURN_CODE PeripheralManagerCustomization::Init(void) +{ + PeripheralManager::Init(); + auto ledHandle = std::make_shared(); + IHal::GetInstance()->GetLedContrlHandle(static_cast(SfLedIndexCustomization::SF_LED_CUSTOMIZATION), ledHandle); + LedHandle handle(ledHandle); + mLeds[static_cast(SfLedIndexCustomization::SF_LED_CUSTOMIZATION)] = handle; + return VReturnCode::NewCode(VReturnCodeDefine::OK); +} \ No newline at end of file diff --git a/code/application/sifarsdk/customization/component/PeripheralManager/PeripheralManagerCustomization.h b/code/application/sifarsdk/customization/component/PeripheralManager/PeripheralManagerCustomization.h new file mode 100644 index 000000000..4da59ce28 --- /dev/null +++ b/code/application/sifarsdk/customization/component/PeripheralManager/PeripheralManagerCustomization.h @@ -0,0 +1,11 @@ +#ifndef PERIPHERA_MANAGER_CUSTOMIZATION_H +#define PERIPHERA_MANAGER_CUSTOMIZATION_H +#include "PeripheralManager.h" +class PeripheralManagerCustomization : public PeripheralManager +{ +public: + PeripheralManagerCustomization() = default; + ~PeripheralManagerCustomization() = default; + RETURN_CODE Init(void) override; +}; +#endif // !PERIPHERA_MANAGER_CUSTOMIZATION_H \ No newline at end of file diff --git a/code/application/sifarsdk/customization/hal/IHalCommonCustomization.h b/code/application/sifarsdk/customization/hal/IHalCommonCustomization.h new file mode 100644 index 000000000..e52e3959a --- /dev/null +++ b/code/application/sifarsdk/customization/hal/IHalCommonCustomization.h @@ -0,0 +1,9 @@ +#ifndef I_HAL_COMMON_CUSTOMIZATION_H +#define I_HAL_COMMON_CUSTOMIZATION_H +#include "IHalCommon.h" +enum class SfLedIndexCustomization +{ + SF_LED_CUSTOMIZATION = SfLedIndex::SF_LED_END, + SF_LED_CUSTOMIZATION_END +}; +#endif // !I_HAL_COMMON_CUSTOMIZATION_H \ No newline at end of file diff --git a/code/application/sifarsdk/doc/README.md b/code/application/sifarsdk/doc/README.md new file mode 100644 index 000000000..9d3a42561 --- /dev/null +++ b/code/application/sifarsdk/doc/README.md @@ -0,0 +1,4 @@ +设计文档基于Markdown语法编写,请使用vscode进行阅读: +hunting_camera_design.md:打猎相机详细设计文档; +mdCreateMenu.js:用于生成markdown的侧边栏导航(生成html文件时); +markdown_user_guide.md:markdown使用手册; \ No newline at end of file diff --git a/code/application/sifarsdk/doc/auto_test.md b/code/application/sifarsdk/doc/auto_test.md new file mode 100644 index 000000000..c1b46d638 --- /dev/null +++ b/code/application/sifarsdk/doc/auto_test.md @@ -0,0 +1,86 @@ +# 1. 嵌入式产品开发的自动化测试方案 +**作者:萧家柱** +   注:本文所述均为个人总结,如有缺陷,盼望指正和优化。 + +## 1.1. 概述 +   自动化测试是指:使用工具(包含软件/硬件)对产品功能进行非人力重复地验证测试的过程。结果是自动生成测试报告作为交付/验收依据。 + +   自动化测试大体分为两个维度: +1. 针对源码进行的自动化测试过程; +2. 针对成品进行的自动化测试过程; + +   本设计文档涉及的自动生成测试报告包含两个维度: +1. 以测试用例(单元测试/集成测试)为单位的测试报告,主要针对集成测试(针对功能); +2. 测试过程的源码覆盖率报告(针对内存/代码统计等); + +## 1.2. 行业现状分析 +   在作者有限认知范围内,以鸿蒙系统为例,自动化测试普遍使用的方法是在源码基础上使用脚本语言(常见python或者gtest开源库)对源码接口进行自动的调用,根据返回值(或者log分析)进行预期判断,并生成测试结果报告,以黑盒测试和单元测试为主。作者认为黑盒测试和单元测试都是相对片面的测试,打桩能力较差,无法深度还原代码的功能场景。至于对成品或者半成品的自动化测试,常见的在release版本里面添加简单测试代码外,未接触到其它更深层次的嵌入式软件的成品自动化测试方法。 + +## 1.3. 针对源码进行的自动化测试过程 +   针对源码进行的自动化测试过程,还可以细分为两个目标源码: +1. 未经过针对测试设计的架构源码; +2. 经过针对测试设计的架构源码; + +   上述两种目标源码的区分标准:经过针对测试设计的架构源码,测试代码并未跟随release版本一起发布实现测试功能,而是在release版本发布后,仍具备打桩进行自动化测试的能力。 + +   第一种目标源码,如果是面向源码时,可使用一些构建手段进行打桩架构的转换实现打桩自动化测试(效果和第二种差不多),但是工作量会多很多。纯C语言项目绝大部分属于第一种。 + +**   由于SifarSDK属于上述第二种目标源码,本文只针对第二种目标源码展开描述。** + +### 1.3.1. 自动化测试架构开发基本流程 +   自动化测试整体过程是,通过人为(非侵入式修改代码,或者打桩)控制程序运行轨迹,实现对前置条件的最终结果自动判断的过程。分两个环节:第一是可以随意控制代码在运行时的运行轨迹;第二是在前述前置运行轨迹下,可以准确自动的判断运行结果;最终实现自动可视化测试报告的输出。 + +开发环节: +1. 选择一个开源的自动化测试框架; + 自动化测试框架作为辅助工具,可以很好对运行结果进行组织和管理,例如:简单地判断返回值,创建测试桩,创建测试数据,自动生成测试报告等; +2. 在主体架构融入“多态”的设计理念; + 主体架构具备“多态”设计属性,才有能力对主体架构进行轻松的打桩操作,否则测试桩只能是空中楼阁,无法发挥作用; +3. 针对业务功能开发大量的测试用例; + +### 1.3.2. 自动化测试两大目标 +1. 对代码业务进行测试,专业术语叫集成测试; + 本设计文档不针对单元测试(通俗讲,只对基础接口进行测试)进行描述,主要描述业务功能的自动化测试能力。 +2. 对代码内存进行监控; + 快速对内存安全漏洞进行检测,可解决90%以上的内存安全漏洞; + +### 1.3.3. 自动化测试用例的开发难度 +   主体架构开发较难,除了主体代码需要谨慎部署外(合理地预埋测试点),测试基础代码(基础测试桩)需要精心设计和部署,在基础架构成型的基础上,开发难度极低,只需要快速copy测试桩代码进行测试用例的部署。 + +## 1.4. 自动生成测试报告 + +### 1.4.1. 相关工具环境 +执行自动化测试脚本: +``` + cd test/testReport/ + ./run_test_to_build_report.sh +``` +可能会提示如下错误: +``` +./run_test_to_build_report.sh: line 17: xsltproc: command not found +./run_test_to_build_report.sh: line 22: lcov: command not found +./run_test_to_build_report.sh: line 23: lcov: command not found +./run_test_to_build_report.sh: line 25: genhtml: command not found +``` +解决办法: +* 执行xsltproc,提示命令不存在,并提供安装方法: +``` +xiaojiazhu@ubuntu:~/project/sifarsdk$ xsltproc + +Command 'xsltproc' not found, but can be installed with: + +sudo apt install xsltproc +``` +* 执行sudo apt install xsltproc,安装xsltproc; +* 执行lcov,并按照提示安装lcov(此时应该会同步安装genhtml): +``` +xiaojiazhu@ubuntu:~/project/sifarsdk$ lcov + +Command 'lcov' not found, but can be installed with: + +sudo apt install lcov +``` +**注:上述描述是基于ubuntu20版本,不同版本可能安装方法不一样。** +再次执行自动化测试脚本: + +## 1.5. 测试用例的管理 +   \ No newline at end of file diff --git a/code/application/sifarsdk/doc/hunting_camera_design.md b/code/application/sifarsdk/doc/hunting_camera_design.md new file mode 100644 index 000000000..be5032f56 --- /dev/null +++ b/code/application/sifarsdk/doc/hunting_camera_design.md @@ -0,0 +1,2192 @@ +# 1. 打猎相机设计文档 +| 作者 | 描述 | 时间 | +| ------ | :------------------------------- | --------- | +| 萧家柱 | SifarSDK设计文档 | 2023-2-14 | +## 1.1. 概述 +   本文详细介绍Sifar SDK的设计原理。基于打猎相机产品需求,在Linux系统构建跨平台的Sifar SDK工程,使项目源码可以快速移植,适配不同品牌芯片;设计组件层架构,使APP业务可以快速进行客制化需求的迭代;设计自动化测试流程,快速验证源码的功能和质量。 + +## 1.2. 设计要求 +* 存在一个公版的SifarSDK,此SDK在做跨平台,定制化项目时,无需修改构建和源码; + +## 1.3. 设计文档维护 +   本设计文档和代码实现是强映射关系,可正确反映代码的分层结构,模块结构,文件依赖关系,接口调用时序等,使用markdown语法维护,项目组成员在实际编码时发生的修改,应及时同步设计文档和源码。 + +## 1.4. 重要未解决问题记录 +* 关键模块使用动态单例模式设计,可以保证单例实例可以在运行态时进行多态切换,此时必须保证切换的多线程操作。如果时启动时单线程状态下创建单例实例,则不存在此问题。 +* main线程可以反复初始化和解初始化其它所有模块,实现运行态切换多态实例功能; + +## 1.5. 基本概念 +### 1.5.1. 源码构建 +   对源码进行组织,管理,编译的工具和方法,本文使用cmake对项目源码进行构建。 + +### 1.5.2. 抽象接口 +   本文的抽象接口统指不依赖实际实现的接口,一般是指虚函数接口。 + +### 1.5.3. UML类图 +   类图精确描述了源码文件或者类之间的依赖关系和耦合关系,是作者最常用的设计图示之一。Markdown语法支持生成UML类图。 +UML使用可参考《markdown_user_guide.md》。 + +### 1.5.4. UML时序图 +   和普通程序流程图相比,UML时序图在普通流程图的基础上精确了文件或者类的调用关系,是作者最常用的设计图之一。Markdown语法支持生成UML时序图。 + +### 1.5.5. 组件 +   组件作为独立代码模块,设计原则是弱化产品业务耦合,本设计文档组件基于相机场景业务设计。 +##产品渲染图 +无 +##产品硬件图示 +简单图示,非专业硬件设计图。 +```mermaid +classDiagram +4G --* CPU:usb +PIR --* CPU:? +CAMERA --* CPU:? +MCU --* CPU:uart +LED --* CPU:GPIO +CPU *-- SD:? +CPU *-- Key:GPIO +CPU *-- NFC:? +CPU *-- LCD +CPU *-- MIC +CPU *-- WIFI:? +``` + +## 1.6. 相机功能 +   待补充。。。 + +## 1.7. SifarSDK跨平台移植和适配 +   SifarSDK在做平台移植时,无需修改SifarSDK的配置和源码,此处以sigmastart平台为例进行说明。 + +### 1.7.1. 如何添加一个新的芯片平台? +* 在SifarSDK根目录添加一个芯片目录,例如:333DE; +* 在333DE目录下,创建build配置目录,内如参考现有配置,关键点如下: + 1. /333DE/build/cmake/toolchain/sigmastart_333DE.toolchain.cmake为COPY根目录/build/cmake/toolchain/linux.toolchain.cmake的复制件; + 2. 修改上述配置文件当中的交叉编译工具链名称,工具链名称由原厂提供,**注意:开发环境应该配置工具链的环境变量以便构建项目时可以找到工具链,也可以用绝对路径对下述两个变量进行配置**。 +``` +set(CMAKE_C_COMPILER gcc) +set(CMAKE_CXX_COMPILER g++) +修改为: +set(CMAKE_C_COMPILER arm-linux-gnueabihf-9.1.0-gcc) +set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-9.1.0-g++) +或使用绝对路径修改为: +set(CMAKE_C_COMPILER /home/user/project/sdk/toolchain/arm-linux-gnueabihf-9.1.0-gcc) +set(CMAKE_CXX_COMPILER /home/user/project/sdk/toolchain/arm-linux-gnueabihf-9.1.0-g++) +``` + 3. 添加下述变量: +**平台目录PLATFORM_PATH将是平台相关的所有代码** +``` +# 1.平台名称TARGET_PLATFORM +set(TARGET_PLATFORM "sigmastart_333DE") +# 2.平台目录PLATFORM_PATH:SifarSDK在linux系统之外的平台都会添加此目录进行源码构建 +set(PLATFORM_PATH "${CMAKE_SOURCE_DIR}/333DE") +``` + 4. 增加Makefile文件:/333DE/build/cmake/Makefile + **主要是配置下述第5行执行cmake命令时指向新增的平台配置文件(工具链和源码目录)。** +```{.line-numbers} +all: + @mkdir -p ../../../cmake-shell-linux;\ + cd ../../../cmake-shell-linux;\ + pwd;\ + cmake -DCMAKE_TOOLCHAIN_FILE="./333DE/build/cmake/toolchain/sigmastart_333DE.toolchain.cmake" ..;\ + cd .. +clean: + rm -rf ../../cmake-shell-linux +``` +### 1.7.2. 编译: +   SifarSDK公版构建和平台工程版本构建是解耦合的,平台工程源码构建依赖SifarSDK公版工程,SifarSDK公版工程不反向依赖平台工程源码。 + +   创建跨平台源码后,跨平台构建切换只需要跳转到平台工程的根目录进行构建即可,在平台目录下执行构建命令,然后跳转到SifarSDK根目录下的cmake-shell-linux目录编译:\ +例如:333DE平台编译: +``` +cd 333DE +make cmake +cd ../cmake-shell-linux/ +make +``` +### 1.7.3. Googletest的交叉编译 +TODO:此处待优化,应该自动关联工具链进行编译。。。 + +### 1.7.4. 跨平台适配 +   新平台需要把hal层的所有抽象接口实现。需要注意的是,芯片平台差异化的代码必须独立管理,杜绝插入到其它模块代码当中。\ +   也可以理解跨平台适配是做一个客制化的SifarSDK版本,SifarSDK的任意抽象接口都可以按需进行重载。按照下述流程实现: +* 创建芯片平台的客制化代码目录./333DE +* 333DE/build/cmake/toolchain/sigmastart_333DE.toolchain.cmake配置文件添加新增的代码目录,把该平台的适配层代码加入到SifarSDK构建工程; +* 在./333DE目录下使用CMakeLists.txt进行该模块的源码构建即可; +* 创建平台代码的设计文档:./333DE/333DE_design.md,对适配层源码模块进行说明,附带关键UML类图和UML时序图; +* 创建hal适配层目录./333DE/hal,对硬件适配层的接口一一实现; +* 也可以按需创建application/component目录进行其它客制化需求的改造; + +### 1.7.5. 快速切换平台构建和编译 +   实际开发过程当中出现需要快速切换平台的情况,例如:在ubuntu开发完基础功能后需要切换到芯片平台测试验证,此时只需要进入到芯片平台的目录(例如:333DE),在芯片平台目录下先执行:make clean命令后(主要是为了清除预编译的一些开源库,这些开源库在换芯片平台时需要重新编译),再按照平台构建文档进行编译即可。 + +## 1.8. 软件设计概述 +   软件设计大体包括项目源码构建,主体架构设计,项目调试/联调,测试,版本管理,生产/售后管理等六大环节。 + +### 1.8.1. 项目源码构建 +   本文件软件设计方法使用cmake+shell脚本作为项目源码构建的主要工具。三方库移植根据具体情况选择源码构建还是使用开源库官方构建方法,尽量使用源码自主构建,方便自主管理。\ +   通过选择工具链实现跨平台编译构建。 + +### 1.8.2. 主体架构设计 +#### 1.8.2.1. 多态单例模式设计 +   针对分层模块化结构设计,兼容自动化测试框架(可拓展至整机自动化测试),基于对相机业务的理解,主体框架大量使用了多态单例的设计模式进行代码部署。\ +   多态单例模式的参考代码如下(这里使用GPIO管理模块源码):\ +GPIO管理模块头文件:IPeripheralManager.h +```C++{.line-numbers} +#ifndef I_GPIO_MANAGER_H +#define I_GPIO_MANAGER_H +#include "VReturnCode.h" +#include "IHalCommon.h" +#include +#include +enum class SfLedState +{ + SF_LED_STATE_OFF = 0, + SF_LED_STATE_ON, + SF_LED_STATE_GREEN, + SF_LED_STATE_RED, + SF_LED_STATE_YELLOW, + SF_LED_STATE_BUIT +}; +enum class SfKeyAction +{ + SF_KEY_ACTION_SHORT_CLICK = 0, + SF_KEY_ACTION_LONG_CLICK, + SF_KEY_ACTION_HOLD_DOWN, + SF_KEY_ACTION_HOLD_UP, + SF_KEY_ACTION_GROUP, + SF_KEY_ACTION_BUTT +}; +class VKeyMonitor +{ +public: + VKeyMonitor() = default; + virtual ~VKeyMonitor() = default; + virtual RETURN_CODE KeyActionHappened(const SfKeyDefine key, const SfKeyAction event) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetBlinkPeriod(unsigned int &period) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetLedState(SfLedState &state) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +// IPeripheralManager:多态单例的声明和定义 +class IPeripheralManager +{ +public: + IPeripheralManager() = default; + virtual ~IPeripheralManager() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual RETURN_CODE Init(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE UnInit(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetKeyContrlHandle(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE GetLedContrlHandle(void) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetKeyMonitor(std::shared_ptr monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetLedState(const SfLedIndex, std::shared_ptr monitor) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } + virtual RETURN_CODE SetLongClickPeriod(unsigned int period) { return VReturnCode::NewCode(VReturnCodeDefine::NOT_OK_VIRTUAL_FUNCTION); } +}; +bool CreatePeripheralManager(void); // 创建模块实例函数 +#endif // !I_GPIO_MANAGER_H +``` +**多态单例模式的设计特点:** +* 独立模块(或组件或业务代码)对外暴露的头文件是完全独立的,即外部使用者引用该头文件时,不需要链接其它代码或者库(常规的枚举,常量,宏定义除外)即可独立编译,调试,测试。 + _源码解析:例如上述源码的 **IPeripheralManager抽象类**,特点是包含一个GetInstance()静态方法获取智能指针实例,而获取的对象的所有方法都是虚函数,编译时无需依赖实例代码,使用者甚至无需关注实例代码的存在即可完成自己代码的编辑和编译。_ +* 上述头文件包含一个特别的函数:CreatePeripheralManager(),该方法负责创建一个真实的release版本的GPIO管理模块实例。该方法需要链接模块库,系统中除了主线程(统指main函数)需要调用完成初始化之外,其它任意的代码无需调用。 +* **VPeripheralMonitor抽象类:** 成员函数全都是虚函数,用于外部使用者继承实现后,向模块注入实例指针,实现捕获模块内部数据功能。可以理解为C语言里面一组函数指针的结构体。 +* 结合上述3点,实现独立模块代码之间的 **“零耦合”** 设计,零耦合也是该架构设计的主旋律。 +* 多态模式的使用:多态单例默认都是“空模块”,需要对单例进行实例化,这种模式在初始化的时候就能在理论上让模块接口可以 **“千变万化”** ,既可以整个模块重载替换,也可以对某些方法重载替换,这样可以让整个系统有序实现迭代。多态单例的设计模式在有客制化需求的产品上更具优势。 +* 多态单例设计模式和自动化测试的完美融合:可以实例化一个测试桩,对整个模块进行接管,实现自动化测试需求。 +* 多态单例模式对架构体系的保障:基于“零耦合”的实现,结合构建工具,可以自动保护架构体系的完整性,在使用一个独立模块时,不管是有意还是无心的破坏架构体系的代码操作,通过在构建项目时编译失败来提示/避免错误操作。 + _特别指出:不在架构设计内的乱引用头文件,滥用extern关键字,滥用全局变量,是对分层模块化架构设计的极大破坏,遭受破坏的模块代码独立性破坏,不再具备可移植性。_ +* 多态单例设计下的独立模块是动态多态的,可以在编译时多态,也可以在程序运行时切换多态,常见的例如:Log日志功能的多态切换,可以在程序运行后开启/关闭/保存本地Log/上传云Log任意切换,根据实际业务需要进行调整;硬件适配层则可以编译时多态。 +* 对独立模块的使用可以“空载”运行,例如使用了GUI模块的代码,运行在没有界面的产品上时,无需修改任意代码,只需要在主线程不初始化GUI模块实例即可(即GUI模块的接口全是空载接口,没有运行任何代码)。 + +**多态单例设计模式的缺点** +* 存在“空模块”默认代码,理论上占用多余内存,可以改为纯虚函数,但又需要强保证必须实例化,不利于应用模块的拆卸和组装; +* 代码逻辑关系会比较模糊,不知道实际调用接口到底是哪个源码文件的接口,必须通过设计文档的UML类图关系来维护代码; +* 多态单例模式看起来是一个“非安全”的设计模式,可以随意切换,更容易出现被恶意篡改功能的可能,当然封闭的嵌入式产品可以忽略; + +**多态单例模式基本类图** +```mermaid +classDiagram +class User{ +<<用户>> +} +class 多态单例{ +<<抽象接口>> +} +class 多态单例实例{ +<<抽象接口实例>> +} +User --> 多态单例 +多态单例 <|.. 多态单例实例 +多态单例实例 --> 依赖库 +``` +   用户使用多态单例模块时无需链接多态单例实例和相关依赖库,在业务依赖的代码之间进行完全的解耦合处理。 +**多态单例模式基本时序图** +```mermaid +sequenceDiagram +User ->> +多态单例:调用抽象接口 +多态单例 --> +多态单例实例:实际调用实例接口 +多态单例实例 --> -多态单例:return +多态单例 -->> -User:return +``` + +**抽象接口的纯虚函数和非纯虚函数的选择** +   多态单例设计模式,会使用大量的抽象接口(虚函数),即使虚函数会占用更多的资源,没有使用纯虚接口的原因是,在智能指针初始化时,可以初始化一个默认的实例来避免每次使用智能指针都必须进行“非空判断”,纯虚函数使用导致增加的代码量(占用资源)会更大。 + +   至于虚函数导致的未知行为(bug),可以使用测试用例的方式来自动检索和判断。 + +#### 1.8.2.2. 抽象接口实例化统管设计 +   除了多态单例模式,独立模块内部整体设计都基于虚函数的原理大量使用抽象类,难点在于基于对产品业务的正确理解来设计抽象接口类;抽象接口类的好处是可以随意用虚函数的重载来改变业务的代码能力,内部的抽象接口类的方法可以部分是非虚函数的;抽象接口实例化统管是指使用一个模块内部唯一的多态单例来创建需要的实例指针,而不能直接在代码中“new”一个实例进行初始化;\ +参考Log创建实例代码: +```C++ {.line-numbers} +#ifndef ILOG_MAKE_PTR_H +#define ILOG_MAKE_PTR_H +#include "ILog.h" +#include "Log.h" +#include +#include +class ILogMakePtr +{ +public: + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr) + { + static std::shared_ptr instance = std::make_shared(); + if (impl) + { + instance = *impl; + } + return instance; + } + ILogMakePtr() = default; + virtual ~ILogMakePtr() = default; + virtual std::shared_ptr MakeLogImplPtr(); // 创建模块实例 + virtual std::shared_ptr MakeLogEasylogging(const LogSetting *setting); // 创建日志功能实例之一; + virtual std::shared_ptr MakeLongCapture(const LogSetting *setting); // 创建日志功能实例之二; +}; +#endif +``` +源码解析: +* 第22行和第23行分别创建了日志模块的两个不同功能的实例,初始化后可以实现不同的日志功能; +* 使用唯一的多态单例进行抽象接口的管理是为了让代码业务有更多的可塑性,通过对多态单例的重载可以在模块内部创造出各种各样的实例对象,让业务代码呈现出更多的变化; +* 对多态单例重载可以在模块内部创建测试桩代码实现自动化白盒测试能力; + +#### 1.8.2.3. 客制化公版架构 +   基于上述两个设计原则基础之下,整个主体架构设计都是具备 **“多态属性”** 的,首先,分层的独立模块是多态的,独立模块内部的业务接口代码也是多态的,整个软件架构的多态颗粒度非常细和精准: +* 整个独立模块直接重载替换,常见:随着技术的发展替换一些开源库;适配层的跨平台替换; +* 独立模块或者内部业务接口重载替换,颗粒度可以精确到替换某个源码文件,某个类,某些接口,某些接口当中的某几行代码; + +基于上述总结客制化公版架构的优势: +* 在不修改公版代码的基础上,对业务完成或粗或细的客制化改造,也包括产品系列的改造; +* 客制化的代码是重载实现的,可以完全独立维护,杜绝客制化版本之间的代码/业务耦合,常见:用宏来切换版本代码导致的版本之间耦合; +* 保证公版版本的绝对稳定性; + +**客制化代码运行时序图** +```mermaid +sequenceDiagram +User ->> +多态单例:调用抽象接口 + 多态单例 --> +公版实例:实际调用公版实例接口 + 公版实例 --> +客制化派生实例:实际调用客制化派生实例接口 + 客制化派生实例 --> -公版实例:return + 公版实例 --> -多态单例:return +多态单例 -->> -User:return +``` + +#### 1.8.2.4. 自动化测试框架 +   多态架构设计,可以完美融合自动化测试框架,本架构使用googletest开源库作为自动化测试框架,使用开源库创建测试桩注入(初始化)到主体代码当中,可以实现白盒自动化测试,常见: +1. 是否调用某个接口,以及调用时的入参,出参,返回值都可以进行修改/监控; +2. 是否调用某些接口,以及这些接口的时序; +3. 参数序列覆盖; +4. 批量测试用例(多态实例的动态切换); + +   可见测试代码也是完全独立于主体架构的,不需要在主体代码编辑测试代码完成测试任务。测试框架还可以生成测试用例报告和覆盖率报告。 +   测试框架配合asan在Ubuntu系统上跑测试用例时可快速检测内存安全相关漏洞,常见:内存泄漏,越界(含读/写)。 + +#### 1.8.2.5. 整机的自动化测试框架 +   在整体多态架构设计基础之下,在产品发布了release版本之后,仍可通过注入测试桩的方式来监控/测试软件系统。 + +#### 1.8.2.6. 跨平台架构 +   除了硬件适配层,其它独立模块代码都可以独立运行在Ubuntu系统,让软件项目在嵌入式Linux系统芯片的移植上提供了强大的适配性,在0修改基础上完成跨芯片平台的移植。 + +### 1.8.3. 调试/联调 +不管是一个全新项目还是一个维护项目,多态架构设计都提供了非常友善的开发支持: +* 所有独立模块代码都可以脱离硬件适配层独立编译和运行,使软件项目可以快速在Ubuntu验证代码功能,而无需每次都进行交叉编译上机运行;配合硬件适配层的测试桩实例仿真硬件接口数据; +* 所有独立模块都可以脱离外部模块的实例代码独立编译和运行,配合依赖的外部接口测试桩实例仿真接口数据,特别可以快速验证各种异常数据的软件鲁棒性; +* 使用asan内存安全检测工具,可以快速暴力主体代码的内存漏洞(提供栈信息),无需上机压测; +* 调试阶段的自验证example作为交付代码长期服务软件架构后续的测试; + +### 1.8.4. 自动化测试 +   在源码开发环节,支持基于Ubuntu系统创建大量自动化测试用例的拓展能力,测试用例分为单元测试和集成测试两个维度,单元测试是简单的对接口进行接口功能测试,集成测试是对产品功能进行测试。 + +   自动化测试的完整性需要视开发程度去评估,常见的问题如: +1. 改一个bug出现3个bug; +2. 已经修复的bug隔代复现; +3. 异常数据的处理能力缺失; +4. 测试场景的复杂繁琐导致的大量人力成本反复投入,吃力不讨好; +5. 常规功能的遗漏测试; + +针对这些问题自动化测试用例都可以有很强大的改善效果,同时也的确需要时间去积累测试用例。 + +   在整机release版本交付的测试环节,也支持整机自动化测试的拓展,例如配合一些机械设备,在发布release版本后,仍可动态地注入测试桩去完成整机的自动化测试并生成测试报告。 + +   **强调,自动化测试的完整性需要测试用例的开发来支持,由于工作量较大,可以慢慢补充完善。多态的架构设计只是让自动化测试更轻松地融合起来,使测试代码绝对不会干扰到主体代码,又可以很轻松的注入到软件业务对代码运行状态进行监控。** + +详见:./doc/auto_test.md + +**测试代码运行时序图** +```mermaid +sequenceDiagram +User ->> +多态单例:调用抽象接口 + 多态单例 --> +多态单例实例:实际调用实例接口 + 多态单例实例 --> +测试派生实例:实际调用测试派生实例接口 + 测试派生实例 ->> 测试派生实例:对程序执行结果进行校验 + 测试派生实例 --> -多态单例实例:return + 多态单例实例 --> -多态单例:return +多态单例 -->> -User:return +``` + +### 1.8.5. 版本管理 +   版本管理统指基于SifarSDK源码目录基础之上,使用构建工具对不同版本进行编译和打包,发布release/debug版本。 + +### 1.8.6. 架构代码命名规则 +* 大模块统一使用Manager作为基本标识,模块内部的细分功能统一使用Handle作为基本标识。 +* 大多数情况下,模块目录下的include文件夹存放对外暴露的头文件(常规有且只有一个头文件),带大写“I”的头文件为抽象接口头文件,此时src会有一个少“I”的文件为此抽象接口的实例。例如: +``` +├── CMakeLists.txt +├── include +│   └── ICameraManager.h +└── src + ├── CameraManager.cpp + ├── CameraManager.h + └── ICameraManager.cpp +``` + +### 1.8.7. 生产/售后 +   多态架构设计,可以动态衍生出生产模式,售后检测模式等一些特殊场景来应付特殊需求,常见: +* 注入测试桩监控出货后特殊场景(强高低温/高湿度等)下的数据; +* 在生产时注入测试桩测试硬件功能完整性,而无需把测试代码发布到release版本; +* 因疏忽流入了某个模块有bug的版本到市场,可以单独恢复有bug模块到旧版本而不是整体倒退版本; + +### 1.8.8. 总结 +   简单总结分层模块化架构设计:基于对产品业务功能的理解,通过虚实结合的编码手段来实现代码的“零耦合”,在“虚幻”的抽象接口层上,通过无约束地“幻化”多态实例,使产品在业务形态上可以呈现“千变万化”的姿态,以不变应万变。 + +   **本文后面将此种架构理念称为FANCY架构。** + +## 1.9. 软件模块 +   根据产品功能对软件进行功能模块划分。 +### 1.9.1. 软件工程组织图示 +![???](./picture/software_diagram.png) +   上图展示了SifarSDK软件工程的基本部署,基本上,每个或大或小的模块框内代码都是独立的,模块框与模块框之间是代码解耦合(功能业务不一定解耦合)的。 +* **SifarSDK** + SifarSDK作为相机软件的公版代码,包含了相机的所有功能实现,且不受任意客制化需求和产品特殊演变需求影响,杜绝和test框图的测试代码有任意的耦合。SifarSDK可以直接发布release版本上机运行。 + 1. **application**:应用层,应用层独立模块之间可以在功能上互相依赖,绝大部分不允许存在代码依赖,以保证独立模块的独立性和可移植性。 + 2. **component**:组件层,组件层的独立模块绝大部分是功能和代码都是独立的,绝大部分不运行存在互相依赖关系,杜绝反向依赖application层的功能和代码。 + 3. **hal**:硬件适配层,负责把ChipSDK的接口代码和SifarSDK解耦合,实现SifarSDK的绝对独立性和跨平台移植能力;由统一的IHal模块实例化SifarSDk所需要的其它功能模块实例。 +* **customization** + customization是客制化软件代码,代码目录保持和SifarSDK一致,通过继承,派生重载函数的方式在SifarSDK的基础上实现客制化功能,为保证SifarSDK的稳定性必须杜绝因为客制化需求而修改SifarSDK的主体代码。 +* **test**:自动化测试代码或者SifarSDK模块接口的example代码。 +* **external**:SifarSDK依赖的外部第三方开源库。 +* **ChipSDK**:芯片平台提供的功能接口。 +* **build**:项目构建配置。 +* **doc**:项目关联的文档目录。 + +**Sifar SDK层级关系** +```mermaid +classDiagram +class APP{ +<<应用业务层>> +} +class component{ +<<组件层>> +} +class Hal{ +<<硬件适配层>> +} +class ChipSDK{ +<<芯片平台SDK>> +} +APP --> component +APP <.. component +component --> Hal +component <.. Hal +Hal --> ChipSDK +``` + +### 1.9.2. Application层 +   APP层通过调用组件层的模块接口实现具体产品功能。 + +#### 1.9.2.1. Main线程 +   main线程主要负责APP的初始化,包括平台初始化,各独立模块多态单例的初始化,同时在公版代码的基础上,客制化版本可以重载初始化函数进行定制化开发,无需修改公版代码。\ +   **Main线程只做初始化(创建抽象类实例对象和运行Init函数),禁止在Main线程上做实际业务功能。** + +##### 1.9.2.1.1. UML类图 +```mermaid +classDiagram +class main{ + <<系统main函数>> +} +class MainThread{ + <> + +Init(void) RETURN_CODE + +CreateAllModules(void) RETURN_CODE +} +main --> MainThread +``` + +##### 1.9.2.1.2. UML时序图 +   main函数实际上什么也没在执行。 +```mermaid +sequenceDiagram +participant main +participant MainThread +participant 所有模块抽象接口 +note left of main:main()函数 +note right of main:初始化客制化代码 +main ->> main:OpenCustomizationMainThread +main ->> +MainThread:Init + MainThread ->> MainThread:CreateAllModules + MainThread ->> +所有模块抽象接口:初始化 + note right of 所有模块抽象接口:先初始化平台相关资源,让系统正常运行 + 所有模块抽象接口 ->> 所有模块抽象接口:初始化IHal模块 + 所有模块抽象接口 -->> -MainThread:return +MainThread -->> -main:Init +loop 阻塞 +main ->> +MainThread:Runing + MainThread ->> MainThread:while(1) + opt 实际业务 + 所有模块抽象接口 -->> 所有模块抽象接口:实际业务 + end +MainThread -->> -main:Runing +end +``` + +##### 1.9.2.1.3. 详见main_module_design.md设计文档 + +[打开main_module_design.md](./main_module_design.md) + +#### 1.9.2.2. 状态管理模块 +   尝试使用状态机机制进行状态图设计。 + +##### 1.9.2.2.1. UML类图 +```mermaid +classDiagram +class IStateManager{ + <<状态管理抽象接口>> +} +class CameraStateMachine{ + <<打猎相机状态机>> +} +class StateManager{ + <<状态管理抽象接口实例>> +} +class StateManagerMakePtr{ + <<实例创建类>> +} +class DefaultState{ + <<起始状态>> +} +class USBState{ + <<插入USB线状态>> +} +class ShutDownState{ + <<启动模式-关机>> +} +class UpgradeState{ + <<启动模式-升级>> +} +class PeripheralAbnormalState{ + <<外设异常状态>> +} +class StartupState{ + <<启动模式状态基类>> +} +class OnKeyState{ + <<启动模式-手动启动>> +} +class TimeLapseState{ + <<启动模式-定时间隔启动>> +} +class RingState{ + <<启动模式-RING启动>> +} +class PirStartState{ + <<启动模式-PIR触发启动>> +} +class SynDataState{ + <<启动模式-数据同步启动>> +} +class BatchSendState{ + <<启动模式-省电模式集中发送启动>> +} +class SDCardHandle{ + <> +} +class StateMachineCode{ + <<模块返回码>> +} +class StateCameraTask{ + <<相机任务实例>> +} +class SimInitState{ + <> +} +VCameraTask <|.. StateCameraTask +IStateManager <|.. StateManager +StateManager --> StateManagerMakePtr +StateManager --> CameraStateMachine +CameraStateMachine --> DefaultState +SDCardHandle <|-- StartupState +DefaultState --|> State +ShutDownState --|> State +UpgradeState --|> State +PeripheralAbnormalState --|> State +StartupState --|> State +USBState --|> State +CameraStateMachine --> USBState +CameraStateMachine --> ShutDownState +CameraStateMachine --> UpgradeState +CameraStateMachine --> PeripheralAbnormalState +CameraStateMachine --> SimInitState +CameraStateMachine --> StartupState +OnKeyState --|> StartupState +ICameraManager <-- OnKeyState +RingState --|> StartupState +StartupState <|-- SynDataState +StartupState <|-- BatchSendState +StartupState <|-- StartupV2State +StartupV2State <|-- TimeLapseState +StartupV2State <|-- PirStartState +``` + +##### 1.9.2.2.2. 关键类 +* CameraStateMachine +```mermaid +classDiagram +class CameraStateMachine{ + <<打猎相机状态机>> +} +``` + +##### 1.9.2.2.3. 状态图 +```mermaid +stateDiagram-v2 +[*] --> defaultState +defaultState --> PowerOff +defaultState --> MSDCState +defaultState --> PeripheralAbnormal +defaultState --> StartUp +StartUp --> 网络异常状态 +StartUp --> 网络正常状态 +StartUp --> P2P +StartUp --> 上传文件 +StartUp --> Sim卡初始化 +StartUp --> 注网状态 +StartUp --> Upgrade +``` + +##### 1.9.2.2.4. 最重要的状态-启动模式状态 +   启动模式状态对应的是对启动模式管理的设计。通过启动之后,在初始化状态机时,创建不同启动模式管理的实例来处理业务事件。\ +   **各启动模式之间是互斥独立的,不存在状态机中途切换启动模式的业务场景。** 对各种事件的处理(例如按键事件,SD卡事件,各种协议事件等),在状态机初始化完成时就已经确定了不同启动模式对其的响应结果。 + +###### 1.9.2.2.4.1. STARTUP_ONKEY启动模式 +* SETUP拨键启动时序图-STARTUP_ONKEY +流程较长,时序图分阶段处理: + 1. Main线程读取启动模式参数流程,根据启动模式初始化状态机; +```mermaid +sequenceDiagram +participant 低功耗小核 +participant CPU +participant IDualCoreManager +participant VProtocolParse +participant UartProtocolParse +participant IStateManager +participant IProtocolParse +低功耗小核 ->> 低功耗小核:SETUP拨键 +低功耗小核 ->> CPU:上电 +activate CPU + CPU ->> CPU:main() + %%activate IDualCoreManager + par 初始化 + CPU ->> +IDualCoreManager:初始化双核通讯模块 + IDualCoreManager ->> IDualCoreManager:创建读取数据线程 + IDualCoreManager -->> -CPU:return + CPU ->> +IProtocolParse:初始化协议模块 + IProtocolParse ->> +UartProtocolParse:new UartProtocolParse + UartProtocolParse -->> -IProtocolParse:return + IProtocolParse ->> +IDualCoreManager:注册协议处理实例 + IDualCoreManager -->> -IProtocolParse:return + IProtocolParse -->> -CPU:return + CPU ->> IStateManager:Init + activate IStateManager + note right of IStateManager:创建状态机 + IStateManager -->> IStateManager:CreateStateMachine + IStateManager -->> IStateManager:InitialStateMachine + IStateManager ->> IDualCoreManager:GetStartupMode + activate IDualCoreManager + IDualCoreManager ->> +低功耗小核:读取启动模式参数 + deactivate IDualCoreManager + IStateManager -->> CPU:return +deactivate CPU + deactivate IStateManager + and 核间通讯读线程 + loop 接收到数据 + 低功耗小核 -->> -CPU:回复启动模式 + CPU -->> IDualCoreManager:接收到数据 + activate IDualCoreManager + IDualCoreManager ->> +VProtocolParse:触发数据处理抽象接口 + VProtocolParse --> +UartProtocolParse:实例处理 + opt 启动模式事件 + UartProtocolParse ->> IStateManager:StartCameraStateMachine + activate IStateManager + IStateManager -->> IStateManager:根据启动模式初始化 + deactivate IStateManager + end + UartProtocolParse --> -VProtocolParse:return + VProtocolParse -->> -IDualCoreManager:return + deactivate IDualCoreManager + end + end + %%deactivate IDualCoreManager +``` + 2. SETUP拨键状态机初始化-STARTUP_ONKEY +```mermaid +sequenceDiagram +participant UartProtocolParse +participant CPU +participant StateManager +participant CameraStateMachine +participant DefaultState +participant OnKeyState +participant INetworkManager +CPU ->> +StateManager:状态管理模块初始化 + StateManager ->> +IDualCoreManager:获取启动模式 + IDualCoreManager -->> -StateManager:return +StateManager -->> -CPU:return +opt 协议模块触发启动模式事件 + UartProtocolParse ->> +StateManager:StartCameraStateMachine + StateManager ->> +CameraStateMachine:StartCameraStateMachine + CameraStateMachine ->> CameraStateMachine:InitAllStates + CameraStateMachine ->> CameraStateMachine:SetFirstState + CameraStateMachine ->> +DefaultState:GoIn函数 + DefaultState ->> DefaultState:判断USB和SIM卡状态 + opt 外设异常 + DefaultState ->> CameraStateMachine:发送外设异常事件 + end + DefaultState ->> DefaultState:判断PIR状态 + opt 外设异常 + DefaultState ->> CameraStateMachine:发送外设异常事件 + end + DefaultState ->> DefaultState:判断SD卡状态 + opt 外设异常 + DefaultState ->> CameraStateMachine:发送外设异常事件 + end + DefaultState ->> DefaultState:启动电量检测 + DefaultState ->> CameraStateMachine:发送开启USB模式事件 + DefaultState ->> CameraStateMachine:SendStateMessage + note right of DefaultState:发送starup事件 + DefaultState -->> -CameraStateMachine:return + CameraStateMachine -->> -StateManager:return + StateManager -->> -UartProtocolParse:return +end +opt STARTUP_ONKEY事件处理 + CameraStateMachine --> DefaultState:处理STARTUP_ONKEY事件 + activate DefaultState + DefaultState ->> CameraStateMachine:切换到OnKeyState + deactivate DefaultState + activate CameraStateMachine + CameraStateMachine ->> +OnKeyState:GoIn函数 + OnKeyState ->> OnKeyState:注网流程 + OnKeyState ->> OnKeyState:USB_is_open + OnKeyState ->> INetworkManager:SIM卡初始化 + OnKeyState ->> INetworkManager:4G注网(手动)? + OnKeyState ->> OnKeyState:USBnet初始化 + OnKeyState ->> OnKeyState:鉴权部分 + OnKeyState ->> OnKeyState:ACM服务器处理 + OnKeyState -->> -CameraStateMachine:return + deactivate CameraStateMachine +end +opt 外设异常事件处理 + CameraStateMachine --> DefaultState:处理外设异常事件 + activate DefaultState + DefaultState ->> CameraStateMachine:切换到PeripheralAbnormalState + deactivate DefaultState + activate CameraStateMachine + CameraStateMachine ->> +PeripheralAbnormalState:GoIn函数 + PeripheralAbnormalState -->> -CameraStateMachine:return + deactivate CameraStateMachine + opt STARTUP_ONKEY事件处理 + CameraStateMachine --> PeripheralAbnormalState:处理STARTUP_ONKEY事件 + activate PeripheralAbnormalState + PeripheralAbnormalState ->> PeripheralAbnormalState:无法处理STARTUP_ONKEY事件 + deactivate PeripheralAbnormalState + end +end +``` + 3. STARTUP_ONKEY状态下的TEST按键响应 +```mermaid +sequenceDiagram +opt TEST按键事件 + CameraStateMachine --> OnKeyState:处理TEST按键事件 + activate OnKeyState + OnKeyState ->> +StateCameraTask:创建拍照任务 + StateCameraTask -->> -OnKeyState:return + OnKeyState ->> +ICameraManager:拍照 + ICameraManager -->> -OnKeyState:return + deactivate OnKeyState + opt 拍照任务回调 + ICameraManager ->> +StateCameraTask:拍照完成 + StateCameraTask ->> +IFilesManager:上传文件 + IFilesManager -->> IFilesManager:上传文件 + IFilesManager -->> -StateCameraTask:return + StateCameraTask -->> -ICameraManager:return + end + opt 拍照任务超时回调 + ICameraManager ->> +StateCameraTask:任务超时 + StateCameraTask ->> StateCameraTask:该干嘛干嘛 + StateCameraTask -->> -ICameraManager:return + end + opt 拍照任务取消 + OnKeyState ->> +StateCameraTask:任务取消 + ICameraManager -->> ICameraManager:任务将会异步取消 + StateCameraTask -->> -OnKeyState:return + end + opt OnKeyState退出 + note right of OnKeyState:异步处理:这里要保证状态退出
和事件回调时序的正确处理! + CameraStateMachine ->> +OnKeyState:GoOut函数 + OnKeyState ->> +ICameraManager:任务取消(同步取消,安全) + ICameraManager -->> ICameraManager:任务同步取消 + ICameraManager -->> -OnKeyState:return + OnKeyState -->> -CameraStateMachine:return + end +end +``` + +#### 1.9.2.3. 文件管理模块 +   负责对图片/音视频文件进行统一管理的模块,包含各种异常情况下的文件缓存管理,文件的增删改查,文件的发送/下载。 + +##### 1.9.2.3.1. 模块UML类图 +```mermaid +classDiagram +class IFilesManager{ +<<文件管理模块抽象接口>> +} +class FilesManager{ +<<文件管理模块抽象接口实例>> +} +class FilesDatabase{ +<<文件数据库>> +} +class FilesHandle{ +<<文件处理>> +} +class sqlit3{ +<<轻量级开源数据库>> +} +class VFileTask{ +<<单个文件处理任务>> +} +class FileSendTask{ +<<网络任务实例>> +} +IFilesManager <|.. FilesManager +IFilesManager *-- VFileTask +FilesManager --> FilesHandle +FilesHandle --> FilesDatabase +FilesHandle --> INetworkManager +FilesHandle --> IStorageManager +INetworkManager *-- NetworkTask +FileSendTask ..|> NetworkTask +VFileTask --o FileSendTask +FilesDatabase --> sqlit3 +FilesManager --> IHal +``` + +##### 1.9.2.3.2. 上传文件时序图 +```mermaid +sequenceDiagram +User ->> User:创建发送任务 +User ->> +FilesManager:上传文件 + FilesManager ->> +FilesHandle:上传文件 + FilesHandle ->> +FilesDatabase:保存数据库 + note right of FilesDatabase:记录文件状态(上传中/上传完) + FilesDatabase -->> -FilesHandle:return + FilesHandle ->> +FilesSendTask:创建上传任务 + FilesSendTask -->> -FilesHandle:return + FilesHandle ->> +INetworkManager:上传文件 + INetworkManager -->> INetworkManager:上传 + INetworkManager -->> -FilesHandle:return + FilesHandle -->> -FilesManager:return +FilesManager -->> -User:return +opt 上传完成回调 + INetworkManager ->> +FilesSendTask:上传完成 + FilesSendTask ->> +VFileTask:上传完成 + VFileTask -->> +User:上传完成事件回调给User + User -->> -VFileTask:return + VFileTask -->> -FilesSendTask:return + FilesSendTask ->> +FilesDatabase:保存数据库 + note right of FilesDatabase:记录文件状态(上传中/上传完) + FilesDatabase -->> -FilesSendTask:return + FilesSendTask -->> -INetworkManager:return +end +``` + +#### 1.9.2.4. 网络管理模块 +   统管网络通讯部分,含协议,外设管理。 + +##### 1.9.2.4.1. UML类图 +```mermaid +classDiagram +class INetworkManager{ +<<网络管理模块抽象接口>> +} +class NetworkManager{ +<<网络管理模块抽象接口实例>> +} +class VNetworkModule{ +<<网络模块抽象接口>> +} +class MobileModule{ +<<移动网络模块实例>> +} +class WifiModule{ +<> +} +class HttpServers{ +<> +} +class VFileServersHandle{ +<<服务器控制抽象接口>> +} +class FileServersHandle{ +<> +} +class ACMServersHandle{ +<> +} +class AuthServersHandle{ +<<鉴权服务器>> +} +class VAuthServers{ +<<鉴权服务器抽象接口>> +} +INetworkManager <|.. NetworkManager +INetworkManager *-- VFileServersHandle +NetworkManager --> VNetworkModule +NetworkManager --> AuthServersHandle +VFileServersHandle <|.. ACMServersHandle +VFileServersHandle <|.. FileServersHandle +ACMServersHandle --> VNetworkModule +FileServersHandle --> VNetworkModule +VNetworkModule <|.. MobileModule +VNetworkModule <|.. WifiModule +MobileModule o-- VNetworkHardwareHandle +WifiModule o-- VNetworkHardwareHandle +ACMServersHandle --|> HttpServers +FileServersHandle --|> HttpServers +AuthServersHandle --|> HttpServers +AuthServersHandle ..|> VAuthServers +VFileServersHandle <|.. ACMServersV2Handle +VFileServersHandle <|.. S3ServersV2Handle +ACMServersV2Handle --|> VAtCommand +S3ServersV2Handle --|> VAtCommand +``` + +### 1.9.3. 组件层 +   组件层一般指通用(或者相对通用)的基础功能模块,一般来说组件层独立模块之间不会存在依赖关系,除了非常常规功能模块,例如:日志模块,返回码模块等。\ +   组件层模块代码不应该反向依赖APP的任意模块的任意文件。 + +#### 1.9.3.1. 外设管理模块 +   APP通过此组件操作芯片平台的外设资源,而无需关心具体的芯片外设资源定义。 +   **特别地,如何抽象化处理不同供应商之间的AT指令的差异?** + +##### 1.9.3.1.1. 外设模块层级关系 +```mermaid +classDiagram +class IPeripheralManager{ +<<外设管理组件抽象接口>> +} +class APP{ +<<统指业务应用>> +} +class PeripheralManager{ +<<接口实现>> +} +class IHal{ +<<硬件适配层抽象接口>> +} +class Hal{ +<<硬件适配层平台实例接口>> +} +APP --> IPeripheralManager +IPeripheralManager <|.. PeripheralManager +PeripheralManager --> IHal +IHal <|.. Hal +``` +##### 1.9.3.1.2. 关键枚举定义 +* 按键部分 +按键定义:详见[SfKeyDefine](#SfKeyDefine)。\ +按键类型: +```mermaid +classDiagram +class SfKeyAction{ +<<枚举>> +SF_KEY_ACTION_SHORT_CLICK = 0, +SF_KEY_ACTION_LONG_CLICK, +SF_KEY_ACTION_HOLD_DOWN, +SF_KEY_ACTION_HOLD_UP, +SF_KEY_ACTION_GROUP, +SF_KEY_ACTION_BUTT +} +``` +* 状态灯部分 +   状态灯部分,设计成APP可以随意控制灯的行为:常亮,常灭,闪烁,变色。\ +状态灯类型定义:详见[SfLedIndex](#SfLedIndex)。\ +状态灯状态:详见[SfLedState](#SfLedState)。 + +##### 1.9.3.1.3. 外设类图依赖关系 +```mermaid +classDiagram +class IPeripheralManager{ +<<外设管理抽象接口>> +} +class VKeyMonitor{ +<<外设监控抽象接口>> +} +class SfKeyAction{ +<<按键行为>> +} +class PeripheralManager{ +<<外设管理抽象接口实例>> +} +class PeripheralManagerMakePtr{ +<<统一的实例创建接口>> +} +class KeyManager{ +<<按键管理>> +} +class LedHandle{ +<<灯控制接口>> +} +class VNetworkHardwareHandle{ +<<网络通讯模块抽象接口>> +} +class MobileHardwareHandle{ +<<移动通讯模块接口实例>> +} +class VAtCommand{ +<> +} +class AtCommand{ +<> +} +APP --> IPeripheralManager +IPeripheralManager --> IHalCommon +IHal --> IHalCommon +IPeripheralManager <|.. PeripheralManager +IPeripheralManager *-- SfKeyAction +IPeripheralManager *-- VNetworkHardwareHandle +VNetworkHardwareHandle <|.. MobileHardwareHandle +MobileHardwareHandle o-- VNetWorkModule +MobileHardwareHandle --|> AtCommand +AtCommand --|> VAtCommand +VKeyMonitor --* IPeripheralManager +VKeyContrl --* IHal +VLedContrl --* IHal +VNetWorkModule --* IHal +PeripheralManager --> PeripheralManagerMakePtr +PeripheralManager --> KeyManager +KeyManager o-- VKeyContrl +PeripheralManager --> LedHandle +LedHandle o-- VLedContrl +PeripheralManager --> MobileHardwareHandle +``` +**移动通讯模块部分设计说明** +1. 外设管理模块提供一个网络模块抽象接口,虚化网络模块的具体属性,例如:网络模块的联网方式(WiFi/RJ45/移动),移动网络模块的制式(4G/5G/6G); +2. 设计VNetworkModule虚化网络模块的硬件属性,例如:USB/串口/其它接口方式; +3. 设计一个VAtCommand的AT指令抽象接口基类,虚化AT指令集的具体实现; +4. 上述3条结合实现网络通讯模块代码在关键功能代码的随意组合; + +##### 1.9.3.1.4. 外部依赖关键类 +* IHal类:硬件适配层,详见[IHal](#IHal)。 +* VKeyContrl类:按键控制抽象接口,详见[VKeyContrl](#VKeyContrl)。 +* VLedContrl类:状态灯控制抽象接口,详见[VLedContrl](#VLedContrl)。 + +##### 1.9.3.1.5. PeripheralManagerMakePtr类 +抽象类,创建实例,可以重载此类进行模块多态功能的初始化。 +```mermaid +classDiagram +class PeripheralManagerMakePtr{ +<<创建多态实例>> ++CreatePeripheralManager(std::shared_ptr< IPeripheralManager >&) VReturnCode +} +``` + +##### 1.9.3.1.6. IPeripheralManager类 +抽象类,提供虚函数接口,使用多态单例模式。 +```mermaid +classDiagram +class IPeripheralManager{ +<<外设管理组件抽象接口>> ++GetKeyContrlHandle(void) VReturnCode ++sf_key_deinit(void) VReturnCode ++SetKeyMonitor(std::shared_ptr< VKeyMonitor >) VReturnCode ++GetLedContrlHandle(void) VReturnCode ++sf_led_deinit(void) VReturnCode ++SetLedState(const SfLedIndex, std::shared_ptr< VKeyMonitor >) VReturnCode ++SetLongClickPeriod(unsigned int) VReturnCode +} +``` +**调用CreatePeripheralManagerModule函数进行实例初始化后使用抽象方法。**\ +实例参考代码: +``` +#include "IPeripheralManager.h" +class KeyMonitor : public VKeyMonitor +{ +public: + KeyMonitor() = default; + ~KeyMonitor() = default; + RETURN_CODE KeyActionHappened(const SfKeyDefine key, const SfKeyAction event) override + { + LogInfo("key action happened.\n"); + // APP do something about key actions. + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } +}; +// ../out/test/bin/PeripheralManagerTest --gtest_filter=IPeripheralManagerDemo.KeyDemo +// This demo show how to use key function by SifarSDK. +TEST(IPeripheralManagerDemo, KeyDemo) +{ + CreatePeripheralManager(); + auto keyMonitor = std::make_shared(); // Used to capture key action. + IPeripheralManager::GetInstance()->Init(); // Init all the keys. + IPeripheralManager::GetInstance()->SetKeyMonitor(keyMonitor); +} +// ../out/test/bin/PeripheralManagerTest --gtest_filter=IPeripheralManagerTest.LedDemo +TEST_F(IPeripheralManagerTest, LedDemo) +{ + class LedMonitor : public VKeyMonitor + { + public: + LedMonitor() = default; + ~LedMonitor() = default; + RETURN_CODE GetLedState(SfLedState &state) override + { + state = SfLedState::SF_LED_STATE_ON; + return VReturnCode::NewCode(VReturnCodeDefine::OK); + } + }; + auto ledMonitor = std::make_shared(); // Used to capture key action. + IPeripheralManager::GetInstance()->Init(); // Init all the keys. + IPeripheralManager::GetInstance()->SetLedState(SfLedIndex::SF_LED_STATUS, ledMonitor); +} +``` + +##### 1.9.3.1.7. VPeripheralMonitor类 +抽象类,由外部重载实现,用于外部接收按键事件或者控制状态灯。 +```mermaid +classDiagram +class VKeyMonitor{ +<<外设监视器>> ++KeyActionHappened(const SfKeyDefine, const SfKeyAction) VReturnCode ++GetBlinkPeriod(unsigned int&) VReturnCode ++GetLedState(SfLedState&) VReturnCode +} +IPeripheralManager *-- VKeyMonitor +``` + +##### 1.9.3.1.8. PeripheralManager类 +抽象类IPeripheralManager的实例类。重载IPeripheralManager的所有虚函数接口。 +```mermaid +classDiagram +class PeripheralManager{ +<> ++LedHandle_thread(void) void ++create_key_manager(std::shared_ptr< VKeyContrl >) bool +-std::shared_ptr< VKeyMonitor > mGpioMonitor +-std::map< SfLedIndex, std::shared_ptr< VKeyMonitor > > mLedStatus +-std::map< SfKeyDefine, KeyManager > keys +} +IPeripheralManager <|.. PeripheralManager +``` + +##### 1.9.3.1.9. KeyManager类 +   按键管理类,处理按键触发类型。硬件适配层的按键事件会通过VKeyContrl对象上报并被KeyManager对象捕获进行二次处理。\ +   **组合功能暂未实现,组合按键功能会有适当延时。**\ +   **组合功能还涉及到多状态模式,是否在APP层处理更合适。** +```mermaid +classDiagram +class KeyManager{ +<<按键管理类>> +KeyManager(std::shared_ptr, KeyActionCallback, unsigned int longClickTime) ++KeyEventCallback(void*) void ++SetLongClickPeriod(unsign int) void +-std::shared_ptr< VKeyContrl > mKeyCtrl +-KeyActionCallback mKeyActionEvent +-unsigned int mPressedTime +-unsigned int mLongClickTime +-SfKeyEvent mKeyState +} +``` +   KeyManager可以向APP上报“长按”,“短按”,“按住”,“松开”按键动作,APP可以设置长按的时长标准来进行客制化开发。 + +##### 1.9.3.1.10. 外设模块按键时序图 +   外设管理组件无需创建线程进行主动的按键检测操作,此操作在硬件适配层完成。外设管理组件捕获到按键事件并二次处理后,通过VPeripheralMonitor监视器把按键动作上报给APP处理。\ +   按键事件:按键的“按下”或者“松开”事件;\ +   按键动作:按键的“长按”,“短按”,“按住”,“松开”; +```mermaid +sequenceDiagram +participant APP +participant PeripheralManager +participant KeyManager +participant VKeyMonitor +participant IHal +participant VKeyContrl +note left of APP:应用模块 +activate APP + APP ->> APP:start + APP ->> +PeripheralManager:Init + loop 循环初始化按键 + PeripheralManager ->> +IHal:GetKeyContrlHandle + IHal ->> IHal:创建VKeyContrl实例 + IHal -->> -PeripheralManager:return + activate PeripheralManager + PeripheralManager ->> +KeyManager:new KeyManager + PeripheralManager ->> KeyManager:注册回调 + KeyManager ->> +VKeyContrl:SetKeyEventMonitor + note right of VKeyContrl:HAL层通过此回调上报按键事件 + VKeyContrl -->> -KeyManager:return + KeyManager -->> -PeripheralManager:return + end + deactivate PeripheralManager + PeripheralManager -->> -APP:return + opt 客制化定制长按时长 + APP ->> +PeripheralManager:SetLongClickPeriod + PeripheralManager ->> +KeyManager:SetLongClickPeriod + KeyManager -->> -PeripheralManager:return + PeripheralManager -->> -APP:return + end + APP ->> +PeripheralManager:SetKeyMonitor + note right of PeripheralManager:注册按键事件回调 + PeripheralManager -->> -APP:return +deactivate APP + +note right of KeyManager:按键管理对象会注册回调函数捕获上报的按键事件 +note right of KeyManager:此处无需关注Hal是如何上报按键事件的 +opt KeyManager收到按键事件 + VKeyContrl ->> KeyManager:KeyEventCallback + activate KeyManager + KeyManager ->> KeyManager:对按下事件进行二次处理 + opt 发生按键动作 + KeyManager ->> +PeripheralManager:回调函数 + PeripheralManager ->> +VKeyMonitor:KeyActionHappened + VKeyMonitor ->> +APP:实际调用了APP的实例处理函数 + note left of VKeyMonitor:此处无需关心APP如何处理,不阻塞即可 + APP -->> -VKeyMonitor:return + VKeyMonitor -->> -PeripheralManager:KeyActionHappened + PeripheralManager -->> -KeyManager:return + end + deactivate KeyManager +end +``` + +##### 1.9.3.1.11. 外设管理模块状态灯时序图 +```mermaid +sequenceDiagram +participant APP +participant VKeyMonitor +participant PeripheralManager +participant LedHandle +participant VLedContrl +participant LedHandle_thread +participant IHal +note left of APP:应用模块 +activate APP +APP ->> APP:start +APP ->> +PeripheralManager:GetLedContrlHandle +PeripheralManager ->> +IHal:GetLedContrlHandle +IHal ->> IHal:new VLedContrl +IHal -->> -PeripheralManager:return +PeripheralManager -->> -APP:return +APP ->> +PeripheralManager:SetLedState + +note right of PeripheralManager:设置灯状态 + alt 设置闪烁 + PeripheralManager ->> +LedHandle:SetLedState + LedHandle ->> LedHandle_thread:LedHandle_thread + activate LedHandle_thread + note left of LedHandle_thread:闪烁状态创建线程处理 + else 其它 + LedHandle ->> +VKeyMonitor:GetLedState + note right of LedHandle:获取APP欲设置的状态 + VKeyMonitor -->> -LedHandle:return + LedHandle ->>+ VLedContrl:SetLedState + VLedContrl -->> -LedHandle:return + LedHandle -->> -PeripheralManager:return + end + +PeripheralManager -->> -APP:return +deactivate APP + loop 循环处理灯状态 + LedHandle_thread ->>LedHandle:ledctrl_check + activate LedHandle + opt 闪烁状态 + LedHandle ->> +VKeyMonitor:GetBlinkPeriod + VKeyMonitor -->> -LedHandle:return + LedHandle ->> +VLedContrl:SetLedState + VLedContrl -->> -LedHandle:return + end + deactivate LedHandle + end +deactivate LedHandle_thread +``` +   上述流程图介绍了APP只许简单设置灯状态即可,具体业务无需进行对外设硬件的任意操作。 +存在问题: +* 按键事件是否支持并发?例如是否支持多个外部模块同时监控按键事件? +* 如何解决按键事件冲突?通过按键组件模块的初始化? +* 并发的按键事件是否设置阻塞/非阻塞?单线程会阻塞。 +* **T110源码当中的按键处理代码和USB和启动模式还有4g相关代码耦合,属于不合理耦合?** 组件功能和业务场景强耦合,不符合组件设计原则。 +* 状态灯闪烁多种组合如何防止冲突?约束闪烁周期?例如多线程使用组件的并发控制灯状态。 +* **客制化如何添加按键或者灯?** + +#### 1.9.3.2. 返回码管理模块 +   SifarSDK创建一个统一的返回码定义,在定义函数的时候,尽量使用标准的返回码类型作为函数返回值。返回码类型使用抽象接口进行设计,方便各模块独立管理的同时,在系统全局提供标准接口。\ +统一返回码类型作用: +* 抽象的标准接口,方便后期拓展返回码功能时,尽可能无需修改原调用代码; +* 独立模块独立管理,独立模块相关的返回码只会存在于模块内部,模块删除时杜绝废弃定义的冗余代码仍遗留在项目源码当中; +* 独立模块自由拓展返回码定义; +* 通过对返回码的统一管理,可实时监控各种异常; + +##### 1.9.3.2.1. VReturnCode类图 +```mermaid +classDiagram +class VReturnCode{ +<> ++GetIntCode(void) const int +} +``` + +##### 1.9.3.2.2. 返回码使用基本原则 +1. 独立模块的对外暴力接口统一使用标准返回码,便于后续对返回码的迭代;例如:保持类型统一,减少修改代码量级; +2. 独立模块内部按需选择,由于架构零耦合的设计模式,内部修改类型对外部影响为0; + +#### 1.9.3.3. 状态机管理模块 +   状态机机制模块实现。状态机是在事件队列功能的基础上,解耦合各状态代码,使代码逻辑简单。\ +   详细设计文档待补充,可参考海思芯片平台的状态机介绍文档。本设计文档移植了鸿蒙系统开源代码当中的状态机源码进行二次封装(修改了源码)。\ +   状态机管理使用了三方开源代码,进行了抽象接口二次封装,大大减弱对开源代码强依赖性,不好用时可进行替换或者自主研发。 + +##### 1.9.3.3.1. UML类图 +```mermaid +classDiagram +class IStateMachineManager{ + <<状态机管理抽象接口>> +} +class State{ + <<单个状态抽象接口>> +} +class VStateMachineMessage{ + <<状态消息抽象接口>> +} +class VMessageObject{ + <<单个消息抽象接口>> +} +class VStateMachine{ + <<单个状态机抽象接口>> +} +class StateMachineManagerImpl{ + <<状态机管理抽象接口实例>> +} +class StateMachine{ + <<状态机实例>> +} +IStateMachineManager <|.. StateMachineManagerImpl +IStateMachineManager *-- State +IStateMachineManager *-- VStateMachineMessage +IStateMachineManager *-- VMessageObject +IStateMachineManager *-- VStateMachine +VStateMachine <|.. StateMachine +StateMachineManagerImpl --> StateMachine +``` + +##### 1.9.3.3.2. UML时序图 +```mermaid +sequenceDiagram +participant APP +participant StateMachine +participant State +participant StateMachineManagerImpl +note left of APP:外部应用 +activate APP + APP ->> APP:CreateStateMachineManager + APP ->> +StateMachineManagerImpl:CreateStateMachine + StateMachineManagerImpl ->> StateMachineManagerImpl:new VStateMachine + StateMachineManagerImpl ->> -APP:return + APP ->> +StateMachine:初始化状态机 + StateMachine -->> -APP:return + APP ->> +StateMachine:StartStateMachine + StateMachine -->> -APP:return + opt 向状态机发送消息 + APP ->> StateMachine:SendMessage +deactivate APP + activate StateMachine + StateMachine ->> +State:ExecuteStateMsg + State ->> +APP:APP状态实例处理消息 + APP -->> -State:return + State -->> -StateMachine:return + deactivate StateMachine + end +``` + +#### 1.9.3.4. 相机管理模块 +   负责摄像头工作模式,媒体相关设置的管理。 + +##### 1.9.3.4.1. UML类图 +```mermaid +classDiagram +class ICameraManager{ +<<摄像头管理抽象接口>> +} +class CameraManager{ +<<摄像头管理抽象接口实例>> +} +class CameraMode{ +<<摄像头工作模式>> +} +class VCameraTask{ +<<单个摄像任务>> +} +class VCameraHandle{ +<<单个摄像操作接口>> +} +class CameraHandle{ +<<单个摄像操作接口实例>> +} +ICameraManager <|.. CameraManager +ICameraManager *-- VCameraTask +ICameraManager *-- VCameraHandle +VCameraHandle <|.. CameraHandle +CameraHandle o-- VCameraHal +CameraHandle o-- CameraType +CameraHandle o-- CameraMode +``` + +##### 1.9.3.4.2. 关键定义 +* 摄像头类型 +   摄像头类型支持多个摄像头拓展,目前打猎相机只有一个摄像头。 +```mermaid +classDiagram +class CameraType{ + MAIN_CAMERA = 0, + END +} +``` +* 任务数据结构体 +```mermaid +classDiagram +class TaskData{ ++? 数据类型 ++char* 数据指针 ++unsigned int 长度 +} +``` +* 任务类型 +```mermaid +classDiagram +class TaskType{ + TASK_TPYE_PICTURE = 0, + TASK_TPYE_VIDEO, + TASK_TPYE_PICTURE_VIDEO, + TASK_TPYE_END +} +``` + +##### 1.9.3.4.3. 关键类 +* VCameraTask + 由外部使用者继承重载接口,内部管理。 +```mermaid +classDiagram +class VCameraTask{ +<<单个摄像任务>> ++TaskFinish(TaskData) void ++GetTimeout(void) unsigned int ++TaskTimeout(void) void ++IsCancel(void) bool ++GetTaskType(void) TaskType +} +``` + +* ICameraManager + 相机管理抽象接口。 +```mermaid +classDiagram +class ICameraManager{ +<<摄像头管理抽象接口>> ++Init(void) RETURN_CODE ++UnInit(void) RETURN_CODE ++SendTask(std::shared_ptr< VCameraTask >) RETURN_CODE ++CancelTask(std::shared_ptr< VCameraTask >) RETURN_CODE +} +``` + +##### 1.9.3.4.4. 相机拍照功能时序图 +```mermaid +sequenceDiagram +CameraHandle ->> CameraHandle:Init +opt 初始化 + CameraHandle ->> +MediaHandle:初始化 + MediaHandle ->> +IHal:创建VMediaHandle实例 + IHal -->> -MediaHandle:return + MediaHandle -->> -CameraHandle:return +end +CameraHandle ->> +MediaHandle:发送VCameraTask拍照任务 + MediaHandle ->> MediaHandle:拍照任务进队列 + MediaHandle ->> +MediaThread:创建线程 + MediaThread -->> -MediaHandle:return + activate MediaThread +MediaHandle -->> -CameraHandle:return + loop 循环处理任务队列 + MediaThread ->> +MediaHandle:获取当前任务 + MediaHandle -->> -MediaThread:return + alt 任务未开始 + opt 需要拍照 + MediaThread ->> +VMediaHandle:拍照接口(完成单次拍照任务) + VMediaHandle -->> -MediaThread:return + end + opt 需要录像 + MediaThread ->> +VMediaHandle:录像接口(完成单次录像任务) + VMediaHandle -->> -MediaThread:return + end + activate VMediaHandle + else 任务被外部异步取消 + note right of MediaThread:异步取消存在不安全问题
除非外部不监控任务任何回调 + MediaThread ->> VMediaHandle:任务取消 + VMediaHandle -->> MediaThread:return + MediaThread ->> +MediaHandle:释放任务 + MediaHandle -->> -MediaThread:return + else 超时 + MediaThread ->> VMediaHandle:取消任务 + VMediaHandle -->> MediaThread:return + MediaThread ->> +MediaHandle:释放任务 + MediaThread ->> +VCameraTask:TaskTimeout + VCameraTask -->> -MediaThread:return + MediaHandle -->> -MediaThread:return + end + end + deactivate MediaThread + VMediaHandle -->> VMediaHandle:适配层执行单次任务 +opt 拍照回调触发 + VMediaHandle ->> +MediaHandle:拍照数据回调函数 + MediaHandle ->> +VCameraTask:TaskFinish + VCameraTask -->> VCameraTask:使用者自处理数据 + VCameraTask -->> -MediaHandle:return + MediaHandle ->> MediaHandle:释放任务 + MediaHandle -->> -VMediaHandle:return +end + deactivate VMediaHandle +opt 同步取消任务 +note right of MediaHandle:安全操作,推荐 +CameraHandle ->> +MediaHandle:取消任务 + MediaHandle ->> +VMediaHandle:任务取消 + VMediaHandle -->> -MediaHandle:return + MediaHandle ->> MediaHandle:释放任务 +MediaHandle -->> -CameraHandle:return +end +``` + +存在问题: +* 如何支持多路摄像头管理? + +#### 1.9.3.5. 存储管理 +   负责对SD卡进行管理。上层业务可能存在多个外部模块需要对存储状态和数据进行监控/获取,例如:界面,文件管理模块。 + +##### 1.9.3.5.1. UML类图 +```mermaid +classDiagram +class IStorageManager{ +<<存储管理抽象接口>> +} +class StorageManager{ +<<存储管理抽象接口实例>> +} +class SDCardHandle{ +<> +} +class IHal{ +<<硬件适配层抽象接口>> +} +class VSdCardHandle{ +<> +} +class VStorageMonitor{ +<<存储模块监视器>> +} +IStorageManager <|.. StorageManager +IStorageManager *-- VStorageMonitor +StorageManager --> SDCardHandle +SDCardHandle --> IHal +IHal *-- VSdCardHandle +``` + +##### 1.9.3.5.2. 关键类图 +```mermaid +classDiagram +class IStorageManager{ +<<存储管理抽象接口>> ++SD卡Mount成功/失败的接口或者标识读取() ++SD卡识别错误() ++SD卡总容量、剩余容量读取的接口或者标识() ++SD卡文件/文件夹删除,创建接口() ++SD卡格式化() +} +``` + +#### 1.9.3.6. 双核管理 +   为了可以兼容单核和双核芯片之间的逻辑切换,设计双核管理模块,当芯片是双核时,小核代码跑在小核,当芯片模块为单核时,双核代码跑在单核。**小核一般是rtos系统,小核代码使用纯C语言开发。** + +##### 1.9.3.6.1. UML类图 +```mermaid +classDiagram +class IDualCoreManager{ +<<双核管理抽象接口>> +} +class UartHandle{ +<<串口管理>> +} +class LightKernelHandle{ +<<小核管理>> +} +class VProtocolParse{ +<<协议解析抽象接口>> +} +class IHal{ +<<硬件适配层抽象接口>> +} +IDualCoreManager <|.. UartHandle +IDualCoreManager <|.. LightKernelHandle +IDualCoreManager *-- VProtocolParse +UartHandle --> IHal +LightKernelHandle --> IHal +``` +##### 1.9.3.6.2. UML时序图(启动模式获取) +```mermaid +sequenceDiagram +participant UartHandle +participant ReadHandleThread +participant VProtocolParse +participant IHal +UartHandle ->> UartHandle:Init +activate UartHandle + UartHandle ->> +IHal:获取芯片平台串口资源 + IHal -->> -UartHandle:return + UartHandle ->> ReadHandleThread:创建读取线程 +deactivate UartHandle +activate ReadHandleThread + opt 发送数据 + UartHandle ->> UartHandle:发送命令数据 + end + loop 接收到数据 + ReadHandleThread ->> +VProtocolParse:解析协议 + opt 合法数据 + VProtocolParse ->> VProtocolParse:外部处理数据 + end + VProtocolParse -->> -ReadHandleThread:return + end +deactivate ReadHandleThread + +``` + +#### 1.9.3.7. 通用配置库 +   对Flash的配置文件进行管理。 + +##### 1.9.3.7.1. UML类图 +```mermaid +classDiagram +class IConfigManager{ +<<配置库抽象接口>> +} +class ConfigManager{ +<<配置库抽象接口实例>> +} +class IHal{ +<<硬件适配层抽象接口>> +} +IConfigManager <|.. ConfigManager +ConfigManager --> IHal +``` + +##### 1.9.3.7.2. UML时序图 +   和芯片平台依赖的配置文件路径需要通过IHal接口获取。 +```mermaid +sequenceDiagram +ConfigManager ->> ConfigManager:Init +opt 读配置文件 + ConfigManager ->> IHal:获取配置文件path + ConfigManager ->> ConfigManager:加载配置文件 +end +``` +#### 1.9.3.8. 协议解析库 +   双核管理协议实例。解析协议并根据协议内容处理业务,属于application层的模块,与实际的硬件设计解耦合。 + +##### 1.9.3.8.1. UML类图 +```mermaid +classDiagram +class IProtocolParse{ +<<协议解析库抽象接口>> +} +class ProtocolParse{ +<<协议解析库抽象接口实例>> +} +class UartProtocolParse{ +<> +} +IProtocolParse <|.. ProtocolParse +ProtocolParse --> UartProtocolParse +ProtocolParse --> IStateManager +``` + +##### 1.9.3.8.2. UML时序图 +   +```mermaid +sequenceDiagram +ProtocolParse ->> ProtocolParse:创建协议实例提供外部使用 +opt 接收数据 + ProtocolParse ->> ProtocolParse:解析协议 + opt 启动模式协议 + ProtocolParse ->> IStateManager:往状态机发送启动模式事件 + end +end +``` + +#### 1.9.3.9. 网络通信管理模块 +   通过usb管理4G模块。 + +##### 1.9.3.9.1. UML类图 +```mermaid +classDiagram +class INetworkManager{ +<<网络管理模块抽象接口>> +} +class NetworkManager{ +<<网络管理模块抽象接口实例>> +} +class NetworkModule{ +<<网络处理模块抽象接口>> +} +class 4GModule{ +<<4G通信模块>> +} +class NetworkTask{ +<<单个网络任务>> +} +INetworkManager <|.. NetworkManager +INetworkManager *-- NetworkTask +NetworkManager --> NetworkModule +NetworkModule <|-- 4GModule +NetworkModule <|-- 5GModule +4GModule --> IHal +``` + +##### 1.9.3.9.2. 上传文件时序图 +```mermaid +sequenceDiagram +participant User +User ->> +NetworkManager:Init,创建NetworkModule
的派生类实例 + note right of NetworkManager:外接不同的模块实例不一样 +NetworkManager -->> -User:return +User ->> User:创建发送任务 +User ->> +NetworkManager:上传文件 + NetworkManager ->> +NetworkModule:上传文件 + NetworkModule ->> NetworkModule:任务进缓存队列 + opt 创建任务管理线程 + NetworkModule ->> NetworkThread:创建任务管理线程 + activate NetworkThread + end + NetworkModule -->> -NetworkManager:return +NetworkManager -->> -User:上传文件 +loop 循环处理任务 + NetworkThread ->> +NetworkModule:获取当前任务 + NetworkModule -->> -NetworkThread:return + alt 任务未处理 + NetworkThread -->> +NetworkModule:发送接口 + NetworkModule -->> -NetworkThread:return + NetworkThread ->> +NetworkModule:释放任务 + NetworkModule -->> -NetworkThread:return + else 超时 + NetworkThread ->> +NetworkModule:超时 + NetworkModule -->> -NetworkThread:return + end +end + deactivate NetworkThread +``` + + +#### 1.9.3.10. Upgrade模块 +   + +* 远程ota升级; +* ota服务器; + +存在问题: +* 升级优先级?什么状态下不可以升级? + +#### 1.9.3.11. 日志模块 +   SifarSDK使用统一的宏进行日志的输出,结合使用多态单例设计模块,让日志功能可以运行态多态切换。 + +#### 1.9.3.12. 系统定时器?? + +### 1.9.4. 启动管理 +   CPU的启动是由MCU进行电源管理控制的。 +启动模式 +* 关机 +* 手动启动模式 +* 定时间隔启动 +* RING启动 +* PIR触发启动 +* DELAY REPORT启动 +* 参数同步启动 +* 省电模式集中发送启动 + +#### 1.9.4.1. UML类图 +```mermaid +classDiagram +class IStartupManager{ +<<启动管理抽象接口>> +} +class StartupManager{ +<<启动管理抽象接口实例>> +} +class IStartUpMode{ +<<启动模式>> +} +class IDualCoreManager{ +<<电源控制抽象接口>> +} +class IAuthenticationServers{ +<<鉴权服务器>> +} +class VState{ +<<状态机状态>> +} +class StandardMode{ +<<标准启动模式>> +} +class IACMServer{ +<> +} +class IS3Server{ +<> +} +class INetworkManager{ +<<4G管理抽象接口>> +} +class UartHandle{ +<> +} +class LightKernelHandle{ +<<小核电源控制>> +} +class eg91{ +<<待确认>> +} +class http{ +<<待确认>> +} +IStartupManager <|.. StartupManager +StartupManager --> IDualCoreManager +StartupManager --> INetworkManager +StartupManager --> IStartUpMode +VState <|.. StandardMode +IStartUpMode <|.. StandardMode +StandardMode <-- 关机 +StandardMode <-- 手动启动模式 +StandardMode <-- 定时间隔启动 +StandardMode <-- RING启动 +StandardMode <-- PIR触发启动 +StandardMode <-- DELAY REPORT启动 +StandardMode <-- 参数同步启动 +StandardMode <-- 省电模式集中发送启动 +StartupManager --> IAuthenticationServers +IAuthenticationServers <|.. eg91 +IAuthenticationServers <|.. http +StartupManager --> IACMServer +StartupManager --> IS3Server +IDualCoreManager <|.. UartHandle +IDualCoreManager <|.. LightKernelHandle +``` + +#### 1.9.4.2. 启动模式梳理 +启动模式公共部分:4G管理,注网,鉴权 +##### 1.9.4.2.1. 手动启动模式 +```mermaid +sequenceDiagram +note left of StartupManager:上电 +StartupManager ->> StartupManager:start +StartupManager ->> IDualCoreManager:获取启动模式 +IDualCoreManager ->> +INetworkManager:4G初始化 +INetworkManager ->> INetworkManager:获取imei/iccid/运营商代码 +INetworkManager -->> -IDualCoreManager:return +alt 4G初始化成功 + note right of INetworkManager:下面的操作都是在4G模块内部? + INetworkManager ->> INetworkManager:根据运营商代码配置APN + INetworkManager ->> INetworkManager:4G注网流程 + alt 4G注网成功 + INetworkManager ->> INetworkManager:usb net初始化 + opt 地域地址为空 + INetworkManager ->> IAuthenticationServers:调用鉴权接口获取区域地址 + end + INetworkManager ->> IACMServer:连接ACM服务器 + IACMServer ->> IACMServer:调用登录接口 + IACMServer ->> IACMServer:记录pic套餐状态 + IACMServer ->> IACMServer:执行登录接口命令 + opt 首次开机登陆ACM + IACMServer ->> IACMServer:调用同步配置接口,上传默认设置 + end + else 4G注网失败 + INetworkManager ->> INetworkManager:4G注网失败 + end +else 4G初始化失败 + INetworkManager ->> INetworkManager:4G网络状态异常 +end +opt 按键触发 + IACMServer ->> IACMServer:调用同步配置接口,上传默认设置 +end +``` +存在问题: +* 启动模式是指上电启动还是休眠之后启动? +* 每个模式退出时是否强制回收资源?避免启动导致的瞬时功能异常?例如:图片上传到一半就断电。 +* 不同启动模式之间是如何切换的?状态直接切换逻辑 +* 不同启动模式之间会影响到什么功能会有差异? +* 是否存在mcu被双核低功耗芯片替换?考虑电源管理模块的多态设计。 +* **不同启动模式下启动的设备,业务的执行权限不一样,是否可以把启动模块设计成状态机机制?** + 答:不同启动模式之间无耦合关系,无需使用状态机机制。 +* 服务器是否可抽象化处理? + +#### 1.9.4.3. GPS业务 +GPS功能: +* 获取地理位置; + +存在问题: +* GPS业务对应的硬件模块接口? +* GPS模块供电控制? +* 如何管理GPS不同状态下的启动流程? + +### 1.9.5. P2P业务 +#### 1.9.5.1. 概述 +   P2P直播业务,分为三大块:应用层,直播平台层(组件层),芯片适配层(芯片配体库)。每层都进行解耦合(零耦合)设计模式进行接口设计和开发,以达到快速切换直播平台或者芯片媒体库的目的。 +   直播平台通过SifarSDK公版的构建脚本配置选择,芯片适配层通过项目构建脚本配置选择。 +### 1.9.6. 套餐管理 +套餐类型: +* P2P直播live套餐; +* 基础套餐PICS; +* 预约HD套餐; + +存在问题: +* 3中套餐并存? +### 1.9.7. 硬件适配层 +#### 1.9.7.1. 概述 +   硬件适配层最关键的作用是把芯片平台相关的代码与SifarSDK进行解耦合设计,使SifarSDK主体代码可以在剥离芯片平台源码的基础上,仍可自由进行开发,编译,调试,测试。**SifarSDK有且仅有硬件适配层是强依赖芯片SDK的,除此之外的其它代码均可跨芯片平台移植,且适配层代码仍有部分代码是可移植到Linxu系统的。** + +   主要分为两大部分:硬件相关接口和音视频处理接口。 + +#### 1.9.7.2. IHalCommon头文件 +   纯定义头文件,例如枚举,宏。**不能定义依赖平台的定义**。 + +包含: +* 按键定义:SfKeyDefine。 +```mermaid +classDiagram +class SfKeyDefine{ +<<枚举>> +SF_KEY_PIN_RESET +SF_KEY_PIN_SYNC +SF_KEY_PIN_FORMAT +SF_KEY_PIN_DATAREADY +SF_KEY_PIN_FILESTATUS +} +``` + +* 按键类型:SfKeyPinType。 +```mermaid +classDiagram +class SfKeyPinType{ +<<枚举>> +KEY_PIN_TYPE_IN +KEY_PIN_TYPE_OUT +} +``` + +* GPIO PIN值:SfPinValue。 +```mermaid +classDiagram +class SfPinValue{ +<<枚举>> +PIN_VALUE_HIGHT +PIN_VALUE_LOW +} +``` + +* 状态灯定义:SfLedIndex。 +```mermaid +classDiagram +class SfLedIndex{ +<<枚举>> +SF_LED_IDX_0 = 0, +SF_LED_IDX_1, +SF_LED_STATUS, +SF_LED_WIFI, +SF_LED_SD, +SF_LED_BAT, +SF_LED_SIG1, +SF_LED_USERBIND, +SF_LED_END +} +``` + +* 状态灯状态:SfLedState。 +```mermaid +classDiagram +class SfLedState{ +<<枚举>> +SF_LED_STATE_OFF = 0, +SF_LED_STATE_ON, +SF_LED_STATE_GREEN, +SF_LED_STATE_RED, +SF_LED_STATE_YELLOW, +SF_LED_STATE_BUIT +} +``` + +UML类图 +```mermaid +classDiagram +class Halxxx{ +<<适配层实例>> +} +class Gpio{ +<> +} +class VLedContrl{ +<<灯控制抽象接口>> +} +class VKeyContrl{ +<<按键控制抽象接口>> +} +class KeyContrl{ +<<按键控制抽象接口实例>> +} +class OneColorLed{ +<<单色灯控制实例>> +} +class MultiColorLed{ +<<多色灯控制实例>> +} +class VKeyEventMonitor{ +<<外部的监视器>> +} +class VNetWorkModule{ +<<网络模块控制抽象接口>> +} +class NetworkModule{ +<<网络模块控制抽象接口实例>> +} +class Usb{ +<> +} +class VCameraHal{ +<<摄像头适配芯片接口>> +} +class CameraHal{ +<> +} +class CameraChip{ +<<摄像头芯片接口>> +} +class ChipSDK{ +<<芯片SDK接口>> +} +SfKeyDefine --* IHalCommon +SfKeyPinType --* IHalCommon +SfPinValue --* IHalCommon +SfLedIndex --* IHalCommon +SfLedState --* IHalCommon +IHal *-- VNetWorkModule +IHal *-- VKeyContrl +IHal *-- VLedContrl +IHal *-- VMediaHandle +IHal *-- VSdCardHandle +IHal *-- VCameraHal +VNetWorkModule <|.. NetworkModule +IHal *-- VKeyEventMonitor +IHalCommon --o IHal +IHal <|.. Halxxx +NetworkModule <-- Halxxx +OneColorLed <-- Halxxx +MultiColorLed <-- Halxxx +KeyContrl <-- Halxxx +CameraChip <-- Halxxx +Halxxx --> Uart +PWM <-- Halxxx +PwmLedContrl <-- PWM +VLedContrl <|.. OneColorLed +Gpio <|-- KeyContrl +VKeyContrl <|.. KeyContrl +VCameraHal <|.. CameraHal +ChipSDK <|-- CameraChip +CameraHal <|-- CameraChip +Gpio <|-- OneColorLed +Gpio <|-- MultiColorLed +Usb <|-- NetworkModule +VLedContrl <|.. MultiColorLed +VLedContrl <|.. PwmLedContrl +``` +#### 1.9.7.3. IHal类 +抽象类,提供虚函数接口。 +```mermaid +classDiagram +class IHal{ +<<硬件适配层抽象接口>> ++Init(void) VReturnCode ++UnInit(void) VReturnCode ++GetKeyContrlHandle(const SfKeyDefine, std::shared_ptr< VKeyContrl >) VReturnCode ++sf_key_deinit(const SfKeyDefine) VReturnCode ++GetLedContrlHandle(const SfLedIndex, std::shared_ptr< VLedContrl >) VReturnCode +} +``` + +#### 1.9.7.4. VKeyContrl类 +按键控制抽象接口。 +```mermaid +classDiagram +class VKeyContrl{ +<<按键控制接口>> ++SetKeyEventMonitor(EventCallback, void*) void ++GetKeyEventReportPeriod(void) int +} +``` + +#### 1.9.7.5. VLedContrl类 +状态灯控制抽象接口,含可调亮度灯的控制。 +```mermaid +classDiagram +class VLedContrl{ +<<状态灯控制接口>> ++SetLedState(const SfLedState) VReturnCode ++SetLedState(const unsigned int) VReturnCode +} +``` + +#### 1.9.7.6. GpioKeyContrl类 +VKeyContrl抽象类的实例类。 +```mermaid +classDiagram +class GpioKeyContrl{ +<<按键控制接口实例>> ++KeyEvent(const SfKeySate) void +-const SfKeyDefine mKey +-EventCallback HalKeyEventHappened +-void* mEventContext +} +``` + +#### 1.9.7.7. Gpio类 +Gpio接口基础功能接口。 +```mermaid +classDiagram +class Gpio{ +<> ++GpioInit(const U32 &, const char *) SINT32 ++GpioSet(const U32 &, const U32 &) SINT32 ++GpioGet(U32 , SINT8 *) SINT32 ++GpioDeinit(U32 ) SINT32 +} +``` + +#### 1.9.7.8. VCameraHal摄像头适配抽象接口 +   不同的芯片厂家对适配的处理方式是不一样的,通过抽象接口类进行适配解耦合。实现对图片/视频的单次操作功能。 + +```mermaid +classDiagram +class VCameraHal{ +<<摄像头适配芯片接口>> +} +``` + +##### 1.9.7.8.1. 按键控制时序图 +   介于不同芯片的GPIO处理方法存在差异,Hal层对按键的处理,只对按键的按下和松开进行处理,然后把“按下”或者“松开”的事件上报。对按键功能的复杂处理放在组件层进行二次处理。\ +   **在Hal创建唯一处理单线程,只把按键事件往高层传递,避免上层在处理GPIO时的时序混乱问题或者加锁影响效率问题。** +```mermaid +sequenceDiagram +note left of APP:初始化开始 +activate APP + APP ->> APP:start + APP ->> +Halxxx:Init + Halxxx ->> Halxxx:InitAllKeys + Halxxx ->> +Hal333DEMakePtr:CreateGpioLedContrlInstance + Hal333DEMakePtr ->> +KeyContrl:new KeyContrl + KeyContrl -->> -Hal333DEMakePtr:return + Hal333DEMakePtr -->> -Halxxx:return + Halxxx ->> GpioHandleThread:创建线程 + activate GpioHandleThread + Halxxx -->> -APP:return + APP ->> +Halxxx:GetKeyContrlHandle + Halxxx -->> -APP:return + APP -->> +KeyContrl:SetKeyEventMonitor + note right of KeyContrl:通过监视器触发按键事件 + KeyContrl -->> -APP:return +deactivate APP + loop IsHalRuning + GpioHandleThread ->> +Halxxx:CheckAllPins + Halxxx ->> +KeyContrl:CheckKeyValue + KeyContrl ->> KeyContrl:GpioGet + opt KEY_EVENT_PRESSED or KEY_EVENT_UN_PRESSED + KeyContrl -->> +APP:HalKeyEventHappened + APP -->> -KeyContrl:return + end + KeyContrl -->> -Halxxx:return + Halxxx -->> -GpioHandleThread:return + end + deactivate GpioHandleThread + +APP ->> +Halxxx:UnInit + Halxxx ->> GpioHandleThread:停止线程 +Halxxx -->> -APP:return +``` + +##### 1.9.7.8.2. 状态灯控制时序图 +   只是简单控制灯对象的脚位高低。 +```mermaid +sequenceDiagram +note left of APP:初始化开始 +activate APP + APP ->> APP:start + APP ->> +Halxxx:Init + Halxxx ->> Halxxx:InitAllLeds + Halxxx ->> +VLedContrl实例:new instance + note over VLedContrl实例:统指VLedContrl的实例 + VLedContrl实例 -->> -Halxxx:return + Halxxx -->> -APP:return + APP ->> +Halxxx:GetLedContrlHandle + Halxxx -->> -APP:return + opt APP控制状态灯 + APP ->> +VLedContrl实例:SetLedState + note right of APP:APP通过VLedContrl抽象接口控制灯状态 + VLedContrl实例 -->> -APP:return + end +deactivate APP +``` + +```mermaid +classDiagram +class IHal{ +<<硬件适配层抽象接口>> +} +class Hal{ +<<硬件适配层实例>> +} +IHal <|.. Hal +Hal --> Gpio +Hal --> Uart +Hal --> USB +``` +#### 1.9.7.9. 硬件适配层启动时序图 + +## 1.10. 组件部分 +## 1.11. 协议 +产品协议。 +### 1.11.1. APP协议 +## 1.12. 测试 +   基础架构设计,关键模块接口,关键类接口可使用测试框架无缝切入,为自动化测试用例开发提供更灵活的可能性,也具备白盒测试的能力。详细设计说明待补充。。。 \ No newline at end of file diff --git a/code/application/sifarsdk/doc/main_module_design.md b/code/application/sifarsdk/doc/main_module_design.md new file mode 100644 index 000000000..e670d141d --- /dev/null +++ b/code/application/sifarsdk/doc/main_module_design.md @@ -0,0 +1,3 @@ +# 1. Main线程设计文档 +## 1.1. 概述 +   main线程主要负责创建各模块实例并拉起各模块的初始化接口,main线程不执行任何业务操作,只运行一个空壳代码,根据实例化的代码执行对应的业务代码。 \ No newline at end of file diff --git a/code/application/sifarsdk/doc/markdown_user_guide.md b/code/application/sifarsdk/doc/markdown_user_guide.md new file mode 100644 index 000000000..070cd4d00 --- /dev/null +++ b/code/application/sifarsdk/doc/markdown_user_guide.md @@ -0,0 +1,92 @@ +# Markdown使用手册 +作者:萧家柱 2023-2-13 + +## 概述 +使用markdown编辑开发文档有以下好处: +* markdown语法是一种语言,类似代码一样可以方便git管理,查看修改记录; +* 对代码显示支持良好; +* 可以进行UML类图和时序图的编辑/迭代/维护(强烈推荐); + +## 如何使用Markdown +此处介绍基于vscode编辑环境下使用Markdown的方法: +* 首先安装vscode插件: + 1. Markdown All in One + 2. Markdown Preview Enhanced +* 使用Markdown语法编辑开发文档,并使用vscode预览; +* 右键使用浏览器打开并打印可生成PDF文档; + +## 基本语法介绍 +提供常用语法参考,直接copy模块代码进行编辑。 + +### 常用命令 +``` +Markdown All in One: Create Table of Contents 创建目录 +Markdown All in One: Update Table of Contents 更新目录 +Markdown All in One: Add/Update section numbers 添加 / 更新章节编号 +Markdown All in One: Remove section numbers 删除章节编号 +Markdown All in One: Toggle code span 触发设置代码范围(`code`) +Markdown All in One: Toggle code block 触发设置代码块(```codes```) +Markdown All in One: Print current document to HTML +Markdown All in One: Toggle math environment 触发设置数学环境 +Markdown All in One: Toggle list 触发设置列表环境 +``` + +### 代码段 +``` +/*This is your code.*/ +#include +int main() +{ + return 0; +} +``` + +### UML类图语法 +```mermaid +classDiagram + Animal <|-- Fish:继承 + Animal <|.. Zebra:实现 + Animal : +int age + Animal : +String gender + Animal: +isMammal() + Animal: +mate() + class Animal{ + <> + +call() int + } + class Fish{ + -int sizeInFeet + -canEat() + } + class Zebra{ + <> + -func(int, int) int + +bool is_wild + +run(void) + } +``` +实现:一般指对抽象类的实例类 \ +继承:一般指对普通功能基类的派生/重载 + +### UML时序图 +```mermaid +sequenceDiagram +Alice->>+Jhon:Call function +Jhon->>Jhon:handle +Jhon-->>-Alice:Call return +note left of Alice:function + +Alice->>+Jhon:Call function +Jhon->>+Fancy:Call +Fancy-->>-Jhon:Call return +Jhon-->>-Alice:Call return + +Alice->>+Jhon:Call function +Jhon->>+Fancy:Call +Fancy->>-Fancy:End +Jhon-->>-Alice:Call return +``` + +### 踩坑记录 + +1. 状态图不能使用default关键字作为一个状态名称,无法画图; \ No newline at end of file diff --git a/code/application/sifarsdk/doc/mdCreateMenu.js b/code/application/sifarsdk/doc/mdCreateMenu.js new file mode 100644 index 000000000..4d3f690db --- /dev/null +++ b/code/application/sifarsdk/doc/mdCreateMenu.js @@ -0,0 +1,57 @@ +/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; + if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("