--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
+ * @file bsl_err_internal.h
+ * Description: 错误码模块
+ * Author: zhanghui
+ * Create: 2023-05-30
+ */
+
+#ifndef BSL_ERR_INTERNAL_H
+#define BSL_ERR_INTERNAL_H
+
+#include <stdint.h>
+
+/**
+ * @ingroup BSL
+ * @brief 将错误信息存入错误信息栈中
+ *
+ * @par 描述:
+ * 将错误信息存入错误信息栈中
+ *
+ * @attention err不能为0
+ * @param err [IN] 错误码,高16位表示模块子模块id,低16位表示错误号
+ * @param file [IN] 文件名,不含目录路径
+ * @param lineNo [IN] 错误产生的行号
+ */
+void BSL_ERR_PushError(int32_t err, const char *file, uint32_t lineNo);
+
+/**
+ * @ingroup BSL
+ * @brief 将错误信息存入错误信息栈中
+ *
+ * @par 描述:
+ * 将错误信息存入错误信息栈中
+ *
+ * @attention err不能为0
+ */
+#define BSL_ERR_PUSH_ERROR(e) BSL_ERR_PushError((e), __FILENAME__, __LINE__)
+
+#endif // BSL_ERR_INTERNAL_H
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * Description: 平衡二叉树的实现
+ * Author: guzhou
+ * Create: 2022-02-18
+ */
+
+#include <inttypes.h>
+#include "sal_mem.h"
+#include "bsl_log_internal.h"
+#include "bsl_binlog_id.h"
+#include "avl.h"
+
+// avl树的最大高度
+#define AVL_MAX_HEIGHT 64
+
+static uint32_t GetMaxHeight(uint32_t a, uint32_t b)
+{
+ if (a >= b) {
+ return a;
+ } else {
+ return b;
+ }
+}
+
+static uint32_t GetAvlTreeHeight(const BSL_AvlTree *node)
+{
+ if (node == NULL) {
+ return 0;
+ } else {
+ return node->height;
+ }
+}
+
+static void UpdateAvlTreeHeight(BSL_AvlTree *node)
+{
+ if (node != NULL) {
+ uint32_t leftHeight = GetAvlTreeHeight(node->leftNode);
+ uint32_t rightHeight = GetAvlTreeHeight(node->rightNode);
+ if (node->height >= AVL_MAX_HEIGHT) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05001, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "avl tree height exceed max limit", NULL, NULL, NULL, NULL);
+ return;
+ }
+ node->height = GetMaxHeight(leftHeight, rightHeight) + 1u;
+ }
+}
+
+/**
+ * @brief 创建avl节点
+ * @param nodeId [IN]节点ID
+ * data [IN]节点存储的数据
+ * @return curNode 申请成功返回节点
+ * NULL 申请失败
+ */
+BSL_AvlTree *BSL_AVL_MakeLeafNode(BSL_ElementData data)
+{
+ BSL_AvlTree *curNode = (BSL_AvlTree *)SAL_MALLOC(sizeof(BSL_AvlTree));
+ if (curNode == NULL) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05002, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "MALLOC for avl tree node failed", NULL, NULL, NULL, NULL);
+ return NULL;
+ }
+
+ curNode->height = 1;
+ curNode->rightNode = NULL;
+ curNode->leftNode = NULL;
+ curNode->data = data;
+
+ return curNode;
+}
+
+/**
+ * @brief AVL左旋转
+ * @param root [IN] 待旋转的根节点
+ * @return rNode 旋转后的根节点
+ */
+static BSL_AvlTree *AVL_RotateLeft(BSL_AvlTree *root)
+{
+ /* Rotate Left
+ 10 20
+ 5 20 --Rotate Left---> 10 30
+ 30 5 40
+ 40
+
+ 此场景下输入根节点为10, 输出为20 */
+ BSL_AvlTree *rNode = root->rightNode;
+ BSL_AvlTree *lNode = rNode->leftNode;
+ root->rightNode = lNode;
+ rNode->leftNode = root;
+ UpdateAvlTreeHeight(root);
+ UpdateAvlTreeHeight(rNode);
+ return rNode;
+}
+
+/**
+ * @brief AVL右旋转
+ * @param root [IN] 待旋转的根节点
+ * @return lNode 旋转后的根节点
+ */
+static BSL_AvlTree *AVL_RotateRight(BSL_AvlTree *root)
+{
+ /* Rotate Right
+ 40 30
+ / \ / \
+ 30 50 --Rotate Right---> 20 40
+ 20 35 10 35 50
+ 10
+ 此场景下输入根节点为40, 输出为30 */
+ BSL_AvlTree *lNode = root->leftNode;
+ BSL_AvlTree *rNode = lNode->rightNode;
+ root->leftNode = rNode;
+ lNode->rightNode = root;
+ UpdateAvlTreeHeight(root);
+ UpdateAvlTreeHeight(lNode);
+ return lNode;
+}
+
+/**
+ * @brief AVL右平衡
+ * @param root [IN] 待平衡的根节点
+ * @return root 平衡后的根节点
+ */
+static BSL_AvlTree *AVL_RebalanceRight(BSL_AvlTree *root)
+{
+ // 左右子树高度只相差1
+ if ((GetAvlTreeHeight(root->leftNode) + 1u) >= GetAvlTreeHeight(root->rightNode)) {
+ UpdateAvlTreeHeight(root);
+ return root;
+ }
+ /* 左子树高度大于右子树, 先右旋转再左旋转 */
+ BSL_AvlTree *curNode = root->rightNode;
+ if (GetAvlTreeHeight(curNode->leftNode) > GetAvlTreeHeight(curNode->rightNode)) {
+ root->rightNode = AVL_RotateRight(curNode);
+ }
+ return AVL_RotateLeft(root);
+}
+
+/**
+ * @brief AVL左平衡
+ * @param root [IN] 待平衡的根节点
+ * @return root 平衡后的根节点
+ */
+static BSL_AvlTree *AVL_RebalanceLeft(BSL_AvlTree *root)
+{
+ // 左右子树高度只相差1
+ if ((GetAvlTreeHeight(root->rightNode) + 1u) >= GetAvlTreeHeight(root->leftNode)) {
+ UpdateAvlTreeHeight(root);
+ return root;
+ }
+ /* 右子树高度大于左子树, 先左旋转再右旋转 */
+ BSL_AvlTree *curNode = root->leftNode;
+ if (GetAvlTreeHeight(curNode->rightNode) > GetAvlTreeHeight(curNode->leftNode)) {
+ root->leftNode = AVL_RotateLeft(curNode);
+ }
+ return AVL_RotateRight(root);
+}
+
+static void AVL_FreeData(BSL_ElementData data, BSL_AVL_DATA_FREE_FUNC freeFunc)
+{
+ if (freeFunc != NULL) {
+ freeFunc(data);
+ }
+}
+
+BSL_AvlTree *BSL_AVL_InsertNode(BSL_AvlTree *root, uint64_t nodeId, BSL_AvlTree *node)
+{
+ if (root == NULL) {
+ node->nodeId = nodeId;
+ return node;
+ }
+
+ if (root->nodeId > nodeId) {
+ // nodeId比根节点nodeId小, 插入左子树
+ root->leftNode = BSL_AVL_InsertNode(root->leftNode, nodeId, node);
+
+ return AVL_RebalanceLeft(root);
+ } else if (root->nodeId < nodeId) {
+ // nodeId比根节点nodeId大, 插入右子树
+ root->rightNode = BSL_AVL_InsertNode(root->rightNode, nodeId, node);
+
+ return AVL_RebalanceRight(root);
+ }
+
+ /* key相同不能插入 */
+ LOG_BINLOG_FIXLEN(BINLOG_ID05003, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "AVL tree insert key nodeId(%"PRIu64") already exist", nodeId, NULL, NULL, NULL);
+ return NULL;
+}
+
+BSL_AvlTree *BSL_AVL_SearchNode(BSL_AvlTree *root, uint64_t nodeId)
+{
+ BSL_AvlTree *curNode = root;
+ while (curNode != NULL) {
+ // 匹配到节点
+ if (curNode->nodeId == nodeId) {
+ break;
+ } else if (curNode->nodeId > nodeId) {
+ // nodeId比根节点nodeId小, 搜索左子树
+ curNode = curNode->leftNode;
+ } else {
+ // nodeId比根节点nodeId大, 搜索右子树
+ curNode = curNode->rightNode;
+ }
+ }
+
+ // 搜索不到指定节点, 返回NULL
+ return curNode;
+}
+
+/**
+ * @brief 删除同时拥有左右子节点的指定avl节点
+ * @param rmNodeChild [IN] 待删除avl节点的子节点
+ * removeNode [IN] 待删除avl节点
+ * @return root 返回删除后的avl树根节点
+ */
+static BSL_AvlTree *AVL_DeleteNodeWithTwoChilds(BSL_AvlTree *rmNodeChild, BSL_AvlTree *removeNode)
+{
+ if (rmNodeChild == NULL || removeNode == NULL) {
+ return NULL;
+ }
+
+ if (rmNodeChild->rightNode == NULL) {
+ // 无论rmNodeChild是否有左节点, 都将左节点与祖父节点连接起来
+ BSL_AvlTree *curNode = rmNodeChild->leftNode;
+ removeNode->nodeId = rmNodeChild->nodeId;
+ removeNode->data = rmNodeChild->data;
+
+ SAL_FREE(rmNodeChild);
+ return curNode;
+ }
+
+ rmNodeChild->rightNode = AVL_DeleteNodeWithTwoChilds(rmNodeChild->rightNode, removeNode);
+ return AVL_RebalanceLeft(rmNodeChild);
+}
+
+BSL_AvlTree *BSL_AVL_DeleteNode(BSL_AvlTree *root, uint64_t nodeId, BSL_AVL_DATA_FREE_FUNC func)
+{
+ if (root == NULL) {
+ return root;
+ }
+
+ if (root->nodeId == nodeId) {
+ if (root->leftNode == NULL) {
+ if (root->rightNode == NULL) {
+ // 左右节点均为NULL
+ AVL_FreeData(root->data, func);
+ SAL_FREE(root);
+ return NULL;
+ } else {
+ // 只有右节点
+ BSL_AvlTree *curNode = root->rightNode;
+ AVL_FreeData(root->data, func);
+ SAL_FREE(root);
+ return (curNode);
+ }
+ } else if (root->rightNode == NULL) {
+ // 只有左节点
+ BSL_AvlTree *curNode = root->leftNode;
+ AVL_FreeData(root->data, func);
+ SAL_FREE(root);
+ return (curNode);
+ } else {
+ // 有左右节点
+ AVL_FreeData(root->data, func);
+ root->leftNode = AVL_DeleteNodeWithTwoChilds(root->leftNode, root);
+ return AVL_RebalanceRight(root);
+ }
+ }
+
+ if (root->nodeId > nodeId) {
+ root->leftNode = BSL_AVL_DeleteNode(root->leftNode, nodeId, func);
+ return AVL_RebalanceRight(root);
+ } else {
+ root->rightNode = BSL_AVL_DeleteNode(root->rightNode, nodeId, func);
+ return AVL_RebalanceLeft(root);
+ }
+}
+
+void BSL_AVL_DeleteTree(BSL_AvlTree *root, BSL_AVL_DATA_FREE_FUNC func)
+{
+ if (root == NULL) {
+ return;
+ }
+
+ BSL_AVL_DeleteTree(root->leftNode, func);
+ BSL_AVL_DeleteTree(root->rightNode, func);
+ AVL_FreeData(root->data, func);
+ SAL_FREE(root);
+}
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file avl.h
+ * Description: 平衡树功能相关接口
+ * Author: guzhou
+ * Create: 2022-02-18
+ */
+
+#ifndef AVL_H
+#define AVL_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *BSL_ElementData;
+
+typedef void (*BSL_AVL_DATA_FREE_FUNC)(BSL_ElementData data);
+
+/* AVL tree node structure */
+typedef struct AvlTree {
+ uint32_t height;
+ uint64_t nodeId;
+ struct AvlTree *rightNode;
+ struct AvlTree *leftNode;
+ BSL_ElementData data;
+} BSL_AvlTree;
+
+/**
+ * @ingroup BSL
+ * @brief 创建一个树节点
+ *
+ * @par 描述:
+ * 创建一个树节点,并设置节点数据
+ *
+ * @attention 无
+ * @param data [IN] 树节点的数据指针
+ * @retval NULL 内存分配失败
+ */
+BSL_AvlTree *BSL_AVL_MakeLeafNode(BSL_ElementData data);
+
+/**
+ * @ingroup BSL
+ * @brief 查找节点
+ *
+ * @par 描述:
+ * 通过nodeId查找avl树的节点
+ *
+ * @attention 无
+ * @param root 树的根节点指针
+ * @param nodeId [IN] 作为key,树的节点id
+ * @retval NULL 没有查到相应的节点
+ * @retval 非NULL 查到的相应节点的指针
+ */
+BSL_AvlTree *BSL_AVL_SearchNode(BSL_AvlTree *root, uint64_t nodeId);
+
+/**
+ * @ingroup BSL
+ * @brief 在树中创建一个节点
+ *
+ * @par 描述:
+ * 在树中创建一个节点
+ *
+ * @attention 如果nodeId已经存在,则无法插入
+ * @param root [IN] 树的根节点指针
+ * @param nodeId [IN] 作为被创建节点的key
+ * @param node [IN] 树节点
+ * @retval 非NULL 树或子树的根节点
+ */
+BSL_AvlTree *BSL_AVL_InsertNode(BSL_AvlTree *root, uint64_t nodeId, BSL_AvlTree *node);
+
+/**
+ * @ingroup BSL
+ * @brief 删除特定的树节点
+ *
+ * @par 描述:
+ * 删除nodeId相应的树节点
+ *
+ * @attention 无
+ * @param root [IN] 树的根节点指针
+ * @param nodeId [IN] 被删节点的key
+ * @param func [IN] 被删节点数据释放的函数指针
+ * @retval NULL 树中的节点都已删除
+ * @retval 非NULL 树或子树的根结点指针
+ */
+BSL_AvlTree *BSL_AVL_DeleteNode(BSL_AvlTree *root, uint64_t nodeId, BSL_AVL_DATA_FREE_FUNC func);
+
+/**
+ * @ingroup BSL
+ * @brief 删除树的所有节点
+ *
+ * @par 描述:
+ * 删除树的所有节点
+ *
+ * @attention 无
+ * @param root [IN] 树的根节点指针
+ * @param func [IN] 被删节点数据释放的函数指针
+ */
+void BSL_AVL_DeleteTree(BSL_AvlTree *root, BSL_AVL_DATA_FREE_FUNC func);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * Description: 错误码栈的实现
+ * Author: guzhou
+ * Create: 2022-02-11
+ */
+
+#include <stdbool.h>
+#include <inttypes.h>
+#include "securec.h"
+#include "bsl_log_internal.h"
+#include "sal_mem.h"
+#include "sal_threadlock.h"
+#include "avl.h"
+#include "bsl_errno.h"
+#include "bsl_binlog_id.h"
+#include "bsl_err_internal.h"
+#include "bsl_err.h"
+
+/* 错误信息栈大小 */
+#define SAL_MAX_ERROR_STACK 20
+
+/* 错误信息栈 */
+typedef struct {
+ /* 栈的当前指向位置,为-1时表示空栈 */
+ uint16_t bottom; // 栈底
+ uint16_t top; // 栈顶
+ uint32_t flag; // 用于保护错误栈不被清理,目前用于异步场景中
+
+ /* 存储特定线程的错误码信息 */
+ int32_t errorStack[SAL_MAX_ERROR_STACK];
+
+ /* 错误码的标记,用于部分清除、防侧信道 */
+ uint32_t errorFlags[SAL_MAX_ERROR_STACK];
+
+ /* 存储出错的文件名 */
+ const char *filename[SAL_MAX_ERROR_STACK];
+
+ /* 存储出错文件的行号 */
+ uint32_t line[SAL_MAX_ERROR_STACK];
+} ErrorCodeStack;
+
+/* 错误栈的avl树根节点 */
+static BSL_AvlTree *g_avlRoot = NULL;
+
+/* 当前avl节点数量 */
+static uint32_t g_avlNodeCount = 0;
+
+/* avl树所允许的最大节点数 */
+static uint32_t g_maxAvlNodes = 0x0000FFFF;
+
+/* 线程锁的句柄 */
+static BSL_SAL_ThreadLockHandle g_errLock;
+
+static void StackReset(ErrorCodeStack *stack)
+{
+ if (stack != NULL) {
+ (void)memset_s(stack, sizeof(*stack), 0, sizeof(*stack));
+ }
+}
+
+static void StackResetIndex(ErrorCodeStack *stack, uint32_t i)
+{
+ bool invalid = stack == NULL || i >= SAL_MAX_ERROR_STACK;
+ if (!invalid) {
+ stack->errorStack[i] = 0;
+ stack->line[i] = 0;
+ stack->filename[i] = NULL;
+ stack->errorFlags[i] = 0;
+ }
+}
+
+static void StackDataFree(BSL_ElementData data)
+{
+ SAL_FREE(data);
+}
+
+static ErrorCodeStack *GetStack(void)
+{
+ const uint64_t threadId = SAL_ThreadGetId();
+ BSL_AvlTree *curNode = BSL_AVL_SearchNode(g_avlRoot, threadId);
+ if (curNode != NULL) {
+ return curNode->data; // 已有错误栈直接返回
+ }
+ // 需要新建错误栈
+ if (g_avlNodeCount >= g_maxAvlNodes) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05005, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "New Avl Node failed.", 0, 0, 0, 0);
+ return NULL;
+ }
+ ErrorCodeStack *stack = (ErrorCodeStack *)SAL_CALLOC(1, sizeof(ErrorCodeStack));
+ if (stack == NULL) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05004, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "CALLOC error code stack failed", 0, 0, 0, 0);
+ return NULL;
+ }
+ BSL_AvlTree *node = BSL_AVL_MakeLeafNode(stack);
+ if (node == NULL) {
+ StackDataFree(stack);
+ LOG_BINLOG_FIXLEN(BINLOG_ID05006, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "avl insert node failed, threadId %"PRIu64, threadId, 0, 0, 0);
+ return NULL;
+ }
+ g_avlNodeCount++;
+ g_avlRoot = BSL_AVL_InsertNode(g_avlRoot, threadId, node); /* 上层已经保证threadId节点不存在 */
+ return stack;
+}
+
+void BSL_ERR_PushError(int32_t err, const char *file, uint32_t lineNo)
+{
+ if (err == BSL_SUCCESS) {
+ return; // 不允许push success
+ }
+
+ const uint64_t threadId = SAL_ThreadGetId();
+
+ int32_t ret = SAL_ThreadWriteLock(g_errLock);
+ if (ret != BSL_SUCCESS) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05007, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "acquire lock failed when pushing error, threadId %"PRIu64", error code %d", threadId, ret, 0, 0);
+ return;
+ }
+
+ ErrorCodeStack *stack = GetStack();
+ if (stack != NULL) {
+ if (stack->top == stack->bottom && stack->errorStack[stack->top] != 0) {
+ stack->bottom = (stack->bottom + 1) % SAL_MAX_ERROR_STACK;
+ }
+ stack->errorFlags[stack->top] = 0;
+ stack->errorStack[stack->top] = err;
+ stack->filename[stack->top] = file;
+ stack->line[stack->top] = lineNo;
+ stack->top = (stack->top + 1) % SAL_MAX_ERROR_STACK;
+ }
+
+ SAL_ThreadUnlock(g_errLock);
+}
+
+void BSL_ERR_ClearError(void)
+{
+ uint64_t threadId = SAL_ThreadGetId();
+ int32_t ret = SAL_ThreadWriteLock(g_errLock);
+ if (ret != BSL_SUCCESS) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05008, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "acquire lock failed when clearing error, threadId %"PRIu64, threadId, 0, 0, 0);
+ return;
+ }
+
+ BSL_AvlTree *curNode = BSL_AVL_SearchNode(g_avlRoot, threadId);
+ if (curNode != NULL) {
+ ErrorCodeStack *errStack = curNode->data;
+ if (errStack->flag == 0) {
+ StackReset(errStack);
+ }
+ }
+
+ SAL_ThreadUnlock(g_errLock);
+}
+
+void BSL_ERR_RemoveErrorStack(bool isRemoveAll)
+{
+ int32_t ret = SAL_ThreadWriteLock(g_errLock);
+ if (ret != BSL_SUCCESS) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05009, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "acquire lock failed when removing error stack, threadId %"PRIu64, SAL_ThreadGetId(), 0, 0, 0);
+ return;
+ }
+
+ if (g_avlRoot != NULL) {
+ if (isRemoveAll) {
+ BSL_AVL_DeleteTree(g_avlRoot, StackDataFree);
+ g_avlNodeCount = 0;
+ g_avlRoot = NULL;
+ } else {
+ uint64_t threadId = SAL_ThreadGetId();
+ BSL_AvlTree *curNode = BSL_AVL_SearchNode(g_avlRoot, threadId);
+ if (curNode != NULL) {
+ g_avlNodeCount--;
+ g_avlRoot = BSL_AVL_DeleteNode(g_avlRoot, threadId, StackDataFree);
+ }
+ }
+ }
+
+ SAL_ThreadUnlock(g_errLock);
+}
+
+// 获取索引,last表示获取最后一个错误码或第一个错误码
+uint16_t GetIndex(ErrorCodeStack *errStack, bool last)
+{
+ uint16_t idx;
+
+ if (last) {
+ idx = errStack->top - 1;
+ if (idx >= SAL_MAX_ERROR_STACK) {
+ idx = SAL_MAX_ERROR_STACK - 1;
+ }
+ } else {
+ idx = errStack->bottom;
+ }
+
+ return idx;
+}
+
+// clr为true表示外部操作是get,false表示外部操作是peek
+// get操作会在获取错误信息后清理,而peek操作则不会
+// last为true表示获取栈顶的最后一个错误码,false表示获取栈底的第一个错误码
+static int32_t GetErrorInfo(const char **file, uint32_t *lineNo, bool clr, bool last)
+{
+ uint16_t idx;
+
+ int32_t ret = SAL_ThreadReadLock(g_errLock);
+ if (ret != BSL_SUCCESS) {
+ return BSL_ERR_ERR_ACQUIRE_READ_LOCK_FAIL;
+ }
+
+ if (g_avlRoot == NULL) {
+ /* 如果avlRoot为空,说明没有任何线程push error,所以error理应为success */
+ SAL_ThreadUnlock(g_errLock);
+ return BSL_SUCCESS;
+ }
+
+ const uint64_t threadId = SAL_ThreadGetId();
+ BSL_AvlTree *curNode = BSL_AVL_SearchNode(g_avlRoot, threadId);
+ if (curNode == NULL) {
+ /* 如果curNode为空,说明当前线程没有push error,所以error理应为success */
+ SAL_ThreadUnlock(g_errLock);
+ return BSL_SUCCESS;
+ }
+
+ ErrorCodeStack *errStack = curNode->data; // 不会为NULL
+
+ idx = GetIndex(errStack, last);
+ if (errStack->errorStack[idx] == 0) { // 错误栈为空
+ SAL_ThreadUnlock(g_errLock);
+ return BSL_SUCCESS;
+ }
+
+ int32_t errorCode = errStack->errorStack[idx]; /* 获取指定的错误号 */
+ uint32_t fileLine = errStack->line[idx]; /* 获取指定的行号 */
+ const char *f = errStack->filename[idx]; // 获取指定的文件名
+ if (clr) { // get or peek?
+ StackResetIndex(errStack, idx);
+ if (last) {
+ errStack->top = idx;
+ } else {
+ errStack->bottom = (idx + 1) % SAL_MAX_ERROR_STACK;
+ }
+ }
+
+ SAL_ThreadUnlock(g_errLock);
+
+ if (file != NULL && lineNo != NULL) { // 这两一起,只获得其中一个没有意义
+ if (f == NULL) {
+ *file = "NA";
+ *lineNo = 0;
+ } else {
+ *file = f;
+ *lineNo = fileLine;
+ }
+ }
+
+ return errorCode;
+}
+
+static int32_t GetLastErrorInfo(const char **file, uint32_t *lineNo, bool clr)
+{
+ return GetErrorInfo(file, lineNo, clr, true);
+}
+
+static int32_t GetFirstErrorInfo(const char **file, uint32_t *lineNo, bool clr)
+{
+ return GetErrorInfo(file, lineNo, clr, false);
+}
+
+int32_t BSL_ERR_GetLastErrorFileLine(const char **file, uint32_t *lineNo)
+{
+ return GetLastErrorInfo(file, lineNo, true);
+}
+
+int32_t BSL_ERR_PeekLastErrorFileLine(const char **file, uint32_t *lineNo)
+{
+ return GetLastErrorInfo(file, lineNo, false);
+}
+
+int32_t BSL_ERR_GetLastError(void)
+{
+ return GetLastErrorInfo(NULL, NULL, true);
+}
+
+int32_t BSL_ERR_GetErrorFileLine(const char **file, uint32_t *lineNo)
+{
+ return GetFirstErrorInfo(file, lineNo, true);
+}
+
+int32_t BSL_ERR_PeekErrorFileLine(const char **file, uint32_t *lineNo)
+{
+ return GetFirstErrorInfo(file, lineNo, false);
+}
+
+int32_t BSL_ERR_GetError(void)
+{
+ return GetFirstErrorInfo(NULL, NULL, true);
+}
+
+int32_t BSL_ERR_Init(void)
+{
+ if (g_errLock != NULL) {
+ return BSL_SUCCESS;
+ }
+ int32_t ret = SAL_ThreadLockNew(&g_errLock);
+ return ret;
+}
+
+void BSL_ERR_DeInit(void)
+{
+ if (g_errLock == NULL) {
+ return;
+ }
+ SAL_ThreadLockFree(g_errLock);
+ g_errLock = NULL;
+}
--- /dev/null
+/**
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief BSL模块的打点日志点号id
+ */
+
+#ifndef BSL_BINLOG_ID_H
+#define BSL_BINLOG_ID_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum BSL_BINLOG_ID {
+ BINLOG_ID05001 = 5001, BINLOG_ID05002, BINLOG_ID05003, BINLOG_ID05004, BINLOG_ID05005,
+ BINLOG_ID05006, BINLOG_ID05007, BINLOG_ID05008, BINLOG_ID05009, BINLOG_ID05010,
+ BINLOG_ID05011, BINLOG_ID05012, BINLOG_ID05013, BINLOG_ID05014, BINLOG_ID05015,
+ BINLOG_ID05016, BINLOG_ID05017, BINLOG_ID05018, BINLOG_ID05019, BINLOG_ID05020,
+ BINLOG_ID05021, BINLOG_ID05022, BINLOG_ID05023, BINLOG_ID05024, BINLOG_ID05025,
+ BINLOG_ID05026, BINLOG_ID05027, BINLOG_ID05028, BINLOG_ID05029, BINLOG_ID05030,
+ BINLOG_ID05031, BINLOG_ID05032, BINLOG_ID05033, BINLOG_ID05034, BINLOG_ID05035,
+ BINLOG_ID05036, BINLOG_ID05037, BINLOG_ID05038, BINLOG_ID05039, BINLOG_ID05040,
+ BINLOG_ID05041, BINLOG_ID05042, BINLOG_ID05043, BINLOG_ID05044, BINLOG_ID05045,
+ BINLOG_ID05046, BINLOG_ID05047, BINLOG_ID05048, BINLOG_ID05049, BINLOG_ID05050,
+ BINLOG_ID05051, BINLOG_ID05052, BINLOG_ID05053, BINLOG_ID05054, BINLOG_ID05055,
+ BINLOG_ID05056, BINLOG_ID05057, BINLOG_ID05058, BINLOG_ID05059, BINLOG_ID05060,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief 字节流的编解码接口
+ */
+
+#ifndef BSL_BYTES_H
+#define BSL_BYTES_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief uint8_t 字节流转 uint16_t 类型数据
+ *
+ * @attention data 不能为空
+ *
+ * @param data [IN] uint8_t 字节流
+ *
+ * @return uint16_t,转换后的数据
+ */
+static inline uint16_t BSL_ByteToUint16(const uint8_t *data)
+{
+ /** 第0字节左移8位,第1字节不变,或操作后得到 uint16_t */
+ return ((uint16_t)data[0] << 8) | ((uint16_t)data[1]);
+}
+
+/**
+ * @brief uint16_t 类型数据转 uint8_t 字节流
+ *
+ * @attention data 不能为空
+ *
+ * @param num [IN] 待转换的数据
+ * @param data [OUT] 转换后的数据
+ */
+static inline void BSL_Uint16ToByte(uint16_t num, uint8_t *data)
+{
+ /** 转换到字节流 */
+ data[0] = (uint8_t)(num >> 8); // 数据右移8位,放到第0字节
+ data[1] = (uint8_t)(num & 0xffu); // 数据与上0xffu,放到第1字节
+ return;
+}
+
+/**
+ * @brief uint8_t 字节流转 uint24_t 类型数据
+ *
+ * @attention data 不能为空
+ *
+ * @param data [IN] uint8_t 字节流
+ *
+ * @return uint24_t,转换后的数据
+ */
+static inline uint32_t BSL_ByteToUint24(const uint8_t *data)
+{
+ /** 第0字节左移16位,第1字节左移8位,第2字节不变,或操作后得到 uint24_t */
+ return ((uint32_t)data[0] << 16) | ((uint32_t)data[1] << 8) | ((uint32_t)data[2]);
+}
+
+/**
+ * @brief uint24_t 类型数据转 uint8_t 字节流
+ *
+ * @attention data 不能为空
+ *
+ * @param num [IN] 待转换的数据
+ * @param data [OUT] 转换后的数据
+ */
+static inline void BSL_Uint24ToByte(uint32_t num, uint8_t *data)
+{
+ /** 转换到字节流 */
+ data[0] = (uint8_t)(num >> 16); // 数据右移16位,放到第0字节
+ data[1] = (uint8_t)(num >> 8); // 数据右移8位,放到第1字节
+ data[2] = (uint8_t)(num & 0xffu); // 数据与上0xffu,放到第2字节
+ return;
+}
+
+/**
+ * @brief uint8_t 字节流转 uint32_t 类型数据
+ *
+ * @attention data 不能为空
+ *
+ * @param data [IN] uint8_t 字节流
+ *
+ * @return uint32_t,转换后的数据
+ */
+static inline uint32_t BSL_ByteToUint32(const uint8_t *data)
+{
+ /** 第0字节左移24位,第1字节左移16位,第2字节左移8位,第3字节不变,或操作后得到 uint32_t */
+ return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | ((uint32_t)data[3]);
+}
+
+/**
+ * @brief uint8_t 字节流转 uint48_t 类型数据
+ *
+ * @attention data 不能为空
+ *
+ * @param data [IN] uint8_t 字节流
+ *
+ * @return uint48_t,转换后的数据
+ */
+static inline uint64_t BSL_ByteToUint48(const uint8_t *data)
+{
+ /** 第0字节左移40位,第1字节左移32位,第2字节左移24位,第3字节左移16位,第4字节左移8位,第5字节不变,
+ 或操作后得到 uint48_t */
+ return ((uint64_t)data[0] << 40) | ((uint64_t)data[1] << 32) | ((uint64_t)data[2] << 24) |
+ ((uint64_t)data[3] << 16) | ((uint64_t)data[4] << 8) | ((uint64_t)data[5]);
+}
+
+/**
+ * @brief uint48_t 类型数据转 uint8_t 字节流
+ *
+ * @attention data 不能为空
+ *
+ * @param num [IN] 待转换的数据
+ * @param data [OUT] 转换后的数据
+ */
+static inline void BSL_Uint48ToByte(uint64_t num, uint8_t *data)
+{
+ /** 转换到字节流 */
+ data[0] = (uint8_t)(num >> 40); // 数据右移40位,放到第0字节
+ data[1] = (uint8_t)(num >> 32); // 数据右移32位,放到第1字节
+ data[2] = (uint8_t)(num >> 24); // 数据右移24位,放到第2字节
+ data[3] = (uint8_t)(num >> 16); // 数据右移16位,放到第3字节
+ data[4] = (uint8_t)(num >> 8); // 数据右移8位,放到第4字节
+ data[5] = (uint8_t)(num & 0xffu); // 数据与上0xffu,放到第5字节
+ return;
+}
+
+/**
+ * @brief uint8_t 字节流转 uint64_t 类型数据
+ *
+ * @attention data 不能为空
+ *
+ * @param data [IN] uint8_t 字节流
+ *
+ * @return uint32_t,转换后的数据
+ */
+static inline uint64_t BSL_ByteToUint64(const uint8_t *data)
+{
+ /** 第0字节左移56位,第1字节左移48位,第2字节左移40位,第3字节左移32位,第4字节左移24位,第5字节左移16位,
+ 第6字节左移8位,第7字节不变,或操作后得到 uint64_t */
+ return ((uint64_t)data[0] << 56) | ((uint64_t)data[1] << 48) | ((uint64_t)data[2] << 40) |
+ ((uint64_t)data[3] << 32) | ((uint64_t)data[4] << 24) | ((uint64_t)data[5] << 16) |
+ ((uint64_t)data[6] << 8) | ((uint64_t)data[7]);
+}
+
+/**
+ * @brief uint32_t 类型数据转 uint8_t 字节流
+ *
+ * @attention data 不能为空
+ *
+ * @param num [IN] 待转换的数据
+ * @param data [OUT] 转换后的数据
+ */
+static inline void BSL_Uint32ToByte(uint32_t num, uint8_t *data)
+{
+ /** 转换到字节流 */
+ data[0] = (uint8_t)(num >> 24); // 数据右移24位,放到第0字节
+ data[1] = (uint8_t)(num >> 16); // 数据右移16位,放到第1字节
+ data[2] = (uint8_t)(num >> 8); // 数据右移8位,放到第2字节
+ data[3] = (uint8_t)(num & 0xffu); // 数据与上0xffu,放到第3字节
+ return;
+}
+
+/**
+ * @brief uint64_t 类型数据转 uint8_t 字节流
+ *
+ * @attention data 不能为空
+ *
+ * @param num [IN] 待转换的数据
+ * @param data [OUT] 转换后的数据
+ */
+static inline void BSL_Uint64ToByte(uint64_t num, uint8_t *data)
+{
+ /** 转换到字节流 */
+ data[0] = (uint8_t)(num >> 56); // 数据右移56位,放到第0字节
+ data[1] = (uint8_t)(num >> 48); // 数据右移48位,放到第1字节
+ data[2] = (uint8_t)(num >> 40); // 数据右移40位,放到第2字节
+ data[3] = (uint8_t)(num >> 32); // 数据右移32位,放到第3字节
+ data[4] = (uint8_t)(num >> 24); // 数据右移24位,放到第4字节
+ data[5] = (uint8_t)(num >> 16); // 数据右移16位,放到第5字节
+ data[6] = (uint8_t)(num >> 8); // 数据右移8位,放到第6字节
+ data[7] = (uint8_t)(num & 0xffu); // 数据与上0xffu,放到第7字节
+ return;
+}
+
+#ifdef __cplusplus
+}
+#endif /* end __cplusplus */
+
+#endif // BSL_BYTES_H
--- /dev/null
+/**
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief 链表操作
+ */
+
+#ifndef BSL_LIST_H
+#define BSL_LIST_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * 该结构被用来保存双向链表中节点的前向指针和后向指针。
+ * 这个链表不包含实质的数据区,一般用于组织(串接)数据节点
+ */
+typedef struct ListHeadNode {
+ struct ListHeadNode *next, *prev;
+} ListHead;
+
+/**
+ * @brief 初始化链表(链表重用时的初始化)
+ *
+ * @param head [IN] 链表头结点的地址(The address of the head of a list )
+ */
+#define LIST_INIT(head) (head)->next = (head)->prev = (head)
+
+/**
+ * @brief 将节点item插入到节点where之后
+ 变化前: where->A->B 变化后: where->item->A->B
+ *
+ * @param where [IN] item插入后的前一个节点地址。(The address where the item will be inserted after)
+ * @param item [IN] 待插入节点地址(The address of the item)
+ */
+#define LIST_ADD_AFTER(where, item) do { \
+ (item)->next = (where)->next; \
+ (item)->prev = (where); \
+ (where)->next = (item); \
+ (item)->next->prev = (item); \
+} while (0)
+
+/**
+ * @brief 将节点item插入到节点where之前
+ * 变化前: A->where->B 变化后: A->item->where->B
+ *
+ * @param where [IN] item插入后的后一个节点地址。(The address where the item will be inserted before)
+ * @param item [IN] 待插入节点地址(The address of the item)
+ */
+#define LIST_ADD_BEFORE(where, item) LIST_ADD_AFTER((where)->prev, (item))
+
+/**
+ * @brief 删除节点item
+ *
+ * @param item [IN] 待删除的节点(The address of the item to be removed)
+ */
+#define LIST_REMOVE(item) do { \
+ (item)->prev->next = (item)->next; \
+ (item)->next->prev = (item)->prev; \
+} while (0)
+
+/**
+ * @brief 检查链表是否为空(Judge whether a list is empty)
+ *
+ * @param head [IN] 需要检查的链表(The address of the list to be judged)
+ */
+#define LIST_IS_EMPTY(head) ((head)->next == (head))
+
+/**
+ * @brief 安全遍历一个链表(Travel through a list safety)
+ *
+ * @param head [IN] 需要遍历的链表(The head of a list)
+ * @param temp [IN] 指向当前节点以便安全删除当前节点(pointer used to save current item so you can free item safety)
+ * @param item [IN] 遍历链表所用的缓存节点(A temporary list item for travelling the list)
+ */
+#define LIST_FOR_EACH_ITEM_SAFE(item, temp, head) \
+ for ((item) = (head)->next, (temp) = (item)->next; (item) != (head); (item) = (temp), (temp) = (item)->next)
+
+/**
+ * @brief 通过链表某个节点(小结点)找到该节点所在结构(大节点)的起始地址
+ *
+ * @param item [IN] 特定节点变量(The address of a list item)
+ * @param type [IN] 包含链表节点的大节点类型(The type of a struct which includes the list item)
+ * @param member [IN] 结构体内的list节点成员名称(The member variable of the struct whose type is list item)
+ *
+ * 说明:
+ * 每个结构变量形成一个一个的大节点(包含数据和list小结点), 大节点是通过list 这个链表(小节点)串起来的。
+ * --------- --------- --------- -- ----
+ * | pre |<---| pre |<---| pre | |==>小结点 |
+ * | next |--->| next |--->| next | | |
+ * --------- --------- --------- -- | ===> 大节点
+ * | data1 | | data1 | | data1 | |
+ * | data2 | | data2 | | data2 | |
+ * --------- --------- --------- ----
+ * 不直接用list作为大节点的原因是 list(ListHead 类型)只有头尾指针,不包含数据区。
+ * 这样 list链表可以适用挂接任意个数据的场合,具有通用性。
+ */
+#define LIST_ENTRY(item, type, member) \
+ ((type *)((uintptr_t)(char *)(item) - (uintptr_t)(&((type *)0)->member)))
+
+#ifdef __cplusplus
+}
+#endif
+#endif // BSL_LIST_H
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file bsl_log_internal.h
+ * Description: 日志模块
+ * Author: guzhou
+ * Create: 2022-02-11
+ */
+
+#ifndef BSL_LOG_INTERNAL_H
+#define BSL_LOG_INTERNAL_H
+
+#include <stdint.h>
+#include "bsl_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void LOG_BinLogFixLen(uint32_t logId, uint32_t logLevel, uint32_t logType,
+ void *format, void *para1, void *para2, void *para3, void *para4);
+
+void LOG_BinLogVarLen(uint32_t logId, uint32_t logLevel, uint32_t logType, void *format, void *para);
+
+/**
+ * @ingroup BSL
+ * @brief 打点日志,format中只能含有不超过4个参数,参数中不能有%s
+ *
+ * @attention format中只能含有不超过4个参数,参数中不能有%s。不够4个参数要被0或NULL,多于4个参数则要多次调用本函数。
+ * 要打%s日志请使用LOG_BINLOG_FIXLEN。
+ * @param logId [IN] 点号id,每个点号id只能用一次
+ * @param level [IN] 日志级别
+ * @param logType [IN] 日志类别,目前仅有BSL_LOG_BINLOG_TYPE_RUN,为后续预留扩展
+ * @param format [IN] 仅含有1个%s的格式化字符串
+ * @param para [IN] 字符串指针
+ */
+#define LOG_BINLOG_FIXLEN(logId, logLevel, logType, format, para1, para2, para3, para4) \
+ LOG_BinLogFixLen(logId, logLevel, logType, \
+ (void *)(uintptr_t)(const void *)(format), (void *)(uintptr_t)(para1), (void *)(uintptr_t)(para2), \
+ (void *)(uintptr_t)(para3), (void *)(uintptr_t)(para4))
+
+/**
+ * @ingroup BSL
+ * @brief 打点日志,format中含有且只能含有1个%s
+ *
+ * @attention format中含有且只能含有1个%s,多个字符串打点则要多次调用本函数。
+ * 要打非%s的参数请使用LOG_BINLOG_FIXLEN。
+ * @param logId [IN] 点号id,每个点号id只能用一次
+ * @param level [IN] 日志级别
+ * @param logType [IN] 日志类别,目前仅有BSL_LOG_BINLOG_TYPE_RUN,为后续预留扩展
+ * @param format [IN] 仅含有1个%s的格式化字符串
+ * @param para [IN] 字符串指针
+ */
+#define LOG_BINLOG_VARLEN(logId, logLevel, logType, format, para) \
+ LOG_BinLogVarLen(logId, logLevel, logType, \
+ (void *)(uintptr_t)(const void *)(format), (void *)(uintptr_t)(const void *)(para))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BSL_LOG_INTERNAL_H
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * Description: 日志模块的实现,调用由产品注册的日志输出函数
+ * Author: guzhou
+ * Create: 2022-02-11
+ */
+
+#include <stdbool.h>
+#include "securec.h"
+#include "bsl_errno.h"
+#include "bsl_log_internal.h"
+
+/* HiTLS版本字符串 */
+static char g_hitlsVersion[HITLS_VERSION_LEN] = HITLS_VERSION;
+
+int32_t BSL_LOG_GetVersion(char *version, uint32_t *versionLen)
+{
+ if (version == NULL || versionLen == NULL) {
+ return BSL_LOG_ERR_BAD_PARAM;
+ }
+
+ if (*versionLen < HITLS_VERSION_LEN) {
+ return BSL_LOG_ERR_BAD_PARAM;
+ }
+
+ uint32_t len = (uint32_t)strlen(g_hitlsVersion);
+ if (memcpy_s(version, *versionLen, g_hitlsVersion, len) != EOK) {
+ return BSL_LOG_ERR_MEMCPY_FAIL;
+ }
+
+ *versionLen = len;
+ return BSL_SUCCESS;
+}
+
+static BSL_LOG_BinLogFixLenFunc g_fixLenFunc = NULL;
+static BSL_LOG_BinLogVarLenFunc g_varLenFunc = NULL;
+static uint32_t g_binlogLevel = BSL_LOG_LEVEL_ERR; // 默认开启error级
+static uint32_t g_binlogType = BSL_LOG_BINLOG_TYPE_RUN; // 默认开启run类型,可扩展增加其它类型
+
+int32_t BSL_LOG_RegBinLogFunc(const BSL_LOG_BinLogFuncs *funcs)
+{
+ bool invalid = funcs == NULL || funcs->fixLenFunc == NULL || funcs->varLenFunc == NULL;
+ if (invalid) {
+ return BSL_NULL_INPUT;
+ }
+ g_fixLenFunc = funcs->fixLenFunc;
+ g_varLenFunc = funcs->varLenFunc;
+ return BSL_SUCCESS;
+}
+
+int32_t BSL_LOG_SetBinLogLevel(uint32_t level)
+{
+ if (level > BSL_LOG_LEVEL_DEBUG) {
+ return BSL_LOG_ERR_BAD_PARAM;
+ }
+ g_binlogLevel = level;
+ return BSL_SUCCESS;
+}
+
+uint32_t BSL_LOG_GetBinLogLevel(void)
+{
+ return g_binlogLevel;
+}
+
+void LOG_BinLogFixLen(uint32_t logId, uint32_t logLevel, uint32_t logType,
+ void *format, void *para1, void *para2, void *para3, void *para4)
+{
+ bool invalid = (logLevel > g_binlogLevel) || ((logType & g_binlogType) == 0) || (g_fixLenFunc == NULL);
+ if (!invalid) {
+ g_fixLenFunc(logId, logLevel, logType, format, para1, para2, para3, para4);
+ }
+}
+
+void LOG_BinLogVarLen(uint32_t logId, uint32_t logLevel, uint32_t logType, void *format, void *para)
+{
+ bool invalid = (logLevel > g_binlogLevel) || ((logType & g_binlogType) == 0) || (g_varLenFunc == NULL);
+ if (!invalid) {
+ g_varLenFunc(logId, logLevel, logType, format, para);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file sal_mem.h
+ * Description: 内存模块
+ * Author: guzhou
+ * Create: 2022-02-11
+ */
+
+/** @defgroup SAL SAL子模块接口 */
+
+#ifndef SAL_MEM_H
+#define SAL_MEM_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup SAL
+ * @brief 分配内存空间
+ *
+ * @par 描述:
+ * 分配内存空间
+ *
+ * @attention 无
+ * @param size [IN] 分配内存的大小
+ * @return 申请成功返回指向内存的指针,NULL为申请失败
+ */
+void *SAL_Malloc(uint32_t size);
+
+/**
+ * @ingroup SAL
+ * @brief 分配内存空间并清零
+ *
+ * @par 描述:
+ * 分配内存空间并清零,最大分配UINT32_MAX大小的内存空间
+ *
+ * @attention num*size不应出现溢出回绕
+ * @param num [IN] 分配内存的数量
+ * @param size [IN] 每块内存的大小
+ * @return 申请成功返回指向内存的指针,NULL为申请失败或溢出回绕
+ */
+void *SAL_Calloc(uint32_t num, uint32_t size);
+
+/**
+ * @ingroup SAL
+ * @brief 拷贝内存空间
+ * @param src 源内存地址
+ * @param size 内存空间总大小
+ * @return 申请成功返回指向内存的指针,NULL为申请失败
+ */
+void *SAL_Dump(const void *src, uint32_t size);
+
+/**
+ * @ingroup SAL
+ * @brief 释放指定的内存
+ *
+ * @par 描述:
+ * 释放指定的内存
+ *
+ * @attention 无
+ * @param value [IN] 待释放的内存空间指针
+ */
+void SAL_Free(void *value);
+
+/**
+ * @ingroup SAL
+ * @brief 敏感信息置零
+ *
+ * @param ptr [IN] 要置零的内存
+ * @param size [IN] 要置零的内存的长度
+ *
+ * @return 无
+ */
+void SAL_CleanseData(void *ptr, uint32_t size);
+
+#define SAL_MALLOC(size_) SAL_Malloc((size_))
+
+#define SAL_CALLOC(num_, size_) SAL_Calloc((num_), (size_))
+
+#define SAL_DUMP(src_, size_) SAL_Dump((src_), (size_))
+
+#define SAL_FREE(value_) \
+ do { \
+ if ((value_) != NULL) { \
+ SAL_Free((void *)(value_)); \
+ (value_) = NULL; \
+ } \
+ } while (false)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file sal_threadlock.h
+ * Description: 线程锁模块
+ * Author: guzhou
+ * Create: 2022-02-11
+ */
+
+#ifndef SAL_THREADLOCK_H
+#define SAL_THREADLOCK_H
+
+#include <stdint.h>
+#include "bsl_sal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup SAL
+ * @brief 新建一个线程锁
+ *
+ * @par 描述:
+ * 新建一个线程锁,如果是单线程环境则总是返回成功
+ *
+ * @attention 无
+ * @param lock [IN/OUT] 锁句柄
+ * @retval #BSL_SUCCESS 新建成功,或者是单线程环境
+ * @retval #BSL_SAL_ERR_NO_MEMORY 内存空间不足,无法申请进程锁空间
+ * @retval #BSL_SAL_ERR_UNKNOWN 线程锁初始化失败
+ * @retval #BSL_SAL_ERR_BAD_PARAM 参数错误,lock为NULL
+ */
+int32_t SAL_ThreadLockNew(BSL_SAL_ThreadLockHandle *lock);
+
+/**
+ * @ingroup SAL
+ * @brief 锁住读操作
+ *
+ * @par 描述:
+ * 锁住读操作,如果是单线程环境则总是返回成功
+ *
+ * @attention 无
+ * @param lock [IN] 锁句柄
+ * @retval #BSL_SUCCESS 成功,或者是单线程环境
+ * @retval #BSL_SAL_ERR_UNKNOWN 操作失败
+ * @retval #BSL_SAL_ERR_BAD_PARAM 参数错误,lock为NULL
+ */
+int32_t SAL_ThreadReadLock(BSL_SAL_ThreadLockHandle lock);
+
+/**
+ * @ingroup SAL
+ * @brief 锁住写操作
+ *
+ * @par 描述:
+ * 锁住写操作,如果是单线程环境则总是返回成功
+ *
+ * @attention 无
+ * @param lock [IN] 锁句柄
+ * @retval #BSL_SUCCESS 成功,或者是单线程环境
+ * @retval #BSL_SAL_ERR_UNKNOWN 操作失败
+ * @retval #BSL_SAL_ERR_BAD_PARAM 参数错误,lock为NULL
+ */
+int32_t SAL_ThreadWriteLock(BSL_SAL_ThreadLockHandle lock);
+
+/**
+ * @ingroup SAL
+ * @brief 解锁
+ *
+ * @par 描述:
+ * 解锁,如果是单线程环境则总是返回成功
+ *
+ * @attention 无
+ * @param lock [IN] 锁句柄
+ * @retval #BSL_SUCCESS 成功,或者是单线程环境
+ * @retval #BSL_SAL_ERR_UNKNOWN 操作失败
+ * @retval #BSL_SAL_ERR_BAD_PARAM 参数错误,lock为NULL
+ */
+int32_t SAL_ThreadUnlock(BSL_SAL_ThreadLockHandle lock);
+
+/**
+ * @ingroup SAL
+ * @brief 释放线程锁
+ *
+ * @par 描述:
+ * 释放线程锁
+ *
+ * @attention 无
+ * @param lock [IN] 锁句柄
+ */
+void SAL_ThreadLockFree(BSL_SAL_ThreadLockHandle lock);
+
+/**
+ * @ingroup SAL
+ * @brief 获取线程id
+ *
+ * @par 描述:
+ * 获取线程id
+ *
+ * @attention 无
+ * @retval 线程id,单线程环境为0
+ */
+uint64_t SAL_ThreadGetId(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * Description: 内存分配、释放的实现,由产品注册内存分配、释放的函数
+ * Author: guzhou
+ * Create: 2022-02-11
+ */
+
+#include <stdlib.h>
+#include "securec.h"
+#include "bsl_log_internal.h"
+#include "bsl_sal.h"
+#include "bsl_errno.h"
+#include "bsl_binlog_id.h"
+#include "sal_mem.h"
+
+static BSL_SAL_MemCallback g_memCallback = {0};
+
+void *SAL_Malloc(uint32_t size)
+{
+ if (g_memCallback.pfMalloc == NULL) {
+ return NULL;
+ }
+ return g_memCallback.pfMalloc(size);
+}
+
+void SAL_Free(void *value)
+{
+ if (g_memCallback.pfFree == NULL) {
+ return;
+ }
+ g_memCallback.pfFree(value);
+}
+
+void *SAL_Calloc(uint32_t num, uint32_t size)
+{
+ if (num == 0 || size == 0) {
+ return SAL_Malloc(0);
+ }
+ if (num > UINT32_MAX / size) { // 按《华为C语言编程规范V5.1》G.INT.02处理回绕
+ return NULL;
+ }
+ uint32_t blockSize = num * size;
+ uint8_t *ptr = SAL_Malloc(blockSize);
+ if (ptr == NULL) {
+ return NULL;
+ }
+ // 大于SECUREC_MEM_MAX_LEN的话要分段处理,因为memset_s仅能处理SECUREC_MEM_MAX_LEN这么大的
+ uint32_t offset = 0;
+ while (blockSize > SECUREC_MEM_MAX_LEN) {
+ if (memset_s(&ptr[offset], SECUREC_MEM_MAX_LEN, 0, SECUREC_MEM_MAX_LEN) != EOK) {
+ SAL_FREE(ptr);
+ return NULL;
+ }
+ offset += SECUREC_MEM_MAX_LEN;
+ blockSize -= SECUREC_MEM_MAX_LEN;
+ }
+ if (memset_s(&ptr[offset], blockSize, 0, blockSize) != EOK) {
+ SAL_FREE(ptr);
+ return NULL;
+ }
+ return ptr;
+}
+
+void *SAL_Dump(const void *src, uint32_t size)
+{
+ if (g_memCallback.pfMalloc == NULL) {
+ return NULL;
+ }
+
+ void *ptr = g_memCallback.pfMalloc(size);
+ if (ptr == NULL) {
+ return NULL;
+ }
+
+ if (memcpy_s(ptr, size, src, size) != EOK) {
+ SAL_FREE(ptr);
+ return NULL;
+ }
+
+ return ptr;
+}
+
+int32_t BSL_SAL_RegMemCallback(BSL_SAL_MemCallback *cb)
+{
+ if ((cb == NULL) || (cb->pfMalloc == NULL) || (cb->pfFree == NULL)) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05011, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "invalid params", NULL, NULL, NULL, NULL);
+ return BSL_SAL_ERR_BAD_PARAM;
+ }
+ g_memCallback.pfMalloc = cb->pfMalloc;
+ g_memCallback.pfFree = cb->pfFree;
+ return BSL_SUCCESS;
+}
+
+#if !defined(__clang__)
+#pragma GCC push_options
+#pragma GCC optimize("O3")
+#endif
+#define CLEAN_THRESHOLD_SIZE 16UL
+
+static void CleanSensitiveDataLess16Byte(void *buf, uint32_t bufLen)
+{
+ uint8_t *tmp = (uint8_t *)buf;
+ switch (bufLen) {
+ case 16: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-16内存写0
+ /* FALLTHRU */
+ case 15: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-15内存写0
+ /* FALLTHRU */
+ case 14: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-14内存写0
+ /* FALLTHRU */
+ case 13: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-13内存写0
+ /* FALLTHRU */
+ case 12: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-12内存写0
+ /* FALLTHRU */
+ case 11: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-11内存写0
+ /* FALLTHRU */
+ case 10: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-10内存写0
+ /* FALLTHRU */
+ case 9: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-9内存写0
+ /* FALLTHRU */
+ case 8: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-8内存写0
+ /* FALLTHRU */
+ case 7: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-7内存写0
+ /* FALLTHRU */
+ case 6: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-6内存写0
+ /* FALLTHRU */
+ case 5: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-5内存写0
+ /* FALLTHRU */
+ case 4: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-4内存写0
+ /* FALLTHRU */
+ case 3: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-3内存写0
+ /* FALLTHRU */
+ case 2: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-2内存写0
+ /* FALLTHRU */
+ case 1: *(tmp++) = (uint8_t)0; // fall-through, 对第bufLen-1内存写0
+ /* FALLTHRU */
+ default: /* Do nothing */
+ break;
+ }
+}
+
+static void CleanSensitiveData(void *buf, uint32_t bufLen)
+{
+ uint8_t *tmp = (uint8_t *)buf;
+ uint32_t boundOpt;
+
+ if (((uintptr_t)buf & 0x3) == 0) { // buf & 0x3,用于判断是否是4字节对齐
+ boundOpt = (bufLen >> 4) << 4; // 右移4bit再左移4bit,用于计算16的整数倍
+ for (uint32_t i = 0; i < boundOpt; i += 16) { // 每次清零16片内存
+ uint32_t *ctmp = (uint32_t *)(tmp + i);
+ ctmp[0] = 0;
+ ctmp[1] = 0; // 对i + 1内存进行清零
+ ctmp[2] = 0; // 对i + 2内存进行清零
+ ctmp[3] = 0; // 对i + 3内存进行清零
+ }
+ } else {
+ boundOpt = (bufLen >> 2) << 2; // 右移2bit再左移2bit,用于计算4的整数倍
+ for (uint32_t i = 0; i < boundOpt; i += 4) { // 每次清零4片内存
+ tmp[i] = 0;
+ tmp[i + 1] = 0; // 对i + 1内存进行清零
+ tmp[i + 2] = 0; // 对i + 2内存进行清零
+ tmp[i + 3] = 0; // 对i + 3内存进行清零
+ }
+ }
+ for (uint32_t i = boundOpt; i < bufLen; ++i) {
+ tmp[i] = 0;
+ }
+}
+
+void SAL_CleanseData(void *ptr, uint32_t size)
+{
+ if (ptr == NULL) {
+ return;
+ }
+ if (size > CLEAN_THRESHOLD_SIZE) {
+ CleanSensitiveData(ptr, size);
+ } else {
+ CleanSensitiveDataLess16Byte(ptr, size);
+ }
+}
+
+#if !defined(__clang__)
+#pragma GCC pop_options
+#endif
--- /dev/null
+/**
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * Description: 线程锁接口的实现,由产品注册线程相关的函数
+ * Author: guzhou
+ * Create: 2022-02-11
+ */
+
+#include <stddef.h>
+#include "bsl_log_internal.h"
+#include "bsl_errno.h"
+#include "bsl_binlog_id.h"
+#include "sal_threadlock.h"
+
+static BSL_SAL_ThreadCallback g_threadCallback = {0};
+
+/* 线程功能可裁剪,若产品不注册线程相关函数,视为使用单线程,线程相关函数默认返回成功 */
+
+int32_t SAL_ThreadLockNew(BSL_SAL_ThreadLockHandle *lock)
+{
+ if (g_threadCallback.pfThreadLockNew == NULL) {
+ return BSL_SUCCESS;
+ }
+ if (lock == NULL) {
+ return BSL_SAL_ERR_BAD_PARAM;
+ }
+ return g_threadCallback.pfThreadLockNew(lock);
+}
+
+int32_t SAL_ThreadReadLock(BSL_SAL_ThreadLockHandle lock)
+{
+ if (g_threadCallback.pfThreadReadLock == NULL) {
+ return BSL_SUCCESS;
+ }
+ if (lock == NULL) {
+ return BSL_SAL_ERR_BAD_PARAM;
+ }
+ return g_threadCallback.pfThreadReadLock(lock);
+}
+
+int32_t SAL_ThreadWriteLock(BSL_SAL_ThreadLockHandle lock)
+{
+ if (g_threadCallback.pfThreadWriteLock == NULL) {
+ return BSL_SUCCESS;
+ }
+ if (lock == NULL) {
+ return BSL_SAL_ERR_BAD_PARAM;
+ }
+ return g_threadCallback.pfThreadWriteLock(lock);
+}
+
+int32_t SAL_ThreadUnlock(BSL_SAL_ThreadLockHandle lock)
+{
+ if (g_threadCallback.pfThreadUnlock == NULL) {
+ return BSL_SUCCESS;
+ }
+ if (lock == NULL) {
+ return BSL_SAL_ERR_BAD_PARAM;
+ }
+ return g_threadCallback.pfThreadUnlock(lock);
+}
+
+void SAL_ThreadLockFree(BSL_SAL_ThreadLockHandle lock)
+{
+ if (g_threadCallback.pfThreadLockFree == NULL) {
+ return;
+ }
+ if (lock == NULL) {
+ return;
+ }
+ g_threadCallback.pfThreadLockFree(lock);
+}
+
+uint64_t SAL_ThreadGetId(void)
+{
+ if (g_threadCallback.pfThreadGetId == NULL) {
+ return 0;
+ }
+ return g_threadCallback.pfThreadGetId();
+}
+
+int32_t BSL_SAL_RegThreadCallback(BSL_SAL_ThreadCallback *cb)
+{
+ if ((cb == NULL) || (cb->pfThreadLockNew == NULL) || (cb->pfThreadLockFree == NULL) ||
+ (cb->pfThreadReadLock == NULL) || (cb->pfThreadWriteLock == NULL) ||
+ (cb->pfThreadUnlock == NULL) || (cb->pfThreadGetId == NULL)) {
+ LOG_BINLOG_FIXLEN(BINLOG_ID05012, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
+ "invalid params", NULL, NULL, NULL, NULL);
+ return BSL_SAL_ERR_BAD_PARAM;
+ }
+ g_threadCallback.pfThreadLockNew = cb->pfThreadLockNew;
+ g_threadCallback.pfThreadLockFree = cb->pfThreadLockFree;
+ g_threadCallback.pfThreadReadLock = cb->pfThreadReadLock;
+ g_threadCallback.pfThreadWriteLock = cb->pfThreadWriteLock;
+ g_threadCallback.pfThreadUnlock = cb->pfThreadUnlock;
+ g_threadCallback.pfThreadGetId = cb->pfThreadGetId;
+ return BSL_SUCCESS;
+}
--- /dev/null
+/**
+ * @defgroup crypt_aes crypt_aes.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief AES加解密接口
+ */
+#ifndef CRYPT_AES_H
+#define CRYPT_AES_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define CRYPT_AES_MAX_ROUNDS 14
+#define CRYPT_AES_MAX_KEYLEN (4 * (CRYPT_AES_MAX_ROUNDS + 1))
+
+/**
+ * @ingroup CRYPT_AES_Key
+ *
+ * aes 密钥结构体
+ */
+typedef struct {
+ uint32_t key[CRYPT_AES_MAX_KEYLEN];
+ uint32_t rounds;
+} CRYPT_AES_Key;
+
+/**
+ * @ingroup aes
+ * @brief 设置AES加密秘钥。
+ *
+ * @param ctx [IN] AES 句柄
+ * @param key [IN] 加密密钥
+ * @param len [IN] 秘钥长度,为128。
+*/
+int32_t CRYPT_AES_SetEncryptKey128(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len);
+/**
+ * @ingroup aes
+ * @brief 设置AES加密秘钥。
+ *
+ * @param ctx [IN] AES 句柄
+ * @param key [IN] 加密密钥
+ * @param len [IN] 秘钥长度,为192。
+*/
+int32_t CRYPT_AES_SetEncryptKey192(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len);
+/**
+ * @ingroup aes
+ * @brief 设置AES加密秘钥。
+ *
+ * @param ctx [IN] AES 句柄
+ * @param key [IN] 加密密钥
+ * @param len [IN] 秘钥长度,为256。
+*/
+int32_t CRYPT_AES_SetEncryptKey256(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len);
+/**
+ * @ingroup aes
+ * @brief 设置AES解密秘钥。
+ *
+ * @param ctx [IN] AES 句柄
+ * @param key [IN] 解密密钥
+ * @param len [IN] 秘钥长度,为128
+*/
+int32_t CRYPT_AES_SetDecryptKey128(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len);
+/**
+ * @ingroup aes
+ * @brief 设置AES解密秘钥。
+ *
+ * @param ctx [IN] AES 句柄
+ * @param key [IN] 解密密钥
+ * @param len [IN] 秘钥长度,为192
+*/
+int32_t CRYPT_AES_SetDecryptKey192(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len);
+/**
+ * @ingroup aes
+ * @brief 设置AES解密秘钥。
+ *
+ * @param ctx [IN] AES 句柄
+ * @param key [IN] 解密密钥
+ * @param len [IN] 秘钥长度,可以为256。
+*/
+int32_t CRYPT_AES_SetDecryptKey256(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len);
+/**
+ * @ingroup aes
+ * @brief AES加密。
+ *
+ * @param ctx [IN] AES句柄,存有密钥
+ * @param in [IN] 输入明文数据,需为16字节。
+ * @param out [OUT] 输出密文数据,长度为16字节。
+ * @param len [IN] 块长度。
+*/
+int32_t CRYPT_AES_Encrypt(const CRYPT_AES_Key *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+/**
+ * @ingroup aes
+ * @brief AES解密。
+ *
+ * @param ctx [IN] AES句柄,存有密钥
+ * @param in [IN] 输入密文数据,需为16字节。
+ * @param out [OUT] 输出明文数据,长度为16字节。
+ * @param len [IN] 块长度,长度为16。
+*/
+int32_t CRYPT_AES_Decrypt(const CRYPT_AES_Key *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+/**
+ * @ingroup aes
+ * @brief 清除aes密钥信息
+ *
+ * @param ctx [IN] AES句柄,存有密钥
+ * @return void
+*/
+void CRYPT_AES_Clean(CRYPT_AES_Key *ctx);
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_aes.c
+ * Description: 提供AES算法实现
+ * Author: mayihui
+ * Create: 2022-5-5
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-5-5 mayihui 提供AES算法实现
+ */
+#include "crypt_aes.h"
+#include "securec.h"
+#include "bsl_err_internal.h"
+#include "crypt_utils.h"
+#include "crypt_errno.h"
+#include "sal_mem.h"
+
+#define SSEARCH(t0, t1, t2, t3) \
+ (((uint32_t)S[((t0) >> 24)] << 24) ^ ((uint32_t)S[((t1) >> 16) & 0xff] << 16) ^ \
+ ((uint32_t)S[((t2) >> 8) & 0xff] << 8) ^ ((uint32_t)S[(t3) & 0xff]))
+
+#define INVSSEARCH(t0, t1, t2, t3) \
+ (((uint32_t)INV_S[((t0) >> 24)] << 24) ^ ((uint32_t)INV_S[((t3) >> 16) & 0xff] << 16) ^ \
+ ((uint32_t)INV_S[((t2) >> 8) & 0xff] << 8) ^ ((uint32_t)INV_S[(t1) & 0xff]))
+
+/* S盒 来源于 FIPS 197 Figure 7. S-box */
+static const uint8_t S[256] = {
+ 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U,
+ 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U,
+ 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U,
+ 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U,
+ 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U,
+ 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU,
+ 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U,
+ 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U,
+ 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U,
+ 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU,
+ 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U,
+ 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U,
+ 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU,
+ 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU,
+ 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU,
+ 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U,
+};
+/* 逆S盒 来源于 FIPS 197 Figure 14. Inverse S-box */
+static const uint8_t INV_S[256] = {
+ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+
+static const uint32_t RCON[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000,
+ 0x36000000,
+};
+
+static const uint32_t TE0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+static const uint32_t TE1[256] = {
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const uint32_t TE2[256] = {
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const uint32_t TE3[256] = {
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+
+static const uint32_t TD0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+static const uint32_t TD1[256] = {
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+static const uint32_t TD2[256] = {
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+static const uint32_t TD3[256] = {
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+
+void SetDecryptKey(CRYPT_AES_Key *ctx);
+
+static inline uint32_t AES_G(uint32_t w, uint32_t rcon)
+{
+ uint32_t ret = 0;
+ /* 查表并进行移位 */
+ ret ^= (uint32_t)S[(w & 0x000000FF) >> 0] << 8; // 0, 8, S盒内行列转换关系
+ ret ^= (uint32_t)S[(w & 0x0000FF00) >> 8] << 16; // 8, 16, S盒内行列转换关系
+ ret ^= (uint32_t)S[(w & 0x00FF0000) >> 16] << 24; // 16, 24, S盒内行列转换关系
+ ret ^= (uint32_t)S[(w & 0xFF000000) >> 24] << 0; // 24, S盒内行列转换关系
+ ret ^= rcon;
+ return ret;
+}
+
+int32_t CRYPT_AES_SetEncryptKey128(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len)
+{
+ if (ctx == NULL || key == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ // 16 bytes = 128 bits
+ if (len != 16) {
+ BSL_ERR_PUSH_ERROR(CRYPT_AES_ERR_KEYLEN);
+ return CRYPT_AES_ERR_KEYLEN;
+ }
+ uint32_t *ekey = ctx->key;
+ ekey[0] = GET_UINT32_BE(key, 0); // ekey 0: key 0 下标开始的4个字节
+ ekey[1] = GET_UINT32_BE(key, 4); // ekey 1: key 4 下标开始的4个字节
+ ekey[2] = GET_UINT32_BE(key, 8); // ekey 2: key 8 下标开始的4个字节
+ ekey[3] = GET_UINT32_BE(key, 12); // ekey 3: key 12 下标开始的4个字节
+
+ // 128bit 需要秘钥长度 11 * 4 = 44,拓展轮数为10 -> 10 * 4 + 4 = 44
+ uint32_t times;
+ ctx->rounds = 10; // 10 rounds
+ for (times = 0; times < 9; times++) { // 9 times
+ ekey[4] = AES_G(ekey[3], RCON[times]) ^ ekey[0]; // ekey 4 = (ekey 3 xor rcon) ^ ekey 0
+ ekey[5] = ekey[4] ^ ekey[1]; // ekey 5 = ekey 4 ^ ekey 1
+ ekey[6] = ekey[5] ^ ekey[2]; // ekey 6 = ekey 5 ^ ekey 2
+ ekey[7] = ekey[6] ^ ekey[3]; // ekey 7 = ekey 6 ^ ekey 3
+ ekey += 4; // add 4
+ }
+ // the last times
+ ekey[4] = AES_G(ekey[3], RCON[times]) ^ ekey[0]; // ekey 4 = (ekey 3 xor rcon) ^ ekey 0
+ ekey[5] = ekey[4] ^ ekey[1]; // ekey 5 = ekey 4 ^ ekey 1
+ ekey[6] = ekey[5] ^ ekey[2]; // ekey 6 = ekey 5 ^ ekey 2
+ ekey[7] = ekey[6] ^ ekey[3]; // ekey 7 = ekey 6 ^ ekey 3
+ return CRYPT_SUCCESS;
+}
+
+int32_t CRYPT_AES_SetEncryptKey192(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len)
+{
+ if (ctx == NULL || key == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ // 24 bytes = 192 bits
+ if (len != 24) {
+ BSL_ERR_PUSH_ERROR(CRYPT_AES_ERR_KEYLEN);
+ return CRYPT_AES_ERR_KEYLEN;
+ }
+ uint32_t *ekey = ctx->key;
+ ekey[0] = GET_UINT32_BE(key, 0); // ekey 0: key 0 下标开始的4个字节
+ ekey[1] = GET_UINT32_BE(key, 4); // ekey 1: key 4 下标开始的4个字节
+ ekey[2] = GET_UINT32_BE(key, 8); // ekey 2: key 8 下标开始的4个字节
+ ekey[3] = GET_UINT32_BE(key, 12); // ekey 3: key 12 下标开始的4个字节
+ ekey[4] = GET_UINT32_BE(key, 16); // ekey 4: key 16 下标开始的4个字节
+ ekey[5] = GET_UINT32_BE(key, 20); // ekey 5: key 20 下标开始的4个字节
+
+ uint32_t times;
+ ctx->rounds = 12; // 12 rounds
+
+ for (times = 0; times < 7; times++) { // 7 times
+ ekey[6] = AES_G(ekey[5], RCON[times]) ^ ekey[0]; // ekey 6 = AES_G(ekey 5 xor rcon) ^ ekey 0
+ ekey[7] = ekey[6] ^ ekey[1]; // ekey 7 = ekey 6 ^ ekey 1
+ ekey[8] = ekey[7] ^ ekey[2]; // ekey 8 = ekey 7 ^ ekey 2
+ ekey[9] = ekey[8] ^ ekey[3]; // ekey 9 = ekey 8 ^ ekey 3
+ ekey[10] = ekey[9] ^ ekey[4]; // ekey 10 = ekey 9 ^ ekey 4
+ ekey[11] = ekey[10] ^ ekey[5]; // ekey 11 = ekey 10 ^ ekey 5
+ ekey += 6; // add 6
+ }
+ // the last times
+ ekey[6] = AES_G(ekey[5], RCON[times]) ^ ekey[0]; // ekey 6 = AES_G(ekey 5 xor rcon) ^ ekey 0
+ ekey[7] = ekey[6] ^ ekey[1]; // ekey 7 = ekey 6 ^ ekey 1
+ ekey[8] = ekey[7] ^ ekey[2]; // ekey 8 = ekey 7 ^ ekey 2
+ ekey[9] = ekey[8] ^ ekey[3]; // ekey 9 = ekey 8 ^ ekey 3
+ return CRYPT_SUCCESS;
+}
+
+int32_t CRYPT_AES_SetEncryptKey256(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len)
+{
+ if (ctx == NULL || key == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ uint32_t *ekey = ctx->key;
+ // 32 bytes = 256 bits
+ if (len != 32) {
+ BSL_ERR_PUSH_ERROR(CRYPT_AES_ERR_KEYLEN);
+ return CRYPT_AES_ERR_KEYLEN;
+ }
+ ekey[0] = GET_UINT32_BE(key, 0); // ekey 0: key 0 下标开始的4个字节
+ ekey[1] = GET_UINT32_BE(key, 4); // ekey 1: key 4 下标开始的4个字节
+ ekey[2] = GET_UINT32_BE(key, 8); // ekey 2: key 8 下标开始的4个字节
+ ekey[3] = GET_UINT32_BE(key, 12); // ekey 3: key 12 下标开始的4个字节
+ ekey[4] = GET_UINT32_BE(key, 16); // ekey 4: key 16 下标开始的4个字节
+ ekey[5] = GET_UINT32_BE(key, 20); // ekey 5: key 20 下标开始的4个字节
+ ekey[6] = GET_UINT32_BE(key, 24); // ekey 6: key 24 下标开始的4个字节
+ ekey[7] = GET_UINT32_BE(key, 28); // ekey 7: key 28 下标开始的4个字节
+
+ /* 需要秘钥长度 15 * 4 = 60,拓展轮数为7 -> 7 * 8 + 8 - 4 = 60 */
+ uint32_t times;
+ ctx->rounds = 14; // 14 轮
+ uint32_t tmp;
+ for (times = 0; times < 6; times++) { // 6 times
+ ekey[8] = AES_G(ekey[7], RCON[times]) ^ ekey[0]; // ekey 8 = AES_G(ekey 7 xor rcon) ^ ekey 0
+ ekey[9] = ekey[8] ^ ekey[1]; // ekey 9 = ekey 8 ^ ekey 1
+ ekey[10] = ekey[9] ^ ekey[2]; // ekey 10 = ekey 9 ^ ekey 2
+ ekey[11] = ekey[10] ^ ekey[3]; // ekey 11 = ekey 10 ^ ekey 3
+ /* 弥补G操作的移位 */
+ tmp = (ekey[11] >> 8) | (ekey[11] << 24); // tmp is ekey 11 >> 8 | ekey 11 << 24
+ ekey[12] = AES_G(tmp, 0) ^ ekey[4]; // ekey 12 = AES_G(tme, 0) ^ ekey 4
+ ekey[13] = ekey[12] ^ ekey[5]; // ekey 13 = ekey 12 ^ ekey 5
+ ekey[14] = ekey[13] ^ ekey[6]; // ekey 14 = ekey 13 ^ ekey 6
+ ekey[15] = ekey[14] ^ ekey[7]; // ekey 15 = ekey 14 ^ ekey 7
+ ekey += 8; // add 8
+ }
+ // the last times
+ ekey[8] = AES_G(ekey[7], RCON[times]) ^ ekey[0]; // ekey 8 = AES_G(ekey 7 xor rcon) ^ ekey 0
+ ekey[9] = ekey[8] ^ ekey[1]; // ekey 9 = ekey 8 ^ ekey 1
+ ekey[10] = ekey[9] ^ ekey[2]; // ekey 10 = ekey 9 ^ ekey 2
+ ekey[11] = ekey[10] ^ ekey[3]; // ekey 11 = ekey 10 ^ ekey 3
+ return CRYPT_SUCCESS;
+}
+
+void SetDecryptKey(CRYPT_AES_Key *ctx)
+{
+ uint32_t i, j;
+ uint32_t *dkey = ctx->key;
+ for (i = 1; i < ctx->rounds; i++) {
+ dkey += 4; // 4, 每次运算16个字节
+ for (j = 0; j < 4; j++) { // for 0 to 4 , 运算 16 / sizeof(uint32_t) 个循环
+ dkey[j] = TD0[S[(dkey[j] >> 24) & 0xff]] ^ // dkey j >> 24
+ TD1[S[(dkey[j] >> 16) & 0xff]] ^ // dkey j >> 16
+ TD2[S[(dkey[j] >> 8) & 0xff]] ^ // dkey j >> 8
+ TD3[S[(dkey[j] >> 0) & 0xff]]; // dkey j >> 0
+ }
+ }
+}
+
+int32_t CRYPT_AES_SetDecryptKey128(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len)
+{
+ int32_t ret;
+ ret = CRYPT_AES_SetEncryptKey128(ctx, key, len);
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+ SetDecryptKey(ctx);
+ return CRYPT_SUCCESS;
+}
+
+int32_t CRYPT_AES_SetDecryptKey192(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len)
+{
+ int32_t ret;
+ ret = CRYPT_AES_SetEncryptKey192(ctx, key, len);
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+ SetDecryptKey(ctx);
+ return CRYPT_SUCCESS;
+}
+
+int32_t CRYPT_AES_SetDecryptKey256(CRYPT_AES_Key *ctx, const uint8_t *key, uint32_t len)
+{
+ int32_t ret;
+ ret = CRYPT_AES_SetEncryptKey256(ctx, key, len);
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+ SetDecryptKey(ctx);
+ return CRYPT_SUCCESS;
+}
+
+#define AES_ROUND_INIT(in, r, enc) \
+do { \
+ r##0 = GET_UINT32_BE(in, 0) ^ enc##key[0]; \
+ r##1 = GET_UINT32_BE(in, 4) ^ enc##key[1]; \
+ r##2 = GET_UINT32_BE(in, 8) ^ enc##key[2]; \
+ r##3 = GET_UINT32_BE(in, 12) ^ enc##key[3]; \
+} while (0)
+
+#define AES_ENC_ROUND(in, r, i, ekey) \
+do { \
+ r##0 = TE0[(in##0 >> 24)] ^ TE1[(in##1 >> 16) & 0xff] ^ TE2[(in##2 >> 8) & 0xff] ^ TE3[(in##3) & 0xff] \
+ ^ (ekey)[((i) << 2) + 0]; \
+ r##1 = TE0[(in##1 >> 24)] ^ TE1[(in##2 >> 16) & 0xff] ^ TE2[(in##3 >> 8) & 0xff] ^ TE3[(in##0) & 0xff] \
+ ^ (ekey)[((i) << 2) + 1]; \
+ r##2 = TE0[(in##2 >> 24)] ^ TE1[(in##3 >> 16) & 0xff] ^ TE2[(in##0 >> 8) & 0xff] ^ TE3[(in##1) & 0xff] \
+ ^ (ekey)[((i) << 2) + 2]; \
+ r##3 = TE0[(in##3 >> 24)] ^ TE1[(in##0 >> 16) & 0xff] ^ TE2[(in##1 >> 8) & 0xff] ^ TE3[(in##2) & 0xff] \
+ ^ (ekey)[((i) << 2) + 3]; \
+} while (0)
+
+int32_t CRYPT_AES_Encrypt(const CRYPT_AES_Key *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
+{
+ (void)len;
+ const uint32_t *ekey = ctx->key;
+ uint32_t c0, c1, c2, c3, t0, t1, t2, t3;
+
+ AES_ROUND_INIT(in, c, e);
+
+ AES_ENC_ROUND(c, t, 1, ekey);
+ AES_ENC_ROUND(t, c, 2, ekey);
+ AES_ENC_ROUND(c, t, 3, ekey);
+ AES_ENC_ROUND(t, c, 4, ekey);
+ AES_ENC_ROUND(c, t, 5, ekey);
+ AES_ENC_ROUND(t, c, 6, ekey);
+ AES_ENC_ROUND(c, t, 7, ekey);
+ AES_ENC_ROUND(t, c, 8, ekey);
+ AES_ENC_ROUND(c, t, 9, ekey);
+
+ if (ctx->rounds > 10) { // AES192/AES256执行10、11轮运算
+ AES_ENC_ROUND(t, c, 10, ekey);
+ AES_ENC_ROUND(c, t, 11, ekey);
+ }
+
+ if (ctx->rounds > 12) { // AES256执行12、13轮运算
+ AES_ENC_ROUND(t, c, 12, ekey);
+ AES_ENC_ROUND(c, t, 13, ekey);
+ }
+
+ /* 最后一轮不进行列混淆,直接进行移位并查找s盒 */
+ ekey += ctx->rounds * 4; // 最后一轮计算ekey的位置,前面已经使用过4 * rounds的ekey
+
+ c0 = SSEARCH(t0, t1, t2, t3) ^ ekey[0]; // operation ekey 0
+ c1 = SSEARCH(t1, t2, t3, t0) ^ ekey[1]; // operation ekey 1
+ c2 = SSEARCH(t2, t3, t0, t1) ^ ekey[2]; // operation ekey 2
+ c3 = SSEARCH(t3, t0, t1, t2) ^ ekey[3]; // operation ekey 3
+
+ PUT_UINT32_BE(c0, out, 0); // c0转换为out下标为0的4个字节
+ PUT_UINT32_BE(c1, out, 4); // c1转换为out下标为4的4个字节
+ PUT_UINT32_BE(c2, out, 8); // c2转换为out下标为8的4个字节
+ PUT_UINT32_BE(c3, out, 12); // c3转换为out下标为12的4个字节
+
+ return CRYPT_SUCCESS;
+}
+
+#define AES_DEC_ROUND(in, r, i, dkey) \
+do { \
+ r##0 = TD0[(in##0 >> 24)] ^ TD1[(in##3 >> 16) & 0xff] ^ TD2[(in##2 >> 8) & 0xff] ^ TD3[(in##1) & 0xff] \
+ ^ (dkey)[((i) << 2) + 0]; \
+ r##1 = TD0[(in##1 >> 24)] ^ TD1[(in##0 >> 16) & 0xff] ^ TD2[(in##3 >> 8) & 0xff] ^ TD3[(in##2) & 0xff] \
+ ^ (dkey)[((i) << 2) + 1]; \
+ r##2 = TD0[(in##2 >> 24)] ^ TD1[(in##1 >> 16) & 0xff] ^ TD2[(in##0 >> 8) & 0xff] ^ TD3[(in##3) & 0xff] \
+ ^ (dkey)[((i) << 2) + 2]; \
+ r##3 = TD0[(in##3 >> 24)] ^ TD1[(in##2 >> 16) & 0xff] ^ TD2[(in##1 >> 8) & 0xff] ^ TD3[(in##0) & 0xff] \
+ ^ (dkey)[((i) << 2) + 3]; \
+} while (0)
+
+int32_t CRYPT_AES_Decrypt(const CRYPT_AES_Key *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
+{
+ (void)len;
+ const uint32_t *dkey = ctx->key + ctx->rounds * 4; // 4 byte
+ uint32_t p0, p1, p2, p3, t0, t1, t2, t3;
+
+ // 初始化p0,dkey从key的尾部开始
+ AES_ROUND_INIT(in, p, d);
+
+ dkey = ctx->key;
+
+ if (ctx->rounds > 12) { // AES256执行12、13轮运算
+ AES_DEC_ROUND(p, t, 13, dkey);
+ AES_DEC_ROUND(t, p, 12, dkey);
+ }
+
+ if (ctx->rounds > 10) { // AES192执行10、11轮运算
+ AES_DEC_ROUND(p, t, 11, dkey);
+ AES_DEC_ROUND(t, p, 10, dkey);
+ }
+
+ AES_DEC_ROUND(p, t, 9, dkey);
+ AES_DEC_ROUND(t, p, 8, dkey);
+ AES_DEC_ROUND(p, t, 7, dkey);
+ AES_DEC_ROUND(t, p, 6, dkey);
+ AES_DEC_ROUND(p, t, 5, dkey);
+ AES_DEC_ROUND(t, p, 4, dkey);
+ AES_DEC_ROUND(p, t, 3, dkey);
+ AES_DEC_ROUND(t, p, 2, dkey);
+ AES_DEC_ROUND(p, t, 1, dkey);
+
+ /* 最后一轮不进行列混淆,直接进行移位并查找逆s盒 */
+ p0 = INVSSEARCH(t0, t1, t2, t3) ^ dkey[0]; // dkey 0
+ p1 = INVSSEARCH(t1, t2, t3, t0) ^ dkey[1]; // dkey 1
+ p2 = INVSSEARCH(t2, t3, t0, t1) ^ dkey[2]; // dkey 2
+ p3 = INVSSEARCH(t3, t0, t1, t2) ^ dkey[3]; // dkey 3
+
+ PUT_UINT32_BE(p0, out, 0); // in 从 0 下标开始的4个字节
+ PUT_UINT32_BE(p1, out, 4); // in 从 4 下标开始的4个字节
+ PUT_UINT32_BE(p2, out, 8); // in 从 8 下标开始的4个字节
+ PUT_UINT32_BE(p3, out, 12); // in 从 12 下标开始的4个字节
+ SAL_CleanseData(&p0, sizeof(uint32_t));
+ SAL_CleanseData(&p1, sizeof(uint32_t));
+ SAL_CleanseData(&p2, sizeof(uint32_t));
+ SAL_CleanseData(&p3, sizeof(uint32_t));
+
+ return CRYPT_SUCCESS;
+}
+
+void CRYPT_AES_Clean(CRYPT_AES_Key *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+
+ SAL_CleanseData((void *)(ctx), sizeof(CRYPT_AES_Key));
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_hkdf.h
+ * Description: hkdf算法原语实现
+ * Author: liushaoming
+ * Create: 2022-05-11
+ */
+
+#ifndef CRYPT_HKDF_H
+#define CRYPT_HKDF_H
+
+#include <stdint.h>
+#include "crypt_local_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * @brief hkdf密钥派生算法
+ *
+ * @param macMeth [in] hmac算法method,仅支持HMAC方法
+ * @param mdMeth [in] md算法method
+ * @param key [IN] 密码,用户输入的字符串
+ * @param keyLen [IN] 密码长度,任意长度,包括0长度。
+ * @param salt [IN] 盐值,用户输入的字符串
+ * @param saltLen [IN] 盐值长度,任意长度,包括0长度。
+ * @param info [in] 额外信息
+ * @param infoLen [in] 额外信息长度,任意长度,包括0长度。
+ * @param out [OUT] 派生密钥
+ * @param outLen [IN] 派生密钥长度,不为0的任意整数,其中最大值:
+ * CRYPT_MAC_HMAC_SHA1对应最大值为5100、
+ * CRYPT_MAC_HMAC_SHA224对应最大值为7140、
+ * CRYPT_MAC_HMAC_SHA256对应最大值为8160、
+ * CRYPT_MAC_HMAC_SHA384对应最大值为12240、
+ * CRYPT_MAC_HMAC_SHA512对应最大值为16320、
+ *
+ * @return CRYPT_OK 成功
+ * 其他错误码参考 ht_error.h
+ */
+
+int32_t CRYPT_HKDF(const EAL_MacMethod *macMeth, const EAL_MdMethod *mdMeth, const uint8_t *key, uint32_t keyLen,
+ const uint8_t *salt, uint32_t saltLen, const uint8_t *info, uint32_t infoLen, uint8_t *out, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file hkdf.c
+ * Description: hkdf算法原语实现
+ * Author: liushaoming
+ * Create: 2022-05-11
+ */
+#include <stdint.h>
+#include "securec.h"
+#include "bsl_err_internal.h"
+#include "sal_mem.h"
+#include "crypt_local_types.h"
+#include "crypt_errno.h"
+#include "crypt_utils.h"
+#include "crypt_hkdf.h"
+
+#define HKDF_MAX_HMACSIZE 64
+
+int32_t CRYPT_HKDF_Extract(const EAL_MacMethod *macMeth, const EAL_MdMethod *mdMeth, const uint8_t *key,
+ uint32_t keyLen, const uint8_t *salt, uint32_t saltLen, uint8_t *prk, uint32_t *prkLen)
+{
+ int32_t ret = CRYPT_SUCCESS;
+ void *macCtx = SAL_MALLOC(macMeth->ctxSize);
+ if (macCtx == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
+ return CRYPT_MEM_ALLOC_FAIL;
+ }
+ (void)memset_s(macCtx, macMeth->ctxSize, 0, macMeth->ctxSize);
+
+ ret = macMeth->initCtx(macCtx, mdMeth);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->init(macCtx, salt, saltLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->update(macCtx, key, keyLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->final(macCtx, prk, prkLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+
+EXIT:
+ macMeth->deinit(macCtx);
+ macMeth->deinitCtx(macCtx);
+ SAL_FREE(macCtx);
+ return ret;
+}
+
+int32_t CRYPT_HKDF_Expand(const EAL_MacMethod *macMeth, const EAL_MdMethod *mdMeth, const uint8_t *prk, uint32_t prkLen,
+ const uint8_t *info, uint32_t infoLen, uint8_t *out, uint32_t outLen)
+{
+ int32_t ret = CRYPT_SUCCESS;
+ uint8_t hash[HKDF_MAX_HMACSIZE];
+ uint32_t hashLen = HKDF_MAX_HMACSIZE;
+ uint8_t counter = 1;
+ uint32_t totalLen = 0;
+ uint32_t n;
+ void *macCtx = SAL_MALLOC(macMeth->ctxSize);
+ if (macCtx == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
+ return CRYPT_MEM_ALLOC_FAIL;
+ }
+
+ ret = macMeth->initCtx(macCtx, mdMeth);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->init(macCtx, prk, prkLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->update(macCtx, info, infoLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->update(macCtx, &counter, 1);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->final(macCtx, hash, &hashLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ if (hashLen >= outLen) {
+ (void)memcpy_s(out, outLen, hash, outLen);
+ goto EXIT;
+ }
+ (void)memcpy_s(out, outLen, hash, hashLen);
+ totalLen += hashLen;
+ /* ceil(a / b) = (a + b - 1) / b */
+ n = (outLen + hashLen - 1) / hashLen;
+ // 2 表示计数2,上面代码已经使用了计数1
+ counter = 2;
+ for (uint32_t i = 2; i <= n; i++, counter++) {
+ macMeth->reinit(macCtx);
+ ret = macMeth->update(macCtx, hash, hashLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->update(macCtx, info, infoLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->update(macCtx, &counter, 1);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ ret = macMeth->final(macCtx, hash, &hashLen);
+ GOTO_EXIT_IF(ret != CRYPT_SUCCESS);
+ hashLen = hashLen > (outLen - totalLen) ? (outLen - totalLen) : hashLen;
+ (void)memcpy_s(out + totalLen, outLen - totalLen, hash, hashLen);
+ totalLen += hashLen;
+ }
+
+EXIT:
+ macMeth->deinit(macCtx);
+ macMeth->deinitCtx(macCtx);
+ SAL_FREE(macCtx);
+ return ret;
+}
+
+int32_t CRYPT_HKDF(const EAL_MacMethod *macMeth, const EAL_MdMethod *mdMeth, const uint8_t *key, uint32_t keyLen,
+ const uint8_t *salt, uint32_t saltLen, const uint8_t *info, uint32_t infoLen, uint8_t *out, uint32_t len)
+{
+ if (macMeth == NULL || mdMeth == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ if (key == NULL && keyLen > 0) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ if (salt == NULL && saltLen > 0) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ if (info == NULL && infoLen > 0) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ if ((out == NULL) || (len == 0)) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ int ret;
+ uint32_t hashLen = mdMeth->mdSize;
+ /* len cannot be larger than 255 * hashLen */
+ if (len > hashLen * 255) {
+ return CRYPT_HKDF_DKLEN_OVERFLOW;
+ }
+
+ uint8_t prk[HKDF_MAX_HMACSIZE];
+ uint32_t prkLen = HKDF_MAX_HMACSIZE;
+ ret = CRYPT_HKDF_Extract(macMeth, mdMeth, key, keyLen, salt, saltLen, prk, &prkLen);
+ if (ret != CRYPT_SUCCESS) {
+ return ret;
+ }
+ ret = CRYPT_HKDF_Expand(macMeth, mdMeth, prk, prkLen, info, infoLen, out, len);
+ if (ret != CRYPT_SUCCESS) {
+ return ret;
+ }
+ return CRYPT_SUCCESS;
+}
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_hmac.h
+ * Description: hmac原语实现头文件
+ * Author: liushaoming
+ * Create: 2022-04-18
+ */
+#ifndef CRYPT_HMAC_H
+#define CRYPT_HMAC_H
+
+#include <stdint.h>
+#include "crypt_local_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cpluscplus */
+
+#define HMAC_MAXBLOCKSIZE 128
+#define HMAC_MAXOUTSIZE 64
+
+typedef struct HMAC_Ctx {
+ const EAL_MdMethod *method;
+ void *mdCtx; /* md ctx */
+ void *oCtx; /* opad ctx */
+ void *iCtx; /* ipad ctx */
+} CRYPT_HMAC_Ctx;
+
+int32_t CRYPT_HMAC_InitCtx(CRYPT_HMAC_Ctx *ctx, const EAL_MdMethod *m);
+void CRYPT_HMAC_DeinitCtx(CRYPT_HMAC_Ctx *ctx);
+int32_t CRYPT_HMAC_Init(CRYPT_HMAC_Ctx *ctx, const uint8_t *key, uint32_t len);
+int32_t CRYPT_HMAC_Update(CRYPT_HMAC_Ctx *ctx, const uint8_t *in, uint32_t len);
+int32_t CRYPT_HMAC_Final(CRYPT_HMAC_Ctx *ctx, uint8_t *out, uint32_t *len);
+void CRYPT_HMAC_Reinit(CRYPT_HMAC_Ctx *ctx);
+void CRYPT_HMAC_Deinit(CRYPT_HMAC_Ctx *ctx);
+uint32_t CRYPT_HMAC_GetMacLen(const CRYPT_HMAC_Ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif /* __cpluscplus */
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file hmac.c
+ * Description: hmac原语实现
+ * Author: liushaoming
+ * Create: 2022-04-18
+ */
+#include <stdlib.h>
+#include <stdbool.h>
+#include "securec.h"
+#include "sal_mem.h"
+#include "crypt_errno.h"
+#include "bsl_err_internal.h"
+#include "crypt_hmac.h"
+
+
+#define GOTO_ERROR_IF(condition, ret) do { \
+ if (condition) { \
+ BSL_ERR_PUSH_ERROR((ret)); \
+ goto ERR; \
+ } \
+} while (0)
+
+uint32_t CRYPT_HMAC_GetMacLen(const CRYPT_HMAC_Ctx *ctx)
+{
+ if (ctx == NULL || ctx->method == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return 0;
+ }
+ return ctx->method->mdSize;
+}
+
+int32_t CRYPT_HMAC_InitCtx(CRYPT_HMAC_Ctx *ctx, const EAL_MdMethod *m)
+{
+ if (ctx == NULL || m == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+
+ void *mdCtx = (void *)SAL_MALLOC(m->ctxSize * 3); // 3个ctx 包括mdCtx iCtx oCtx
+ if (mdCtx == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
+ return CRYPT_MEM_ALLOC_FAIL;
+ }
+ // 3个ctx清零 包括mdCtx iCtx oCtx
+ (void)memset_s(mdCtx, m->ctxSize * 3, 0, m->ctxSize * 3);
+
+ ctx->mdCtx = mdCtx;
+ ctx->iCtx = (void *)((uint8_t *)mdCtx + m->ctxSize);
+ // 偏移2个ctxSize (mdCtx,iCtx)
+ ctx->oCtx = (void *)((uint8_t *)mdCtx + m->ctxSize * 2);
+ ctx->method = m;
+
+ return CRYPT_SUCCESS;
+}
+
+void CRYPT_HMAC_DeinitCtx(CRYPT_HMAC_Ctx *ctx)
+{
+ if (ctx == NULL || ctx->method == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return;
+ }
+ const EAL_MdMethod *method = ctx->method;
+ // 3个ctx清零 包括mdCtx iCtx oCtx
+ SAL_CleanseData((void *)(ctx->mdCtx), method->ctxSize * 3);
+ SAL_FREE(ctx->mdCtx);
+}
+
+int32_t CRYPT_HMAC_Init(CRYPT_HMAC_Ctx *ctx, const uint8_t *key, uint32_t len)
+{
+ if (ctx == NULL || ctx->method == NULL || (key == NULL && len != 0)) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ const EAL_MdMethod *method = ctx->method;
+ uint32_t blockSize = method->blockSize;
+ uint8_t tmp[HMAC_MAXBLOCKSIZE];
+ uint32_t tmpLen = HMAC_MAXBLOCKSIZE;
+ const uint8_t *keyTmp = key;
+ uint32_t i, keyLen = len;
+ uint8_t ipad[HMAC_MAXBLOCKSIZE];
+ uint8_t opad[HMAC_MAXBLOCKSIZE];
+ int32_t ret;
+
+ if (keyLen > blockSize) {
+ keyTmp = tmp;
+ ret = method->init(ctx->mdCtx);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ ret = method->update(ctx->mdCtx, key, keyLen);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ ret = method->final(ctx->mdCtx, tmp, &tmpLen);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ keyLen = method->mdSize;
+ }
+ for (i = 0; i < keyLen; i++) {
+ ipad[i] = 0x36 ^ keyTmp[i];
+ opad[i] = 0x5c ^ keyTmp[i];
+ }
+ for (i = keyLen; i < blockSize; i++) {
+ ipad[i] = 0x36;
+ opad[i] = 0x5c;
+ }
+ ret = method->init(ctx->iCtx);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ ret = method->update(ctx->iCtx, ipad, method->blockSize);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ ret = method->init(ctx->oCtx);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ ret = method->update(ctx->oCtx, opad, method->blockSize);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ ret = method->copyCtx(ctx->mdCtx, ctx->iCtx);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+
+ (void)memset_s(tmp, HMAC_MAXBLOCKSIZE, 0, HMAC_MAXBLOCKSIZE);
+ return CRYPT_SUCCESS;
+
+ERR:
+ method->deinit(ctx->mdCtx);
+ method->deinit(ctx->iCtx);
+ method->deinit(ctx->oCtx);
+ return ret;
+}
+
+int32_t CRYPT_HMAC_Update(CRYPT_HMAC_Ctx *ctx, const uint8_t *in, uint32_t len)
+{
+ if (ctx == NULL || ctx->method == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ return ctx->method->update(ctx->mdCtx, in, len);
+}
+
+int32_t CRYPT_HMAC_Final(CRYPT_HMAC_Ctx *ctx, uint8_t *out, uint32_t *len)
+{
+ if (ctx == NULL || ctx->method == NULL || out == NULL || len == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ const EAL_MdMethod *method = ctx->method;
+ if (*len < method->mdSize) {
+ BSL_ERR_PUSH_ERROR(CRYPT_HMAC_OUT_BUFF_LEN_NOT_ENOUGH);
+ return CRYPT_HMAC_OUT_BUFF_LEN_NOT_ENOUGH;
+ }
+ *len = method->mdSize;
+ uint8_t tmp[HMAC_MAXOUTSIZE];
+ uint32_t tmpLen = sizeof(tmp);
+ int32_t ret;
+ ret = method->final(ctx->mdCtx, tmp, &tmpLen);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ ret = method->copyCtx(ctx->mdCtx, ctx->oCtx);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ ret = method->update(ctx->mdCtx, tmp, tmpLen);
+ GOTO_ERROR_IF(ret != CRYPT_SUCCESS, ret);
+ return method->final(ctx->mdCtx, out, len);
+ERR:
+ return ret;
+}
+
+void CRYPT_HMAC_Reinit(CRYPT_HMAC_Ctx *ctx)
+{
+ if (ctx == NULL || ctx->method == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return;
+ }
+ const EAL_MdMethod *method = ctx->method;
+ method->copyCtx(ctx->mdCtx, ctx->iCtx);
+}
+
+void CRYPT_HMAC_Deinit(CRYPT_HMAC_Ctx *ctx)
+{
+ if (ctx == NULL || ctx->method == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return;
+ }
+ const EAL_MdMethod *method = ctx->method;
+ (void)method->deinit(ctx->mdCtx);
+ (void)method->deinit(ctx->iCtx);
+ (void)method->deinit(ctx->oCtx);
+}
--- /dev/null
+/**
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
+ * @defgroup crypt_arm.h
+ * @ingroup crypto
+ * @brief arm_arch 对应的宏设置
+ */
+
+#ifndef CRYPT_ARM_H
+#define CRYPT_ARM_H
+
+#ifndef CRYPT_VAL
+#define CRYPT_VAL 16
+#endif
+#ifndef CRYPT_VAL2
+#define CRYPT_VAL2 26
+#endif
+#if defined(__arm__) || defined (__arm)
+#define CRYPT_CAP CRYPT_VAL
+#define CRYPT_CE CRYPT_VAL2
+#define CRYPT_ARM_NEON (1 << 12)
+#define CRYPT_ARM_AES (1 << 0)
+#define CRYPT_ARM_PMULL (1 << 1)
+#define CRYPT_ARM_SHA1 (1 << 2)
+#define CRYPT_ARM_SHA256 (1 << 3)
+#elif defined(__aarch64__)
+#define CRYPT_CAP CRYPT_VAL
+#define CRYPT_CE CRYPT_VAL
+#define CRYPT_ARM_NEON (1 << 1)
+#define CRYPT_ARM_AES (1 << 3)
+#define CRYPT_ARM_PMULL (1 << 4)
+#define CRYPT_ARM_SHA1 (1 << 5)
+#define CRYPT_ARM_SHA256 (1 << 6)
+#define CRYPT_ARM_SM3 (1 << 18)
+#define CRYPT_ARM_SM4 (1 << 19)
+#define CRYPT_ARM_SHA512 (1 << 21)
+#endif
+
+#ifndef __ASSEMBLER__
+extern unsigned int g_cryptArmCpuInfo;
+#endif
+
+#endif
--- /dev/null
+/**
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief CRYPTO模块的打点日志点号id
+ */
+
+#ifndef CRYPT_BINLOG_ID_H
+#define CRYPT_BINLOG_ID_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum CRYPTO_BINLOG_ID {
+ BINLOG_ID10001 = 10001, BINLOG_ID10002, BINLOG_ID10003, BINLOG_ID10004, BINLOG_ID10005,
+ BINLOG_ID10006, BINLOG_ID10007, BINLOG_ID10008,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_encode.h
+ * Description: dsa中der-asn1相关的编解码接口
+ * Author: linkaixin
+ * Create: 2022-3-21
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-3-21 linkaixin dsa中der-asn1相关的编解码接口
+ */
+#ifndef CRYPT_ENCODE_H
+#define CRYPT_ENCODE_H
+#if defined(HITLS_CRYPTO_DSA) || defined(HITLS_CRYPTO_SM2) \
+ || defined(HITLS_CRYPTO_SM9) || defined(HITLS_CRYPTO_ECDSA)
+#include "crypt_bn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cpluscplus */
+
+#define DSA_MIN_PBITS 1024 // DSA最小规格1024bit
+#define DSA_MAX_PBITS 3072 // DSA最大规格3072bit
+#define DSA_MIN_QBITS 160 // DSA参数q最小规格
+
+typedef struct {
+ BN_BigNum *r;
+ BN_BigNum *s;
+} DSA_Sign;
+// 签名数据编码
+int32_t SignDataEncode(const DSA_Sign *s, uint8_t *sign, uint32_t *signLen);
+
+// 签名数据解码
+int32_t SignDataDecode(DSA_Sign *s, const uint8_t *sign, uint32_t signLen);
+
+// 获取签名数据所需长度
+uint32_t SignEnCodeLen(uint32_t rLen, uint32_t sLen);
+
+// 大数进行编码时的流长度
+uint32_t SignStringLenOfBn(const BN_BigNum *num);
+
+#ifdef HITLS_CRYPTO_SM9
+int32_t SignDataEncodeByString(uint8_t *sign, uint32_t *signLen,
+ const uint8_t *h, uint32_t hLen, const uint8_t *s, uint32_t sLen);
+
+int32_t SignDataDecode2String(const uint8_t *sign, uint32_t signLen,
+ uint8_t *h, uint32_t *hLen, uint8_t *s, uint32_t *sLen);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.\r
+ * @file crypt_local_types.h\r
+ * Description: 算法操作语义抽象\r
+ * Author: zhangqiankun\r
+ * Create: 2022-2-14\r
+ * Modification History\r
+ * DATE NAME DESCRIPTION\r
+ * --------------------------------------------------------------------------\r
+ * 2022-2-14 zhangqiankun 创建算法操作语义抽象文件\r
+ * 2022-2-16 zhangqiankun 修改MD抽象层内容\r
+ */\r
+\r
+#ifndef CRYPT_LOCAL_TYPES_H\r
+#define CRYPT_LOCAL_TYPES_H\r
+\r
+#include <stdint.h>\r
+#include <stdlib.h>\r
+#include "crypt_algid.h"\r
+#include "crypt_types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+/* MD算法操作接口原型 */\r
+typedef int32_t (*MdInit)(void *data);\r
+typedef int32_t (*MdUpdate)(void *data, const uint8_t *input, uint32_t len);\r
+typedef int32_t (*MdFinal)(void *data, uint8_t *out, uint32_t *len);\r
+typedef void (*MdDeinit)(void *data);\r
+typedef int32_t (*MdCopyCtx)(void *dst, void *src);\r
+\r
+typedef struct {\r
+ uint16_t blockSize; // HASH算法单次处理的blockSize,配合其他算法使用\r
+ uint16_t mdSize; // HASH算法的输出长度\r
+ uint16_t ctxSize; // HASH的上下文的size\r
+ MdInit init; // 初始化MD上下文的密钥\r
+ MdUpdate update; // 添加MD计算的分块数据\r
+ MdFinal final; // 完成MD计算,得到MD结果\r
+ MdDeinit deinit; // 清理MD上下文密钥信息\r
+ MdCopyCtx copyCtx; // 拷贝MD上下文\r
+} EAL_MdMethod;\r
+\r
+typedef struct {\r
+ uint16_t hashSize; // Siphash算法的输出长度\r
+ uint16_t compressionRounds; // 压缩轮数\r
+ uint16_t finalizationRounds; // 收尾轮数\r
+} EAL_SiphashMethod;\r
+\r
+/* 非对称原语方法提供 */\r
+typedef void *(*PkeyNew)(void);\r
+typedef void (*PkeyFree)(void *key);\r
+typedef void *(*PkeyNewParaById)(int32_t id);\r
+typedef void (*PkeyFreePara)(void *para);\r
+typedef int32_t (*PkeySetPara)(void *key, const void *para);\r
+typedef int32_t (*PkeyGetPara)(const void *key, void *para);\r
+typedef int32_t (*PkeyGen)(void *key);\r
+typedef uint32_t (*PkeyBits)(void *key);\r
+typedef uint32_t (*PkeyGetSignLen)(void *key);\r
+typedef int32_t (*PkeyCtrl)(void *key, CRYPT_PkeyCtrl opt, void *val, uint32_t len);\r
+typedef int32_t (*PkeySetPrv)(void *key, const void *prv);\r
+typedef int32_t (*PkeySetPub)(void *key, const void *pub);\r
+typedef int32_t (*PkeyGetPrv)(const void *key, void *prv);\r
+typedef int32_t (*PkeyGetPub)(const void *key, void *pub);\r
+typedef void *(*PkeyNewPara)(const void *para);\r
+typedef int32_t (*PkeySign)(const void *key, const uint8_t *data, uint32_t dataLen,\r
+ uint8_t *sign, uint32_t *signLen);\r
+typedef int32_t (*PkeyVerify)(const void *key, const uint8_t *data, uint32_t dataLen,\r
+ const uint8_t *sign, uint32_t signLen);\r
+typedef int32_t (*PkeyComputeShareKey)(const void *key, const void *pub,\r
+ uint8_t *share, uint32_t *shareLen);\r
+typedef int32_t (*PkeyCrypt)(const void *key, const uint8_t *data, uint32_t dataLen,\r
+ uint8_t *out, uint32_t *outLen);\r
+typedef int32_t (*PkeyCheck)(const void *key);\r
+\r
+\r
+/**\r
+* @ingroup EAL\r
+*\r
+* eal的method结构体\r
+*/\r
+typedef struct {\r
+ PkeyNew newCtx; // 申请秘钥对结构体资源\r
+ PkeyFree freeCtx; // 秘钥结构体释放\r
+ PkeySetPara setPara; // 在秘钥对结构体中设置参数\r
+ PkeyGetPara getPara; // 在秘钥对结构体中获取参数\r
+ PkeyGen gen; // 生成秘钥对\r
+ PkeyBits bits; // 获取秘钥长\r
+ PkeyGetSignLen signLen; // 获取签名数据长度\r
+ PkeyCtrl ctrl; // 控制参数\r
+ PkeyNewParaById newParaById; // 通过参数ID生成参数\r
+ PkeyFreePara freePara; // 释放秘钥参数\r
+ PkeyNewPara newPara; // 生成秘钥参数\r
+ PkeySetPub setPub; // 设置公钥\r
+ PkeySetPrv setPrv; // 设置私钥\r
+ PkeyGetPub getPub; // 获取公钥\r
+ PkeyGetPrv getPrv; // 获取私钥\r
+ PkeySign sign; // 签名\r
+ PkeyVerify verify; // 验签\r
+ PkeyComputeShareKey computeShareKey; // 计算共享秘钥\r
+ PkeyCrypt encrypt; // 加密\r
+ PkeyCrypt decrypt; // 解密\r
+ PkeyCheck check; // 检查密钥对一致性\r
+} EAL_PkeyMethod;\r
+\r
+/**\r
+ * @ingroup sym_algid\r
+ * 对称加解密算法ID\r
+ */\r
+typedef enum {\r
+ CRYPT_SYM_AES128 = 0,\r
+ CRYPT_SYM_AES192,\r
+ CRYPT_SYM_AES256,\r
+ CRYPT_SYM_CHACHA20,\r
+ CRYPT_SYM_SM4,\r
+ CRYPT_SYM_TDES,\r
+ CRYPT_SYM_MAX\r
+} CRYPT_SYM_AlgId;\r
+\r
+typedef struct EAL_CipherMethodLocal {\r
+ /**\r
+ * @ingroup crypt_type\r
+ * @brief 初始化句柄,注册其他模块\r
+ * @return 0表示成功,其他表示失败\r
+ */\r
+ int32_t (*initCtx)(void *ctx, const struct EAL_CipherMethodLocal *m);\r
+ /**\r
+ * @ingroup crypt_type\r
+ * @brief 反初始化句柄,回到调用init后的状态, 包括释放内存\r
+ * @return void\r
+ */\r
+ void (*deinitCtx)(void *ctx);\r
+ /**\r
+ * @ingroup crypt_type\r
+ * @brief 清除密钥,敏感信息,但不释放内存,回到initCtx后的状态\r
+ * @return void\r
+ */\r
+ void (*clean)(void *ctx);\r
+ /**\r
+ * @ingroup crypt_type\r
+ * @brief 设置加密密钥和密钥长度\r
+ * @return 0表示成功,其他表示失败\r
+ */\r
+ int32_t (*setEncryptKey)(void *ctx, const uint8_t *key, uint32_t len);\r
+ /**\r
+ * @ingroup crypt_type\r
+ * @brief 设置解密密钥和密钥长度\r
+ * @return 0表示成功,其他表示失败\r
+ */\r
+ int32_t (*setDecryptKey)(void *ctx, const uint8_t *key, uint32_t len);\r
+ /**\r
+ * @ingroup crypt_type\r
+ * @brief 对输入数据进行加密,加解密的数据长度一致\r
+ * @return 0表示成功,其他表示失败\r
+ */\r
+ int32_t (*encrypt)(void *ctx, const uint8_t *in, uint8_t *out, uint32_t len);\r
+ /**\r
+ * @ingroup crypt_type\r
+ * @brief 对输入数据进行加密,加解密的数据长度一致\r
+ * @return 0表示成功,其他表示失败\r
+ */\r
+ int32_t (*decrypt)(void *ctx, const uint8_t *in, uint8_t *out, uint32_t len);\r
+ /**\r
+ * @ingroup crypt_type\r
+ * @brief 对ctx进行参数设置\r
+ * @return 0表示成功,其他表示失败\r
+ */\r
+ int32_t (*ctrl)(void *ctx, uint32_t opt, void *val, uint32_t len);\r
+\r
+ uint8_t blockSize; /**< 块大小的字节数 */\r
+ uint16_t ctxSize; /**< ctx句柄大小,最大支持到65535字节 */\r
+ CRYPT_SYM_AlgId algId; /**< 算法ID */\r
+} EAL_CipherMethod;\r
+\r
+/* MAC算法操作接口原型 */\r
+// 初始化内存,并设置方法\r
+typedef int32_t (*MacInitCtx)(void *ctx, const void *method);\r
+// 完成key初始化\r
+typedef int32_t (*MacInit)(void *ctx, const uint8_t *key, uint32_t len);\r
+typedef int32_t (*MacUpdate)(void *ctx, const uint8_t *in, uint32_t len);\r
+typedef int32_t (*MacFinal)(void *ctx, const uint8_t *out, uint32_t *len);\r
+typedef void (*MacDeinit)(void *ctx);\r
+// 与initCtx接口动作相反。清理敏感数据\r
+typedef void (*MacDeinitCtx)(void *ctx);\r
+typedef void (*MacReinit)(void *ctx);\r
+typedef uint32_t (*MacGetMacLen)(void *ctx);\r
+\r
+/* MAC算法操作方法集合 */\r
+typedef struct {\r
+ MacInitCtx initCtx; // 申请内存,初始化并设置方法\r
+ MacInit init; // 初始化MAC上下文的密钥\r
+ MacUpdate update; // 添加MAC计算的分块数据\r
+ MacFinal final; // 完成MAC计算,得到MAC结果\r
+ MacDeinit deinit; // 清理MAC上下文密钥信息\r
+ MacDeinitCtx deinitCtx; // 清理敏感数据并释放内存\r
+ MacReinit reinit; // 重新初始化MAC上下文中的密钥,用于多次MAC计算密钥相同的场景\r
+ MacGetMacLen getLen; // 获取MAC计算结果数据长度\r
+ uint16_t ctxSize; // MAC 算法上下文大小\r
+} EAL_MacMethod;\r
+\r
+typedef struct {\r
+ union {\r
+ const EAL_MacMethod *macMethod;\r
+ const EAL_CipherMethod *modeMethod; // gmac 依赖对称算法的方法\r
+ const void *masMeth; // 主算法的方法指针\r
+ };\r
+ union {\r
+ const EAL_MdMethod *md; // hmac 依赖md算法\r
+ const EAL_CipherMethod *ciph; // cmac 依赖aes接口\r
+ const EAL_SiphashMethod *sip; // siphash method\r
+ const void *depMeth; // 依赖算法指针,预留用于拓展\r
+ };\r
+} EAL_MacMethLookup;\r
+\r
+/**\r
+ * @ingroup mode_algid\r
+ * 对称加解密模式ID\r
+ */\r
+typedef enum {\r
+ CRYPT_MODE_CBC = 0,\r
+ CRYPT_MODE_CTR,\r
+ CRYPT_MODE_ECB,\r
+ CRYPT_MODE_XTS,\r
+ CRYPT_MODE_CCM,\r
+ CRYPT_MODE_GCM,\r
+ CRYPT_MODE_CHACHA20_POLY1305,\r
+ CRYPT_MODE_CFB,\r
+ CRYPT_MODE_OFB,\r
+ CRYPT_MODE_MAX\r
+} CRYPT_MODE_AlgId;\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ *\r
+ * RSA用于签名时,PSS填充方式的结构体\r
+ */\r
+typedef struct {\r
+ int32_t saltLen; /**< pss 盐值长度,-1表示hashLen,-2表示MaxLen */\r
+ const EAL_MdMethod *mdMeth; /**< pss 填充时的mdid */\r
+ const EAL_MdMethod *mgfMeth; /**< pss 填充时的mgfid */\r
+} RSA_PadingPara;\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+#endif // EAL_LOCAL_TYPES_H\r
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_util_rand.h
+ * Description: 公共随机数注册头文件
+ * Author: panxinrong
+ * Create: 2022-5-14
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-5-14 panxinrong 创建
+ */
+
+#ifndef CRYPT_UTIL_RAND_H
+#define CRYPT_UTIL_RAND_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int32_t (*CRYPT_RandFunc)(uint8_t *rand, uint32_t randLen);
+
+/**
+ * @brief 随机数注册
+ *
+ * @param func [IN] 随机数获取接口
+ */
+void CRYPT_RandRegist(CRYPT_RandFunc func);
+
+/**
+ * @brief 生成随机数
+ *
+ * @param rand [OUT] 随机数buffer
+ * @param randLen [IN] 随机数长度
+ *
+ * @retval CRYPT_SUCCESS 生成随机数成功
+ * @retval CRYPT_NO_REGIST_RAND 随机数未注册
+ * @retval 注册的随机数生成失败返回的错误
+ */
+int32_t CRYPT_Rand(uint8_t *rand, uint32_t randLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_utils.h
+ * Description: 公共头文件
+ * Author: zhangqiankun
+ * Create: 2022-3-5
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-3-5 zhangqiankun 创建公共头文件
+ */
+
+#ifndef CRYPT_UTILS_H
+#define CRYPT_UTILS_H
+
+#include <stdint.h>
+#include "crypt_algid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define PUT_UINT32_BE(v, p, i) \
+do { \
+ (p)[(i) + 0] = (uint8_t)((v) >> 24); /* 24: 4th byte */ \
+ (p)[(i) + 1] = (uint8_t)((v) >> 16); /* 16: 3rd byte */ \
+ (p)[(i) + 2] = (uint8_t)((v) >> 8); /* 8: 2nd byte */ \
+ (p)[(i) + 3] = (uint8_t)((v) >> 0); /* 0: 1st byte */ \
+} while (0)
+
+#define GET_UINT32_BE(p, i) \
+( \
+ ((uint32_t)(p)[(i) + 0] << 24) | /* 24: 4th byte */ \
+ ((uint32_t)(p)[(i) + 1] << 16) | /* 16: 3rd byte */ \
+ ((uint32_t)(p)[(i) + 2] << 8) | /* 8: 2nd byte */ \
+ ((uint32_t)(p)[(i) + 3] << 0) /* 0: 1st byte */ \
+)
+
+#define PUT_UINT32_LE(v, p, i) \
+do { \
+ (p)[(i) + 3] = (uint8_t)((v) >> 24); /* 24: 4th byte */ \
+ (p)[(i) + 2] = (uint8_t)((v) >> 16); /* 16: 3rd byte */ \
+ (p)[(i) + 1] = (uint8_t)((v) >> 8); /* 8: 2nd byte */ \
+ (p)[(i) + 0] = (uint8_t)((v) >> 0); /* 0: 1st byte */ \
+} while (0)
+
+#define PUT_UINT64_LE(v, p, i) do { \
+ (p)[(i) + 7] = (uint8_t)((v) >> 56); /* 56: 8th byte */ \
+ (p)[(i) + 6] = (uint8_t)((v) >> 48); /* 48: 7rd byte */ \
+ (p)[(i) + 5] = (uint8_t)((v) >> 40); /* 40: 6nd byte */ \
+ (p)[(i) + 4] = (uint8_t)((v) >> 32); /* 32: 5st byte */ \
+ (p)[(i) + 3] = (uint8_t)((v) >> 24); /* 24: 4th byte */ \
+ (p)[(i) + 2] = (uint8_t)((v) >> 16); /* 16: 3rd byte */ \
+ (p)[(i) + 1] = (uint8_t)((v) >> 8); /* 8: 2nd byte */ \
+ (p)[(i) + 0] = (uint8_t)((v) >> 0); /* 0: 1st byte */ \
+} while (0)
+
+#define GET_UINT64_LE(p, i) \
+( \
+ ((uint64_t)(p)[(i) + 7] << 56) | ((uint64_t)(p)[(i) + 6] << 48) | \
+ ((uint64_t)(p)[(i) + 5] << 40) | ((uint64_t)(p)[(i) + 4] << 32) | \
+ ((uint64_t)(p)[(i) + 3] << 24) | ((uint64_t)(p)[(i) + 2] << 16) | \
+ ((uint64_t)(p)[(i) + 1] << 8) | ((uint64_t)(p)[(i) + 0] << 0) \
+)
+
+/**
+ * 判断是否满足条件condition,如果满足则跳转到EXIT标签
+ */
+#define GOTO_EXIT_IF(condition) \
+ do { \
+ if (condition) { \
+ goto EXIT; \
+ } \
+ } while (0)
+
+/**
+ * func返回值不为CRYPT_SUCCESS跳转到错误退出位置
+ */
+#define GOTO_ERR_IF(func, ret) do { \
+ (ret) = (func); \
+ if ((ret) != CRYPT_SUCCESS) { \
+ BSL_ERR_PUSH_ERROR((ret)); \
+ goto ERR; \
+ } \
+ } while (0)
+
+/**
+ * @brief 将两个数组的数据进行异或运算
+ *
+ * @param a [IN] 输入数据a
+ * @param b [IN] 输入数据b
+ * @param r [out] 输出结果数据
+ * @param len [IN] 输出结果数据长度
+ */
+#define DATA_XOR(a, b, r, len) \
+ do { \
+ uint32_t subscript; \
+ for (subscript = 0; subscript < (len); subscript++) { \
+ (r)[subscript] = (a)[subscript] ^ (b)[subscript]; \
+ } \
+ } while (0)
+
+/**
+ * @brief 将两个数组的数据每次32bit进行异或运算, 调用者保证输入输出是32bit的整数倍.地址为4字节对齐才做类型转换
+ *
+ * @param a [IN] 输入数据a
+ * @param b [IN] 输入数据b
+ * @param r [out] 输出结果数据
+ * @param len [IN] 输出结果数据长度
+ */
+#define DATA32_XOR(a, b, r, len) \
+ do { \
+ uint32_t ii; \
+ uintptr_t aPtr = (uintptr_t)(a); \
+ uintptr_t bPtr = (uintptr_t)(b); \
+ uintptr_t rPtr = (uintptr_t)(r); \
+ if (((aPtr & 0x3) != 0) || ((bPtr & 0x3) != 0) || ((rPtr & 0x3) != 0)) { \
+ for (ii = 0; ii < (len); ii++) { \
+ (r)[ii] = (a)[ii] ^ (b)[ii]; \
+ } \
+ } else { \
+ for (ii = 0; ii < (len); ii += 4) { \
+ *(uint32_t *)((r) + ii) = (*(const uint32_t *)((a) + ii)) ^ (*(const uint32_t *)((b) + ii)); \
+ } \
+ } \
+ } while (0)
+
+/**
+ * @brief 将两个数组的数据每次64bit进行异或运算, 调用者保证输入输出是64bit的整数倍。地址为8字节对齐才做类型转换
+ *
+ * @param a [IN] 输入数据a
+ * @param b [IN] 输入数据b
+ * @param r [out] 输出结果数据
+ * @param len [IN] 输出结果数据长度
+ */
+#define DATA64_XOR(a, b, r, len) \
+ do { \
+ uint32_t ii; \
+ uintptr_t aPtr = (uintptr_t)(a); \
+ uintptr_t bPtr = (uintptr_t)(b); \
+ uintptr_t rPtr = (uintptr_t)(r); \
+ if (((aPtr & 0x7) != 0) || ((bPtr & 0x7) != 0) || ((rPtr & 0x7) != 0)) { \
+ for (ii = 0; ii < (len); ii++) { \
+ (r)[ii] = (a)[ii] ^ (b)[ii]; \
+ } \
+ } else { \
+ for (ii = 0; ii < (len); ii += 8) { \
+ *(uint64_t *)((r) + ii) = (*(const uint64_t *)((a) + ii)) ^ (*(const uint64_t *)((b) + ii)); \
+ } \
+ } \
+ } while (0)
+
+/* Assumes that x is uint32_t and 0 < n < 32 */
+#define ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+#define ROTR64(x, n) (((x) << (64 - (n))) | ((x) >> (n))) // Assumes that x is uint64_t and 0 < n < 64
+
+#define IS_BUF_NON_ZERO(out, outLen) (((out) != NULL) && ((outLen) > 0))
+#define CRYPT_IS_BUF_NON_ZERO(out, outLen) (((out) != NULL) && ((outLen) > 0))
+#define CRYPT_CHECK_DATA_INVALID(d) (((d)->data == NULL && (d)->len != 0))
+#define CRYPT_IsDataNull(d) ((d) == NULL || (d)->data == NULL || (d)->len == 0)
+#define CRYPT_IN_RANGE(x, range) ((x) >= (range)->min && (x) <= (range)->max)
+#define CRYPT_CHECK_BUF_INVALID(buf, len) (((buf) == NULL && (len) != 0))
+#define CRYPT_SWAP32(x) ((((x) & 0xff000000) >> 24) | \
+ (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | \
+ (((x) & 0x000000ff) << 24))
+#ifdef HITLS_BIG_ENDIAN
+
+#define CRYPT_HTONL(x) (x)
+
+// 将p + i解释为小端序, p的类型需要为uint8_t*
+#define GET_UINT32_LE(p, i) \
+( \
+ ((uint32_t)((const uint8_t *)(p))[(i) + 3] << 24) | /* 24: 4th byte */ \
+ ((uint32_t)((const uint8_t *)(p))[(i) + 2] << 16) | /* 16: 3rd byte */ \
+ ((uint32_t)((const uint8_t *)(p))[(i) + 1] << 8) | /* 8: 2nd byte */ \
+ ((uint32_t)((const uint8_t *)(p))[(i) + 0] << 0) /* 0: 1st byte */ \
+)
+
+// 小端序转换位主机序
+#define CRYPT_LE32TOH(x) CRYPT_SWAP32(x)
+// 主机序转换为小端序
+#define CRYPT_HTOLE32(x) CRYPT_SWAP32(x)
+
+#else
+
+#define CRYPT_HTONL(x) CRYPT_SWAP32(x)
+
+// 将p + i解释为小端序
+#define GET_UINT32_LE(p, i) \
+( \
+ (((uintptr_t)(p) & 0x7) != 0) ? ((uint32_t)((const uint8_t *)(p))[(i) + 3] << 24) | /* 24: 4th byte */ \
+ ((uint32_t)((const uint8_t *)(p))[(i) + 2] << 16) | /* 16: 3rd byte */ \
+ ((uint32_t)((const uint8_t *)(p))[(i) + 1] << 8) | /* 8: 2nd byte */ \
+ ((uint32_t)((const uint8_t *)(p))[(i) + 0] << 0) /* 0: 1st byte */ \
+ : (*(uint32_t *)((uint8_t *)(uintptr_t)(p) + (i))) \
+)
+
+// 小端序转换位主机序
+#define CRYPT_LE32TOH(x) (x)
+// 主机序转换为小端序
+#define CRYPT_HTOLE32(x) (x)
+
+#endif
+
+#ifdef HITLS_BIG_ENDIAN
+
+// 将p + i解释为小端序, p的类型需要为uint8_t*
+#define GET_UINT16_LE(p, i) \
+( \
+ ((uint16_t)((const uint8_t *)(p))[(i) + 1] << 8) | /* 8: 2nd byte */ \
+ ((uint16_t)((const uint8_t *)(p))[(i) + 0] << 0) /* 0: 1st byte */ \
+)
+#else
+// 将p + i解释为小端序
+#define GET_UINT16_LE(p, i) \
+( \
+ (((uintptr_t)(p) & 0x7) != 0) ? ((uint16_t)((const uint8_t *)(p))[(i) + 1] << 8) | /* 8: 2nd byte */ \
+ ((uint16_t)((const uint8_t *)(p))[(i) + 0] << 0) /* 0: 1st byte */ \
+ : (*(uint16_t *)((uint8_t *)(uintptr_t)(p) + (i))) \
+)
+#endif
+
+/*
+ * 64-bit integer manipulation functions (big endian)
+ */
+static inline uint64_t Uint64FromBeBytes(const uint8_t *bytes)
+{
+ return (((uint64_t)bytes[0] << 56) | // 第0位左移7个字节(56)
+ ((uint64_t)bytes[1] << 48) | // 第1位左移6个字节(48)
+ ((uint64_t)bytes[2] << 40) | // 第2位左移5个字节(40)
+ ((uint64_t)bytes[3] << 32) | // 第3位左移4个字节(32)
+ ((uint64_t)bytes[4] << 24) | // 第4位左移3个字节(24)
+ ((uint64_t)bytes[5] << 16) | // 第5位左移2个字节(16)
+ ((uint64_t)bytes[6] << 8) | // 第6位左移1个字节(8)
+ (uint64_t)bytes[7]); // 第7位可直接使用
+}
+
+static inline void Uint64ToBeBytes(uint64_t v, uint8_t *bytes)
+{
+ bytes[0] = (uint8_t)(v >> 56); // 右移7个字节(56)
+ bytes[1] = (uint8_t)(v >> 48); // 右移6个字节(48)
+ bytes[2] = (uint8_t)(v >> 40); // 第2位右移5个字节(40)
+ bytes[3] = (uint8_t)(v >> 32); // 第3位右移4个字节(32)
+ bytes[4] = (uint8_t)(v >> 24); // 第4位右移3个字节(24)
+ bytes[5] = (uint8_t)(v >> 16); // 第5位右移2个字节(16)
+ bytes[6] = (uint8_t)(v >> 8); // 第6位右移1个字节(8)
+ bytes[7] = (uint8_t)(v & 0xffu); // 第7位使用0xffu将其他位置0
+}
+
+uint32_t GetMdSizeById(CRYPT_MD_AlgId id);
+
+static inline uint32_t Uint32ConstTimeMsb(uint32_t a)
+{
+ // 31 == (4 * 8 - 1)
+ return 0u - (a >> 31);
+}
+
+static inline uint32_t Uint32ConstTimeIsZero(uint32_t a)
+{
+ return Uint32ConstTimeMsb(~a & (a - 1));
+}
+
+static inline uint32_t Uint32ConstTimeEqual(uint32_t a, uint32_t b)
+{
+ return Uint32ConstTimeIsZero(a ^ b);
+}
+// (mask & a) | (~mask & b)
+static inline uint32_t Uint32ConstTimeSelect(uint32_t mask, uint32_t a, uint32_t b)
+{
+ return ((mask) & a) | ((~mask) & b);
+}
+
+static inline uint32_t Uint32ConstTimeLt(uint32_t a, uint32_t b)
+{
+ return Uint32ConstTimeMsb(a ^ ((a ^ b) | ((a - b) ^ a)));
+}
+
+static inline uint32_t Uint32ConstTimeGt(uint32_t a, uint32_t b)
+{
+ return ~Uint32ConstTimeLt(a, b);
+}
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // CRYPT_UTILS_H
--- /dev/null
+/**
+ * @defgroup modes crypt_modes.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief modes句柄类型
+ */
+#ifndef CRYPT_MODES_H
+#define CRYPT_MODES_H
+
+#include <stdint.h>
+#include "crypt_eal_cipher.h"
+#include "crypt_types.h"
+#include "crypt_algid.h"
+#include "crypt_local_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define MODES_MAX_IV_LENGTH 24
+#define MODES_MAX_BUF_LENGTH 24
+#define DES_BLOCK_BYTE_NUM 8
+/**
+ * @ingroup crypt_mode_cipherctx
+ * 模式句柄
+ */
+typedef struct {
+ void *ciphCtx; /* 每种算法自已定义的key */
+ const EAL_CipherMethod *ciphMeth; /* 对应底层的加解密, 操作keyctx */
+ uint8_t iv[MODES_MAX_IV_LENGTH]; /* 长度为blocksize */
+ uint8_t buf[MODES_MAX_BUF_LENGTH]; /* 缓存上一块的信息 */
+ uint8_t blockSize; /* 保存块大小长度 */
+ uint8_t offset; /* ctr、ofb模式下使用,若offset>0,iv的[0, offset-1]表示已使用过的数据,
+ [offset, blockSize-1]表示未使用过的数据 */
+ uint8_t flag3Iv; /* 是否为3个IV的标识 */
+ uint32_t ivIndex; /* 表示使用第几块IV,TDES可能会有3个IV */
+ CRYPT_SYM_AlgId algId; /* 对称算法ID */
+} MODE_CipherCtx;
+
+/**
+ * @brief 模块初始化,将加解密算法的method注册到模块中,并且开辟算法的上下文
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param method [IN] 对称加解密的方法
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_InitCtx(MODE_CipherCtx *ctx, const EAL_CipherMethod *method);
+
+/**
+ * @brief 模块反初始化,解除与算法模块的关系,并且释放算法的上下文
+ *
+ * @param ctx [IN] 模式句柄
+ * @param method [IN] 对称加解密的方法
+ */
+void MODE_DeInitCtx(MODE_CipherCtx *ctx);
+
+/**
+ * @brief 设置加密密钥
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param key [IN] 加密密钥
+ * @param len [IN] 加密密钥长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_SetEncryptKey(MODE_CipherCtx *ctx, const uint8_t *key, uint32_t len);
+
+/**
+ * @brief 设置解密密钥
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param key [IN] 解密密钥
+ * @param len [IN] 解密密钥长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_SetDecryptKey(MODE_CipherCtx *ctx, const uint8_t *key, uint32_t len);
+
+/**
+ * @brief 对mode进行参数操作
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param opt [IN] 操作
+ * @param val [IN/OUT] 参数,可以是入参也可以是出参
+ * @param len [IN] 参数的长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_Ctrl(MODE_CipherCtx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+/**
+ * @brief 获取分组大小
+ *
+ * @param ctx [IN] 模式句柄
+ * @param val [IN/OUT] 参数,可以是入参也可以是出参
+ * @param len [IN] 参数的长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t GetBlockSize(MODE_CipherCtx *ctx, uint32_t *val, uint32_t len);
+
+/**
+ * @brief 模式内容清理,清除敏感数据,保留算法模块的内存以及方法
+ *
+ * @param ctx [IN] 模式句柄
+ * @return 无
+ */
+void MODE_Clean(MODE_CipherCtx *ctx);
+
+int32_t MODE_SetIv(MODE_CipherCtx *ctx, uint8_t *val, uint32_t len);
+int32_t MODE_GetIv(MODE_CipherCtx *ctx, uint8_t *val, uint32_t len);
+
+/**
+ * @brief SM4设置秘钥
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param key [IN] 秘钥
+ * @param len [IN] 秘钥的长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t SM4_SetKey(MODE_CipherCtx *ctx, const uint8_t *key, uint32_t len);
+
+/**
+ * @brief SM4 deinit模式上下文
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ */
+void SM4_DeInitModeCtx(MODE_CipherCtx *ctx);
+
+// 从counter开始, 长度为counterLen的计数器
+static inline void IncCounter(uint8_t *counter, uint32_t counterLen)
+{
+ uint32_t i = counterLen;
+ uint16_t carry = 1;
+
+ while (i > 0) {
+ i--;
+ carry += counter[i];
+ counter[i] = carry & (0xFFu);
+ carry >>= 8; // 取高8位
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * @defgroup modes_cbc crypt_modes_cbc.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief modes句柄类型
+ */
+
+#ifndef CRYPT_MODES_CBC_H
+#define CRYPT_MODES_CBC_H
+
+#ifndef HITLS_CRYPTO_NO_CBC
+#include <stdbool.h>
+#include "crypt_modes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define CRYPT_SM4_BLOCKSIZE 16
+
+typedef struct {
+ uint8_t iv[CRYPT_SM4_BLOCKSIZE];
+ uint32_t rk[32]; // sm4 秘钥扩展后为32长度的uint32
+ bool safeMode; // 侧信道安全选项
+} CRYPT_SM4_ASM_Ctx;
+
+/**
+ * @brief CBC模式设置加密密钥
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param key [IN] 加密密钥
+ * @param len [IN] 加密密钥长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CBC_SetEncryptKey(MODE_CipherCtx *ctx, const uint8_t *key, uint32_t len);
+
+/**
+ * @brief CBC模式加密
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CBC_Encrypt(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief CBC模式解密
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param in [IN] 待加密数据
+ * @param out [OUT] 已加密数据
+ * @param len [IN] 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CBC_Decrypt(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief 原语SM4 CBC模式加密块
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t SM4_CBC_EncryptBlock(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief 原语SM4 CBC模式解密块
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t SM4_CBC_DecryptBlock(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief 使用memset_s清理信息,仅供非认证算法使用
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ */
+void MODES_SM4_CBC_Clean(MODE_CipherCtx *ctx);
+
+/**
+ * @brief SM4 CBC模式下,对mode进行参数操作
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param opt [IN] 操作
+ * @param val [IN/OUT] 参数,可以是入参也可以是出参
+ * @param len [IN] 参数的长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_SM4_CBC_Ctrl(MODE_CipherCtx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_modes_ccm.h
+ * Description: ccm模式
+ * Author: linkaixin
+ * Create: 2022-05-17
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-05-17 linkaixin ccm模式头文件
+ */
+
+#ifndef CRYPT_MODES_CCM_H
+#define CRYPT_MODES_CCM_H
+
+#ifndef HITLS_CRYPTO_NO_CCM
+#include <stdint.h>
+#include "crypt_local_types.h"
+#include "crypt_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define CCM_BLOCKSIZE 16
+
+typedef struct {
+ void *ciphCtx; /* 每种算法自已定义的key */
+ const EAL_CipherMethod *ciphMeth; /* 对应底层的加解密, 操作keyctx */
+ uint8_t tagLen; // tag长度 默认为16 在每次设置秘钥时进行重置
+
+ uint8_t nonce[CCM_BLOCKSIZE]; // nonce数据,ctr加密数据
+ uint8_t tag[CCM_BLOCKSIZE]; // tag数据,cbc加密中间数据
+ uint8_t last[CCM_BLOCKSIZE]; // ctr模式下上一块数据
+ uint64_t msgLen; // 消息长度
+ uint8_t lastLen; // ctr模式下上一块数据未使用数据长度
+ uint8_t tagInit; // 标识tag是否做了初始化
+} MODES_CCM_Ctx;
+
+int32_t MODES_CCM_InitCtx(MODES_CCM_Ctx *ctx, const struct EAL_CipherMethodLocal *m);
+
+void MODES_CCM_DeinitCtx(MODES_CCM_Ctx *ctx);
+
+void MODES_CCM_Clean(MODES_CCM_Ctx *ctx);
+
+int32_t MODES_CCM_Ctrl(MODES_CCM_Ctx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+int32_t MODES_CCM_SetKey(MODES_CCM_Ctx *ctx, const uint8_t *key, uint32_t len);
+
+int32_t MODES_CCM_Encrypt(MODES_CCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+int32_t MODES_CCM_Decrypt(MODES_CCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif
+#endif
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_modes_cfb.h
+ * Description: cfb模式
+ * Author: chenrenhao
+ * Create: 2022-10-08
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-10-08 chenrenhao cfb模式头文件
+ */
+
+#ifndef CRYPT_MODES_CFB_H
+#define CRYPT_MODES_CFB_H
+
+#ifndef HITLS_CRYPTO_NO_CFB
+#include "crypt_modes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef struct {
+ MODE_CipherCtx *modeCtx; /* 存放指向MODE_CipherCtx的指针 */
+ uint8_t feedbackBits; /* 保存FeedBack长度 */
+ uint8_t cipherCache[3][DES_BLOCK_BYTE_NUM]; /* 3IV的TDES用,缓存前3块密文用于反馈 */
+ uint8_t cacheIndex; /* 3IV的TDES用,当前使用哪一块缓存 */
+} MODE_CFB_Ctx;
+
+/**
+ * @brief 模块初始化,将加解密算法的method注册到模块中,并且开辟算法的上下文
+ *
+ * @param ctx [IN] 模式句柄
+ * @param method [IN] 对称加解密的方法
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CFB_InitCtx(MODE_CFB_Ctx *ctx, const EAL_CipherMethod *method);
+
+/**
+ * @brief CFB模式加密,可对任意字节进行加密,包含1-bit/8-bit/64-bit/128-bit CFB
+ *
+ * @param [IN] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CFB_Encrypt(MODE_CFB_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief CFB模式解密,可对任意字节进行解密,包含1-bit/8-bit/64-bit/128-bit CFB
+ *
+ * @param ctx [IN] 模式句柄
+ * @param in [IN] 待解密数据
+ * @param out [OUT] 已解密数据
+ * @param len [IN] 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CFB_Decrypt(MODE_CFB_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief 对mode进行参数操作
+ *
+ * @param ctx [IN] 模式句柄
+ * @param opt [IN] 操作 (Set/Get IV; Set/Get FeedbackSize)
+ * @param val [IN/OUT] 参数,可以是入参也可以是出参
+ * @param len [IN] 参数的长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CFB_Ctrl(MODE_CFB_Ctx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+/**
+ * @brief CFB模式内容清理,清除敏感数据,保留算法模块的内存以及方法
+ *
+ * @param ctx [IN] 模式句柄
+ * @return 无
+ */
+void MODE_CFB_Clean(MODE_CFB_Ctx *ctx);
+
+/**
+ * @brief CFB模式设置加密密钥
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param key [IN] 加密密钥
+ * @param len [IN] 加密密钥长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CFB_SetEncryptKey(MODE_CFB_Ctx *ctx, const uint8_t *key, uint32_t len);
+
+/**
+ * @brief 模块反初始化,解除与算法模块的关系,并且释放算法的上下文
+ *
+ * @param ctx [IN] 模式句柄
+ * @param method [IN] 对称加解密的方法
+ */
+void MODE_CFB_DeInitCtx(MODE_CFB_Ctx *ctx);
+
+/**
+ * @brief CFB模式对bit进行加解密的接口(内部接口,仅测试用)
+ */
+int32_t MODE_CFB_BitCrypt(MODE_CFB_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_modes_chacha20poly1305.h
+ * Description: chacha20_poly1305模式
+ * Author: linkaixin
+ * Create: 2022-05-05
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-05-05 linkaixin chacha20_poly1305模式头文件
+ */
+
+#ifndef CRYPT_MODES_CHACHA20POLY1305_H
+#define CRYPT_MODES_CHACHA20POLY1305_H
+
+#ifndef HITLS_CRYPTO_NO_CHACHA20POLY1305
+#include <stdint.h>
+#include "crypt_local_types.h"
+#include "crypt_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef struct {
+ uint32_t acc[6]; // acc中间数据 需大于130bit
+ uint32_t r[4]; // 秘钥信息r 16字节 即4 * sizeof(uint32_t)
+ uint32_t s[4]; // 秘钥信息s 16字节 即4 * sizeof(uint32_t)
+ uint32_t table[36]; // 用于汇编计算加速的表
+ uint8_t last[16]; // 上一次未处理数据缓存 一个block16字节
+ uint32_t lastLen; // 上一次数据还有剩下的长度 字节长度
+ uint32_t flag; // 用于保存汇编状态信息
+} Poly1305Ctx;
+
+typedef struct {
+ void *key; // 方法用的句柄
+ const EAL_CipherMethod *method; // 算法方法
+ Poly1305Ctx polyCtx;
+ uint64_t aadLen; // 状态,标识数据是否设置
+ uint64_t cipherTextLen; // 状态,标识数据是否设置
+} MODES_CHACHA20POLY1305_Ctx;
+
+int32_t MODES_CHACHA20POLY1305_InitCtx(MODES_CHACHA20POLY1305_Ctx *ctx, const struct EAL_CipherMethodLocal *m);
+
+void MODES_CHACHA20POLY1305_DeinitCtx(MODES_CHACHA20POLY1305_Ctx *ctx);
+
+void MODES_CHACHA20POLY1305_Clean(MODES_CHACHA20POLY1305_Ctx *ctx);
+
+int32_t MODES_CHACHA20POLY1305_Ctrl(MODES_CHACHA20POLY1305_Ctx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+int32_t MODES_CHACHA20POLY1305_SetEncryptKey(MODES_CHACHA20POLY1305_Ctx *ctx, const uint8_t *key, uint32_t len);
+
+int32_t MODES_CHACHA20POLY1305_SetDecryptKey(MODES_CHACHA20POLY1305_Ctx *ctx, const uint8_t *key, uint32_t len);
+
+int32_t MODES_CHACHA20POLY1305_Encrypt(MODES_CHACHA20POLY1305_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+int32_t MODES_CHACHA20POLY1305_Decrypt(MODES_CHACHA20POLY1305_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
+#endif
--- /dev/null
+/**
+ * @defgroup modes_ctr crypt_modes_ctr.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief modes句柄类型
+ */
+
+#ifndef CRYPT_MODES_CTR_H
+#define CRYPT_MODES_CTR_H
+
+#ifndef HITLS_CRYPTO_NO_CTR
+#include "crypt_modes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * @brief CTR模式加密
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_CTR_Crypt(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * @defgroup modes_ecb crypt_modes_ecb.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief modes句柄类型
+ */
+
+#ifndef CRYPT_MODES_ECB_H
+#define CRYPT_MODES_ECB_H
+
+#ifndef HITLS_CRYPTO_NO_ECB
+#include "crypt_modes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * @brief ECB模式加密
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_ECB_Encrypt(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief ECB模式解密
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param in [IN] 待加密数据
+ * @param out [OUT] 已加密数据
+ * @param len [IN] 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_ECB_Decrypt(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief ECB模式下,对mode进行参数操作
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param opt [IN] 操作
+ * @param val [IN/OUT] 参数,可以是入参也可以是出参
+ * @param len [IN] 参数的长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_ECB_Ctrl(MODE_CipherCtx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+/**
+ * @brief 原语SM4 ECB模式加密块
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t SM4_ECB_EncryptBlock(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief 原语SM4 ECB模式解密块
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t SM4_ECB_DecryptBlock(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief 使用memset_s清理信息,仅供非认证算法使用
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ */
+void MODES_SM4_ECB_Clean(MODE_CipherCtx *ctx);
+
+/**
+ * @brief SM4 ECB模式下,对mode进行参数操作
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param opt [IN] 操作
+ * @param val [IN/OUT] 参数,可以是入参也可以是出参
+ * @param len [IN] 参数的长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_SM4_ECB_Ctrl(MODE_CipherCtx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_modes_gcm.h
+ * Description: gcm模式
+ * Author: linkaixin
+ * Create: 2022-05-13
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-05-13 linkaixin gcm模式头文件
+ */
+
+#ifndef CRYPT_MODES_GCM_H
+#define CRYPT_MODES_GCM_H
+
+#ifndef HITLS_CRYPTO_NO_GCM
+#include <stdint.h>
+#include "crypt_local_types.h"
+#include "crypt_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define GCM_BLOCKSIZE 16
+
+typedef struct {
+ uint64_t h;
+ uint64_t l;
+} MODES_GCM_GF128;
+
+typedef struct {
+ // 该信息可一次设置,多次使用
+ uint8_t iv[GCM_BLOCKSIZE]; // 经过处理后的iv信息,长度为16字节
+ uint8_t ghash[GCM_BLOCKSIZE]; // tag计算的中间数据
+ MODES_GCM_GF128 hTable[16]; // 窗口使用4bit 需要预计算2^4(16)个表项
+ void *ciphCtx; // 方法用的句柄
+ const EAL_CipherMethod *ciphMeth; // 算法方法
+ /**
+ * tagLen may be any one of the following five values: 128, 120, 112, 104, or 96
+ * For certain applications, tagLen may be 64 or 32
+ */
+ uint8_t tagLen;
+ uint32_t cryptCnt; // 秘钥设置可用的加密次数
+
+ // 加解密中间信息,生命周期为一次加密操作,在每次加解密操作需要重置
+ uint8_t last[GCM_BLOCKSIZE]; // ctr mode last
+ uint8_t remCt[GCM_BLOCKSIZE]; // 剩余密文
+ uint8_t ek0[GCM_BLOCKSIZE]; // ek0
+ uint64_t plaintextLen; // use for calc tag
+ uint32_t aadLen; // use for calc tag
+ uint32_t lastLen; // ctr mode lastLen
+} MODES_GCM_Ctx;
+
+int32_t MODES_GCM_InitCtx(MODES_GCM_Ctx *ctx, const struct EAL_CipherMethodLocal *m);
+
+void MODES_GCM_DeinitCtx(MODES_GCM_Ctx *ctx);
+
+void MODES_GCM_Clean(MODES_GCM_Ctx *ctx);
+
+int32_t MODES_GCM_Ctrl(MODES_GCM_Ctx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+int32_t MODES_GCM_SetKey(MODES_GCM_Ctx *ctx, const uint8_t *ciphCtx, uint32_t len);
+
+int32_t MODES_GCM_Encrypt(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+int32_t MODES_GCM_Decrypt(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+int32_t AES_GCM_EncryptBlock(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+int32_t AES_GCM_DecryptBlock(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif
+#endif
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_modes_ofb.h
+ * Description: ofb模式
+ * Author: chenrenhao
+ * Create: 2022-10-08
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-10-08 chenrenhao ofb模式头文件
+ */
+
+#ifndef CRYPT_MODES_OFB_H
+#define CRYPT_MODES_OFB_H
+
+#ifndef HITLS_CRYPTO_NO_OFB
+#include "crypt_modes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+
+/**
+ * @brief OFB模式加/解密,可对任意字节长度进行加/解密
+ *
+ * @param [IN] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_OFB_Crypt(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * @defgroup modes_xts crypt_modes_xts.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief modes句柄类型
+ */
+
+#ifndef CRYPT_MODES_XTS_H
+#define CRYPT_MODES_XTS_H
+
+#ifndef HITLS_CRYPTO_NO_XTS
+#include "crypt_modes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+/**
+ * @brief 模块初始化,将加解密算法的method注册到模块中,并且开辟算法的上下文
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param method [IN] 对称加解密的方法
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_XTS_InitCtx(MODE_CipherCtx *ctx, EAL_CipherMethod *method);
+/**
+ * @brief XTS模式设置加密密钥
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param key [IN] 加密密钥
+ * @param len [IN] 加密密钥长度,只支持32(256bit) 和 64(512bit)
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_XTS_SetEncryptKey(MODE_CipherCtx *ctx, const uint8_t *key, uint32_t len);
+
+/**
+ * @brief XTS模式设置解密密钥
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param key [IN] 解密密钥
+ * @param len [IN] 解密密钥长度,只支持32(256bit) 和 64(512bit)
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_XTS_SetDecryptKey(MODE_CipherCtx *ctx, const uint8_t *key, uint32_t len);
+
+/**
+ * @brief XTS模式加密, 当len不是16的整数倍时,不能再调用MODE_XTS_Encrypt进行新数据的加密
+ *
+ * @param [IN/OUT] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] len 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_XTS_Encrypt(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief XTS模式解密,当len不是16的整数倍时,本轮解密结束
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param in [IN] 待加密数据
+ * @param out [OUT] 已加密数据
+ * @param len [IN] 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_XTS_Decrypt(MODE_CipherCtx *ctx, const uint8_t *in, uint8_t *out, uint32_t len);
+
+/**
+ * @brief 对xts mode进行参数操作
+ *
+ * @param ctx [IN/OUT] 模式句柄
+ * @param opt [IN] 操作
+ * @param val [IN/OUT] 参数,可以是入参也可以是出参
+ * @param len [IN] 参数的长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t MODE_XTS_Ctrl(MODE_CipherCtx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file asm_aes_gcm.h
+ * Description: aes_gcm 汇编优化头文件
+ * Author: haoruixiang
+ * Create: 2022-06-27
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-06-27 haoruixiang aes_gcm 汇编优化头文件
+ */
+#ifndef ASM_AES_GCM_H
+#define ASM_AES_GCM_H
+
+#include "crypt_modes_gcm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+void AES_GCM_EncryptBlockAsm(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, void *key);
+void AES_GCM_DecryptBlockAsm(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, void *key);
+void AES_GCM_Encrypt16BlockAsm(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, void *key);
+void AES_GCM_Decrypt16BlockAsm(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, void *key);
+void AES_GCM_ClearAsm(void);
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file asm_sm4.h
+ * Description: 汇编SM4算法头文件
+ * Author: panxinrong
+ * Create: 2022-08-16
+ */
+
+#ifndef ASM_SM4_H
+#define ASM_SM4_H
+
+#include <stdint.h>
+#include "crypt_types.h"
+#include "crypt_modes_cbc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cpluscplus */
+
+/**
+ * @brief SM4 cbc设置加解密秘钥
+ *
+ * @param [IN] ctx sm4上下文
+ * @param [IN] key 秘钥
+ * @param [IN] keyLen 秘钥长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t CRYPT_SM4_ASM_SetKey(CRYPT_SM4_ASM_Ctx *ctx, const uint8_t *key, uint32_t keyLen);
+
+/**
+ * @brief SM4上下文清零
+ *
+ * @param [IN] ctx sm4上下文
+ */
+void CRYPT_SM4_ASM_Clean(CRYPT_SM4_ASM_Ctx *ctx);
+
+/**
+ * @brief sm4 CBC模式加密,使用前需要用Ctrl接口设置iv,数据长度必须是16整数倍
+ *
+ * @param [IN] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] length 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t CRYPT_SM4_CbcDecrypt(CRYPT_SM4_ASM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t length);
+
+/**
+ * @brief sm4 CBC模式解密,使用前需要用Ctrl接口设置iv,数据长度必须是16整数倍
+ *
+ * @param [IN] ctx 模式句柄
+ * @param [IN] in 待解密数据
+ * @param [OUT] out 已解密数据
+ * @param [IN] length 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t CRYPT_SM4_CbcEncrypt(CRYPT_SM4_ASM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t length);
+
+/**
+ * @brief sm4 CBC模式设置获取iv接口
+ *
+ * @param [IN] ctx 模式句柄
+ * @param [IN] opt 模式,支持CRYPT_CTRL_SET_IV和CRYPT_CTRL_GET_IV
+ * @param [IN/OUT] 设置的iv/获取的iv
+ * @param [IN] len iv长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t CRYPT_SM4_Ctrl(CRYPT_SM4_ASM_Ctx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len);
+
+/**
+ * @brief sm4 ECB模式加密,数据长度必须是16整数倍
+ *
+ * @param [IN] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] length 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t CRYPT_SM4_EcbEncrypt(CRYPT_SM4_ASM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t length);
+
+/**
+ * @brief sm4 ECB模式解密,数据长度必须是16整数倍
+ *
+ * @param [IN] ctx 模式句柄
+ * @param [IN] in 待加密数据
+ * @param [OUT] out 已加密数据
+ * @param [IN] length 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 失败返回:其他错误码
+ */
+int32_t CRYPT_SM4_EcbDecrypt(CRYPT_SM4_ASM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t length);
+
+void Sm4CbcDecrypt_80(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecrypt_96(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecrypt_112(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecrypt_128(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecrypt_144(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecrypt_160(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecrypt_176(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecrypt_192(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecrypt_64(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcDecryptConsTime_64(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcEncrypt(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4CbcEncryptConsTime(uint32_t *key, uint8_t *iv, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4SetKey(const uint8_t *key, uint32_t rk[32]);
+
+void Sm4Decrypt(uint32_t *key, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4DecryptConsTime(uint32_t *key, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4Encrypt(uint32_t *key, const uint8_t *in, uint8_t *out, uint32_t len);
+
+void Sm4EncryptConsTime(uint32_t *key, const uint8_t *in, uint8_t *out, uint32_t len);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cpluscplus */
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file gcm.c
+ * Description: gcm模式
+ * Author: linkaixin
+ * Create: 2022-05-13
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-05-13 linkaixin gcm模式
+ */
+#ifndef HITLS_CRYPTO_NO_GCM
+#include <stdint.h>
+#include "securec.h"
+#include "crypt_utils.h"
+#include "crypt_errno.h"
+#include "sal_mem.h"
+#include "bsl_err_internal.h"
+#include "modes_local.h"
+#include "crypt_modes_gcm.h"
+
+/**
+ * NIST_800-38D-5.2
+ * len(P) ≤ 2^39-256 (bit)
+ * 等价于 len(P) ≤ 2^36 - 32 (byte)
+ */
+#define GCM_MAX_COMBINED_LENGTH (((uint64_t)1 << 36) - 32)
+/**
+ * NIST_800-38D-8.3
+ * The total number of invocations of the authenticated encryption function shall not exceed
+ * 2^32, including all IV lengths and all instances of the authenticated encryption function with
+ * the given ciphCtx
+ */
+#define GCM_MAX_INVOCATIONS_TIMES ((uint32_t)(-1))
+
+#define GCM_BLOCK_MASK (0xfffffff0)
+
+int32_t MODES_GCM_InitCtx(MODES_GCM_Ctx *ctx, const struct EAL_CipherMethodLocal *m)
+{
+ if (ctx == NULL || m == NULL) {
+ return CRYPT_NULL_INPUT;
+ }
+ (void)memset_s(ctx, sizeof(MODES_GCM_Ctx), 0, sizeof(MODES_GCM_Ctx));
+ ctx->ciphMeth = m;
+ ctx->ciphCtx = SAL_MALLOC(m->ctxSize);
+ if (ctx->ciphCtx == NULL) {
+ return CRYPT_MEM_ALLOC_FAIL;
+ }
+ return CRYPT_SUCCESS;
+}
+
+void MODES_GCM_DeinitCtx(MODES_GCM_Ctx *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+ (void)SAL_CleanseData(ctx->ciphCtx, ctx->ciphMeth->ctxSize);
+ SAL_FREE(ctx->ciphCtx);
+ (void)SAL_CleanseData(ctx, sizeof(MODES_GCM_Ctx));
+}
+
+void MODES_GCM_Clean(MODES_GCM_Ctx *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+ void *ciphCtx = ctx->ciphCtx;
+ const EAL_CipherMethod *ciphMeth = ctx->ciphMeth;
+ SAL_CleanseData((void *)(ciphCtx), ciphMeth->ctxSize);
+ SAL_CleanseData((void *)(ctx), sizeof(MODES_GCM_Ctx));
+ ctx->ciphCtx = ciphCtx;
+ ctx->ciphMeth = ciphMeth;
+}
+
+int32_t MODES_GCM_SetKey(MODES_GCM_Ctx *ctx, const uint8_t *ciphCtx, uint32_t len)
+{
+ if (ctx == NULL) {
+ return CRYPT_NULL_INPUT;
+ }
+ uint8_t gcmKey[GCM_BLOCKSIZE] = { 0 };
+ MODES_GCM_Clean(ctx);
+ int32_t ret = ctx->ciphMeth->setEncryptKey(ctx->ciphCtx, ciphCtx, len);
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+ ret = ctx->ciphMeth->encrypt(ctx->ciphCtx, gcmKey, gcmKey, GCM_BLOCKSIZE);
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+ GcmTableGen4bit(gcmKey, ctx->hTable);
+ ctx->tagLen = 16; // 默认tag长度为128bit 即16字节
+ SAL_CleanseData(gcmKey, sizeof(gcmKey));
+ return CRYPT_SUCCESS;
+}
+
+// 更新使用次数
+static int32_t CheckUseCnt(const MODES_GCM_Ctx *ctx)
+{
+ // 128, 120, 112, 104, or 96 即 12 byte - 16 byte
+ if (ctx->cryptCnt == GCM_MAX_INVOCATIONS_TIMES) {
+ return CRYPT_MODES_KEYUSE_TOOMANY_TIME;
+ }
+ return CRYPT_SUCCESS;
+}
+
+/**
+ * NIST_800-38D-5.2
+ * 1 ≤ len(IV) ≤ 2^64 - 1 (bit)
+ * 当前限制其不超过 2^32 - 1 byte
+ */
+static int32_t SetIv(MODES_GCM_Ctx *ctx, const uint8_t *iv, uint32_t ivLen)
+{
+ if (iv == NULL || ivLen == 0) {
+ return CRYPT_NULL_INPUT;
+ }
+ int32_t ret = CheckUseCnt(ctx); // 检查使用次数
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+ uint32_t i;
+ uint64_t len = (uint64_t)ivLen;
+ // when ivLen == 0, do reinit, no need to refersh iv
+ if (len == 12) { // len(IV ) = 96bit = 12byte
+ const uint8_t ivPad[4] = {0x00, 0x00, 0x00, 0x01};
+ /* Y0 = IV || 0^31 || 1 if len(IV ) = 96 = 12byte */
+ (void)memcpy_s(ctx->iv, GCM_BLOCKSIZE, iv, 12);
+ (void)memcpy_s(ctx->iv + 12, GCM_BLOCKSIZE - 12, ivPad, sizeof(ivPad)); // 补充后4bit(base = 12)
+ } else {
+ /* Y0 = GHASH(H, {}, IV ) otherwise */
+ (void)memset_s(ctx->iv, GCM_BLOCKSIZE, 0, GCM_BLOCKSIZE);
+ const uint8_t *off = iv;
+ uint32_t blockLen = ivLen & GCM_BLOCK_MASK;
+ uint32_t lastLen = ivLen - blockLen;
+ uint8_t tmp[GCM_BLOCKSIZE] = {0};
+ if (blockLen > 0) {
+ GcmHashMultiBlock(ctx->iv, ctx->hTable, off, blockLen);
+ off += blockLen;
+ }
+ if (lastLen > 0) {
+ for (i = 0; i < lastLen; i++) {
+ tmp[i] = off[i];
+ }
+ GcmHashMultiBlock(ctx->iv, ctx->hTable, tmp, GCM_BLOCKSIZE);
+ }
+ len = (uint64_t)ivLen << 3; // bitLen = byteLen << 3
+ (void)SAL_CleanseData(tmp, GCM_BLOCKSIZE);
+ Uint64ToBeBytes(len, tmp + 8); // 后8字节存放iv长度
+ GcmHashMultiBlock(ctx->iv, ctx->hTable, tmp, GCM_BLOCKSIZE);
+ }
+ /**
+ * NIST_800-38D-7.1
+ * GCTR(J0)
+ */
+ ctx->ciphMeth->encrypt(ctx->ciphCtx, ctx->iv, ctx->ek0, GCM_BLOCKSIZE);
+
+ /**
+ * NIST_800-38D-7.1
+ * INC32
+ * the 32-bit incrementing function is applied to the pre-counter block
+ * to produce the initial counter block for an invocation of the GCTR
+ * function on the plaintext
+ */
+ uint32_t ctr = GET_UINT32_BE(ctx->iv, 12); // 偏移12字节,取最后四字节
+ ctr++;
+ PUT_UINT32_BE(ctr, ctx->iv, 12); // 偏移12字节写回
+
+ // 重置信息
+ (void)memset_s(ctx->ghash, GCM_BLOCKSIZE, 0, GCM_BLOCKSIZE);
+ ctx->aadLen = 0;
+ ctx->lastLen = 0;
+ ctx->plaintextLen = 0;
+
+ // 敏感信息清除
+ SAL_CleanseData(&ctr, sizeof(uint32_t));
+ return CRYPT_SUCCESS;
+}
+
+/**
+ * NIST_800-38D-5.2
+ * len(AAD) ≤ 2^64 - 1 (bit)
+ * 当前限制其不超过 2^32 - 1 byte
+ */
+static int32_t SetAad(MODES_GCM_Ctx *ctx, const uint8_t *aad, uint32_t aadLen)
+{
+ if (aad == NULL && aadLen != 0) {
+ return CRYPT_NULL_INPUT;
+ }
+ const uint8_t *off = aad;
+ uint32_t i;
+ if (ctx->aadLen != 0) { // aad已设置
+ BSL_ERR_PUSH_ERROR(CRYPT_MODES_AAD_REPEAT_SET_ERROR);
+ return CRYPT_MODES_AAD_REPEAT_SET_ERROR;
+ }
+ uint32_t blockLen = aadLen & GCM_BLOCK_MASK;
+ uint32_t lastLen = aadLen - blockLen;
+ if (blockLen > 0) {
+ GcmHashMultiBlock(ctx->ghash, ctx->hTable, off, blockLen);
+ off += blockLen;
+ }
+ if (lastLen > 0) {
+ uint8_t temp[GCM_BLOCKSIZE] = {0};
+ for (i = 0; i < lastLen; i++) {
+ temp[i] = off[i];
+ }
+ GcmHashMultiBlock(ctx->ghash, ctx->hTable, temp, GCM_BLOCKSIZE);
+ }
+ ctx->aadLen = aadLen;
+ return CRYPT_SUCCESS;
+}
+
+// 判断加密长度时候溢出,并刷新已加密长度信息
+int32_t CryptLenCheckAndRefresh(MODES_GCM_Ctx *ctx, uint32_t len)
+{
+ // len只有32bit 结合该长度限制,该计算不会产生溢出
+ uint64_t plaintextLen = ctx->plaintextLen + len;
+ if (plaintextLen > GCM_MAX_COMBINED_LENGTH) {
+ BSL_ERR_PUSH_ERROR(CRYPT_MODES_CRYPTLEN_OVERFLOW);
+ return CRYPT_MODES_CRYPTLEN_OVERFLOW;
+ }
+ ctx->plaintextLen = plaintextLen;
+ return CRYPT_SUCCESS;
+}
+
+typedef struct {
+ const uint8_t *in;
+ uint8_t *out;
+ const uint8_t *ctr;
+ uint8_t *ct;
+} XorCryptData;
+
+static void XorInEncrypt(XorCryptData *data, uint32_t len)
+{
+ uint32_t i;
+ for (i = 0; i < len; i++) {
+ data->out[i] = data->in[i] ^ data->ctr[i];
+ data->ct[i] = data->out[i];
+ }
+}
+
+static void XorInDecrypt(XorCryptData *data, uint32_t len)
+{
+ uint32_t i;
+ for (i = 0; i < len; i++) {
+ data->ct[i] = data->in[i];
+ data->out[i] = data->in[i] ^ data->ctr[i];
+ }
+}
+
+// 处理上一次update剩余数据
+uint32_t LastHandle(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc)
+{
+ uint32_t lastLen = 0;
+ if (ctx->lastLen > 0) {
+ XorCryptData data;
+ lastLen = (ctx->lastLen < len) ? ctx->lastLen : len;
+ data.in = in;
+ data.out = out;
+ data.ctr = &(ctx->last[GCM_BLOCKSIZE - ctx->lastLen]);
+ data.ct = &(ctx->remCt[GCM_BLOCKSIZE - ctx->lastLen]);
+ if (enc) { // ctx->lastLen 必然小于 GCM_BLOCKSIZE
+ XorInEncrypt(&data, lastLen);
+ } else {
+ XorInDecrypt(&data, lastLen);
+ }
+ // 刷新剩余长度
+ ctx->lastLen -= lastLen;
+ if (ctx->lastLen == 0) {
+ GcmHashMultiBlock(ctx->ghash, ctx->hTable, ctx->remCt, GCM_BLOCKSIZE);
+ }
+ }
+ return lastLen;
+}
+
+static void GcmMultiBlockCrypt(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc)
+{
+ uint32_t blockLen = len;
+ const uint8_t *dataIn = in;
+ uint8_t *dataOut = out;
+ uint32_t ctr = GET_UINT32_BE(ctx->iv, 12); // 计数信息,iv的最后32位,需偏移12字节(16 - 4 = 12)
+ if (enc == false) {
+ GcmHashMultiBlock(ctx->ghash, ctx->hTable, in, len);
+ }
+ while (blockLen > 0) {
+ ctx->ciphMeth->encrypt(ctx->ciphCtx, ctx->iv, ctx->last, GCM_BLOCKSIZE);
+ DATA64_XOR(dataIn, ctx->last, dataOut, GCM_BLOCKSIZE);
+ /**
+ * NIST_800-38D-7.1
+ * INC32
+ */
+ ctr++;
+ PUT_UINT32_BE(ctr, ctx->iv, 12); // 偏移12字节,取最后四字节
+ // 刷新剩余长度
+ blockLen -= GCM_BLOCKSIZE;
+ // 偏移
+ dataIn += GCM_BLOCKSIZE;
+ dataOut += GCM_BLOCKSIZE;
+ }
+ if (enc) {
+ GcmHashMultiBlock(ctx->ghash, ctx->hTable, out, len);
+ }
+ // 敏感信息清除
+ SAL_CleanseData(&ctr, sizeof(uint32_t));
+}
+
+// enc标识为true时为加密操作,false为解密操作
+static int32_t MODES_GCM_Crypt(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc)
+{
+ if (ctx == NULL || in == NULL || out == NULL || len == 0) {
+ return CRYPT_NULL_INPUT;
+ }
+ int32_t ret = CryptLenCheckAndRefresh(ctx, len);
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+ uint32_t lastLen = LastHandle(ctx, in, out, len, enc);
+ // 数据处理完毕,提前退出
+ if (lastLen == len) {
+ return CRYPT_SUCCESS;
+ }
+
+ XorCryptData data;
+ data.in = in + lastLen;
+ data.out = out + lastLen;
+ data.ctr = ctx->last;
+ data.ct = ctx->remCt;
+
+ uint32_t multiBlockLen = (len - lastLen) & GCM_BLOCK_MASK;
+ if (multiBlockLen > 0) {
+ GcmMultiBlockCrypt(ctx, data.in, data.out, multiBlockLen, enc);
+ data.in += multiBlockLen;
+ data.out += multiBlockLen;
+ }
+ uint32_t remLen = len - lastLen - multiBlockLen;
+ if (remLen > 0) {
+ uint32_t ctr = GET_UINT32_BE(ctx->iv, 12); // 计数信息,iv的最后32位,需偏移12字节(16 - 4 = 12)
+ (void)ctx->ciphMeth->encrypt(ctx->ciphCtx, ctx->iv, ctx->last, GCM_BLOCKSIZE);
+ if (enc) {
+ XorInEncrypt(&data, remLen);
+ } else {
+ XorInDecrypt(&data, remLen);
+ }
+ /**
+ * NIST_800-38D-7.1
+ * INC32
+ */
+ ctr++;
+ PUT_UINT32_BE(ctr, ctx->iv, 12); // 偏移12字节,取最后四字节
+ // 敏感信息清除
+ SAL_CleanseData(&ctr, sizeof(uint32_t));
+ }
+ ctx->lastLen = (remLen > 0) ? (GCM_BLOCKSIZE - remLen) : 0;
+
+ return CRYPT_SUCCESS;
+}
+
+static void GcmPad(MODES_GCM_Ctx *ctx)
+{
+ // S = GHASHH (A || 0v || C || 0u || [len(A)]64 || [len(C)]64).
+ if (ctx->lastLen != 0) {
+ uint32_t offset = GCM_BLOCKSIZE - ctx->lastLen;
+ (void)memset_s(ctx->remCt + offset, GCM_BLOCKSIZE - offset, 0, ctx->lastLen);
+ GcmHashMultiBlock(ctx->ghash, ctx->hTable, ctx->remCt, GCM_BLOCKSIZE);
+ }
+ uint64_t aadLen = (uint64_t)(ctx->aadLen) << 3; // bitLen = byteLen << 3
+ uint64_t plaintextLen = ctx->plaintextLen << 3; // bitLen = byteLen << 3
+ uint8_t padBuf[GCM_BLOCKSIZE];
+ Uint64ToBeBytes(aadLen, padBuf);
+ Uint64ToBeBytes(plaintextLen, padBuf + 8); // 后64bit(8byte)为密文长度
+
+ GcmHashMultiBlock(ctx->ghash, ctx->hTable, padBuf, GCM_BLOCKSIZE);
+}
+
+static int32_t SetTagLen(MODES_GCM_Ctx *ctx, const uint8_t *val, uint32_t len)
+{
+ if (val == NULL) {
+ return CRYPT_NULL_INPUT;
+ }
+ if (len != sizeof(uint32_t)) {
+ BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_TAGLEN_ERROR);
+ return CRYPT_MODES_CTRL_TAGLEN_ERROR;
+ }
+ /**
+ * NIST_800-38D-5.2.1.2
+ * The bit length of the tag, denoted t, is a security parameter, as discussed in Appendix B.
+ * In general, t may be any one of the following five values: 128, 120, 112, 104, or 96. For certain
+ * applications, t may be 64 or 32; guidance for the use of these two tag lengths, including
+ * requirements on the length of the input data and the lifetime of the ciphCtx in these cases,
+ * is given in Appendix C
+ */
+ uint32_t tagLen = *((const uint32_t *)val);
+ // 32bit 即 4 byte 64bit 即 8 byte 128, 120, 112, 104, or 96 即 12 byte - 16 byte
+ if (tagLen == 4 || tagLen == 8 || (tagLen >= 12 && tagLen <= 16)) {
+ ctx->tagLen = (uint8_t)tagLen;
+ return CRYPT_SUCCESS;
+ }
+ BSL_ERR_PUSH_ERROR(CRYPT_MODES_CTRL_TAGLEN_ERROR);
+ return CRYPT_MODES_CTRL_TAGLEN_ERROR;
+}
+
+static int32_t GetTag(MODES_GCM_Ctx *ctx, uint8_t *val, uint32_t len)
+{
+ if (val == NULL) {
+ return CRYPT_NULL_INPUT;
+ }
+ if (len != ctx->tagLen) {
+ BSL_ERR_PUSH_ERROR(CRYPT_MODES_TAGLEN_ERROR);
+ return CRYPT_MODES_TAGLEN_ERROR;
+ }
+ ctx->cryptCnt++; // 加解密流程结束 秘钥使用次数+1
+ GcmPad(ctx);
+ uint32_t i;
+ for (i = 0; i < len; i++) {
+ val[i] = ctx->ghash[i] ^ ctx->ek0[i];
+ }
+ return CRYPT_SUCCESS;
+}
+
+int32_t MODES_GCM_Encrypt(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
+{
+ return MODES_GCM_Crypt(ctx, in, out, len, true);
+}
+
+int32_t MODES_GCM_Decrypt(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
+{
+ return MODES_GCM_Crypt(ctx, in, out, len, false);
+}
+
+int32_t MODES_GCM_Ctrl(MODES_GCM_Ctx *ctx, CRYPT_CipherCtrl opt, void *val, uint32_t len)
+{
+ if (ctx == NULL) {
+ return CRYPT_NULL_INPUT;
+ }
+ switch (opt) {
+ case CRYPT_CTRL_SET_IV:
+ return SetIv(ctx, val, len);
+ case CRYPT_CTRL_SET_TAGLEN:
+ return SetTagLen(ctx, val, len);
+ case CRYPT_CTRL_SET_AAD:
+ return SetAad(ctx, val, len);
+ case CRYPT_CTRL_GET_TAG:
+ return GetTag(ctx, val, len);
+ default:
+ return CRYPT_MODES_CTRL_TYPE_ERROR;
+ }
+}
+#endif
\ No newline at end of file
--- /dev/null
+
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file modes_local.h
+ * Description: modes 内部处理函数
+ * Author: haoruixiang
+ * Create: 2022-6-26
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-06-26 haoruixiang chacha20 内部处理函数
+ */
+#ifndef MODES_LOCAL_H
+#define MODES_LOCAL_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "crypt_modes_gcm.h"
+
+void GcmTableGen4bit(uint8_t key[GCM_BLOCKSIZE], MODES_GCM_GF128 hTable[16]);
+
+void GcmHashMultiBlock(uint8_t t[GCM_BLOCKSIZE], const MODES_GCM_GF128 hTable[16], const uint8_t *in, uint32_t inLen);
+
+int32_t CryptLenCheckAndRefresh(MODES_GCM_Ctx *ctx, uint32_t len);
+
+uint32_t LastHandle(MODES_GCM_Ctx *ctx, const uint8_t *in, uint8_t *out, uint32_t len, bool enc);
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file noasm_ghash.c
+ * Description: ghash算法实现, C实现,对应有相应的汇编加速实现
+ * Author: linkaixin
+ * Create: 2022-05-13
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-05-13 linkaixin gcm模式
+ */
+#ifndef HITLS_CRYPTO_NO_GCM
+#include "modes_local.h"
+#include "crypt_utils.h"
+#include "sal_mem.h"
+
+/* table[i] = (P^4)*i, P = 0x4000000000000000, i = 0...16 */
+static const uint64_t TABLE_P4_BITS[16] = {
+ 0x0000000000000000, 0x1c20000000000000, 0x3840000000000000, 0x2460000000000000,
+ 0x7080000000000000, 0x6ca0000000000000, 0x48c0000000000000, 0x54e0000000000000,
+ 0xe100000000000000, 0xfd20000000000000, 0xd940000000000000, 0xc560000000000000,
+ 0x9180000000000000, 0x8da0000000000000, 0xa9c0000000000000, 0xb5e0000000000000
+};
+
+// 计算 n*H n为0 .... 16
+void GcmTableGen4bit(uint8_t key[GCM_BLOCKSIZE], MODES_GCM_GF128 hTable[16])
+{
+ uint32_t i;
+ uint32_t j;
+ const uint64_t r = 0xE100000000000000;
+ hTable[0].h = 0;
+ hTable[0].l = 0;
+ hTable[8].h = Uint64FromBeBytes(key); // 表的中间项(16 / 2 == 8)为H本身
+ hTable[8].l = Uint64FromBeBytes(key + sizeof(uint64_t)); // 表的中间项(16 / 2 == 8)为H本身
+
+ for (i = 4; i > 0; i >>= 1) { // 4bit表,先计算2^n项的值
+ hTable[i].l = (hTable[ i * 2].h << 63) | (hTable[ i * 2].l >> 1); // 循环右移1bit h的高1位于l的低63位结合
+ hTable[i].h = (hTable[ i * 2].h >> 1) ^ ((hTable[ i * 2].l & 1) * r); // 2^n项的值
+ }
+ for (i = 1; i < 16; i <<= 1) { // 16个表项
+ for (j = 1; j < i; j++) {
+ hTable[i + j].h = hTable[i].h ^ hTable[j].h;
+ hTable[i + j].l = hTable[i].l ^ hTable[j].l;
+ }
+ }
+}
+
+// 计算 t = t * H
+void GcmHashMultiBlock(uint8_t t[GCM_BLOCKSIZE], const MODES_GCM_GF128 hTable[16], const uint8_t *in, uint32_t inLen)
+{
+ MODES_GCM_GF128 x;
+ uint8_t r;
+ uint8_t h, l, tag; // 密文信息,摘要信息,非敏感信息
+ const uint8_t *tempIn = in;
+ for (uint32_t i = 0; i < inLen; i += GCM_BLOCKSIZE) {
+ uint8_t cnt = GCM_BLOCKSIZE - 1;
+ x.h = 0;
+ x.l = 0;
+ while (1) {
+ tag = t[cnt] ^ tempIn[cnt];
+
+ l = tag & 0xf;
+ h = (tag >> 4) & 0xf; // 高4bit
+ x.h ^= hTable[l].h;
+ x.l ^= hTable[l].l;
+
+ r = (x.l & 0xf);
+ x.l = (x.h << 60) | (x.l >> 4); // 循环右移4bit h的高4位于l的低60位结合
+ x.h = (x.h >> 4); // 循环右移4bit
+ x.h ^= TABLE_P4_BITS[r];
+
+ x.h ^= hTable[h].h;
+ x.l ^= hTable[h].l;
+ if (cnt == 0) {
+ break;
+ }
+ cnt--;
+ r = (x.l & 0xf);
+ x.l = (x.h << 60) | (x.l >> 4); // 循环右移4bit h的高4位于l的低60位结合
+ x.h = (x.h >> 4); // 循环右移4bit
+ x.h ^= TABLE_P4_BITS[r];
+ }
+ tempIn += GCM_BLOCKSIZE;
+ Uint64ToBeBytes(x.h, t); // 高8位
+ Uint64ToBeBytes(x.l, t + 8); // 低8位
+ }
+ // 敏感信息清除
+ SAL_CleanseData(&x, sizeof(MODES_GCM_GF128));
+ SAL_CleanseData(&r, sizeof(uint8_t));
+}
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file poly1305_core.h
+ * Description: poly1305内部头文件
+ * Author: pandeguang
+ * Create: 2022-06-27
+ * Modification History
+ * DATE NAME DESCRIPTION
+ * --------------------------------------------------------------------------
+ * 2022-06-27 pandeguang poly1305内部算法头文件
+ */
+#ifndef POLY1305_CORE_H
+#define POLY1305_CORE_H
+
+#include "crypt_modes_chacha20poly1305.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define POLY1305_BLOCKSIZE 16
+#define POLY1305_TAGSIZE 16
+#define POLY1305_KEYSIZE 32
+
+void Poly1305InitForAsm(Poly1305Ctx *ctx);
+uint32_t Poly1305Block(Poly1305Ctx *ctx, const uint8_t *data, uint32_t dataLen, uint32_t padbit);
+void Poly1305Last(Poly1305Ctx *ctx, uint8_t mac[POLY1305_TAGSIZE]);
+void Poly1305CleanRegister(void);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_sha2.h
+ * Description: SHA2自研算法头文件,源码引用于HICRYPTO组件自研SHA2算法
+ * Author: liushaoming
+ * Create: 2022-02-11
+ */
+
+#ifndef CRYPT_SHA2_H
+#define CRYPT_SHA2_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cpluscplus */
+
+
+/** @defgroup LLF SHA2 Low level function */
+
+#ifndef HITLS_CRYPTO_NO_SHA224
+/* SHA2-224 */
+#define CRYPT_SHA2_224_BLOCKSIZE 64
+#define CRYPT_SHA2_224_DIGESTSIZE 28
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA256
+/* SHA2-256 */
+#define CRYPT_SHA2_256_BLOCKSIZE 64
+#define CRYPT_SHA2_256_DIGESTSIZE 32
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA384
+/* SHA2-384 */
+#define CRYPT_SHA2_384_BLOCKSIZE 128
+#define CRYPT_SHA2_384_DIGESTSIZE 48
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA512
+/* SHA2-512 */
+#define CRYPT_SHA2_512_BLOCKSIZE 128
+#define CRYPT_SHA2_512_DIGESTSIZE 64
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA256
+/* SHA2 256 ctx */
+typedef struct {
+ uint32_t h[CRYPT_SHA2_256_DIGESTSIZE / sizeof(uint32_t)]; /* 256 bits for SHA256 state */
+ uint32_t block[CRYPT_SHA2_256_BLOCKSIZE / sizeof(uint32_t)]; /* 512 bits block cache */
+ uint32_t lNum, hNum; /* input bits counter, max 2^64 bits */
+ uint32_t blocklen; /* block length */
+ uint32_t outlen; /* digest output length */
+ uint32_t errorCode; /* error Code */
+} CRYPT_SHA2_256_Ctx;
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA224
+/* SHA2 224 ctx */
+typedef CRYPT_SHA2_256_Ctx CRYPT_SHA2_224_Ctx;
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA512
+/* SHA2 512 ctx */
+typedef struct {
+ uint64_t h[CRYPT_SHA2_512_DIGESTSIZE / sizeof(uint64_t)];
+ uint8_t block[CRYPT_SHA2_512_BLOCKSIZE];
+ uint64_t lNum, hNum;
+ uint32_t num, mdlen;
+ uint32_t errorCode; /* error Code */
+} CRYPT_SHA2_512_Ctx;
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA384
+/* SHA2 384 ctx */
+typedef CRYPT_SHA2_512_Ctx CRYPT_SHA2_384_Ctx;
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA224
+/**
+ * @defgroup CRYPT_SHA2_224_Init
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_224_Init(CRYPT_SHA2_224_Ctx *ctx)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to initialize the SHA224 ctx for a digest operation.
+ *
+ * @par Description
+ * CRYPT_SHA2_224_Init function initializes the ctx for a digest operation. This function must be called before
+ * CRYPT_SHA2_224_Update or CRYPT_SHA2_224_Final operations. This function will not allocate memory for any of the
+ * ctx variables. Instead the caller is expected to pass a ctx pointer pointing to a valid memory location
+ * (either locally or dynamically allocated).
+ *
+ * @param[in] ctx The sha224 ctx [N/A]
+ *
+ * @retval #CRYPT_SUCCESS ctx is initialized
+ * @retval #CRYPT_NULL_INPUT ctx is NULL
+ */
+int32_t CRYPT_SHA2_224_Init(CRYPT_SHA2_224_Ctx *ctx);
+
+/**
+ * @defgroup CRYPT_SHA2_224_Update
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_224_Update(CRYPT_SHA2_224_Ctx *ctx, const uint8_t *data, usize_t nbytes)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to perform sha224 digest operation on chunks of data.
+ *
+ * @par Description
+ * CRYPT_SHA2_224_Update function performs digest operation on chunks of data. This method of digesting is used when
+ * data is present in multiple buffers or not available all at once. CRYPT_SHA2_224_Init must have been called before
+ * calling this function.
+ *
+ * @param[in] ctx The sha224 ctx [N/A]
+ * @param[in] data The input data [N/A]
+ * @param[in] nbytes The input data length [N/A]
+ *
+ * @retval #CRYPT_SUCCESS If partial digest is calculated
+ * @retval #CRYPT_NULL_INPUT input arguments is NULL
+ * @retval #CRYPT_SHA2_ERR_OVERFLOW input message is overflow
+ */
+int32_t CRYPT_SHA2_224_Update(CRYPT_SHA2_224_Ctx *ctx, const uint8_t *data, uint32_t nbytes);
+
+/**
+ * @defgroup CRYPT_SHA2_224_Final
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_224_Final(CRYPT_SHA2_224_Ctx *ctx, uint8_t *digest, uint32_t *len)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to complete sha224 digest operation on remaining data, and is
+ * called at the end of digest operation.
+ *
+ * @par Description
+ * CRYPT_SHA2_224_Final function completes digest operation on remaining data, and is called at the end of digest
+ * operation. CRYPT_SHA2_224_Init must have been called before calling this function. This function calculates the
+ * digest. The memory for digest must already have been allocated.
+ *
+ * @param[in] ctx The sha224 ctx [N/A]
+ * @param[out] digest The digest [N/A]
+ *
+ * @retval #CRYPT_SUCCESS If partial digest is calculated
+ * @retval #CRYPT_NULL_INPUT input arguments is NULL
+ * @retval #CRYPT_SHA2_ERR_OVERFLOW input message is overflow
+ * @retval #CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH output buffer is not enough
+ */
+int32_t CRYPT_SHA2_224_Final(CRYPT_SHA2_224_Ctx *ctx, uint8_t *digest, uint32_t *len);
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA256
+/**
+ * @defgroup CRYPT_SHA2_256_Init
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_256_Init(CRYPT_SHA2_256_Ctx *ctx)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to initialize the SHA256 ctx for a digest operation.
+ *
+ * @par Description
+ * CRYPT_SHA2_256_Init function initializes the ctx for
+ * a digest operation. This function must be called before
+ * CRYPT_SHA2_256_Update or CRYPT_SHA2_256_Final operations. This function will not
+ * allocate memory for any of the ctx variables. Instead the caller is
+ * expected to pass a ctx pointer pointing to a valid memory location
+ * (either locally or dynamically allocated).
+ *
+ * @param[in] ctx The sha256 ctx [N/A]
+ *
+ * @retval #CRYPT_SUCCESS ctx is initialized
+ * @retval #CRYPT_NULL_INPUT ctx is NULL
+ */
+int32_t CRYPT_SHA2_256_Init(CRYPT_SHA2_256_Ctx *ctx);
+
+/**
+ * @defgroup CRYPT_SHA2_256_Update
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, usize_t nbytes)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to perform sha256 digest operation on chunks of data.
+ *
+ * @par Description
+ * CRYPT_SHA2_256_Update function performs digest operation on
+ * chunks of data. This method of digesting is used when data is
+ * present in multiple buffers or not available all at once.
+ * CRYPT_SHA2_256_Init must have been called before calling this
+ * function.
+ *
+ * @param[in] ctx The sha256 ctx [N/A]
+ * @param[in] data The input data [N/A]
+ * @param[in] nbytes The input data length [N/A]
+ *
+ * @retval #CRYPT_SUCCESS If partial digest is calculated
+ * @retval #CRYPT_NULL_INPUT input arguments is NULL
+ * @retval #CRYPT_SHA2_ERR_OVERFLOW input message is overflow
+ */
+int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint32_t nbytes);
+
+/**
+ * @defgroup CRYPT_SHA2_256_Final
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_256_Final(CRYPT_SHA2_256_Ctx *ctx, uint8_t *digest, uint32_t *len)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to complete sha256 digest operation on remaining data, and is
+ * called at the end of digest operation.
+ *
+ * @par Description
+ * CRYPT_SHA2_256_Final function completes digest operation on remaining data, and
+ * is called at the end of digest operation.
+ * CRYPT_SHA2_256_Init must have been called before calling this function. This
+ * function calculates the digest. The memory for digest must
+ * already have been allocated.
+ *
+ * @param[in] ctx The sha256 ctx [N/A]
+ * @param[out] digest The digest [N/A]
+ *
+ * @retval #CRYPT_SUCCESS If partial digest is calculated
+ * @retval #CRYPT_NULL_INPUT input arguments is NULL
+ * @retval #CRYPT_SHA2_ERR_OVERFLOW input message is overflow
+ * @retval #CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH output buffer is not enough
+ */
+int32_t CRYPT_SHA2_256_Final(CRYPT_SHA2_256_Ctx *ctx, uint8_t *digest, uint32_t *outlen);
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA384
+/**
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_384_Init(CRYPT_SHA2_384_Ctx *ctx)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to initialize the SHA384 ctx for a digest operation.
+ *
+ * @par Description
+ * CRYPT_SHA2_384_Init function initializes the ctx for a digest operation. This function must be called before
+ * CRYPT_SHA2_384_Update or CRYPT_SHA2_384_Final operations. This function will not allocate memory for any of the
+ * ctx variables. Instead the caller is expected to pass a ctx pointer pointing to a valid memory location
+ * (either locally or dynamically allocated).
+ *
+ * @param[in,out] ctx The sha384 ctx [N/A]
+ *
+ * @retval #CRYPT_SUCCESS ctx is initialized
+ * @retval #CRYPT_NULL_INPUT ctx is NULL
+ */
+int32_t CRYPT_SHA2_384_Init(CRYPT_SHA2_384_Ctx *ctx);
+
+/**
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_384_Update(CRYPT_SHA2_384_Ctx *ctx, const uint8_t *data, uint32_t nbytes)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to perform sha384 digest operation on chunks of data.
+ *
+ * @par Description
+ * CRYPT_SHA2_384_Update function performs digest operation on chunks of data. This method of digesting is used when
+ * data is present in multiple buffers or not available all at once. CRYPT_SHA2_384_Init must have been called before
+ * calling this function.
+ *
+ * @param[in,out] ctx The sha384 ctx [N/A]
+ * @param[in] data The input data [N/A]
+ * @param[in] nbytes The input data length [N/A]
+ *
+ * @retval #CRYPT_SUCCESS If partial digest is calculated
+ * @retval #CRYPT_NULL_INPUT input arguments is NULL
+ * @retval #CRYPT_SHA2_INPUT_OVERFLOW input message is overflow
+ * @retval #CRYPT_SECUREC_FAIL secure c function fail.
+ */
+int32_t CRYPT_SHA2_384_Update(CRYPT_SHA2_384_Ctx *ctx, const uint8_t *data, uint32_t nbytes);
+/**
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_384_Final(CRYPT_SHA2_384_Ctx *ctx, uint8_t *digest, uint32_t *len)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to complete sha384 digest operation on remaining data, and is
+ * called at the end of digest operation.
+ *
+ * @par Description
+ * CRYPT_SHA2_384_Final function completes digest operation on remaining data, and is called at the end of digest
+ * operation. CRYPT_SHA2_384_Init must have been called before calling this function. This function calculates the
+ * digest. The memory for digest must already have been allocated.
+ *
+ * @param[in,out] ctx The sha384 ctx [N/A]
+ * @param[out] digest The digest [N/A]
+ * @param[in,out] len length of buffer[N/A]
+ *
+ * @retval #CRYPT_SUCCESS If partial digest is calculated
+ * @retval #CRYPT_NULL_INPUT input arguments is NULL
+ * @retval #CRYPT_SHA2_INPUT_OVERFLOW input message is overflow
+ * @retval #CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH output buffer is not enough
+ */
+int32_t CRYPT_SHA2_384_Final(CRYPT_SHA2_384_Ctx *ctx, uint8_t *digest, uint32_t *len);
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA512
+/**
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_512_Init(CRYPT_SHA2_512_Ctx *ctx)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to initialize the SHA512 ctx for a digest operation.
+ *
+ * @par Description
+ * CRYPT_SHA2_512_Init function initializes the ctx for a digest operation. This function must be called before
+ * CRYPT_SHA2_512_Update or CRYPT_SHA2_512_Final operations. This function will not allocate memory for any of the
+ * ctx variable. Instead the caller is expected to pass a ctx pointer pointing to a valid memory location
+ * (either locally or dynamically allocated).
+ *
+ * @param[in,out] ctx The sha512 ctx [N/A]
+ *
+ * @retval #CRYPT_SUCCESS ctx is initialized
+ * @retval #CRYPT_NULL_INPUT ctx is NULL
+ */
+int32_t CRYPT_SHA2_512_Init(CRYPT_SHA2_512_Ctx *ctx);
+
+/**
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_512_Update(CRYPT_SHA2_512_Ctx *ctx, const uint8_t *data, usize_t nbytes)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to perform sha512 digest operation on chunks of data.
+ *
+ * @par Description
+ * CRYPT_SHA2_512_Update function performs digest operation on chunks of data. This method of digesting is used when
+ * data is present in multiple buffers or not available all at once. CRYPT_SHA2_512_Init must have been called before
+ * calling this function.
+ *
+ * @param[in,out] ctx The sha512 ctx [N/A]
+ * @param[in] data The input data [N/A]
+ * @param[in] nbytes The input data length [N/A]
+ *
+ * @retval #CRYPT_SUCCESS If partial digest is calculated
+ * @retval #CRYPT_NULL_INPUT input arguments is NULL
+ * @retval #CRYPT_SHA2_INPUT_OVERFLOW input message is overflow
+ * @retval #CRYPT_SECUREC_FAIL secure c function fail.
+ */
+int32_t CRYPT_SHA2_512_Update(CRYPT_SHA2_512_Ctx *ctx, const uint8_t *data, uint32_t nbytes);
+
+/**
+ * @ingroup LLF Low Level Functions
+ * @par Prototype
+ * @code
+ * int32_t CRYPT_SHA2_512_Final(CRYPT_SHA2_512_Ctx *ctx, uint8_t *digest, uint32_t *len)
+ * @endcode
+ *
+ * @par Purpose
+ * This is used to complete sha512 digest operation on remaining data, and is called at the end of digest operation.
+ *
+ * @par Description
+ * CRYPT_SHA2_512_Final function completes digest operation on remaining data, and is called at the end of digest
+ * operation. CRYPT_SHA2_512_Init must have been called before calling this function. This function calculates the
+ * digest. The memory for digest must already have been allocated.
+ *
+ * @param[in,out] ctx The sha512 ctx [N/A]
+ * @param[out] digest The digest [N/A]
+ * @param[in,out] len length of buffer[N/A]
+ *
+ * @retval #CRYPT_SUCCESS If partial digest is calculated
+ * @retval #CRYPT_NULL_INPUT input arguments is NULL
+ * @retval #CRYPT_SHA2_INPUT_OVERFLOW input message is overflow
+ * @retval #CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH output buffer is not enough
+ */
+int32_t CRYPT_SHA2_512_Final(CRYPT_SHA2_512_Ctx *ctx, uint8_t *digest, uint32_t *len);
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA224
+/**
+ * @ingroup LLF Low Level Functions
+ *
+ * @brief SHA224 deinit function
+ *
+ * @param[in,out] ctx The SHA224 ctx
+ */
+void CRYPT_SHA2_224_Deinit(CRYPT_SHA2_224_Ctx *ctx);
+
+int32_t CRYPT_SHA2_224_CopyCtx(CRYPT_SHA2_224_Ctx *dst, CRYPT_SHA2_224_Ctx *src);
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA256
+/**
+ * @ingroup LLF Low Level Functions
+ *
+ * @brief SHA256 deinit function
+ *
+ * @param[in,out] ctx The SHA256 ctx
+ */
+void CRYPT_SHA2_256_Deinit(CRYPT_SHA2_256_Ctx *ctx);
+
+int32_t CRYPT_SHA2_256_CopyCtx(CRYPT_SHA2_256_Ctx *dst, CRYPT_SHA2_256_Ctx *src);
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA384
+/**
+ * @ingroup LLF Low Level Functions
+ *
+ * @brief SHA384 deinit function
+ *
+ * @param[in,out] ctx The SHA384 ctx
+ */
+void CRYPT_SHA2_384_Deinit(CRYPT_SHA2_384_Ctx *ctx);
+
+int32_t CRYPT_SHA2_384_CopyCtx(CRYPT_SHA2_384_Ctx *dst, CRYPT_SHA2_384_Ctx *src);
+#endif
+
+#ifndef HITLS_CRYPTO_NO_SHA512
+/**
+ * @ingroup LLF Low Level Functions
+ *
+ * @brief SHA512 deinit function
+ *
+ * @param[in,out] ctx The SHA512 ctx
+ */
+void CRYPT_SHA2_512_Deinit(CRYPT_SHA2_512_Ctx *ctx);
+
+int32_t CRYPT_SHA2_512_CopyCtx(CRYPT_SHA2_512_Ctx *dst, CRYPT_SHA2_512_Ctx *src);
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
+ * @file noasm_sha256.c
+ * Description: SHA2自研算法实现,源码引用于HICRYPTO组件自研SHA2算法
+ */
+
+#ifndef HITLS_CRYPTO_NO_SHA256
+#include "crypt_sha2.h"
+#include "crypt_utils.h"
+#include "sha2_core.h"
+
+static const uint32_t K256[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
+};
+#define ROTR32(x, n) (((x) << (32 - (n))) | ((x) >> (n))) // Assumes that x is uint32_t and 0 < n < 32
+
+#define S0(x) (ROTR32((x), 7) ^ ROTR32((x), 18) ^ ((x) >> 3))
+#define S1(x) (ROTR32((x), 17) ^ ROTR32((x), 19) ^ ((x) >> 10))
+
+#define R(w, t) \
+ (S1((w)[(t) - 2]) + (w)[(t) - 7] + \
+ S0((w)[(t) - 15]) + (w)[(t) - 16])
+
+#define ROUND(a, b, c, d, e, f, g, h, i, k) \
+ do { \
+ /* constants: 6, 11, 25 */ \
+ (h) += (ROTR32((e), 6) ^ ROTR32((e), 11) ^ ROTR32((e), 25)) + \
+ ((g) ^ ((e) & ((f) ^ (g)))) + (k) + (i); \
+ (d) += (h); \
+ /* constants: 2, 13, 22 */ \
+ (h) += (ROTR32((a), 2) ^ ROTR32((a), 13) ^ ROTR32((a), 22)) + \
+ (((a) & ((b) | (c))) | ((b) & (c))); \
+ } while (0)
+
+static void CompressBlock(uint32_t state[8], const uint8_t block[CRYPT_SHA2_256_BLOCKSIZE])
+{
+ uint32_t w[64];
+
+ // RFC 6.2.1. Prepare the message schedule w:
+ // For t = 0 to 15
+ // Wt = M(i)t
+ for (unsigned i = 0; i < 16; i++) { // 16 rounds to prepare the message schedule
+ w[i] = GET_UINT32_BE(block, 4 * (i)); /* 4 means bytes of uint32_t */
+ }
+
+ // For t = 16 to 63
+ // Wt = SSIG1(w(t-2)) + w(t-7) + SSIG0(t-15) + w(t-16)
+ // @perf: speed up about 18% than expanded in x86_64
+
+ // RFC 6.2.2. Initialize the working variables:
+ // a, b, ..., g, h = H(i-1)[0..7]
+ uint32_t a = state[0]; // a = H(i-1)0
+ uint32_t b = state[1]; // b = H(i-1)1
+ uint32_t c = state[2]; // c = H(i-1)2
+ uint32_t d = state[3]; // d = H(i-1)3
+ uint32_t e = state[4]; // e = H(i-1)4
+ uint32_t f = state[5]; // f = H(i-1)5
+ uint32_t g = state[6]; // g = H(i-1)6
+ uint32_t h = state[7]; // h = H(i-1)7
+
+ // RFC 6.2.3. Perform the main hash computation:
+ for (unsigned i = 0; i < 16; i += 8) { /* 0 ~ 16 rounds to do hash computation, 8 rounds pre loop */
+ ROUND(a, b, c, d, e, f, g, h, w[i + 0], K256[i + 0]);
+ ROUND(h, a, b, c, d, e, f, g, w[i + 1], K256[i + 1]);
+ ROUND(g, h, a, b, c, d, e, f, w[i + 2], K256[i + 2]);
+ ROUND(f, g, h, a, b, c, d, e, w[i + 3], K256[i + 3]);
+ ROUND(e, f, g, h, a, b, c, d, w[i + 4], K256[i + 4]);
+ ROUND(d, e, f, g, h, a, b, c, w[i + 5], K256[i + 5]);
+ ROUND(c, d, e, f, g, h, a, b, w[i + 6], K256[i + 6]);
+ ROUND(b, c, d, e, f, g, h, a, w[i + 7], K256[i + 7]);
+ }
+
+ for (unsigned i = 16; i < 64; i += 8) { /* 16 ~ 64 rounds to do hash computation, 8 rounds pre loop */
+ w[i + 0] = R(w, i + 0); /* 8 rounds pre loop, the NO.1 computation shift 0 bytes */
+ ROUND(a, b, c, d, e, f, g, h, w[i + 0], K256[i + 0]);
+ w[i + 1] = R(w, i + 1); /* 8 rounds pre loop, the NO.2 computation shift 1 bytes */
+ ROUND(h, a, b, c, d, e, f, g, w[i + 1], K256[i + 1]);
+ w[i + 2] = R(w, i + 2); /* 8 rounds pre loop, the NO.3 computation shift 2 bytes */
+ ROUND(g, h, a, b, c, d, e, f, w[i + 2], K256[i + 2]);
+ w[i + 3] = R(w, i + 3); /* 8 rounds pre loop, the NO.4 computation shift 3 bytes */
+ ROUND(f, g, h, a, b, c, d, e, w[i + 3], K256[i + 3]);
+ w[i + 4] = R(w, i + 4); /* 8 rounds pre loop, the NO.5 computation shift 4 bytes */
+ ROUND(e, f, g, h, a, b, c, d, w[i + 4], K256[i + 4]);
+ w[i + 5] = R(w, i + 5); /* 8 rounds pre loop, the NO.6 computation shift 5 bytes */
+ ROUND(d, e, f, g, h, a, b, c, w[i + 5], K256[i + 5]);
+ w[i + 6] = R(w, i + 6); /* 8 rounds pre loop, the NO.7 computation shift 6 bytes */
+ ROUND(c, d, e, f, g, h, a, b, w[i + 6], K256[i + 6]);
+ w[i + 7] = R(w, i + 7); /* 8 rounds pre loop, the NO.8 computation shift 7 bytes */
+ ROUND(b, c, d, e, f, g, h, a, w[i + 7], K256[i + 7]);
+ }
+
+ // RFC 6.2.4. Compute the intermediate hash value H(i):
+ // H(i) = [a, b, ..., g, h] + H(i-1)[0..7]
+ state[0] += a; // H(i)0 = a + H(i-1)0
+ state[1] += b; // H(i)1 = b + H(i-1)1
+ state[2] += c; // H(i)2 = c + H(i-1)2
+ state[3] += d; // H(i)3 = d + H(i-1)3
+ state[4] += e; // H(i)4 = e + H(i-1)4
+ state[5] += f; // H(i)5 = f + H(i-1)5
+ state[6] += g; // H(i)6 = g + H(i-1)6
+ state[7] += h; // H(i)7 = h + H(i-1)7
+}
+#undef ROTR32
+#undef ROUND
+
+void SHA256CompressMultiBlocks(uint32_t hash[8], const uint8_t *in, uint32_t num)
+{
+ uint32_t n = num;
+ const uint8_t *p = in;
+ while (n > 0) {
+ CompressBlock(hash, p);
+ p += CRYPT_SHA2_256_BLOCKSIZE;
+ n--;
+ }
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @file crypt_sha2_256.c
+ * Description: SHA2自研算法实现,源码引用于HICRYPTO组件自研SHA2算法
+ * Author: liushaoming
+ * Create: 2022-02-14
+******************************************************************************/
+
+#ifndef HITLS_CRYPTO_NO_SHA256
+#include "crypt_sha2.h"
+#include <stdlib.h>
+#include "securec.h"
+#include "crypt_errno.h"
+#include "crypt_utils.h"
+#include "bsl_err_internal.h"
+#include "sha2_core.h"
+#include "sal_mem.h"
+
+// clang-format off
+#define BITS_PRE_BYTE 8 // bits per byte
+#define SHIFTS_PER_BYTE 3 // shifts per byte
+#define BITSIZE(t) (sizeof(t) * BITS_PRE_BYTE)
+
+// clang-format on
+
+int32_t CRYPT_SHA2_256_Init(CRYPT_SHA2_256_Ctx *ctx)
+{
+ if (ctx == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ (void)memset_s(ctx, sizeof(CRYPT_SHA2_256_Ctx), 0, sizeof(CRYPT_SHA2_256_Ctx));
+ /**
+ * @RFC 4634 6.1 SHA-224 and SHA-256 Initialization
+ * SHA-256, the initial hash value, H(0):
+ * H(0)0 = 6a09e667
+ * H(0)1 = bb67ae85
+ * H(0)2 = 3c6ef372
+ * H(0)3 = a54ff53a
+ * H(0)4 = 510e527f
+ * H(0)5 = 9b05688c
+ * H(0)6 = 1f83d9ab
+ * H(0)7 = 5be0cd19
+ */
+ ctx->h[0] = 0x6a09e667UL;
+ ctx->h[1] = 0xbb67ae85UL;
+ ctx->h[2] = 0x3c6ef372UL; // 第2位按照RFC 4634赋值
+ ctx->h[3] = 0xa54ff53aUL; // 第3位按照RFC 4634赋值
+ ctx->h[4] = 0x510e527fUL; // 第4位按照RFC 4634赋值
+ ctx->h[5] = 0x9b05688cUL; // 第5位按照RFC 4634赋值
+ ctx->h[6] = 0x1f83d9abUL; // 第6位按照RFC 4634赋值
+ ctx->h[7] = 0x5be0cd19UL; // 第7位按照RFC 4634赋值
+ ctx->outlen = CRYPT_SHA2_256_DIGESTSIZE;
+ return CRYPT_SUCCESS;
+}
+
+void CRYPT_SHA2_256_Deinit(CRYPT_SHA2_256_Ctx *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+ SAL_CleanseData((void *)(ctx), sizeof(CRYPT_SHA2_256_Ctx));
+}
+
+int32_t CRYPT_SHA2_256_CopyCtx(CRYPT_SHA2_256_Ctx *dst, CRYPT_SHA2_256_Ctx *src)
+{
+ if (dst == NULL || src == NULL) {
+ return CRYPT_NULL_INPUT;
+ }
+
+ (void)memcpy_s(dst, sizeof(CRYPT_SHA2_256_Ctx), src, sizeof(CRYPT_SHA2_256_Ctx));
+ return CRYPT_SUCCESS;
+}
+
+static uint32_t CheckIsCorrupted(CRYPT_SHA2_256_Ctx *ctx, uint32_t nbytes);
+static int32_t UpdateParamIsValid(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint32_t nbytes)
+{
+ /* NULL check */
+ if ((ctx == NULL) || (data == NULL && nbytes != 0)) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+
+ if (ctx->errorCode != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(CRYPT_SHA2_INPUT_OVERFLOW);
+ return CRYPT_SHA2_INPUT_OVERFLOW;
+ }
+
+ if (CheckIsCorrupted(ctx, nbytes) != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(CRYPT_SHA2_INPUT_OVERFLOW);
+ return CRYPT_SHA2_INPUT_OVERFLOW;
+ }
+
+ return CRYPT_SUCCESS;
+}
+
+static uint32_t CheckIsCorrupted(CRYPT_SHA2_256_Ctx *ctx, uint32_t nbytes)
+{
+ uint32_t cnt0 = (ctx->lNum + (nbytes << SHIFTS_PER_BYTE)) & 0xffffffffUL;
+ if (cnt0 < ctx->lNum) { /* overflow */
+ if (++ctx->hNum == 0) {
+ ctx->errorCode = CRYPT_SHA2_INPUT_OVERFLOW;
+ return CRYPT_SHA2_INPUT_OVERFLOW;
+ }
+ }
+ uint32_t cnt1 = ctx->hNum + (uint32_t)(nbytes >> (BITSIZE(uint32_t) - SHIFTS_PER_BYTE));
+ if (cnt1 < ctx->hNum) { /* overflow */
+ ctx->errorCode = CRYPT_SHA2_INPUT_OVERFLOW;
+ return CRYPT_SHA2_INPUT_OVERFLOW;
+ }
+ ctx->hNum = cnt1;
+ ctx->lNum = cnt0;
+ return CRYPT_SUCCESS;
+}
+
+int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint32_t nbytes)
+{
+ int32_t ret = UpdateParamIsValid(ctx, data, nbytes);
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+
+ if (nbytes == 0) {
+ return CRYPT_SUCCESS;
+ }
+
+ const uint8_t *d = data;
+ uint32_t left = nbytes;
+ uint32_t n = ctx->blocklen;
+ uint8_t *p = (uint8_t *)ctx->block;
+
+ if (left < CRYPT_SHA2_256_BLOCKSIZE - n) {
+ if (memcpy_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, d, left) != EOK) {
+ BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
+ return CRYPT_SECUREC_FAIL;
+ }
+ ctx->blocklen += (uint32_t)left;
+ return CRYPT_SUCCESS;
+ }
+ if ((n != 0) && (left >= CRYPT_SHA2_256_BLOCKSIZE - n)) {
+ if (memcpy_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, d, CRYPT_SHA2_256_BLOCKSIZE - n) != EOK) {
+ BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
+ return CRYPT_SECUREC_FAIL;
+ }
+ SHA256CompressMultiBlocks(ctx->h, p, 1);
+ n = CRYPT_SHA2_256_BLOCKSIZE - n;
+ d += n;
+ left -= n;
+ ctx->blocklen = 0;
+ (void)memset_s(p, CRYPT_SHA2_256_BLOCKSIZE, 0, CRYPT_SHA2_256_BLOCKSIZE);
+ }
+
+ n = (uint32_t)(left / CRYPT_SHA2_256_BLOCKSIZE);
+ if (n > 0) {
+ SHA256CompressMultiBlocks(ctx->h, d, n);
+ n *= CRYPT_SHA2_256_BLOCKSIZE;
+ d += n;
+ left -= n;
+ }
+
+ if (left != 0) {
+ ctx->blocklen = (uint32_t)left;
+ if (memcpy_s((uint8_t *)ctx->block, CRYPT_SHA2_256_BLOCKSIZE, d, left) != EOK) {
+ BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
+ return CRYPT_SECUREC_FAIL;
+ }
+ }
+
+ return CRYPT_SUCCESS;
+}
+
+static int32_t FinalParamIsValid(const CRYPT_SHA2_256_Ctx *ctx, const uint8_t *out, const uint32_t *outLen)
+{
+ if ((ctx == NULL) || (out == NULL) || (outLen == NULL)) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+
+ if (*outLen < ctx->outlen) {
+ BSL_ERR_PUSH_ERROR(CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH);
+ return CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH;
+ }
+
+ if (ctx->errorCode == CRYPT_SHA2_INPUT_OVERFLOW) {
+ BSL_ERR_PUSH_ERROR(CRYPT_SHA2_INPUT_OVERFLOW);
+ return CRYPT_SHA2_INPUT_OVERFLOW;
+ }
+
+ return CRYPT_SUCCESS;
+}
+int32_t CRYPT_SHA2_256_Final(CRYPT_SHA2_256_Ctx *ctx, uint8_t *digest, uint32_t *outlen)
+{
+ int32_t ret = FinalParamIsValid(ctx, digest, outlen);
+ if (ret != CRYPT_SUCCESS) {
+ BSL_ERR_PUSH_ERROR(ret);
+ return ret;
+ }
+
+ uint8_t *p = (uint8_t *)ctx->block;
+ uint32_t n = ctx->blocklen;
+
+ p[n++] = 0x80;
+ if (n > (CRYPT_SHA2_256_BLOCKSIZE - 8)) { /* 8 bytes to save bits of input */
+ (void)memset_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, 0, CRYPT_SHA2_256_BLOCKSIZE - n);
+ n = 0;
+ SHA256CompressMultiBlocks(ctx->h, p, 1);
+ }
+ (void)memset_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, 0,
+ CRYPT_SHA2_256_BLOCKSIZE - 8 - n); /* 8 bytes to save bits of input */
+
+ p += CRYPT_SHA2_256_BLOCKSIZE - 8; /* 8 bytes to save bits of input */
+ PUT_UINT32_BE(ctx->hNum, p, 0);
+ p += sizeof(uint32_t);
+ PUT_UINT32_BE(ctx->lNum, p, 0);
+ p += sizeof(uint32_t);
+ p -= CRYPT_SHA2_256_BLOCKSIZE;
+ SHA256CompressMultiBlocks(ctx->h, p, 1);
+ ctx->blocklen = 0;
+ (void)memset_s(p, CRYPT_SHA2_256_BLOCKSIZE, 0, CRYPT_SHA2_256_BLOCKSIZE);
+
+ n = ctx->outlen / sizeof(uint32_t);
+ for (uint32_t nn = 0; nn < n; nn++) {
+ PUT_UINT32_BE(ctx->h[nn], digest, sizeof(uint32_t) * nn);
+ }
+ *outlen = ctx->outlen;
+
+ return CRYPT_SUCCESS;
+}
+
+#ifndef HITLS_CRYPTO_NO_SHA224
+int32_t CRYPT_SHA2_224_Init(CRYPT_SHA2_224_Ctx *ctx)
+{
+ if (ctx == NULL) {
+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
+ return CRYPT_NULL_INPUT;
+ }
+ (void)memset_s(ctx, sizeof(CRYPT_SHA2_224_Ctx), 0, sizeof(CRYPT_SHA2_224_Ctx));
+ /**
+ * @RFC 4634 6.1 SHA-224 and SHA-256 Initialization
+ * SHA-224, the initial hash value, H(0):
+ * H(0)0 = c1059ed8
+ * H(0)1 = 367cd507
+ * H(0)2 = 3070dd17
+ * H(0)3 = f70e5939
+ * H(0)4 = ffc00b31
+ * H(0)5 = 68581511
+ * H(0)6 = 64f98fa7
+ * H(0)7 = befa4fa4
+ */
+ ctx->h[0] = 0xc1059ed8UL;
+ ctx->h[1] = 0x367cd507UL;
+ ctx->h[2] = 0x3070dd17UL; // 第2位按照RFC 4634赋值
+ ctx->h[3] = 0xf70e5939UL; // 第3位按照RFC 4634赋值
+ ctx->h[4] = 0xffc00b31UL; // 第4位按照RFC 4634赋值
+ ctx->h[5] = 0x68581511UL; // 第5位按照RFC 4634赋值
+ ctx->h[6] = 0x64f98fa7UL; // 第6位按照RFC 4634赋值
+ ctx->h[7] = 0xbefa4fa4UL; // 第7位按照RFC 4634赋值
+ ctx->outlen = CRYPT_SHA2_224_DIGESTSIZE;
+ return CRYPT_SUCCESS;
+}
+
+void CRYPT_SHA2_224_Deinit(CRYPT_SHA2_224_Ctx *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+ SAL_CleanseData((void *)(ctx), sizeof(CRYPT_SHA2_224_Ctx));
+}
+
+int32_t CRYPT_SHA2_224_CopyCtx(CRYPT_SHA2_224_Ctx *dst, CRYPT_SHA2_224_Ctx *src)
+{
+ if (dst == NULL || src == NULL) {
+ return CRYPT_NULL_INPUT;
+ }
+
+ (void)memcpy_s(dst, sizeof(CRYPT_SHA2_224_Ctx), src, sizeof(CRYPT_SHA2_224_Ctx));
+ return CRYPT_SUCCESS;
+}
+
+int32_t CRYPT_SHA2_224_Update(CRYPT_SHA2_224_Ctx *ctx, const uint8_t *data, uint32_t nbytes)
+{
+ return CRYPT_SHA2_256_Update((CRYPT_SHA2_256_Ctx *)ctx, data, nbytes);
+}
+
+int32_t CRYPT_SHA2_224_Final(CRYPT_SHA2_224_Ctx *ctx, uint8_t *digest, uint32_t *len)
+{
+ return CRYPT_SHA2_256_Final((CRYPT_SHA2_256_Ctx *)ctx, digest, len);
+}
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
+ * @file sha2_core.h
+ * Description: sha2 内部函数
+ */
+#ifndef SHA2_CORE_H
+#define SHA2_CORE_H
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef U64
+#define U64(v) (uint64_t)(v)
+#endif
+
+void SHA256CompressMultiBlocks(uint32_t hash[8], const uint8_t *in, uint32_t num);
+void SHA512CompressMultiBlocks(uint64_t hash[8], const uint8_t *bl, uint32_t bcnt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * @defgroup bsl_err bsl_err.h
+ * @ingroup bsl
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief 由产品调用,初始化、反初始化错误码模块,获取错误码,使用之前必
+ * 须要注册内存分配、释放相关函数,单线程环境可以不注册线程相关函数
+ */
+
+/** @defgroup bsl BSL */
+
+#ifndef BSL_ERR_H
+#define BSL_ERR_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "bsl_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup bsl_err
+ * @brief 错误码模块初始化
+ *
+ * @par 描述:
+ * 产品如果是单线程的,则该函数可调可不调;
+ * 产品如果是多线程的,则必须在进程初始化时调用,且必须在调用BSL_SAL_RegThreadCallback
+ * 之后调用。
+ *
+ * @attention 无
+ * @retval #BSL_SUCCESS 错误码模块初始化成功
+ * @retval #BSL_SAL_ERR_NO_MEMORY 内存空间不足,无法申请线程锁空间
+ * @retval #BSL_SAL_ERR_UNKNOWN 线程锁初始化失败
+ */
+int32_t BSL_ERR_Init(void);
+
+/**
+ * @ingroup bsl_err
+ * @brief 错误码模块反初始化
+ *
+ * @par 描述:
+ * 产品在进程退出时调用
+ *
+ * @attention 无
+ */
+void BSL_ERR_DeInit(void);
+
+/**
+ * @ingroup bsl_err
+ * @brief 删除错误栈
+ *
+ * @par 描述:
+ * 删除错误栈,在进程和线程退出时调用
+ *
+ * @attention 线程退出时必须要调用,否则会有内存泄漏
+ * @param isRemoveAll [IN] 是否删除全部错误栈,进程退出时用true,线程退出时用false
+ */
+void BSL_ERR_RemoveErrorStack(bool isRemoveAll);
+
+/**
+ * @ingroup bsl_err
+ * @brief 获取错误栈中最后一次push的错误码
+ *
+ * @par 描述:
+ * 产品在HiTLS某个接口发生错误后调用,获取错误码。可以一直调用,每次返回的错误码组成该接口发生错误
+ * 的错误栈,直到返回BSL_SUCCESS为止。
+ *
+ * @attention
+ * @return 错误码,高16位是发生错误的模块子模块id,低16位是原因号
+ */
+int32_t BSL_ERR_GetLastError(void);
+
+/**
+ * @ingroup bsl_err
+ * @brief 获取错误栈中最后一次push的错误码、文件名和行号
+ *
+ * @par 描述:
+ * 产品在HiTLS某个接口发生错误后调用,获取一个错误码,并且可以获取文件名和行号,这些已获取的信息会从错误栈中删除。
+ * 可以一直调用,每次返回的错误码组成该接口发生错误的错误栈,直到返回BSL_SUCCESS为止。
+ *
+ * @attention 两个参数其中任一为NULL则无法获取文件名和行号
+ * @param file [OUT] 用于获取发生错误的文件名,不含目录路径
+ * @param lineNo [OUT] 用于获取发生错误的文件行号
+ * @return 错误码,高16位是发生错误的模块子模块id,低16位是原因号
+ */
+int32_t BSL_ERR_GetLastErrorFileLine(const char **file, uint32_t *lineNo);
+
+/**
+ * @ingroup bsl_err
+ * @brief 获取错误栈中最后一次push的错误码、文件名和行号
+ *
+ * @par 描述:
+ * 产品在HiTLS某个接口发生错误后调用,获取一个错误码,并且可以获取文件名和行号,这些已获取的信息不会从错误栈中删除。
+ *
+ * @attention 两个参数其中任一为NULL则无法获取文件名和行号
+ * @param file [OUT] 用于获取发生错误的文件名,不含目录路径
+ * @param lineNo [OUT] 用于获取发生错误的文件行号
+ * @return 错误码,高16位是发生错误的模块子模块id,低16位是原因号
+ */
+int32_t BSL_ERR_PeekLastErrorFileLine(const char **file, uint32_t *lineNo);
+
+/**
+ * @ingroup bsl_err
+ * @brief 获取错误栈中最早一次push的错误码
+ *
+ * @par 描述:
+ * 产品在HiTLS某个接口发生错误后调用,获取错误码。可以一直调用,每次返回的错误码组成该接口发生错误
+ * 的错误栈,直到返回BSL_SUCCESS为止。
+ *
+ * @attention
+ * @return 错误码,高16位是发生错误的模块子模块id,低16位是原因号
+ */
+int32_t BSL_ERR_GetError(void);
+
+/**
+ * @ingroup bsl_err
+ * @brief 获取错误栈中最早一次push的错误码、文件名和行号
+ *
+ * @par 描述:
+ * 产品在HiTLS某个接口发生错误后调用,获取一个错误码,并且可以获取文件名和行号,这些已获取的信息会从错误栈中删除。
+ * 可以一直调用,每次返回的错误码组成该接口发生错误的错误栈,直到返回BSL_SUCCESS为止。
+ *
+ * @attention 两个参数其中任一为NULL则无法获取文件名和行号
+ * @param file [OUT] 用于获取发生错误的文件名,不含目录路径
+ * @param lineNo [OUT] 用于获取发生错误的文件行号
+ * @return 错误码,高16位是发生错误的模块子模块id,低16位是原因号
+ */
+int32_t BSL_ERR_GetErrorFileLine(const char **file, uint32_t *lineNo);
+
+/**
+ * @ingroup bsl_err
+ * @brief 获取错误栈中最早一次push的错误码、文件名和行号
+ *
+ * @par 描述:
+ * 产品在HiTLS某个接口发生错误后调用,获取一个错误码,并且可以获取文件名和行号,这些已获取的信息不会从错误栈中删除。
+ *
+ * @attention 两个参数其中任一为NULL则无法获取文件名和行号
+ * @param file [OUT] 用于获取发生错误的文件名,不含目录路径
+ * @param lineNo [OUT] 用于获取发生错误的文件行号
+ * @return 错误码,高16位是发生错误的模块子模块id,低16位是原因号
+ */
+int32_t BSL_ERR_PeekErrorFileLine(const char **file, uint32_t *lineNo);
+
+/**
+ * @ingroup bsl_err
+ * @brief 清除错误栈
+ *
+ * @par 描述:
+ * 在调用HiTLS接口后检测到错误,如果无需理会错误信息,那么在再次调用HiTLS接口之前应该调用本接口清理错误信息
+ *
+ * @attention 无
+ */
+void BSL_ERR_ClearError(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * @defgroup bsl_errno bsl_errno.h
+ * @ingroup bsl
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief BSL模块的函数返回值
+ */
+
+#ifndef BSL_ERRNO_H
+#define BSL_ERRNO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup bsl_errno
+ * @brief 返回成功
+ */
+#define BSL_SUCCESS 0
+
+/**
+ * @ingroup bsl_errno
+ *
+ * BSL模块的返回值从 0x03000000 ~ 0x03ffffff
+ */
+enum BSL_ERROR {
+ /* 通用返回值从0x03000000开始 */
+ BSL_NULL_INPUT = 0x03000000,
+ BSL_INTERNAL_EXCEPTION,
+ BSL_MEMCPY_FAIL,
+ BSL_MEMMOVE_FAIL,
+ BSL_ERROR_INPUT,
+
+ /* SAL子模块的返回值从0x03010001开始 */
+ BSL_SAL_ERR_UNKNOWN = 0x03010001, /**< 未知错误 */
+ BSL_SAL_ERR_NO_MEMORY, /**< 申请内存失败 */
+ BSL_SAL_ERR_BAD_PARAM, /**< 参数错误 */
+
+ /* LOG子模块的返回值从0x03020001开始 */
+ BSL_LOG_ERR_REG_FUNC_FAIL = 0x03020001, /**< 注册日志输出函数失败 */
+ BSL_LOG_ERR_BAD_PARAM, /**< 参数错误 */
+ BSL_LOG_ERR_MEMCPY_FAIL, /**< 内存拷贝失败 */
+
+ /* TLV子模块的返回值从0x03030001开始 */
+ BSL_TLV_ERR_BAD_PARAM = 0x03030001, /**< 参数错误 */
+ BSL_TLV_ERR_MEMCPY_FAIL, /**< 内存拷贝失败 */
+ BSL_TLV_ERR_NO_WANT_TYPE, /**< 没有找到TLV */
+
+ /* ERR子模块的返回值从0x03040001开始 */
+ BSL_ERR_ERR_ACQUIRE_READ_LOCK_FAIL = 0x03040001, /**< 获取读锁失败 */
+ BSL_ERR_ERR_ACQUIRE_WRITE_LOCK_FAIL,
+ BSL_ERR_ERR_NO_STACK,
+ BSL_ERR_ERR_NO_ERROR,
+ BSL_ERR_ERR_NO_MARK,
+
+ // 0x03050001 预留给time
+
+ /* UIO子模块的返回值从0x03060001开始 */
+ BSL_UIO_FAIL = 0x03060001,
+ BSL_UIO_IO_EXCEPTION,
+ BSL_UIO_IO_BUSY,
+ BSL_UIO_CTRL_INVALID_PARAM,
+ BSL_UIO_FILE_OPEN_FAIL,
+ BSL_UIO_MEM_GROW_FAIL,
+ BSL_UIO_REF_MAX,
+ BSL_UIO_MEM_ALLOC_FAIL,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * @defgroup bsl_log bsl_log.h
+ * @ingroup bsl
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief 由产品注册日志相关的函数
+ */
+
+#ifndef BSL_LOG_H
+#define BSL_LOG_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup bsl_log
+ *
+ * 审计日志级别
+ */
+#define BSL_LOG_LEVEL_SEC 0U
+
+/**
+ * @ingroup bsl_log
+ *
+ * 紧急日志级别
+ */
+#define BSL_LOG_LEVEL_FATAL 1U
+
+/**
+ * @ingroup bsl_log
+ *
+ * 错误日志级别
+ */
+#define BSL_LOG_LEVEL_ERR 2U
+
+/**
+ * @ingroup bsl_log
+ *
+ * 警告日志级别
+ */
+#define BSL_LOG_LEVEL_WARN 3U
+
+/**
+ * @ingroup bsl_log
+ *
+ * 信息日志级别
+ */
+#define BSL_LOG_LEVEL_INFO 4U
+
+/**
+ * @ingroup bsl_log
+ *
+ * 调试日志级别
+ */
+#define BSL_LOG_LEVEL_DEBUG 5U
+
+/**
+ * @ingroup bsl_log
+ *
+ * HiTLS版本字符串
+ */
+#ifndef HITLS_VERSION
+#define HITLS_VERSION ""
+#endif
+
+#define HITLS_VERSION_LEN 150
+
+/**
+ * @ingroup bsl_log
+ * @brief 获取HiTLS版本号
+ * @attention 接收版本字符串的空间长度versionLen必须大于等于HITLS_VERSION_LEN
+ * @param version [OUT] HiTLS当前版本号字符串
+ * @param versionLen [IN/OUT] HiTLS当前版本号字符串长度
+ * @retval BSL_SUCCESS 成功
+ * @retval BSL_LOG_ERR_MEMCPY 内存拷贝失败
+ */
+int32_t BSL_LOG_GetVersion(char *version, uint32_t *versionLen);
+
+/**
+ * @ingroup bsl_log
+ * @brief 打点日志类型,可扩展其它类型
+ */
+#define BSL_LOG_BINLOG_TYPE_RUN 0x01
+
+/**
+ * @ingroup bsl_log
+ * @brief 打点日志定长回调类型
+ */
+typedef void (*BSL_LOG_BinLogFixLenFunc)(uint32_t logId, uint32_t logLevel, uint32_t logType,
+ void *format, void *para1, void *para2, void *para3, void *para4);
+
+/**
+ * @ingroup bsl_log
+ * @brief 打点日志变长回调类型
+ */
+typedef void (*BSL_LOG_BinLogVarLenFunc)(uint32_t logId, uint32_t logLevel, uint32_t logType,
+ void *format, void *para);
+
+/**
+ * @ingroup bsl_log
+ * @brief 注册打点日志回调函数的参数类型
+ */
+typedef struct {
+ BSL_LOG_BinLogFixLenFunc fixLenFunc; // 4参回调
+ BSL_LOG_BinLogVarLenFunc varLenFunc; // 1参回调
+} BSL_LOG_BinLogFuncs;
+
+/**
+ * @ingroup bsl_log
+ * @brief 设置打点日志的定长和变长回调函数
+ * @attention 入参可为NULL
+ * @param funcs [IN] 打点日志回调函数指针集合体,不可为NULL,其成员可为NULL
+ * @retval BSL_SUCCESS 成功
+ */
+int32_t BSL_LOG_RegBinLogFunc(const BSL_LOG_BinLogFuncs *funcs);
+
+/**
+ * @ingroup bsl_log
+ * @brief 设置打点日志的日志级别
+ * @attention 级别必须要合法
+ * @param level [IN] 打点日志的级别,合法值为BSL_LOG_LEVEL_SEC、BSL_LOG_LEVEL_FATAL、BSL_LOG_LEVEL_ERR、
+ * BSL_LOG_LEVEL_WARN、BSL_LOG_LEVEL_INFO、BSL_LOG_LEVEL_DEBUG
+ * @retval BSL_SUCCESS 成功
+ * @retval BSL_LOG_ERR_BAD_PARAM 入参非法
+ */
+int32_t BSL_LOG_SetBinLogLevel(uint32_t level);
+
+/**
+ * @ingroup bsl_log
+ * @brief 获取打点日志的日志级别
+ * @return 打点日志的级别,合法值为BSL_LOG_LEVEL_SEC、BSL_LOG_LEVEL_FATAL、BSL_LOG_LEVEL_ERR、
+ * BSL_LOG_LEVEL_WARN、BSL_LOG_LEVEL_INFO、BSL_LOG_LEVEL_DEBUG
+ */
+uint32_t BSL_LOG_GetBinLogLevel(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * @defgroup bsl_sal bsl_sal.h
+ * @ingroup bsl
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief 系统抽象层,由产品注册系统相关的函数
+ */
+
+#ifndef BSL_SAL_H
+#define BSL_SAL_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup bsl_sal
+ *
+ * 产品为内存分配/释放可注册函数结构体
+ */
+typedef struct MemCallback {
+ /**
+ * @ingroup bsl_sal
+ * @brief 分配一块内存
+ *
+ * @par 描述:
+ * 分配一块内存
+ *
+ * @param size [IN] 分配内存的大小
+ * @retval 非NULL 内存分配成功,被分配内存的首地址
+ * @retval NULL 内存分配失败
+ */
+ void *(*pfMalloc)(uint32_t size);
+
+ /**
+ * @ingroup bsl_sal
+ * @brief 回收由pfMalloc分配的一块内存
+ *
+ * @par 描述:
+ * 回收由pfMalloc分配的一块内存
+ *
+ * @param addr [IN] 由pfMalloc分配的内存首地址
+ */
+ void (*pfFree)(void *addr);
+} BSL_SAL_MemCallback;
+
+/**
+ * @ingroup bsl_sal
+ *
+ * 线程锁句柄,在产品注册时由产品提供相应结构体
+ */
+typedef void *BSL_SAL_ThreadLockHandle;
+
+/**
+ * @ingroup bsl_sal
+ *
+ * 产品为线程相关操作可注册函数结构体
+ */
+typedef struct ThreadCallback {
+ /**
+ * @ingroup bsl_sal
+ * @brief 新建一个线程锁
+ *
+ * @par 描述:
+ * 新建一个线程锁
+ *
+ * @param lock [IN/OUT] 锁句柄
+ * @retval #BSL_SUCCESS 新建成功
+ * @retval #BSL_SAL_ERR_NO_MEMORY 内存空间不足,无法申请线程锁空间
+ * @retval #BSL_SAL_ERR_UNKNOWN 线程锁初始化失败
+ * @retval #BSL_SAL_ERR_BAD_PARAM 参数错误,lock为NULL
+ */
+ int32_t (*pfThreadLockNew)(BSL_SAL_ThreadLockHandle *lock);
+
+ /**
+ * @ingroup bsl_sal
+ * @brief 释放线程锁
+ *
+ * @par 描述:
+ * 释放线程锁,要保证在有其它线程获得锁的情况下,释放锁是没有问题的
+ *
+ * @param lock [IN] 锁句柄
+ */
+ void (*pfThreadLockFree)(BSL_SAL_ThreadLockHandle lock);
+
+ /**
+ * @ingroup bsl_sal
+ * @brief 锁住读操作
+ *
+ * @par 描述:
+ * 锁住读操作
+ *
+ * @param lock [IN] 锁句柄
+ * @retval #BSL_SUCCESS 成功
+ * @retval #BSL_SAL_ERR_UNKNOWN 操作失败
+ * @retval #BSL_SAL_ERR_BAD_PARAM 参数错误,lock为NULL
+ */
+ int32_t (*pfThreadReadLock)(BSL_SAL_ThreadLockHandle lock);
+
+ /**
+ * @ingroup bsl_sal
+ * @brief 锁住写操作
+ *
+ * @par 描述:
+ * 锁住写操作
+ *
+ * @param lock [IN] 锁句柄
+ * @retval #BSL_SUCCESS 成功
+ * @retval #BSL_SAL_ERR_UNKNOWN 操作失败
+ * @retval #BSL_SAL_ERR_BAD_PARAM 参数错误,lock为NULL
+ */
+ int32_t (*pfThreadWriteLock)(BSL_SAL_ThreadLockHandle lock);
+
+ /**
+ * @ingroup bsl_sal
+ * @brief 解锁
+ *
+ * @par 描述:
+ * 解锁
+ *
+ * @param lock [IN] 锁句柄
+ * @retval #BSL_SUCCESS 成功
+ * @retval #BSL_SAL_ERR_UNKNOWN 操作失败
+ * @retval #BSL_SAL_ERR_BAD_PARAM 参数错误,lock为NULL
+ */
+ int32_t (*pfThreadUnlock)(BSL_SAL_ThreadLockHandle lock);
+
+ /**
+ * @ingroup bsl_sal
+ * @brief 获取线程id
+ *
+ * @par 描述:
+ * 获取线程id
+ *
+ * @return 线程id
+ */
+ uint64_t (*pfThreadGetId)(void);
+} BSL_SAL_ThreadCallback;
+
+/**
+ * @ingroup bsl_sal
+ * @brief 内存相关回调函数注册接口
+ *
+ * @par 描述:
+ * 注册内存申请、释放函数
+ *
+ * @attention 无
+ * @param cb [IN] 内存相关回调函数指针
+ * @retval #BSL_SUCCESS 内存申请、释放函数注册成功
+ * @retval #BSL_SAL_ERR_BAD_PARAM 0x02010003,cb为NULL或者cb的成员有NULL,请仔细填写cb指针
+ */
+int32_t BSL_SAL_RegMemCallback(BSL_SAL_MemCallback *cb);
+
+/**
+ * @ingroup bsl_sal
+ * @brief 线程相关回调函数注册接口
+ *
+ * @par 描述:
+ * 注册线程锁创建、释放、加锁、解锁、获取线程id相关函数。
+ * 如果产品是单线程的,则不能调用;
+ * 如果产品是多线程的,则必须调用。
+ *
+ * @attention 无
+ * @param cb [IN] 线程相关回调函数指针
+ * @retval #BSL_SUCCESS 线程相关函数注册成功
+ * @retval #BSL_SAL_ERR_BAD_PARAM 0x02010003,cb为NULL或者cb的成员有NULL,请仔细填写cb指针
+ */
+int32_t BSL_SAL_RegThreadCallback(BSL_SAL_ThreadCallback *cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * @defgroup bsl_uio bsl_uio.h
+ * @ingroup bsl
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief 统一IO抽象
+ */
+
+#ifndef BSL_UIO_H
+#define BSL_UIO_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief UIO模块控制结构
+ */
+typedef struct UIO_ControlBlock BSL_UIO;
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 传输协议枚举
+ */
+typedef enum {
+ BSL_UIO_TCP, /**< TCP协议 */
+ BSL_UIO_UDP, /**< UDP协议 */
+ BSL_UIO_SCTP, /**< SCTP协议 */
+ BSL_UIO_UNKNOWN, /**< 未知协议,不应出现 */
+} BSL_UIO_TransportType;
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief Sctp auth key, hitls通过BSL_UIO_Method.ctrl方法传入 BSL_UIO_SCTP_ADD_AUTH_SHARED_KEY 指令
+ * 以通知用户需要设置auth key
+ */
+typedef struct {
+ uint16_t shareKeyId; /**< share key id */
+ uint16_t authKeySize; /**< auth key size */
+ const uint8_t *authKey; /**< auth key */
+} BSL_UIO_SctpAuthKey;
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief BSL_UIO_CtrlParameter 控制IO的回调,hitls通知用户需要实现的功能
+ * 可用作ctrl回调的cmd参数
+ */
+typedef enum {
+ /* 公共的使用0x0xx */
+ BSL_UIO_SET_PEER_IP_ADDR = 0x000,
+ BSL_UIO_GET_PEER_IP_ADDR,
+ BSL_UIO_SET_FD,
+ BSL_UIO_GET_FD,
+
+ /* SCTP 使用0x3XX */
+ BSL_UIO_SCTP_CHECK_PEER_AUTH = 0x300, /**< SCTP检查对端是否支持认证 */
+ BSL_UIO_SCTP_ADD_AUTH_SHARED_KEY, /**< 添加新的sctp auth key,sctp可以用新的key接收数据 */
+ BSL_UIO_SCTP_ACTIVE_AUTH_SHARED_KEY, /**< 激活新的sctp auth key,sctp需要用新的key发送数据 */
+ BSL_UIO_SCTP_DEL_PRE_AUTH_SHARED_KEY, /**< SCTP删除上个shared key */
+ BSL_UIO_SCTP_SND_BUFF_IS_EMPTY, /**< SCTP发送队列是否已为空, ctrl.param为(uint8_t *)的指针
+ 当用户返回ctrl.param大于0,表明队列是为空. 反之等于0,表明队列不为空 */
+ BSL_UIO_SCTP_RECV_BUFF_IS_EMPTY, /**< SCTP接收队列是否已为空, ctrl.param为(uint8_t *)的指针
+ 当用户返回ctrl.param大于0,表明队列是为空. 反之等于0,表明队列不为空 */
+ BSL_UIO_SCTP_GET_SEND_STREAM_ID,
+ BSL_UIO_SCTP_SET_APP_STREAM_ID,
+} BSL_UIO_CtrlParameter;
+
+typedef struct {
+ uint8_t *addr;
+ uint32_t size;
+} BSL_UIO_CtrlGetPeerIpAddrParam;
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief BSL_UIO_Method是控制IO的回调,需要产品注册给HITLS以供HITLS底层调用
+ */
+typedef struct BSL_UIO_MethodStruct {
+ BSL_UIO_TransportType type;
+ int32_t (*write)(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen); /**< UIO写函数 */
+ int32_t (*read)(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen); /**< UIO读函数 */
+ int32_t (*ctrl)(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg); /**< UIO控制函数 */
+} BSL_UIO_Method;
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 创建一个新的UIO对象。
+ * @param method [IN] UIO方法结构体
+ * @retval UIO对象 创建成功
+ * @retval NULL UIO创建失败
+ */
+BSL_UIO *BSL_UIO_New(const BSL_UIO_Method *method);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 释放UIO对象。
+ * @param uio [IN] UIO对象。
+ */
+void BSL_UIO_Free(BSL_UIO *uio);
+
+/**
+ * @brief 按cmd处理特定的UIO实现
+ * @details 如果HiTLS无某个cmd的默认实现,则会调uio的ctrl回调
+ *
+ * @param uio [IN] UIO 对象
+ * @param cmd [IN] 不同的cmd对UIO对象执行不同的操作,必须有HiTLS实现或自定义实现
+ * @param larg [IN] parg的大小,数组为元素个数,指针为指向类型的大小,由cmd决定,详见下
+ * @param parg [IN/OUT] 由cmd决定,详见下
+ * @retval BSL_SUCCESS 成功
+ * @retval 非BSL_SUCCESS 具体参见bsl_errno.h
+ *
+ * @brief 在UIO对象中设置对端ip地址。
+ * @details 设置的地址格式为网络字节序二进制地址,长度为4或者16。
+ * 将为dtls的HelloVerifyRequest所用而提供生成cookie。
+ * @param uio [IN] UIO 对象
+ * @param cmd [IN] BSL_UIO_SET_PEER_IP_ADDR
+ * @param larg [IN] 对端地址的大小:长度应为4或者16。
+ * @param parg [IN] 对端地址。
+ *
+ * @brief 在UIO对象中获取对端ip地址。
+ * @details 获取的地址格式为网络字节序二进制地址,输入长度应大于设置的大小。
+ * 目的将为dtls的HelloVerifyRequest所用而提供生成cookie
+ * @param uio [IN] UIO 对象
+ * @param cmd [IN] BSL_UIO_GET_PEER_IP_ADDR
+ * @param larg [IN] sizeof(BSL_UIO_CtrlGetPeerIpAddrParam)
+ * @param parg [IN] BSL_UIO_CtrlGetPeerIpAddrParam *,其中:
+ * addr [IN/OUT] 对端地址,
+ * size [IN/OUT] IN: 输入缓存的大小 OUT: 输出对端地址的大小。
+ *
+ * @brief 在UIO对象中获取sctp发送的stream id
+ * @details 在需要用户在 BSL_UIO_Method.write中调用,并根据获取的stream id去发送sctp消息
+ * @param uio [IN] UIO 对象
+ * @param cmd [IN] BSL_UIO_SCTP_GET_SEND_STREAM_ID
+ * @param larg [IN] sizeof(uint16_t)
+ * @param parg [IN/OUT] 发送的流id,uint16_t *类型
+ *
+ * @brief 在UIO对象中设置sctp发送的app消息stream id
+ * @details 若用户需要对业务消息走特定的stream id, 则可以调用此接口
+ * @param uio [IN] UIO 对象
+ * @param cmd [IN] BSL_UIO_SCTP_SET_APP_STREAM_ID
+ * @param larg [IN] sizeof(uint16_t)
+ * @param parg [IN] uint16_t指针,指向app流id
+ *
+ * @brief 获取fd
+ * @details 如果UIO对象的底层有fd,则可以获取fd
+ * @param uio [IN] UIO 对象
+ * @param cmd [IN] BSL_UIO_GET_FD
+ * @param larg [IN] sizeof(int32_t)
+ * @param parg [IN/OUT] int32_t类型的指针,用于存放获取的fd
+ *
+ * @brief 设置fd
+ * @details 如果UIO对象的底层有fd,则可以设置fd
+ * @param uio [IN] UIO 对象
+ * @param cmd [IN] BSL_UIO_SET_FD
+ * @param larg [IN] sizeof(int32_t)
+ * @param parg [IN] int32_t类型的指针,用于指向被设置的fd
+ */
+int32_t BSL_UIO_Ctrl(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 获取UIO传输协议类型。
+ * @param uio [IN] UIO 对象。
+ * @return 协议类型
+ */
+BSL_UIO_TransportType BSL_UIO_GetTransportType(const BSL_UIO *uio);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 在UIO对象中设置用户数据。
+ * @details UIO will not modify the user data, user can add some information
+ * for the UIO, and get the information by use BSL_UIO_GetUserData function; After you set user data by calling
+ * BSL_UIO_SetUserData, you need to call BSL_UIO_SetUserData again before calling BSL_UIO_Free to set
+ * user data to null to ensure that all memory is released.
+ * @param uio [IN] UIO 对象。
+ * @param data [IN] 用户数据指针
+ * @retval BSL_SUCCESS 成功
+ * @retval BSL_NULL_INPUT 无效空指针
+ */
+int32_t BSL_UIO_SetUserData(BSL_UIO *uio, void *data);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 获取UIO对象中的用户数据。
+ * @details The user data comes from users, and tls will not change any thing
+ * for user data, user can add some customize information.
+ * @param uio [IN] UIO 对象。
+ * @retval 用户存储的数据结构指针 获取成功
+ * @retval NULL 获取的数据不存在
+ */
+void *BSL_UIO_GetUserData(const BSL_UIO *uio);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 在UIO对象中设置对端ip地址。
+ * @details 设置的地址格式为网络字节序二进制地址,长度为4或者16。 \n
+ * 如果为DTLS 服务器并且使能cookie交换, 则用该对端ip地址用来生成cookie \n
+ * 以让服务器通过发送HelloVerifyRequest给客户端.
+ * @param uio [IN] UIO 对象。
+ * @param addr [IN] addr 对端IP地址。
+ * @param size [IN] size 对端地址的大小:长度应为4或者16。
+ * @retval BSL_SUCCESS 成功
+ * @retval BSL_NULL_INPUT 无效空指针
+ * @retval BSL_UIO_FAIL 设置失败,长度不正确
+ */
+int32_t BSL_UIO_SetPeerIpAddr(BSL_UIO *uio, uint8_t *addr, uint32_t size);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 在UIO对象中获取对端ip地址。
+ * @details 获取的地址格式为网络字节序二进制地址,输入长度应大于设置的大小。 \n
+ * 目的:为dtls服务器的HelloVerifyRequest所用(生成cookie的输入因子)
+ * @param uio [IN] UIO 对象。
+ * @param addr [IN] addr 对端地址。
+ * @param size [IN/OUT] size IN: 输入缓存的大小 OUT: 输出对端地址的大小。
+ * @retval BSL_SUCCESS 成功
+ * @retval BSL_NULL_INPUT 无效空指针
+ * @retval BSL_UIO_FAIL 获取失败,未设置地址或长度不正确
+ */
+int32_t BSL_UIO_GetPeerIpAddr(BSL_UIO *uio, uint8_t *addr, uint32_t *size);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 在UIO对象中获取sctp发送的stream id
+ * @details 如果为DTLS OVER SCTP, 发送数据时SCTP应该从HITLS获取发送的流id,按该流id发送数据。 \n
+ * 非业务数据在DTLS协议规定使用流id为0发送数据。 \n
+ * 至于业务数据(app data)用户可以通过BSL_UIO_SctpSetAppStreamId 设置业务数据发送的流id。
+ * @attention 如果为DTLS OVER SCTP, 用户需要在 BSL_UIO_Method.write中调用,并根据获取的stream id去发送sctp消息。
+ * @param uio [IN] UIO 对象。
+ * @param sendStreamId [OUT] sendStreamId 发送的流id。
+ * @retval BSL_SUCCESS 成功
+ * @retval BSL_NULL_INPUT 无效空指针
+ */
+int32_t BSL_UIO_SctpGetSendStreamId(BSL_UIO *uio, uint16_t *sendStreamId);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 在UIO对象中设置sctp发送的app消息stream id
+ * @details 若用户需要对业务消息走特定的stream id, 则可以调用此接口
+ *
+ * @param uio [IN] UIO 对象。
+ * @param sendAppStreamId [OUT] sendAppStreamId 发送的app流id。
+ * @retval BSL_SUCCESS 成功
+ * @retval BSL_NULL_INPUT 无效空指针
+ */
+int32_t BSL_UIO_SctpSetAppStreamId(BSL_UIO *uio, uint16_t sendAppStreamId);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 为UIO对象设置文件描述符fd。
+ * @param uio [IN] UIO 对象。
+ * @param fd [IN] 文件描述符, 对于TCP/UDP是socket fd, 对于SCTP是偶联id。
+ * @retval BSL_SUCCESS 设置成功
+ * @retval BSL_NULL_INPUT 入参空指针
+ */
+int32_t BSL_UIO_SetFd(BSL_UIO *uio, int32_t fd);
+
+/**
+ * @ingroup bsl_uio
+ *
+ * @brief 获取UIO对象中的文件描述符fd。
+ * @param uio [IN] UIO 对象
+ * @retval -1 获取失败
+ * @retval 其他值 文件描述符fd
+ */
+int32_t BSL_UIO_GetFd(BSL_UIO *uio);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**\r
+ * @defgroup crypt_algid crypt_algid.h\r
+ * @ingroup crypto\r
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.\r
+ * @brief 通用类型对外接口\r
+ */\r
+\r
+#ifndef CRYPT_ALGID_H\r
+#define CRYPT_ALGID_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+/**\r
+ * @ingroup crypt_algid\r
+ * RAND 算法ID\r
+ */\r
+typedef enum {\r
+ CRYPT_RAND_SHA1 = 0,\r
+ CRYPT_RAND_SHA224,\r
+ CRYPT_RAND_SHA256,\r
+ CRYPT_RAND_SHA384,\r
+ CRYPT_RAND_SHA512,\r
+ CRYPT_RAND_HMAC_SHA1,\r
+ CRYPT_RAND_HMAC_SHA224,\r
+ CRYPT_RAND_HMAC_SHA256,\r
+ CRYPT_RAND_HMAC_SHA384,\r
+ CRYPT_RAND_HMAC_SHA512,\r
+ CRYPT_RAND_AES128_CTR,\r
+ CRYPT_RAND_AES192_CTR,\r
+ CRYPT_RAND_AES256_CTR,\r
+ CRYPT_RAND_AES128_CTR_DF,\r
+ CRYPT_RAND_AES192_CTR_DF,\r
+ CRYPT_RAND_AES256_CTR_DF,\r
+ CRYPT_RAND_ALGID_MAX\r
+} CRYPT_RAND_AlgId;\r
+\r
+/**\r
+ * @ingroup crypt_algid\r
+ * 哈希算法ID\r
+ */\r
+typedef enum {\r
+ CRYPT_MD_MD4 = 0,\r
+ CRYPT_MD_MD5,\r
+ CRYPT_MD_SHA1,\r
+ CRYPT_MD_SHA224,\r
+ CRYPT_MD_SHA256,\r
+ CRYPT_MD_SHA384,\r
+ CRYPT_MD_SHA512,\r
+ CRYPT_MD_SHA3_224,\r
+ CRYPT_MD_SHA3_256,\r
+ CRYPT_MD_SHA3_384,\r
+ CRYPT_MD_SHA3_512,\r
+ CRYPT_MD_SHAKE128,\r
+ CRYPT_MD_SHAKE256,\r
+ CRYPT_MD_SM3,\r
+ CRYPT_MD_MAX\r
+} CRYPT_MD_AlgId;\r
+\r
+/**\r
+ * @ingroup crypt_algid\r
+ * MAC算法ID\r
+ */\r
+typedef enum {\r
+ CRYPT_MAC_HMAC_MD5 = 0,\r
+ CRYPT_MAC_HMAC_SHA1,\r
+ CRYPT_MAC_HMAC_SHA224,\r
+ CRYPT_MAC_HMAC_SHA256,\r
+ CRYPT_MAC_HMAC_SHA384,\r
+ CRYPT_MAC_HMAC_SHA512,\r
+ CRYPT_MAC_HMAC_SM3,\r
+ CRYPT_MAC_CMAC_AES128,\r
+ CRYPT_MAC_CMAC_AES192,\r
+ CRYPT_MAC_CMAC_AES256,\r
+ CRYPT_MAC_GMAC_AES128,\r
+ CRYPT_MAC_GMAC_AES192,\r
+ CRYPT_MAC_GMAC_AES256,\r
+ CRYPT_MAC_SIPHASH64,\r
+ CRYPT_MAC_SIPHASH128,\r
+ CRYPT_MAC_MAX\r
+} CRYPT_MAC_AlgId;\r
+\r
+/**\r
+ * @ingroup crypt_algid\r
+ * 非对称算法ID\r
+ */\r
+typedef enum {\r
+ CRYPT_PKEY_DSA = 0,\r
+ CRYPT_PKEY_ED25519,\r
+ CRYPT_PKEY_X25519,\r
+ CRYPT_PKEY_RSA,\r
+ CRYPT_PKEY_DH,\r
+ CRYPT_PKEY_ECDSA,\r
+ CRYPT_PKEY_ECDH,\r
+ CRYPT_PKEY_SM2,\r
+ CRYPT_PKEY_ED448,\r
+ CRYPT_PKEY_X448,\r
+ CRYPT_PKEY_SM9,\r
+ CRYPT_PKEY_MAX\r
+} CRYPT_PKEY_AlgId;\r
+\r
+/**\r
+ * @ingroup cipher_algid\r
+ * 对称加解密模式组合算法ID\r
+ */\r
+typedef enum {\r
+ CRYPT_CIPHER_AES128_CBC = 0,\r
+ CRYPT_CIPHER_AES192_CBC,\r
+ CRYPT_CIPHER_AES256_CBC,\r
+\r
+ CRYPT_CIPHER_AES128_CTR,\r
+ CRYPT_CIPHER_AES192_CTR,\r
+ CRYPT_CIPHER_AES256_CTR,\r
+\r
+ CRYPT_CIPHER_AES128_ECB,\r
+ CRYPT_CIPHER_AES192_ECB,\r
+ CRYPT_CIPHER_AES256_ECB,\r
+\r
+ CRYPT_CIPHER_AES128_XTS,\r
+ CRYPT_CIPHER_AES256_XTS,\r
+\r
+ CRYPT_CIPHER_AES128_CCM,\r
+ CRYPT_CIPHER_AES192_CCM,\r
+ CRYPT_CIPHER_AES256_CCM,\r
+\r
+ CRYPT_CIPHER_AES128_GCM,\r
+ CRYPT_CIPHER_AES192_GCM,\r
+ CRYPT_CIPHER_AES256_GCM,\r
+\r
+ CRYPT_CIPHER_CHACHA20_POLY1305,\r
+\r
+ CRYPT_CIPHER_SM4_CBC,\r
+ CRYPT_CIPHER_SM4_ECB,\r
+\r
+ CRYPT_CIPHER_AES128_CFB,\r
+ CRYPT_CIPHER_AES192_CFB,\r
+ CRYPT_CIPHER_AES256_CFB,\r
+\r
+ CRYPT_CIPHER_AES128_OFB,\r
+ CRYPT_CIPHER_AES192_OFB,\r
+ CRYPT_CIPHER_AES256_OFB,\r
+ \r
+ CRYPT_CIPHER_TDES_ECB,\r
+ CRYPT_CIPHER_TDES_CBC,\r
+ CRYPT_CIPHER_TDES_OFB,\r
+ CRYPT_CIPHER_TDES_CFB,\r
+\r
+ CRYPT_CIPHER_SM4_CTR,\r
+ CRYPT_CIPHER_SM4_GCM,\r
+\r
+ CRYPT_CIPHER_MAX,\r
+} CRYPT_CIPHER_AlgId;\r
+\r
+/**\r
+ * @ingroup crypt_algid\r
+ * 非对称算法参数ID,高16位为算法标识,低16位映射对应算法LowLevel的ID定义\r
+ */\r
+typedef enum {\r
+ CRYPT_DH_RFC2409_768,\r
+ CRYPT_DH_RFC2409_1024,\r
+ CRYPT_DH_RFC3526_1536,\r
+ CRYPT_DH_RFC3526_2048,\r
+ CRYPT_DH_RFC3526_3072,\r
+ CRYPT_DH_RFC3526_4096,\r
+ CRYPT_DH_RFC3526_6144,\r
+ CRYPT_DH_RFC3526_8192,\r
+ CRYPT_DH_RFC7919_2048,\r
+ CRYPT_DH_RFC7919_3072,\r
+ CRYPT_DH_RFC7919_4096,\r
+ CRYPT_DH_RFC7919_6144,\r
+ CRYPT_DH_RFC7919_8192,\r
+ CRYPT_ECC_NISTP224,\r
+ CRYPT_ECC_NISTP256,\r
+ CRYPT_ECC_NISTP384,\r
+ CRYPT_ECC_NISTP521,\r
+ CRYPT_ECC_SM2,\r
+ CRYPT_ECC_SM9,\r
+ CRYPT_ECC_PARAID_MAX,\r
+ CRYPT_PKEY_PARAID_MAX\r
+} CRYPT_PKEY_ParaId;\r
+\r
+/**\r
+ * @ingroup crypt_algid\r
+ * 椭圆曲线点编码格式\r
+ */\r
+typedef enum {\r
+ CRYPT_POINT_COMPRESSED,\r
+ CRYPT_POINT_UNCOMPRESSED, // 默认格式\r
+ CRYPT_POINT_HYBRID,\r
+ CRYPT_POINT_MAX\r
+} CRYPT_PKEY_PointFormat;\r
+\r
+/**\r
+ * @ingroup crypt_algid\r
+ * KDF算法ID\r
+ */\r
+typedef enum {\r
+ CRYPT_KDF_SCRYPT = 0,\r
+ CRYPT_KDF_PBKDF2,\r
+ CRYPT_KDF_KDFTLS12,\r
+ CRYPT_KDF_HKDF,\r
+ CRYPT_KDF_MAX\r
+} CRYPT_KDF_AlgId;\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+#endif // CRYPT_ALGID_H\r
--- /dev/null
+/**
+ * @defgroup crypt_check_macro crypt_check_macro.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief 检查宏之间的依赖关系
+ */
+
+#ifndef CRYPT_CHECK_MACRO_H
+#define CRYPT_CHECK_MACRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#if !defined(HITLS_CRYPTO_NO_PKEY) && \
+ defined(HITLS_CRYPTO_NO_MD)
+#error "HITLS_CRYPTO_NO_PKEY not defined, but HITLS_CRYPTO_NO_MD defined."
+#endif
+
+#if defined(HITLS_CRYPTO_HMAC) && \
+ defined(HITLS_CRYPTO_NO_MD)
+#error "HITLS_CRYPTO_HMAC defined, but HITLS_CRYPTO_NO_MD also defined."
+#endif
+
+#if !defined(HITLS_CRYPTO_NO_RAND) && !defined(HITLS_CRYPTO_NO_DRBG_HASH) && \
+ defined(HITLS_CRYPTO_NO_MD)
+#error "Hash Func in eal-rand should be controlled by HITLS_CRYPTO_NO_DRBG_HASH, not by HITLS_CRYPTO_NO_MD."
+#endif
+
+#if defined(HITLS_CRYPTO_SHA1) && \
+ defined(HITLS_CRYPTO_NO_MD)
+#error "HITLS_CRYPTO_SHA1 defined, but HITLS_CRYPTO_NO_MD also defined."
+#endif
+
+#if defined(HITLS_CRYPTO_SHA2) && \
+ defined(HITLS_CRYPTO_NO_MD)
+#error "HITLS_CRYPTO_SHA2 defined, but HITLS_CRYPTO_NO_MD also defined."
+#endif
+
+#if defined(HITLS_CRYPTO_SHA3) && \
+ defined(HITLS_CRYPTO_NO_MD)
+#error "HITLS_CRYPTO_SHA3 defined, but HITLS_CRYPTO_NO_MD also defined."
+#endif
+
+#if defined(HITLS_CRYPTO_MD5) && \
+ defined(HITLS_CRYPTO_NO_MD)
+#error "HITLS_CRYPTO_MD5 defined, but HITLS_CRYPTO_NO_MD also defined."
+#endif
+
+#if defined(HITLS_CRYPTO_SM3) && \
+ defined(HITLS_CRYPTO_NO_MD)
+#error "HITLS_CRYPTO_SM3 defined, but HITLS_CRYPTO_NO_MD also defined."
+#endif
+
+#if !defined(HITLS_CRYPTO_NO_SHA224) && \
+ defined(HITLS_CRYPTO_NO_SHA256)
+#error "HITLS_CRYPTO_NO_SHA224 not defined, but HITLS_CRYPTO_NO_SHA256 also defined."
+#endif
+
+#if !defined(HITLS_CRYPTO_NO_SHA384) && \
+ defined(HITLS_CRYPTO_NO_SHA512)
+#error "HITLS_CRYPTO_NO_SHA384 not defined, but HITLS_CRYPTO_NO_SHA512 also defined."
+#endif
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif // CRYPT_CHECK_MACRO_H
--- /dev/null
+/**
+ * @defgroup crypt_eal_bn crypt_eal_bn.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
+ * @brief 大数运算对外接口
+ */
+
+#ifndef CRYPT_EAL_BN_H
+#define CRYPT_EAL_BN_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "crypt_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct BigNum CRYPT_BN_BigNum;
+
+typedef struct BnMont CRYPT_BN_Mont;
+
+typedef struct BnOptimizer CRYPT_BN_Optimizer;
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数创建
+ *
+ * @param bits [IN] 位数
+ *
+ * @retval 非NULL 成功
+ * @retval NULL 失败
+ */
+CRYPT_BN_BigNum *CRYPT_EAL_BN_Create(uint32_t bits);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数销毁
+ *
+ * @param a [IN] 大数
+ *
+ * @retval 无
+ */
+void CRYPT_EAL_BN_Destroy(CRYPT_BN_BigNum *a);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数优化器创建
+ *
+ * @retval 非NULL 成功
+ * @retval NULL 失败
+ */
+CRYPT_BN_Optimizer *CRYPT_EAL_BN_OptimizerCreate(void);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数优化器销毁
+ *
+ * @param opt [IN] 大数优化器
+ *
+ * @retval 无
+ */
+void CRYPT_EAL_BN_OptimizerDestroy(CRYPT_BN_Optimizer *opt);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 设置符号
+ *
+ * @param a [IN] 大数
+ * @param sign [IN] 符号,true为负数 false为正数
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_NO_NEGATIVE_ZERO 0不能设置为负数符号
+ */
+int32_t CRYPT_EAL_BN_SetSign(CRYPT_BN_BigNum *a, bool sign);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 判断大数的值是否为1
+ *
+ * @attention 大数入参不能为空指针
+ * @param a [IN] 大数
+ *
+ * @retval true,大数的值为1
+ * @retval false,大数的值不为1
+ *
+ */
+bool CRYPT_EAL_BN_IsOne(const CRYPT_BN_BigNum *a);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 判断大数是否为负数
+ *
+ * @attention 大数入参不能为空指针
+ * @param a [IN] 大数
+ *
+ * @retval true,大数的值为负数
+ * @retval false,大数的值不为负数
+ *
+ */
+bool CRYPT_EAL_BN_IsNegative(const CRYPT_BN_BigNum *a);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数加法
+ *
+ * @param r [OUT] 和
+ * @param a [IN] 加数
+ * @param b [IN] 加数
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_SPACE_NOT_ENOUGH 空间不够
+ */
+int32_t CRYPT_EAL_BN_Add(CRYPT_BN_BigNum *r, const CRYPT_BN_BigNum *a, const CRYPT_BN_BigNum *b);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数减法
+ *
+ * @param r [OUT] 差
+ * @param a [IN] 被减数
+ * @param b [IN] 减数
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_SPACE_NOT_ENOUGH 空间不够
+ */
+int32_t CRYPT_EAL_BN_Sub(CRYPT_BN_BigNum *r, const CRYPT_BN_BigNum *a, const CRYPT_BN_BigNum *b);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数乘法
+ *
+ * @param r [OUT] 乘积
+ * @param a [IN] 乘数
+ * @param b [IN] 乘数
+ * @param opt [IN] 优化器
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_SPACE_NOT_ENOUGH 空间不够
+ * @retval CRYPT_CRYPT_BN_Optimizer_GET_FAIL 从优化器申请空间失败
+ */
+int32_t CRYPT_EAL_BN_Mul(
+ CRYPT_BN_BigNum *r, const CRYPT_BN_BigNum *a, const CRYPT_BN_BigNum *b, CRYPT_BN_Optimizer *opt);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数除法
+ *
+ * @param q [OUT] 商
+ * @param r [OUT] 余数
+ * @param x [IN] 被除数
+ * @param y [IN] 除数
+ * @param opt [IN] 优化器
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_SPACE_NOT_ENOUGH 空间不够
+ * @retval CRYPT_CRYPT_BN_Optimizer_GET_FAIL 从优化器申请空间失败
+ * @retval CRYPT_BN_ERR_DIVISOR_ZERO 除数不能为0
+ */
+int32_t CRYPT_EAL_BN_Div(CRYPT_BN_BigNum *q, CRYPT_BN_BigNum *r, const CRYPT_BN_BigNum *x, const CRYPT_BN_BigNum *y,
+ CRYPT_BN_Optimizer *opt);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数求最大公约数
+ * @par 描述: gcd(a,b) (a、b!=0)
+ *
+ * @param r [OUT] 最大公约数
+ * @param a [IN] 大数
+ * @param b [IN] 大数
+ * @param opt [IN] 优化器
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_SPACE_NOT_ENOUGH 空间不够
+ * @retval CRYPT_CRYPT_BN_Optimizer_GET_FAIL 从优化器申请空间失败
+ * @retval CRYPT_BN_ERR_GCD_NO_ZERO 求最大公约数不能有0
+ */
+int32_t CRYPT_EAL_BN_Gcd(
+ CRYPT_BN_BigNum *r, const CRYPT_BN_BigNum *a, const CRYPT_BN_BigNum *b, CRYPT_BN_Optimizer *opt);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数模逆
+ *
+ * @param r [OUT] 结果
+ * @param x [IN] 大数
+ * @param m [IN] 模
+ * @param opt [IN] 优化器
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_SPACE_NOT_ENOUGH 空间不够
+ * @retval CRYPT_CRYPT_BN_Optimizer_GET_FAIL 从优化器申请空间失败
+ * @retval CRYPT_BN_ERR_NO_INVERSE 无法求出模逆
+ */
+int32_t CRYPT_EAL_BN_ModInv(
+ CRYPT_BN_BigNum *r, const CRYPT_BN_BigNum *x, const CRYPT_BN_BigNum *m, CRYPT_BN_Optimizer *opt);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 二进制转大数
+ *
+ * @param r [OUT] 大数
+ * @param bin [IN] 待转换数据流
+ * @param binLen [IN] 数据流长度
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_SPACE_NOT_ENOUGH 空间不够
+ */
+int32_t CRYPT_EAL_BN_Bin2Bn(CRYPT_BN_BigNum *r, const uint8_t *bin, uint32_t binLen);
+
+/**
+ * @ingroup crypt_eal_bn
+ * @brief 大数转二进制
+ *
+ * @param a [IN] 大数
+ * @param bin [IN/OUT] 待转换数据流 --传入指针不能为空
+ * @param binLen [IN/OUT] 数据流长度 --传入时也是bin缓存区的长度
+ *
+ * @retval CRYPT_SUCCESS
+ * @retval CRYPT_NULL_INPUT 无效空指针
+ * @retval CRYPT_BN_SPACE_NOT_ENOUGH 空间不够
+ * @retval CRYPT_SECUREC_FAIL 拷贝出错
+ */
+int32_t CRYPT_EAL_BN_Bn2Bin(const CRYPT_BN_BigNum *a, uint8_t *bin, uint32_t *binLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * @defgroup crypt_eal_cipher crypt_eal_cipher.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief 对称加解密算法对外接口
+ */
+
+#ifndef CRYPT_EAL_CIPHER_H
+#define CRYPT_EAL_CIPHER_H
+
+#ifndef HITLS_CRYPTO_NO_CIPHER
+#include <stdint.h>
+#include <stdbool.h>
+#include "crypt_algid.h"
+#include "crypt_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef struct CRYPT_EAL_CipherCtxLocal CRYPT_EAL_CipherCtx;
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 对称合规判断
+ *
+ * @param id [IN] 对称算法id
+ *
+ * @return true 成功
+ * false 失败
+ */
+typedef bool (*CRYPT_EAL_CipherC2)(CRYPT_CIPHER_AlgId id);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 对称合规判断回调注册接口,用于判断算法参数是否合规和模块状态是否可用,EAL的哈希接口在执行操作前会调用该回调
+ * 回调失败会导致CRYPT_EAL_CipherNewCtx/CRYPT_EAL_CipherInit/CRYPT_EAL_CipherReinit/
+ * CRYPT_EAL_CipherUpdate/CRYPT_EAL_CipherFinal/CRYPT_EAL_CipherCtrl/CRYPT_EAL_CipherSetPadding接口失败
+ * 非核准模式下可以使用任意算法
+ * ISO19790模式下只允许CRYPT_CIPHER_AES128_CBC/CRYPT_CIPHER_AES192_CBC/CRYPT_CIPHER_AES256_CBC/
+ * CRYPT_CIPHER_AES128_CTR/CRYPT_CIPHER_AES192_CTR/CRYPT_CIPHER_AES256_CTR/
+ * CRYPT_CIPHER_AES128_ECB/CRYPT_CIPHER_AES192_ECB/CRYPT_CIPHER_AES256_ECB/
+ * CRYPT_CIPHER_AES128_XTS/CRYPT_CIPHER_AES256_XTS
+ *
+ * @param func [IN] 对称合规判断回调
+ *
+ * @return 无
+ */
+void CRYPT_EAL_RegCipherC2(CRYPT_EAL_CipherC2 func);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 生成对称加解密句柄
+ *
+ * @param id [IN] 对称加解密算法id
+ * @return 成功返回:cipher ctx
+ * 失败返回:NULL
+ */
+CRYPT_EAL_CipherCtx* CRYPT_EAL_CipherNewCtx(CRYPT_CIPHER_AlgId id);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 释放对称加解密句柄,先清除敏感信息再释放
+ *
+ * @param ctx [IN] 对称加解密句柄, ctx由调用方置空
+ * @return 无
+ */
+void CRYPT_EAL_CipherFreeCtx(CRYPT_EAL_CipherCtx *ctx);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 初始化对称加解密句柄, key不能为NULL;除了ECB模式,其他模式iv不能为NULL
+ * iv的长度必须与块长度一致(ECB模式不做此要求),
+ * 块长度可以通过CRYPT_EAL_CipherCtrl的CRYPT_CTRL_GET_BLOCKSIZE获取。
+ * CRYPT_EAL_CipherInit 在任意阶段可以重复调用,会重置key和iv, 并清除缓存数据。
+ * <table border="1">
+ * <tr><th> 算法ID </th><th> keyLen </th><th> ivLen </th></tr>
+ * <tr><td> CRYPT_CIPHER_AES128_CBC </td><td> 16 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES192_CBC </td><td> 24 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES256_CBC </td><td> 32 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES128_CTR </td><td> 16 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES192_CTR </td><td> 24 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES256_CTR </td><td> 32 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES128_ECB </td><td> 16 </td><td> 0 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES192_ECB </td><td> 24 </td><td> 0 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES256_ECB </td><td> 32 </td><td> 0 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES128_XTS </td><td> 32 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES256_XTS </td><td> 64 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES128_CCM </td><td> 16 </td><td> 7 <= ivLen <= 13 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES192_CCM </td><td> 24 </td><td> 7 <= ivLen <= 13 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES256_CCM </td><td> 32 </td><td> 7 <= ivLen <= 13 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES128_GCM </td><td> 16 </td><td> 1 ≤ ivLen ≤ 2^32 - 1 (byte) </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES192_GCM </td><td> 24 </td><td> 1 ≤ ivLen ≤ 2^32 - 1 (byte) </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES256_GCM </td><td> 32 </td><td> 1 ≤ ivLen ≤ 2^32 - 1 (byte) </td></tr>
+ * <tr><td> CRYPT_CIPHER_CHACHA20_POLY1305 </td><td> 32 </td><td> 8或12 </td></tr>
+ * <tr><td> CRYPT_CIPHER_SM4_CBC </td><td> 16 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_SM4_ECB </td><td> 16 </td><td> 0 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES128_CFB </td><td> 16 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES192_CFB </td><td> 24 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES256_CFB </td><td> 32 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES128_OFB </td><td> 16 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES192_OFB </td><td> 24 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_AES256_OFB </td><td> 32 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_TDES_ECB </td><td> 24 </td><td> 0 </td></tr>
+ * <tr><td> CRYPT_CIPHER_TDES_CBC </td><td> 24 </td><td> 8或24 </td></tr>
+ * <tr><td> CRYPT_CIPHER_TDES_OFB </td><td> 24 </td><td> 8或24 </td></tr>
+ * <tr><td> CRYPT_CIPHER_TDES_CFB </td><td> 24 </td><td> 8或24 </td></tr>
+ * <tr><td> CRYPT_CIPHER_SM4_CTR </td><td> 16 </td><td> 16 </td></tr>
+ * <tr><td> CRYPT_CIPHER_SM4_GCM </td><td> 16 </td><td> 1 ≤ ivLen ≤ 2^32 - 1 (byte) </td></tr>
+ * </table>
+ *
+ * @param ctx [IN] 对称加解密句柄
+ * @param key [IN] 密钥
+ * @param keyLen [IN] 密钥长度
+ * @param iv [IN] 初始化向量
+ * @param ivLen [IN] 初始化向量长度
+ * @param enc [IN] true 为加密, false 为解密
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_CipherInit(CRYPT_EAL_CipherCtx *ctx, const uint8_t *key, uint32_t keyLen, const uint8_t *iv,
+ uint32_t ivLen, bool enc);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 反初始化句柄,还原句柄到刚调用完CRYPT_EAL_CipherNewCtx的状态
+ *
+ * @param ctx [IN] 对称加解密句柄
+ * @return 无
+ */
+void CRYPT_EAL_CipherDeinit(CRYPT_EAL_CipherCtx *ctx);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 重新初始化句柄,保留 key, 重新设置iv, 清除缓存、敏感数据; 除了ECB模式,其他模式iv不能为NULL
+ * iv的设置需要结合对应的算法ID, 参见CRYPT_EAL_CipherInit中的对应关系。
+ *
+ * @param ctx [IN] 对称加解密句柄
+ * @param iv [IN] 向量
+ * @param ivlen [IN] 向量的长度
+ * @return 无
+ */
+int32_t CRYPT_EAL_CipherReinit(CRYPT_EAL_CipherCtx *ctx, uint8_t *iv, uint32_t ivLen);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 持续输入加密、解密数据
+ * CRYPT_EAL_CipherUpdate 应与CRYPT_EAL_CipherFinal配合使用,在一次或多次调用完CRYPT_EAL_CipherUpdate后,
+ * 调用CRYPT_EAL_CipherFinal 获取最终的加密数据。
+ *
+ * @param ctx [IN] 对称加解密句柄
+ * @param in [IN] 持续输入的数据
+ * @param inLen [IN] 持续输入数据的长度
+ * @param out [OUT] 输出的数据
+ * @param outLen [IN/OUT] 输入: CBC、ECB块加密 建议输入outLen > inLen + blockSize, CTR、XTS流加密 建议 outLen >= inLen
+ * blockSize 可使用CRYPT_EAL_CipherCtrl 的CRYPT_CTRL_GET_BLOCKSIZE获取
+ * 输出 : 输出加密数据的长度, 如果是块加密算法且最后待处理数据不足块长度时,outLen输出为0;
+ * eg: CBC、ECB块加密
+ * 1. 首次输入加密数据,且inLen < blockSize 此时outLen输出为0
+ * 2. 首次输入的加密数据长度inLen为blockSize的整数倍 此时outLen 等于 inLen
+ * 3. 首次输入的加密数据长度inLen > blockSize 且不是blockSize的整数倍 此时outLen < inLen
+ * 4. 多次输入加密数据,(inLen % blockSize) + cache(ctx缓存数据) >= blockSize
+ * 此时outLen = (inlen / blockSize) * blockSize + blockSize
+ * CTR outLen 等于 inLen
+ * XTS 模式update会预留最后2 个block到final进行处理, 如果输入数据加上缓存的总长度不足2 * blocksize, 则输出为0
+ * 1. 首次输入数据 此时outLen = (inLen / blocksize - 2) * blocksize
+ * 2. 多次输入加密数据 此时outLen = ((inLen + cache) / blocksize - 2) * blocksize
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_CipherUpdate(CRYPT_EAL_CipherCtx *ctx, const uint8_t *in, uint32_t inLen, uint8_t *out,
+ uint32_t *outLen);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 对不足块大小的数据进行充填,输出加密数据;AEAD的tag通过CRYPT_EAL_CipherCtrl获取
+ * 对于CBC、ECB等块加密算法,必须设置padding, XTS模式需要调用final得到最后2个block数据
+ *
+ * @param ctx [IN] 对称加解密句柄
+ * @param out [OUT] 输出加密数据
+ * @param outLen [IN/OUT] 输入:outLen >= blockSize
+ * 输出:流加密输出为0。
+ * CBC、ECB块加密设置了padding则outLen输出为blockSize
+ * CBC、ECB块加密没设置padding, 且ctx中有缓存数据,则报错
+ * CBC、ECB块加密没设置padding,且ctx中无缓存数据, outLen输出为0
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_CipherFinal(CRYPT_EAL_CipherCtx *ctx, uint8_t *out, uint32_t *outLen);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 设置ctx里面的mode ctx的参数
+ * <table border="1">
+ * <tr><th> 参数 </th><th> 数据类型 </th><th> len的长度(data的字节数) </th></tr>
+ * <tr><td> CRYPT_CTRL_GET_IV </td><td> uint8_t数组 </td><td> IV的长度跟对应算法有关,参见 CRYPT_EAL_CipherInit 中的对应关系 </td></tr>
+ * <tr><td> CRYPT_CTRL_SET_IV </td><td> uint8_t数组 </td><td> IV的长度跟对应算法有关,参见 CRYPT_EAL_CipherInit 中的对应关系 </td></tr>
+ * <tr><td> CRYPT_CTRL_SET_AAD </td><td> uint8_t数组 </td><td> 仅限AEAD计算使用,长度和对应AEAD算法有关 </td></tr>
+ * <tr><td> CRYPT_CTRL_GET_TAG </td><td> uint8_t数组 </td><td> 仅限AEAD计算使用,长度为用户设置的tagLen </td></tr>
+ * <tr><td> CRYPT_CTRL_SET_COUNT </td><td> uint8_t[4] </td><td> len长度为 4 </td></tr>
+ * <tr><td> CRYPT_CTRL_SET_TAGLEN </td><td> uint32_t </td><td> len长度为 4 </td></tr>
+ * <tr><td> CRYPT_CTRL_SET_MSGLEN </td><td> uint64_t </td><td> len长度为 8 </td></tr>
+ * <tr><td> CRYPT_CTRL_SET_FEEDBACKSIZE </td><td> uint32_t </td><td> len长度为 4 </td></tr>
+ * <tr><td> CRYPT_CTRL_GET_FEEDBACKSIZE </td><td> uint32_t指针 </td><td> sizeof(*uint32_t) </td></tr>
+ * <tr><td> CRYPT_CTRL_GET_BLOCKSIZE </td><td> uint32_t </td><td> len长度为 4 </td></tr>
+ * <tr><td> CRYPT_CTRL_SET_SM4_CONSTTIME </td><td> NULL </td><td> 0 </td></tr>
+ * </table>
+ * @param ctx [IN] 对称加解密句柄
+ * @param type [IN] 参数类型
+ * @param data [IN/OUT] 输入、输出数据
+ * @param len [OUT] 数据长度
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_CipherCtrl(CRYPT_EAL_CipherCtx *ctx, CRYPT_CipherCtrl type, void *data, uint32_t len);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 设置padding模式
+ *
+ * @param ctx 对称加解密句柄
+ * @param type padding类型
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_CipherSetPadding(CRYPT_EAL_CipherCtx *ctx, CRYPT_PaddingType type);
+
+/**
+ * @ingroup crypt_eal_cipher
+ * @brief 获取padding类型
+ *
+ * @param ctx 对称加解密句柄
+ * @return 返回模式
+ */
+int32_t CRYPT_EAL_CipherGetPadding(CRYPT_EAL_CipherCtx *ctx);
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
+#endif
--- /dev/null
+/**\r
+ * @defgroup crypt_eal_kdf crypt_eal_kdf.h\r
+ * @ingroup crypto\r
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.\r
+ * @brief 密钥派生(KDF)算法头文件\r
+ */\r
+\r
+#ifndef CRYPT_EAL_KDF_H\r
+#define CRYPT_EAL_KDF_H\r
+\r
+#ifndef HITLS_CRYPTO_NO_KDF\r
+\r
+#include <stdbool.h>\r
+#include <stdint.h>\r
+#include "crypt_algid.h"\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief scrypt 基于密码的密钥派生函数\r
+ *\r
+ * @param key [IN] 密码,用户输入的字符串\r
+ * @param keyLen [IN] 密码长度,任意长度,包括0长度\r
+ * @param salt [IN] 盐值,用户输入的字符串\r
+ * @param saltLen [IN] 盐值长度,任意长度,包括0长度\r
+ * @param n [IN] CPU和内存消耗参数,必须为2的幂次,大于1,小于2 ^ (128 * r / 8)\r
+ * @param r [IN] 块大小参数,不为0的任意正整数,其中 r * p < 2 ^ 30\r
+ * @param p [IN] 并行化参数,不为0的任意正整数,p <= (2 ^ 32 - 1) * 32 / (128 * r)\r
+ * @param out [OUT] 派生密钥,不能为空\r
+ * @param len [IN] 派生密钥长度,取值范围为 (0, 0xFFFFFFFF]\r
+ *\r
+ * @return 成功返回:CRYPT_SUCCESS\r
+ * 其他错误码,请查询crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_Scrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *salt, uint32_t saltLen, uint32_t n,\r
+ uint32_t r, uint32_t p, uint8_t *out, uint32_t len);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief PBKDF 基于密码的密钥派生函数\r
+ *\r
+ * @param id [IN] HMAC算法ID(仅支持CRYPT_MAC_HMAC_SHA1、CRYPT_MAC_HMAC_SHA224、\r
+ * CRYPT_MAC_HMAC_SHA256、CRYPT_MAC_HMAC_SHA384、CRYPT_MAC_HMAC_SHA512)\r
+ * @param key [IN] 密码,用户输入的字符串\r
+ * @param keyLen [IN] 密码长度,任意长度,包括0长度。\r
+ * @param salt [IN] 盐值,用户输入的字符串\r
+ * @param saltLen [IN] 盐值长度,任意长度,包括0长度。\r
+ * @param it [IN] 迭代次数,可以为任意不为0的正整数,其中性能特殊场景可为1000,默认场景推荐10000,\r
+ * 性能不敏感或者高安全性要求场景推荐使用10000000。\r
+ * @param out [OUT] 派生密钥\r
+ * @param len [IN] 派生密钥长度,长度取值范围为 [1, 0xFFFFFFFF]\r
+ *\r
+ * @return 成功返回:CRYPT_SUCCESS\r
+ * 其他错误码,请查询crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_Pbkdf2(CRYPT_MAC_AlgId id, const uint8_t *key, uint32_t keyLen, const uint8_t *salt,\r
+ uint32_t saltLen, uint32_t it, uint8_t *out, uint32_t len);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief PKCS5 PBKDF 本接口为接口CRYPT_EAL_Pbkdf2的封装,默认使用算法CRYPT_MAC_HMAC_SHA256进行计算。\r
+ *\r
+ * @param key [IN] 密码,用户输入的字符串\r
+ * @param keyLen [IN] 密码长度,不为0的任意正整数。\r
+ * @param salt [IN] 盐值,用户输入的字符串\r
+ * @param saltLen [IN] 盐值长度,不为0的任意正整数。\r
+ * @param it [IN] 迭代次数,可以为任意不为0的正整数,其中性能特殊场景可为1000,默认场景推荐10000,\r
+ * 性能不敏感或者高安全性要求场景推荐使用10000000。\r
+ * @param out [OUT] 派生密钥\r
+ * @param len [IN] 派生密钥长度,长度取值范围为 [1, 0xFFFFFFFF]\r
+ *\r
+ * @return 成功返回:CRYPT_SUCCESS\r
+ * 其他错误码,请查询crypt_errno.h\r
+ */\r
+#define CRYPT_EAL_PKCS5_PBKDF2(key, keyLen, salt, saltLen, it, out, len) \\r
+ CRYPT_EAL_Pbkdf2(CRYPT_MAC_HMAC_SHA256, key, keyLen, salt, saltLen, it, out, len)\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief HKDF\r
+ *\r
+ * @param id [IN] MAC算法ID(仅支持CRYPT_MAC_HMAC_SHA1、CRYPT_MAC_HMAC_SHA224、\r
+ * CRYPT_MAC_HMAC_SHA256、CRYPT_MAC_HMAC_SHA384、CRYPT_MAC_HMAC_SHA512)\r
+ * @param key [IN] 密码,用户输入的字符串\r
+ * @param keyLen [IN] 密钥长度,任意长度\r
+ * @param salt [IN] 盐值,用户输入的字符串\r
+ * @param saltLen [IN] 盐值长度,任意长度\r
+ * @param info [IN] 用户可选的附加信息,可选信息。\r
+ * @param infoLen [IN] 附加信息长度,可以为0长度。[0,0xFFFFFFFF]\r
+ * @param out [OUT] 派生密钥\r
+ * @param len [IN] 派生密钥长度,不为0的任意整数,其中最大值:\r
+ * CRYPT_MAC_HMAC_SHA1对应最大值为5100、\r
+ * CRYPT_MAC_HMAC_SHA224对应最大值为7140、\r
+ * CRYPT_MAC_HMAC_SHA256对应最大值为8160、\r
+ * CRYPT_MAC_HMAC_SHA384对应最大值为12240、\r
+ * CRYPT_MAC_HMAC_SHA512对应最大值为16320、\r
+ *\r
+ * @return 成功返回:CRYPT_SUCCESS\r
+ * 其他错误码,请查询crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_Hkdf(CRYPT_MAC_AlgId id, const uint8_t *key, uint32_t keyLen, const uint8_t *salt, uint32_t saltLen,\r
+ const uint8_t *info, uint32_t infoLen, uint8_t *out, uint32_t len);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief KDF-TLS1.2\r
+ *\r
+ * @param id [IN] MAC算法ID(仅支持部分HMAC算法ID,\r
+ * 其中包括 CRYPT_MAC_HMAC_SHA256、CRYPT_MAC_HMAC_SHA384、CRYPT_MAC_HMAC_SHA512)\r
+ * @param key [IN] 密钥,用户输入的字符串\r
+ * @param keyLen [IN] 密钥长度,任意长度\r
+ * @param label [IN] 标签,用户输入的字符串。和seed拼接作为PRF的输入数据\r
+ * @param labelLen [IN] 标签长度,任意长度\r
+ * @param seed [IN] 种子,用户输入的字符串,用于作为PRF的输入数据。\r
+ * @param seedLen [IN] 种子长度,任意长度\r
+ * @param out [OUT] 派生密钥\r
+ * @param len [IN] 派生密钥长度,取值范围为 [1, 0xFFFFFFFF]\r
+ *\r
+ * @return 成功返回:CRYPT_SUCCESS\r
+ * 其他错误码,请查询crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_KdfTls12(CRYPT_MAC_AlgId id, const uint8_t *key, uint32_t keyLen, const uint8_t *label,\r
+ uint32_t labelLen, const uint8_t *seed, uint32_t seedLen, uint8_t *out, uint32_t len);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief scrypt合规判断\r
+ *\r
+ * @return true 测试成功\r
+ * false 测试失败\r
+ */\r
+typedef bool (*CRYPT_EAL_ScryptC2)(void);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief scrypt合规判断回调注册接口,用于判断模块状态是否可用\r
+ * CRYPT_EAL_Scrypt接口在执行操作前会调用该回调,回调失败会导致CRYPT_EAL_Scrypt失败\r
+ *\r
+ * @param func [IN] scrypt合规判断回调\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_RegScryptC2(CRYPT_EAL_ScryptC2 func);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief pbkdf2合规判断\r
+ *\r
+ * @return true 测试成功\r
+ * false 测试失败\r
+ */\r
+typedef bool (*CRYPT_EAL_Pbkdf2C2)(uint32_t saltLen, uint32_t it, uint32_t len);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief pbkdf2合规判断回调注册接口,用于判断模块状态是否可用\r
+ * CRYPT_EAL_Pbkdf2接口在执行操作前会调用该回调,回调失败会导致CRYPT_EAL_Pbkdf2失败\r
+ *\r
+ * @param func [IN] pbkdf2合规判断回调\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_RegPbkdf2C2(CRYPT_EAL_Pbkdf2C2 func);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief hkdf合规判断\r
+ *\r
+ * @return true 测试成功\r
+ * false 测试失败\r
+ */\r
+typedef bool (*CRYPT_EAL_HkdfC2)(void);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief hkdf合规判断回调注册接口,用于判断模块状态是否可用\r
+ * CRYPT_EAL_Hkdf接口在执行操作前会调用该回调,回调失败会导致CRYPT_EAL_Hkdf失败\r
+ *\r
+ * @param func [IN] hkdf合规判断回调\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_RegHkdfC2(CRYPT_EAL_HkdfC2 func);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief KDF-TLS1.2合规判断\r
+ *\r
+ * @param id [IN] MAC算法ID\r
+ * 非核准模式下可以使用任意算法\r
+ * ISO19790模式下只允许CRYPT_MAC_HMAC_SHA256/CRYPT_MAC_HMAC_SHA384/CRYPT_MAC_HMAC_SHA512\r
+ *\r
+ * @return true 测试成功\r
+ * false 测试失败\r
+ */\r
+typedef bool (*CRYPT_EAL_KdfTls12C2)(CRYPT_MAC_AlgId id);\r
+\r
+/**\r
+ * @ingroup crypt_eal_kdf\r
+ * @brief KDF-TLS1.2合规判断回调注册接口,用于判断算法参数是否合规和模块状态是否可用\r
+ * CRYPT_EAL_KdfTls12接口在执行操作前会调用该回调,回调失败会导致CRYPT_EAL_KdfTls12失败\r
+ *\r
+ * @param func [IN] KDF-TLS1.2合规判断回调\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_RegKdfTls12C2(CRYPT_EAL_KdfTls12C2 func);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+#endif\r
+#endif\r
--- /dev/null
+/**
+ * @defgroup crypt_eal_mac crypt_eal_mac.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief MAC算法接口,包含HMAC、CMAC
+ */
+#ifndef CRYPT_EAL_MAC_H
+#define CRYPT_EAL_MAC_H
+
+#ifndef HITLS_CRYPTO_NO_MAC
+#include <stdbool.h>
+#include <stdint.h>
+#include "crypt_algid.h"
+#include "crypt_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct EAL_MacCtx CRYPT_EAL_MacCtx;
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief MAC合规判断
+ *
+ * @param id [IN] MAC算法id
+ * 非核准模式下可以使用任意算法
+ *
+ * @return true 测试成功
+ * false 测试失败
+ */
+typedef bool (*CRYPT_EAL_MacC2)(CRYPT_MAC_AlgId id);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief MAC合规判断回调注册接口,用于判断算法参数是否合规和模块状态是否可用
+ * EAL的哈希接口在执行操作前会调用该回调,回调失败会导致CRYPT_EAL_MacNewCtx/CRYPT_EAL_MacInit/
+ * CRYPT_EAL_MacUpdate/CRYPT_EAL_MacFinal/CRYPT_EAL_MacReinit接口失败
+ * 非核准模式下,该验证不生效
+ * ISO19790模式下只允许CRYPT_MAC_HMAC_SHA1/CRYPT_MAC_HMAC_SHA224/CRYPT_MAC_HMAC_SHA256/
+ * CRYPT_MAC_HMAC_SHA384/CRYPT_MAC_HMAC_SHA512/CRYPT_MAC_CMAC_AES128/
+ * CRYPT_MAC_CMAC_AES192/CRYPT_MAC_CMAC_AES256
+ *
+ * @param func [IN] MAC合规判断回调
+ *
+ * @return 无
+ */
+void CRYPT_EAL_RegMacC2(CRYPT_EAL_MacC2 func);
+
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief 申请MAC上下文
+ *
+ * @param id [IN] MAC算法ID
+ *
+ * @return CRYPT_EAL_MacCtx指针
+ * 若失败返回NULL
+ */
+CRYPT_EAL_MacCtx *CRYPT_EAL_MacNewCtx(CRYPT_MAC_AlgId id);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief 释放MAC上下文内存
+ *
+ * @param ctx [IN] MAC上下文, ctx由调用方置空
+ */
+void CRYPT_EAL_MacFreeCtx(CRYPT_EAL_MacCtx *ctx);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief MAC算法初始化上下文,在调用CRYPT_EAL_MacNewCtx接口之后使用。
+ * 在计算过程中任何时候都可以使用初始化接口,但注意,调用了初始化接口上一次的计算数据全部清零。
+ *
+ * @param ctx [IN] MAC上下文
+ * @param key [IN] 密钥,长度规格如下:
+ * HMAC:长度为大于等于0的任意整数, 其中HMAC-SHA1、HMAC-SHA224、HMAC-SHA256长度为小于2^64bits,
+ * HMAC-SHA384、HMAC-SHA512长度为小于2^128bits
+ * CMAC:CMAC-AES128 长度需要等于128bits、CMAC-AES192 长度需要等于192bits、
+ * CMAC-AES256 长度需要等于256bits
+ * @param len [IN] 密钥长度
+ *
+ * @retval #CRYPT_SUCCESS 初始化成功
+ * @retval #CRYPT_NULL_INPUT 指针ctx参数或者key参数为NULL
+ * @retval #CRYPT_AES_ERR_KEYLEN AES CMAC算法密钥长度错误
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_MacInit(CRYPT_EAL_MacCtx *ctx, const uint8_t *key, uint32_t len);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief 持续输入待mac的数据。需要在接口CRYPT_EAL_MacInit接口执行成功之后使用。
+ *
+ * @param ctx [IN] MAC上下文
+ * @param in [IN] 输入数据,当该变量为NULL时,len参数必须为0,否则报错
+ * @param len [IN] 输入数据长度,可以为0长度。
+ *
+ * @retval #CRYPT_SUCCESS 更新摘要内部状态成功
+ * @retval #CRYPT_NULL_INPUT 输入参数为NULL
+ * @retval #CRYPT_EAL_ERR_STATE 状态错误
+ * @retval #CRYPT_SHA1_INPUT_OVERFLOW HMAC-SHA1输入数据的长度超出最大值
+ * @retval #CRYPT_SHA2_INPUT_OVERFLOW HMAC-SHA224、HMAC-SHA256、HMAC-SHA384、HMAC-SHA512输入数据的长度超出最大值
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_MacUpdate(CRYPT_EAL_MacCtx *ctx, const uint8_t *in, uint32_t len);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief 输出MAC结果。需要在接口CRYPT_EAL_MacInit接口执行成功之后使用,过程中可以不调用CRYPT_EAL_MacUpdate接口。
+ * MAC输出长度,HMAC-SHA1对应20bytes、HMAC-SHA224对应28bytes、HMAC-SHA256对应32bytes、
+ * HMAC-SHA384对应48bytes、HMAC-SHA512对应64bytes、CMAC-AES对应的16bytes
+ *
+ * @param ctx [IN] MAC上下文
+ * @param out [OUT] 输出数据,必须分配足够大的内存用于存储MAC结果,不能为NULL。
+ * @param len [IN/OUT] 输出数据长度,入参该值需要指定out长度,该长度需要大于等于MAC生成的长度,出参为MAC 输出的长度.
+ *
+ * @retval #CRYPT_SUCCESS 计算成功
+ * @retval #CRYPT_NULL_INPUT 输入参数为NULL
+ * @retval #CRYPT_EAL_ERR_STATE 状态错误
+ * @retval #CRYPT_HMAC_OUT_BUFF_LEN_NOT_ENOUGH HMAC算法输出buffer长度不足
+ * @retval #CRYPT_CMAC_OUT_BUFF_LEN_NOT_ENOUGH CMAC算法输出buffer长度不足
+ * @retval #CRYPT_SHA1_INPUT_OVERFLOW HMAC-SHA1输入数据的长度超出最大值
+ * @retval #CRYPT_SHA2_INPUT_OVERFLOW HMAC-SHA224、HMAC-SHA256、HMAC-SHA384、HMAC-SHA512输入数据的长度超出最大值
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_MacFinal(CRYPT_EAL_MacCtx *ctx, uint8_t *out, uint32_t *len);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief 去初始化函数,调用后如果要计算则需要重新初始化。
+ * @param ctx [IN] MAC上下文
+ */
+void CRYPT_EAL_MacDeinit(CRYPT_EAL_MacCtx *ctx);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief 使用ctx中保留的信息重新初始化。不需要重新调用init接口初始化。相当与deinit和init两个接口的结合。
+ * @param ctx [IN] MAC上下文
+ * @retval #CRYPT_SUCCESS reinit成功
+ * @retval #CRYPT_NULL_INPUT 输入参数为NULL
+ */
+int32_t CRYPT_EAL_MacReinit(CRYPT_EAL_MacCtx *ctx);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief 通过上下文获取对应算法的输出MAC长度
+ * @param ctx [IN] MAC上下文
+ * @return 上下文对应的MAC长度
+ */
+uint32_t CRYPT_EAL_GetMacLen(const CRYPT_EAL_MacCtx *ctx);
+
+/**
+ * @ingroup crypt_eal_mac
+ * @brief 设置算法参数,该接口需要在CRYPT_EAL_MacInit接口调用之后使用,且该接口仅支持GMAC算法
+ * <table border="1">
+ * <tr><th> 参数 </th><th> 数据类型 </th><th> len为长度,in的字节数 </th></tr>
+ * <tr><td> CRYPT_CTRL_SET_IV </td><td> uint8_t数组 </td><td> IV的长度 </td></tr>
+ * <tr><td> CRYPT_CTRL_SET_TAGLEN </td><td> uint32_t </td><td> 4字节,sizeof(uint32_t) </td></tr>
+ * </table>
+ * @param ctx [IN] MAC上下文
+ * @param type [IN] 设置参数类型,当前仅支持两种操作码,CRYPT_CTRL_SET_IV 和 CRYPT_CTRL_SET_TAGLEN
+ * @param in [IN] 输入数据
+ * @param len [IN] 输入数据长度
+ * @retval #CRYPT_SUCCESS 参数设置成功
+ * @retval #CRYPT_EAL_ERR_STATE 状态错误
+ * @retval #CRYPT_EAL_MAC_CTRL_TYPE_ERROR 设置参数类型错误
+ * @retval #CRYPT_EAL_ERR_ALGID 算法ID为非GMAC
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_MacCtrl(CRYPT_EAL_MacCtx *ctx, uint32_t type, void *in, uint32_t len);
+#ifdef __cplusplus
+} // end extern "C"
+#endif
+
+#endif
+#endif
--- /dev/null
+/**\r
+ * @defgroup crypt_eal_md crypt_eal_md.h\r
+ * @ingroup crypto\r
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.\r
+ * @brief 消息摘要(MD)算法对外接口文件\r
+ */\r
+\r
+#ifndef CRYPT_EAL_MD_H\r
+#define CRYPT_EAL_MD_H\r
+\r
+#include <stdbool.h>\r
+#include <stdint.h>\r
+#include "crypt_algid.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+typedef struct EAL_MdCtx CRYPT_EAL_MdCTX;\r
+\r
+/**\r
+ * @ingroup crypt_eal_md\r
+ * @brief 哈希合规判断\r
+ *\r
+ * @param id [IN] 哈希算法ID\r
+ *\r
+ * @return true 测试成功\r
+ * false 测试失败\r
+ */\r
+typedef bool (*CRYPT_EAL_MdC2)(CRYPT_MD_AlgId id);\r
+\r
+/**\r
+ * @ingroup crypt_eal_md\r
+ * @brief 哈希合规判断回调注册接口,用于判断算法参数是否合规和模块状态是否可用,EAL的哈希接口在执行操作前会调用该回调\r
+ * 回调失败会导致CRYPT_EAL_MdNewCtx/CRYPT_EAL_MdInit/CRYPT_EAL_MdUpdate/CRYPT_EAL_MdFinal接口失败\r
+ * 非核准模式下可以使用任意算法\r
+ * ISO19790模式下只允许CRYPT_MD_SHA224/CRYPT_MD_SHA256/CRYPT_MD_SHA384/CRYPT_MD_SHA512\r
+ *\r
+ * @param func [IN] 哈希合规判断回调\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_RegMdC2(CRYPT_EAL_MdC2 func);\r
+\r
+/**\r
+ * @ingroup crypt_eal_md\r
+ * @brief 创建MD上下文,计算结束后需要调用CRYPT_EAL_MdFreeCtx接口释放内存。\r
+ *\r
+ * @param id [IN] 算法ID\r
+ *\r
+ * @return CRYPT_EAL_MdCTX MD上下文指针\r
+ * 若失败返回空\r
+ */\r
+CRYPT_EAL_MdCTX *CRYPT_EAL_MdNewCtx(CRYPT_MD_AlgId id);\r
+\r
+/**\r
+ * @ingroup crypt_eal_md\r
+ * @brief MD上下文释放\r
+ *\r
+ * @param ctx [IN] MD上下文,使用CRYPT_EAL_MdNewCtx接口创建, ctx由调用方置空\r
+ *\r
+ * @return void 无返回值\r
+ */\r
+void CRYPT_EAL_MdFreeCtx(CRYPT_EAL_MdCTX *ctx);\r
+\r
+/**\r
+ * @ingroup crypt_eal_md\r
+ * @brief MD上下文初始化\r
+ *\r
+ * @param ctx [IN/OUT] MD上下文,使用CRYPT_EAL_MdNewCtx接口创建。\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_MdInit(CRYPT_EAL_MdCTX *ctx);\r
+\r
+/**\r
+ * @ingroup crypt_eal_md\r
+ * @brief 持续输入待摘要的数据\r
+ *\r
+ * @param ctx [IN/OUT] MD上下文,使用CRYPT_EAL_MdNewCtx接口创建。\r
+ * @param data [IN] 待摘要数据\r
+ * @param len [IN] 数据长度,sha384、sha512最大总长度限制为[0,2^128bits),\r
+ * sha1、sha224、sha256、sm3、md5最大总长度限制[0,2^64bits)。单次最大长度限制都[0,0xffffffff]。\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_MdUpdate(CRYPT_EAL_MdCTX *ctx, const uint8_t *data, uint32_t len);\r
+\r
+/**\r
+ * @ingroup crypt_eal_md\r
+ * @brief 完成摘要,输出最终摘要结果\r
+ *\r
+ * @param ctx [IN/OUT] MD上下文,使用CRYPT_EAL_MdNewCtx接口创建。\r
+ * @param out [OUT] 摘要结果缓存,需要用户创建管理。\r
+ * @param len [IN/OUT] 入参标识out的buffer长度,出参标识获取的out有效长度。长度大小必须大于等于对应算法哈希长度。\r
+ * 哈希长度大小可以通过CRYPT_EAL_MdGetDigestSize接口获取。需要用户创建管理。\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_MdFinal(CRYPT_EAL_MdCTX *ctx, uint8_t *out, uint32_t *len);\r
+\r
+/**\r
+ * @ingroup crypt_eal_md\r
+ * @brief 获取算法输出的摘要长度\r
+ *\r
+ * @param id [IN] 算法ID\r
+ *\r
+ * @return 成功返回摘要长度\r
+ * 失败返回0,且仅有id不合法的情况下返回为0\r
+ */\r
+uint32_t CRYPT_EAL_MdGetDigestSize(CRYPT_MD_AlgId id);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+#endif // CRYPT_EAL_MD_H\r
--- /dev/null
+/**\r
+ * @defgroup crypt_eal_pkey crypt_eal_pkey.h\r
+ * @ingroup crypto\r
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.\r
+ * @brief 消息非对称算法对外接口文件\r
+ */\r
+\r
+#ifndef CRYPT_EAL_PKEY_H\r
+#define CRYPT_EAL_PKEY_H\r
+\r
+#include <stdbool.h>\r
+#include <stdint.h>\r
+#include "crypt_algid.h"\r
+#include "crypt_types.h"\r
+#include "crypt_eal_pkey.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ *\r
+ * EAL公钥结构体\r
+ */\r
+typedef struct {\r
+ CRYPT_PKEY_AlgId id; /**< 公钥算法ID */\r
+ union {\r
+ CRYPT_RsaPub rsaPub; /**< RSA 公钥结构体 */\r
+ CRYPT_DsaPub dsaPub; /**< DSA 公钥结构体 */\r
+ CRYPT_DhPub dhPub; /**< DH 公钥结构体 */\r
+ CRYPT_EccPub eccPub; /**< ECC 公钥结构体 */\r
+ CRYPT_Curve25519Pub curve25519Pub; /**< ed25519/x25519 公钥结构体 */\r
+ CRYPT_Curve448Pub curve448Pub; /**< ed448/x448 公钥结构体 */\r
+ CRYPT_Sm9Pub sm9Pub; /**< sm9 公钥结构体 */\r
+ } key; /**< 全部算法的公钥联合体 */\r
+} CRYPT_EAL_PkeyPub;\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ *\r
+ * EAL私钥结构体\r
+ */\r
+typedef struct {\r
+ CRYPT_PKEY_AlgId id; /**< 私钥算法ID */\r
+ union {\r
+ CRYPT_RsaPrv rsaPrv; /**< RSA 私钥结构体 */\r
+ CRYPT_DsaPrv dsaPrv; /**< DSA 私钥结构体 */\r
+ CRYPT_DhPrv dhPrv; /**< DH 私钥结构体 */\r
+ CRYPT_EccPrv eccPrv; /**< ECC 私钥结构体 */\r
+ CRYPT_Curve25519Prv curve25519Prv; /**< ed25519/x25519 私钥结构体 */\r
+ CRYPT_Curve448Prv curve448Prv; /**< ed448/x448 私钥结构体 */\r
+ CRYPT_Sm9Prv sm9Prv; /**< sm9 私钥结构体 */\r
+ } key; /**< 全部算法的私钥联合体 */\r
+} CRYPT_EAL_PkeyPrv;\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ *\r
+ * 用于非对称算法Para使用的结构体,包括算法id和对应算法的Para联合体\r
+ */\r
+typedef struct {\r
+ CRYPT_PKEY_AlgId id; /**< 非对称算法ID */\r
+ union {\r
+ CRYPT_RsaPara rsaPara; /**< RSA Para结构体 */\r
+ CRYPT_DsaPara dsaPara; /**< DSA Para结构体 */\r
+ CRYPT_DhPara dhPara; /**< DH Para结构体 */\r
+ } para; /**< 全部算法的Para联合体 */\r
+} CRYPT_EAL_PkeyPara;\r
+\r
+/**\r
+* @ingroup crypt_eal_pkey\r
+*\r
+* pkey的会话结构体\r
+*/\r
+typedef struct EAL_PkeyCtx CRYPT_EAL_PkeyCtx;\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 密钥配对一致性测试\r
+ *\r
+ * @param pkey [IN] 秘钥对结构体\r
+ *\r
+ * @return true 测试成功\r
+ * false 测试失败\r
+ */\r
+typedef bool (*CRYPT_EAL_Pct)(CRYPT_EAL_PkeyCtx *pkey);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 密钥配对一致性测试回调注册接口,EAL生成非对称密钥对后会调用该回调,回调失败会导致EAL接口失败\r
+ *\r
+ * @param func [IN] 密钥配对一致性测试回调\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_RegPct(CRYPT_EAL_Pct func);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ *\r
+ * 非对称合规判断数据\r
+ */\r
+typedef struct {\r
+ const CRYPT_EAL_PkeyPara *para; /**< CRYPT_EAL_PkeyPara结构体 */\r
+ const CRYPT_EAL_PkeyPub *pub; /**< CRYPT_EAL_PkeyPub结构体 */\r
+ const CRYPT_EAL_PkeyPrv *prv; /**< CRYPT_EAL_PkeyPrv结构体 */\r
+ CRYPT_MD_AlgId mdId; /**< 哈希算法ID */\r
+ CRYPT_PKEY_ParaId paraId; /**< 非对称算法参数ID */\r
+ CRYPT_EVENT_TYPE oper; /**< 当前执行的操作 */\r
+ const CRYPT_RSA_PkcsV15Para *pkcsv15; /**< CRYPT_RSA_PkcsV15Para结构体 */\r
+ const CRYPT_RSA_PssPara *pss; /**< CRYPT_RSA_PssPara结构体 */\r
+ const CRYPT_RSA_OaepPara *oaep; /**< CRYPT_RSA_OaepPara结构体 */\r
+} EAL_PkeyC2Data;\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 非对称合规判断\r
+ *\r
+ * @param id [IN] 非对称算法id\r
+ * @param data [IN] 数据\r
+ *\r
+ * @return true 测试成功\r
+ * false 测试失败\r
+ */\r
+typedef bool (*CRYPT_EAL_PkeyC2)(CRYPT_PKEY_AlgId id, const EAL_PkeyC2Data *data);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 非对称合规判断回调注册接口,用于判断算法参数是否合规和模块状态是否可用\r
+ * EAL的非对称接口在执行操作前会调用该回调,回调失败会导致EAL接口失败\r
+ * 非核准模式下可以使用任意算法\r
+ * ISO19790模式下只允许CRYPT_PKEY_DSA/CRYPT_PKEY_X25519/CRYPT_PKEY_RSA/CRYPT_PKEY_DH/\r
+ * CRYPT_PKEY_ECDSA/CRYPT_PKEY_ECDH算法\r
+ * RSA密钥长度至少为2048bits\r
+ * DSA算法p至少为2048bits,q至少为224bits\r
+ * ECDSA算法p至少为224bits,曲线只允许P-224/P-256/P-384/P-521\r
+ * DH算法p至少为2048bits,q至少为256bits\r
+ * ECDH算法曲线只允许P-224/P-256/P-384/P-521\r
+ * 签名支持CRYPT_MD_SHA224/CRYPT_MD_SHA256/CRYPT_MD_SHA384/CRYPT_MD_SHA512\r
+ * 验签支持CRYPT_MD_SHA1/CRYPT_MD_SHA224/CRYPT_MD_SHA256/CRYPT_MD_SHA384/CRYPT_MD_SHA512\r
+ *\r
+ * @param func [IN] 非对称合规判断回调\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_RegPkeyC2(CRYPT_EAL_PkeyC2 func);\r
+\r
+\r
+/* Pkey对外接口 */\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 创建一个非对称秘钥对结构体\r
+ *\r
+ * @param id [IN] 算法ID\r
+ *\r
+ * @return CRYPT_EAL_PkeyCtx 指针\r
+ * 若失败返回空\r
+ */\r
+CRYPT_EAL_PkeyCtx *CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_AlgId id);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 释放非对称秘钥对结构体\r
+ *\r
+ * @param pkey [IN] pkey上下文, pkey由调用方置空\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_PkeyFreeCtx(CRYPT_EAL_PkeyCtx *pkey);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 设置秘钥参数,其中para由调用者申请和释放内存\r
+ *\r
+ * @param pkey [IN/OUT] 待设置秘钥对结构体\r
+ * @param para [IN] 参数\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeySetPara(CRYPT_EAL_PkeyCtx *pkey, const CRYPT_EAL_PkeyPara *para);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 设置秘钥参数\r
+ *\r
+ * @param pkey [IN/OUT] 待设置秘钥对结构体\r
+ * @param id [IN] 参数id\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeySetParaById(CRYPT_EAL_PkeyCtx *pkey, CRYPT_PKEY_ParaId id);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 获取秘钥参数,其中para由调用者申请和释放内存\r
+ *\r
+ * @param pkey [IN] 待设置秘钥对结构体\r
+ * @param para [OUT] 参数\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyGetPara(const CRYPT_EAL_PkeyCtx *pkey, CRYPT_EAL_PkeyPara *para);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 生成秘钥数据\r
+ *\r
+ * @param pkey [IN/OUT] 接收秘钥数据的秘钥对结构体\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyGen(CRYPT_EAL_PkeyCtx *pkey);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 公钥设置,其中key由调用者申请和释放内存。\r
+ *\r
+ * @param pkey [OUT] 接收秘钥数据的秘钥对结构体\r
+ * @param key [IN] 公钥数据\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeySetPub(CRYPT_EAL_PkeyCtx *pkey, const CRYPT_EAL_PkeyPub *key);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 私钥设置,其中key由调用者申请和释放内存。\r
+ *\r
+ * @param pkey [OUT] 接收秘钥数据的秘钥对结构体\r
+ * @param key [IN] 私钥数据\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeySetPrv(CRYPT_EAL_PkeyCtx *pkey, const CRYPT_EAL_PkeyPrv *key);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 公钥获取,其中key由调用者申请和释放内存。\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param key [OUT] 公钥数据\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyGetPub(const CRYPT_EAL_PkeyCtx *pkey, CRYPT_EAL_PkeyPub *key);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 私钥获取,其中key由调用者申请和释放内存。\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param key [OUT] 私钥数据\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyGetPrv(const CRYPT_EAL_PkeyCtx *pkey, CRYPT_EAL_PkeyPrv *key);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 签名接口\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param id [IN] 哈希算法ID\r
+ * @param data [IN] 明文数据\r
+ * @param dataLen [IN] 明文长度,最大长度限制为[0,0xffffffff]\r
+ * @param sign [OUT] 签名数据\r
+ * @param signLen [OUT/IN] 签名数据长度。可通过接口 CRYPT_EAL_PkeyGetSignLen 获取该值。\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeySign(const CRYPT_EAL_PkeyCtx *pkey, CRYPT_MD_AlgId id, const uint8_t *data,\r
+ uint32_t dataLen, uint8_t *sign, uint32_t *signLen);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 验签接口\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param id [IN] 哈希算法ID\r
+ * @param data [IN] 明文数据\r
+ * @param dataLen [IN] 明文长度,最大长度限制为[0,0xffffffff]\r
+ * @param sign [IN] 签名数据\r
+ * @param signLen [IN] 签名数据长度\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyVerify(const CRYPT_EAL_PkeyCtx *pkey, CRYPT_MD_AlgId id, const uint8_t *data,\r
+ uint32_t dataLen, const uint8_t *sign, uint32_t signLen);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 对哈希数据进行签名的接口\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param hash [IN] 哈希数据\r
+ * @param hashLen [IN] 哈希长度。\r
+ * 当使用RSA用于签名时,哈希长度应该与填充方法所依赖的哈希算法的摘要长度对应\r
+ * @param sign [OUT] 签名数据\r
+ * @param signLen [OUT/IN] 签名数据长度。可通过接口 CRYPT_EAL_PkeyGetSignLen 获取该值。\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeySignData(const CRYPT_EAL_PkeyCtx *pkey, const uint8_t *hash, uint32_t hashLen,\r
+ uint8_t *sign, uint32_t *signLen);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 对哈希数据进行验签的接口\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param hash [IN] 哈希数据\r
+ * @param hashLen [IN] 哈希长度。\r
+ * 当使用RSA用于签名时,哈希长度应该与填充方法所依赖的哈希算法的摘要长度对应\r
+ * @param sign [IN] 签名数据\r
+ * @param signLen [IN] 签名数据长度\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyVerifyData(const CRYPT_EAL_PkeyCtx *pkey, const uint8_t *hash, uint32_t hashLen,\r
+ const uint8_t *sign, uint32_t signLen);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 对数据进行加密\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param data [IN] 输入明文数据\r
+ * @param dataLen [IN] 数据长度。\r
+ *\r
+ * @param out [OUT] 加密后的数据,RSA加密时用于保存加密数据的内存buff长度必须大于等于秘钥模长\r
+ * @param outLen [OUT/IN] 加密数据长度。\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyEncrypt(const CRYPT_EAL_PkeyCtx *pkey, const uint8_t *data, uint32_t dataLen,\r
+ uint8_t *out, uint32_t *outLen);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 对数据进行解密\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param data [IN] 输入密文数据\r
+ * @param dataLen [IN] 数据长度。\r
+ *\r
+ * @param out [OUT] 解密后的数据\r
+ * @param outLen [OUT/IN] 解密数据长度。\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyDecrypt(const CRYPT_EAL_PkeyCtx *pkey, const uint8_t *data, uint32_t dataLen,\r
+ uint8_t *out, uint32_t *outLen);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 计算共享秘钥\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param pubKey [IN] 公钥会话\r
+ * @param share [OUT] 共享秘钥\r
+ * @param shareLen [IN/OUT] 入参为share空间长度,出参为share有效长度,所需空间可通过接口CRYPT_EAL_PkeyGetKeyLen获取\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyComputeShareKey(const CRYPT_EAL_PkeyCtx *pkey, const CRYPT_EAL_PkeyCtx *pubKey,\r
+ uint8_t *share, uint32_t *shareLen);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 获取秘钥长度的字节数\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ *\r
+ * @return 成功返回秘钥长度\r
+ * 失败返回0\r
+ */\r
+uint32_t CRYPT_EAL_PkeyGetKeyLen(const CRYPT_EAL_PkeyCtx *pkey);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 获取秘钥进行签名的签名长度,只支持可用于签名的算法\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ *\r
+ * @return 成功返回签名长度\r
+ * 失败返回0\r
+ */\r
+uint32_t CRYPT_EAL_PkeyGetSignLen(const CRYPT_EAL_PkeyCtx *pkey);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 对秘钥进行特定的设置/获取动作,支持动作可参考CRYPT_PkeyCtrl枚举\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ * @param opt [IN] 选项信息\r
+ * @param val [IN/OUT] 进行设置/获取的数据\r
+ * @param len [IN] val数据的长度\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyCtrl(CRYPT_EAL_PkeyCtx *pkey, CRYPT_PkeyCtrl opt, void *val, uint32_t len);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 获取密钥算法类型\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ *\r
+ * @return 密钥算法类型\r
+ */\r
+CRYPT_PKEY_AlgId CRYPT_EAL_PkeyGetId(const CRYPT_EAL_PkeyCtx *pkey);\r
+\r
+/**\r
+ * @ingroup crypt_eal_pkey\r
+ * @brief 检查密钥对一致性\r
+ *\r
+ * @param pkey [IN] 秘钥会话\r
+ *\r
+ * @return CRYPT_SUCCESS 成功\r
+ * 其他错误码参考 crypt_errno.h\r
+ */\r
+int32_t CRYPT_EAL_PkeyCheck(const CRYPT_EAL_PkeyCtx *pkey);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+#endif // CRYPT_EAL_PKEY_H\r
--- /dev/null
+/**
+ * @defgroup crypt_eal_rand crypt_eal_rand.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief RAND 算法对外接口文件
+ */
+
+#ifndef CRYPT_EAL_RAND_H
+#define CRYPT_EAL_RAND_H
+
+#ifndef HITLS_CRYPTO_NO_RAND
+#include <stdbool.h>
+#include <stdint.h>
+#include "crypt_algid.h"
+#include "crypt_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup crypt_eal_rand
+ * @brief 随机数合规判断
+ *
+ * id:随机数算法id
+ *
+ * @return true 测试成功
+ * false 测试失败
+ */
+typedef bool (*CRYPT_EAL_RandC2)(CRYPT_RAND_AlgId id);
+
+/**
+ * @ingroup crypt_eal_rand
+ * @brief 随机数算法合规判断注册接口,用于判断模块状态是否可用
+ * EAL的随机数接口在执行操作前会调用该回调,回调失败会导致CRYPT_EAL_RandInit/CRYPT_EAL_RandbytesWithAdin/
+ * CRYPT_EAL_Randbytes/CRYPT_EAL_RandSeedWithAdin/CRYPT_EAL_RandSeed接口失败
+ * 非核准模式下可以使用任意算法
+ * ISO19790模式下允许CRYPT_MD_SHA224/CRYPT_MD_SHA256/CRYPT_MD_SHA384/CRYPT_MD_SHA512
+ * 修改上面注释
+ *
+ * @param func [IN] 随机数合规判断
+ *
+ * @return 无
+ */
+void CRYPT_EAL_RegRandC2(CRYPT_EAL_RandC2 func);
+
+/**
+ * @ingroup crypt_eal_rand
+ * @brief 随机数初始化接口,此接口不支持多线程
+ * @par
+ * 将全局随机数初始为HITLS实现的RAND,种子材料中的熵源和额外随机数,必须由用户提供
+ * 使用场景如下:
+ * 1. seedMeth == NULL ====> 报错
+ * 2. seedMeth != NULL ====> 正常使用, seedCtx不做限制,但要保证seedMeth能够处理各种情况
+ *
+ * @attention 支持多线程获取/生成随机数,但是不支持多线程初始化和去初始化
+ * @param id [IN] RAND id
+ * @param seedMeth [IN] 种子方法,不可以为空
+ * @param seedCtx [IN] 种子上下文信息,可以为空,但用户提供的seedMeth需要能够处理seedCtx为空的情况
+ * seedCtx一般需要包含熵源entropy,额外随机数nonce等数据
+ * @param pers [IN] 个人数据,可以为空
+ * @param persLen [IN] 个人数据长度,长度限制为[0,0x7FFFFFF0]
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_RandInit(CRYPT_RAND_AlgId id, CRYPT_RandSeedMethod *seedMeth, void *seedCtx,
+ const uint8_t *pers, uint32_t persLen);
+
+/**
+ * @ingroup crypt_eal_rand
+ * @brief CRYPT_EAL_RandDeinit 所对应的反初始化全局RAND接口, 此接口不支持多线程
+ * @return void 无返回值
+ */
+void CRYPT_EAL_RandDeinit(void);
+
+/**
+ * @ingroup crypt_eal_rand
+ * @brief 随机数生成,额外数据允许为空,由用户指定额外的混淆数据,此接口支持多线程访问
+ *
+ * @param byte [OUT] 用于输出随机数,内存由用户提供
+ * @param len [IN] 所需随机数长度,限制长度为(0,65536]
+ * @param addin [IN] 额外数据,可以为空
+ * @param addinLen [IN] 额外数据长度,长度限制为[0,0x7FFFFFF0]
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_RandbytesWithAdin(uint8_t *byte, uint32_t len, uint8_t *addin, uint32_t addinLen);
+
+/**
+ * @ingroup crypt_eal_rand
+ * @brief 随机数生成,等同于CRYPT_EAL_RandbytesWithAdin(bytes, len, NULL, 0),此接口支持多线程访问
+ *
+ * @param byte [OUT] 用于存储输出的随机数,内存由用户提供
+ * @param len [IN] 所需随机数长度, 限制长度为(0,65536]
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_Randbytes(uint8_t *byte, uint32_t len);
+
+/**
+ * @ingroup crypt_eal_rand
+ * @brief 重新生成种子,额外数据允许为空,此接口支持多线程访问
+ *
+ * @param addin [IN] 额外数据,可以为空
+ * @param addinLen [IN] 额外数据长度, 长度限制为[0,0x7FFFFFF0]
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_RandSeedWithAdin(uint8_t *addin, uint32_t addinLen);
+
+/**
+ * @ingroup crypt_eal_rand
+ * @brief 重新生成种子,等同于CRYPT_EAL_RandSeedWithAdin(NULL, 0),此接口支持多线程访问
+ *
+ * @return 成功返回:CRYPT_SUCCESS
+ * 其他错误码,请查询crypt_errno.h
+ */
+int32_t CRYPT_EAL_RandSeed(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
--- /dev/null
+/**
+ * @defgroup crypt_errno crypt_errno.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief crypto模块返回码
+ */
+
+/** @defgroup crypto crypto */
+
+#ifndef CRYPT_ERRNO_H
+#define CRYPT_ERRNO_H
+
+#include "crypt_check_macro.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup crypt_errno
+ * @brief 返回成功
+ */
+#define CRYPT_SUCCESS 0
+
+/**
+ * @ingroup crypt_errno
+ *
+ * CRYPTO模块的返回值
+ */
+enum CRYPT_ERROR {
+ CRYPT_NULL_INPUT = 0x01010001, /**< 错误的空指针输入, bufferLen为0 */
+ CRYPT_SECUREC_FAIL, /**< 安全函数返回错误 */
+ CRYPT_MEM_ALLOC_FAIL, /**< 内存资源申请失败 */
+ CRYPT_NO_REGIST_RAND, /**< 未注册全局随机数 */
+ CRYPT_ERR_ALGID, /**< 错误的算法ID */
+ CRYPT_INVALID_ARG, /**< 非法入参 */
+
+ CRYPT_BN_BUFF_LEN_NOT_ENOUGH = 0x01020001, /**< 缓冲区长度不足 */
+ CRYPT_BN_SPACE_NOT_ENOUGH, /**< 大数空间不足 */
+ CRYPT_BN_BITS_TOO_MAX, /**< 超出大数最大bits限制 */
+ CRYPT_BN_RAND_GEN_FAIL, /**< 随机数生成失败 */
+ CRYPT_BN_OPTIMIZER_STACK_FULL, /**< 优化器栈满了失败 */
+ CRYPT_BN_NO_NEGATIVE_ZERO, /**< 大数0只设置为正数符号 */
+ CRYPT_BN_ERR_RAND_ZERO, /**< 生成比0小的随机数 */
+ CRYPT_BN_ERR_RAND_NEGATIVE, /**< 生成负数随机数 */
+ CRYPT_BN_ERR_RAND_TOP_BOTTOM, /**< 随机数生成时top或bottom无效 */
+ CRYPT_BN_ERR_RAND_BITS_NOT_ENOUGH, /**< 随机数生成时bit过小 */
+ CRYPT_BN_OPTIMIZER_GET_FAIL, /**< 从优化器获取空间失败 */
+ CRYPT_BN_ERR_DIVISOR_ZERO, /**< 除数不能为0 */
+ CRYPT_BN_ERR_EXP_NO_NEGATIVE, /**< 幂的值不能为负数 */
+ CRYPT_BN_MONT_BASE_TOO_MAX, /**< 蒙哥马利模幂底数过大 */
+ CRYPT_BN_NOR_GEN_PRIME, /**< 素数生成失败 */
+ CRYPT_BN_NOR_CHECK_PRIME, /**< 素数检查失败 */
+ CRYPT_BN_ERR_GCD_NO_ZERO, /**< 求最大公约数不能有0 */
+ CRYPT_BN_ERR_NO_INVERSE, /**< 无法求出模逆 */
+ CRYPT_BN_ERR_SQRT_PARA, /**< 模开根号参数错误 */
+ CRYPT_BN_ERR_LEGENDE_DATA, /**< 计算平方根时寻找z对p的勒让德符号(z|p)等于-1特定的数失败 */
+ CRYPT_BN_ERR_NO_SQUARE_ROOT, /**< 找不到平方根 */
+ CRYPT_BN_ERR_MASKCOPY_LEN, /**< 带掩码进行拷贝时,数据长度不一致 */
+ CRYPT_BN_ERR_QUICK_MODDATA, /**< 使用BN_ModNistEccMul和BN_ModNistEccSqr接口时,其模数据不支持 */
+
+ CRYPT_RSA_BUFF_LEN_NOT_ENOUGH = 0x01030001, /**< 缓冲区长度不足 */
+ CRYPT_RSA_NO_KEY_INFO, /**< 缺乏有效秘钥信息 */
+ CRYPT_RSA_ERR_KEY_BITS, /**< 秘钥长度错误 */
+ CRYPT_RSA_ERR_E_VALUE, /**< 参数e数值错误 */
+ CRYPT_RSA_NOR_KEYGEN_FAIL, /**< 秘钥生成失败,正常错误 */
+ CRYPT_RSA_NOR_VERIFY_FAIL, /**< 验签失败,正常错误 */
+ CRYPT_RSA_ERR_ENC_BITS, /**< 公钥加密明文长度错误 */
+ CRYPT_RSA_ERR_DEC_BITS, /**< 私钥解密密文长度错误 */
+ CRYPT_RSA_ERR_PSS_SALT_LEN, /**< PSS操作盐长度错误 */
+ CRYPT_RSA_ERR_PSS_SALT_DATA, /**< PSS操作盐数据错误,验签时提取的盐与用户输入比较失败 */
+ CRYPT_RSA_ERR_PKCSV15_SALT_LEN, /**< PKCSV15操作盐长度错误 */
+ CRYPT_RSA_ERR_PKCSV15_SALT_DATA, /**< PKCSV15操作盐数据错误 */
+ CRYPT_RSA_ERR_INPUT_VALUE, /**< 一些比较特殊的值,作为输入所产生的错误 */
+ CRYPT_RSA_ERR_MD_ALGID, /**< 设置pkcs1.5填充方式时入参的哈希id错误 */
+ CRYPT_RSA_PAD_NO_SET_ERROR, /**< 使用RSA秘钥进行签名验签时尚未设置填充信息 */
+ CRYPT_RSA_CTRL_NOT_SUPPORT_ERROR, /**< 使用RSA进行Ctrl时,使用的Ctrl类型不支持 */
+ CRYPT_RSA_SET_SALT_NOT_PSS_ERROR, /**< 当秘钥的填充类型非pss时,进行盐信息设置,返回失败 */
+ CRYPT_RSA_SET_EMS_PKCSV15_LEN_ERROR, /**< 进行PKCSV15填充信息设置时,输入的数据长度错误,返回失败 */
+ CRYPT_RSA_SET_EMS_PSS_LEN_ERROR, /**< 进行PSS填充信息设置时,输入的数据长度错误,返回失败 */
+ CRYPT_RSA_SET_RSAES_OAEP_LEN_ERROR, /**< 进行Oaep填充信息设置时,输入的数据长度错误,返回失败 */
+ CRYPT_RSA_SET_FLAG_LEN_ERROR, /**< 设置flag时,输入数据长度错误,返回失败 */
+ CRYPT_RSA_FLAG_NOT_SUPPORT_ERROR, /**< 不支持的flag */
+ CRYPT_RSA_ERR_SALT_LEN, /**< 盐长度错误 */
+ CRYPT_RSA_ERR_ALGID, /**< 进行签名、验签以及填充参数设置时,入参的哈希ID错误或者有冲突时返回错误 */
+ CRYPT_RSA_ERR_GEN_SALT, /**< 进行PSS签名时生成盐信息时失败返回错误 */
+ CRYPT_RSA_ERR_ENC_INPUT_NOT_ENOUGH, /**< RSA NO PAD加密,明文长度过短*/
+
+ CRYPT_EAL_BUFF_LEN_NOT_ENOUGH = 0x01040001, /**< 缓冲区长度不足 */
+ CRYPT_EAL_ERR_ALGID, /**< 算法ID错误 */
+ CRYPT_EAL_ALG_NOT_SUPPORT, /**< 算法不支持、算法行为不支持 */
+ CRYPT_EAL_RAND_GEN_FAIL, /**< 随机数生成失败 */
+ CRYPT_EAL_ERR_SALT_MEM, /**< 盐内存错误 */
+ CRYPT_EAL_NOR_VERIFY_FAIL, /**< 验签失败,正常错误 */
+ CRYPT_EAL_ERR_NEW_PARA_FAIL, /**< 生成参数失败 */
+ CRYPT_EAL_ERR_RAND_WORKING, /**< DRBG 处于工作状态 */
+ CRYPT_EAL_ERR_RAND_NO_WORKING, /**< DRBG 处于非工作状态 */
+ CRYPT_EAL_ERR_METH_NULL_NUMBER, /**< method变量成员为NULL */
+ CRYPT_EAL_ERR_LOCK_NULL, /**< 锁为NULL */
+ CRYPT_EAL_ERR_GLOBAL_DRBG_NULL, /**< 全局DRBG为NULL */
+ CRYPT_EAL_ERR_DRBG_REPEAT_INIT, /**< DRBG重复初始化 */
+ CRYPT_EAL_ERR_DRBG_INIT_FAIL, /**< DRBG初始化失败 */
+ CRYPT_EAL_ERR_STATE, /**< 使用流程不正确,例如未执行init,直接执行update,具体用法参见相关算法 */
+ CRYPT_EAL_PKEY_PAD_REDUNDANCY, /**< pkey签名验签接口中,RSA以外的算法不需要填充信息;
+ 如果入参包含填充信息返回该错误码 */
+ CRYPT_EAL_CIPHER_DATA_ERROR, /**< 对于解密后的数据进行去充填是数据出错,
+ 对于X923 最后一位是原始数据的长度,其余充填数据是0,如果不满足此要求,则报错
+ 对于pkcs 所有充填的数据是 充填后的长度 - 原始数据长度,如不满足此要求,则报错
+ 对于ISO7816 充填的第一位数据是0x80, 其余充填0, 如不满足此要求,则报错 */
+ CRYPT_EAL_PADDING_NOT_SUPPORT, /**< 不支持的padding */
+ CRYPT_EAL_CIPHER_CTRL_ERROR, /**< CRYPT_EAL_CipherCtrl接口不支持的CTRL */
+ CRYPT_EAL_CIPHER_FIANL_WITH_AEAD_ERROR, /**< 对AEAD算法进行final操作导致错误 */
+ CRYPT_EAL_PKEY_CTRL_ERROR, /**< CRYPT_EAL_PkeyCtrl接口进行CTRL时功能不支持或者输入的长度不正确 */
+ CRYPT_EAL_MAC_CTRL_TYPE_ERROR, /**< CRYPT_EAL_PkeyCtrl接口进行CTRL时功能不支持或者输入的长度不正确 */
+
+ CRYPT_SHA2_INPUT_OVERFLOW = 0x01050001, /**< 输入数据的长度超出SHA2的最大处理范围 */
+ CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH, /**< 承载输出结果的缓冲区长度不足 */
+
+ CRYPT_DRBG_ERR_STATE = 0x01060001, /**< DRBG 状态错误 */
+ CRYPT_DRBG_FAIL_GET_ENTROPY, /**< 获取熵失败 */
+ CRYPT_DRBG_FAIL_GET_NONCE, /**< 获取 nonce 失败 */
+ CRYPT_DRBG_ALG_NOT_SUPPORT, /**< 不支持给定的算法 */
+ CRYPT_DRBG_INVALID_LEN, /**< 错误的数据长度 */
+
+ CRYPT_MPA_POOL_SIZE_EXCEED = 0x01070001, /**< 创建pool时单元个数超限 */
+ CRYPT_MPA_ERR_ALG_MODE, /**< 错误算法模式 */
+ CRYPT_MPA_OUT_BUFF_LEN_NOT_ENOUGH, /**< 承载输出结果的缓冲区长度不足 */
+
+ CRYPT_CURVE25519_NO_PUBKEY = 0x01080001, /**< 没有公钥 */
+ CRYPT_CURVE25519_NO_PRVKEY, /**< 没有私钥 */
+ CRYPT_CURVE25519_KEYLEN_ERROR, /**< 秘钥长度错误 */
+ CRYPT_CURVE25519_SIGNLEN_ERROR, /**< 签名长度错误 */
+ CRYPT_CURVE25519_HASH_METH_ERROR, /**< 哈希方法不是SHA512 */
+ CRYPT_CURVE25519_VERIFY_FAIL, /**< 签名不正确,验签失败 */
+ CRYPT_CURVE25519_NO_HASH_METHOD, /**< 未设置哈希方法 */
+ CRYPT_CURVE25519_UNSUPPORTED_CTRL_OPTION, /**< 不支持的操作模式 */
+ CRYPT_CURVE25519_KEY_COMPUTE_FAILED, /**< 生成共享密钥失败 */
+ CRYPT_CURVE25519_INVALID_PUBKEY, /**< 公钥非法 */
+
+ CRYPT_SHA1_INPUT_OVERFLOW = 0x01090001, /**< 输入数据的长度超出SHA1的最大处理范围 */
+ CRYPT_SHA1_OUT_BUFF_LEN_NOT_ENOUGH, /**< 承载输出结果的缓冲区长度不足 */
+
+ CRYPT_ENTROPY_RCT_FAILURE = 0x010A0001, /**< RCT检测失败,失败时可以重启熵源 */
+ CRYPT_ENTROPY_APT_FAILURE, /**< APT检测失败,失败时可以重启熵源 */
+ CRYPT_ENTROPY_CONDITION_FAILURE, /**< 调用后处理方法出错 */
+ CRYPT_ENTROPY_RANGE_ERROR, /**< 熵源生成范围错误 */
+
+ CRYPT_DSA_BUFF_LEN_NOT_ENOUGH = 0x010B0001, /**< 缓冲区长度不足 */
+ CRYPT_DSA_ERR_KEY_PARA, /**< 秘钥参数数据错误 */
+ CRYPT_DSA_ERR_KEY_INFO, /**< 秘钥信息错误 */
+ CRYPT_DSA_VERIFY_FAIL, /**< 验签失败 */
+ CRYPT_DSA_ERR_TRY_CNT, /**< 秘钥生成、签名在规定的尝试次数内无法生成结果 */
+ CRYPT_DSA_DECODE_FAIL, /**< 数据解码失败,数据不符合解码要求 */
+
+ CRYPT_HMAC_OUT_BUFF_LEN_NOT_ENOUGH = 0x010C0001, /**< 承载输出结果的缓冲区长度不足 */
+
+ CRYPT_DH_BUFF_LEN_NOT_ENOUGH = 0x010D0001, /**< 缓冲区长度不足 */
+ CRYPT_DH_PARA_ERROR, /**< 秘钥参数的数值不符合要求、使用ctx时不包含必要的参数信息 */
+ CRYPT_DH_KEYINFO_ERROR, /**< 公私钥的数值不符合要求、使用ctx时不包含必要的公私钥信息 */
+ CRYPT_DH_RAND_GENERATE_ERROR, /**< 秘钥生成在规定的尝试次数内无法生成结果 */
+ CRYPT_DH_PAIRWISE_CHECK_FAIL, /**< 公私钥不一致*/
+ CRYPT_DH_PRVKEY_CHECK_FAIL, /**< 私钥进行FIPS检查失败*/
+
+ CRYPT_CHACHA20_BUFF_LEN_NOT_ENOUGH = 0x010E0001, /**< 缓冲区长度不足 */
+ CRYPT_CHACHA20_KEYLEN_ERROR, /**< 进行秘钥设置时 输入的秘钥长度错误 */
+ CRYPT_CHACHA20_NONCELEN_ERROR, /**< 进行nounce设置时,输入的nounce长度错误 */
+ CRYPT_CHACHA20_COUNTLEN_ERROR, /**< 进行count设置时,输入的count长度错误 */
+ CRYPT_CHACHA20_NO_KEYINFO, /**< 进行加解密时缺乏有效的秘钥信息 */
+ CRYPT_CHACHA20_NO_NONCEINFO, /**< 进行加解密时缺乏有效的nounce信息 */
+ CRYPT_CHACHA20_CTRLTYPE_ERROR, /**< 使用ctrl接口时输入的type不支持 */
+
+ CRYPT_AES_ERR_KEYLEN = 0x010F0001, /**< 秘钥长度错误 */
+
+ CRYPT_MODES_TAGLEN_ERROR = 0x01100001, /**< 在AEAD模式下,获取TAG和校验TAG时输入的TAG长度错误 */
+ CRYPT_MODES_IVLEN_ERROR, /**< 在设置IV时,输入的IV长度错误 */
+ CRYPT_MODES_KEYUSE_TOOMANY_TIME, /**< GCM模式下,限制了秘钥用于加解密的次数,当一个秘钥使用次数超出该限制时报错 */
+ CRYPT_MODES_CRYPTLEN_OVERFLOW, /**< AEAD模式下,单次加密输入的明文/密文长度超出规格限制 */
+ CRYPT_MODES_CTRL_TAGLEN_ERROR, /**< GCM和CCM模式下,使用ctrl接口设置tag长度时入参长度错误或入参数据表示的长度错误 */
+ CRYPT_MODES_AAD_REPEAT_SET_ERROR, /**< 在AEAD模式下,重复设置AAD信息错误 */
+ CRYPT_MODE_BUFF_LEN_NOT_ENOUGH, /**< 缓冲区长度不足 */
+ CRYPT_MODE_ERR_INPUT_LEN, /**< 函数输入长度不是期望的长度 */
+ CRYPT_MODES_CTRL_TYPE_ERROR, /**< 使用ctrl接口时输入的type不支持 */
+ CRYPT_MODES_CTRL_TAGLEN_AFTER_USED_ERROR, /**< GCM模式下tagLen信息影响秘钥限制的最大使用次数和加密长度。在使用秘钥进行加解密之后,不允许重新设置tagLen,返回该错误码 */
+ CRYPT_MODES_AAD_IS_SET_ERROR, /**< ccm模式下在设置aad之后进行tagLen、msgLen的设置时返回错误 */
+ CRYPT_MODES_MSGLEN_OVERFLOW, /**< ccm模式下加解密时输入的消息长度超出设置的msgLen */
+ CRYPT_MODES_CTRL_MSGLEN_ERROR, /**< ccm模式下,使用ctrl接口设置msg长度时入参长度错误或入参数据表示的长度错误(该规格受ivLen影响) */
+ CRYPT_MODES_MSGLEN_LEFT_ERROR, /**< ccm模式下,使用ctrl接口获取tag时,已加解密的消息长度尚未达到设置的数量,还有剩余,导致错误 */
+ CRYPT_MODES_ERR_KEYLEN, /**< 设置了错误的密钥长度 */
+ CRYPT_MODES_ERR_KEY, /**< 设置了错误的密钥 */
+ CRYPT_MODES_ERR_FEEDBACKSIZE, /**< cfb模式设置了错误的密文反馈长度 */
+ CRYPT_MODES_MODE_NOT_SUPPORT, /**< 当前模式不支持 */
+
+ CRYPT_HKDF_DKLEN_OVERFLOW = 0x01110001, /**< 派生密钥长度超过最大限制 */
+ CRYPT_HKDF_NOT_SUPPORTED, /**< 不支持HKDF算法 */
+
+ CRYPT_CMAC_OUT_BUFF_LEN_NOT_ENOUGH = 0x01120001, /**< 承载输出结果的缓冲区长度不足 */
+ CRYPT_CMAC_INPUT_OVERFLOW, /**< 输入数据的长度超出CMAC的最大处理范围 */
+
+ CRYPT_SCRYPT_PARAM_ERROR = 0x01130001, /**< 入参错误 */
+ CRYPT_SCRYPT_NOT_SUPPORTED, /**< 不支持SCRYPT算法 */
+ CRYPT_SCRYPT_DATA_TOO_MAX, /**< SCRYPT算法计算数据太大 */
+
+ CRYPT_CMVP_ERR_CSP_EXIST = 0x1140001, /**< 内存中存在CSP导致切换模式失败 */
+ CRYPT_CMVP_INVALID_INPUT, /**< 要切换的模式错误 */
+ CRYPT_CMVP_ERR_STATUS, /**< 当前状态不可用 */
+ CRYPT_CMVP_ERR_LOCK, /**< CMVP锁失败 */
+ CRYPT_CMVP_ERR_ALGO_SELFTEST, /**< 算法自检失败 */
+ CRYPT_CMVP_ALREADY_IN_MODE, /**< 已经处在该模式 */
+ CRYPT_CMVP_ERR_PAIRWISETEST, /**< 密钥配对测试失败 */
+ CRYPT_CMVP_NOT_APPROVED, /**< 不满足标准要求 */
+ CRYPT_CMVP_ERR_INTEGRITY, /**< 完整性验证失败 */
+
+ CRYPT_PBKDF2_PARAM_ERROR = 0x01150001, /**< 入参错误 */
+ CRYPT_PBKDF2_NOT_SUPPORTED, /**< 不支持PBKDF2算法 */
+
+ CRYPT_ECC_POINT_AT_INFINITY = 0x1160001, /**< 点在无穷远 */
+ CRYPT_ECC_POINT_NOT_ON_CURVE, /**< 点不在曲线上 */
+ CRYPT_ECC_POINT_ERR_CURVE_ID, /**< 曲线ID不一致或者错误 */
+ CRYPT_ECC_POINT_WINDOW_TOO_MAX, /**< 窗口过大 */
+ CRYPT_ECC_POINT_NOT_EQUAL, /**< 两个点不相等 */
+ CRYPT_ECC_POINT_BLIND_WITH_ZERO, /**< 点加盐时随机数生成值为0 */
+ CRYPT_ECC_POINT_NOT_AFFINE, /**< 点不为仿射坐标 */
+ CRYPT_ECC_NOT_SUPPORT, /**< 不支持该功能 */
+ CRYPT_ECC_POINT_MUL_ADD_WITH_ZERO_K, /**< 使用点乘加功能时,标量值为0返回错误 */
+ CRYPT_ECC_POINT_MUL_ERR_K_LEN, /**< 使用点乘功能时,标量长度超过曲线规格 */
+ CRYPT_ECC_BUFF_LEN_NOT_ENOUGH, /**< 缓冲区长度不足 */
+ CRYPT_ECC_ERR_POINT_FORMAT, /**< 进行点编码时输入的编码格式不对 */
+ CRYPT_ECC_ERR_POINT_CODE, /**< 错误的点编码信息 */
+ CRYPT_ECC_PKEY_ERR_UNSUPPORTED_CTRL_OPTION, /**< 不支持的控制类型 */
+ CRYPT_ECC_PKEY_ERR_EMPTY_KEY, /**< 秘钥为空 */
+ CRYPT_ECC_PKEY_ERR_INVALID_POINT_FORMAT, /**< 无效的点格式 */
+ CRYPT_ECC_PKEY_ERR_CTRL_LEN, /**< 控制入参的长度不正确 */
+ CRYPT_ECC_PKEY_ERR_INVALID_PRIVATE_KEY, /**< 无效的私钥 */
+ CRYPT_ECC_PKEY_ERR_INVALID_PUBLIC_KEY, /**< 无效的公钥 */
+ CRYPT_ECC_PKEY_ERR_TRY_CNT, /**< 秘钥生成、签名在规定的尝试次数内无法生成结果 */
+
+ CRYPT_SHA3_OUT_BUFF_LEN_NOT_ENOUGH = 0x01170001, /**< 承载输出结果的缓冲区长度不足 */
+
+ CRYPT_ECDH_ERR_UNSUPPORT_CURVE_TYPE = 0x01180001, /**< 不支持的曲线类型 */
+ CRYPT_ECDH_ERR_EMPTY_KEY, /**< 秘钥为空 */
+ CRYPT_ECDH_ERR_EMPTY_PARA, /**< 曲线参数为空 */
+ CRYPT_ECDH_ERR_UNSUPPORTED_CTRL_OPTION, /**< 不支持的控制选项 */
+ CRYPT_ECDH_ERR_INVALID_COFACTOR, /**< 无效的cofactor值 */
+ CRYPT_ECDH_ERR_INIFINITY_SHARE_KEY, /**< 计算出的share key为0 */
+
+ CRYPT_ECDSA_ERR_EMPTY_KEY = 0x01190001, /**< 秘钥为空 */
+ CRYPT_ECDSA_ERR_TRY_CNT, /**< 秘钥生成、签名在规定的尝试次数内无法生成结果 */
+ CRYPT_ECDSA_VERIFY_FAIL, /**< 验签失败 */
+ CRYPT_ECDSA_ERR_UNSUPPORTED_CTRL_OPTION, /**< 不支持的控制类型 */
+
+ CRYPT_SM3_INPUT_OVERFLOW = 0x11A0001, /**< 输入数据的长度超出SM3的最大处理范围 */
+ CRYPT_SM3_OUT_BUFF_LEN_NOT_ENOUGH, /**< 承载输出结果的缓冲区长度不足 */
+
+ CRYPT_SM4_ERR_IV_LEN = 0x011B0001, /**< SM4 iv长度不对,不是16 */
+ CRYPT_SM4_ERR_MSG_LEN, /**< SM4消息长度不对,不是16的倍数 */
+ CRYPT_SM4_ERR_KEY_LEN, /**< SM4秘钥长度不对,不是16 */
+
+ CRYPT_SM9_BUFF_LEN_NOT_ENOUGH = 0x011C0001, /**< BUFF长度不足 */
+ CRYPT_SM9_ERR_KEYTYPE, /**< 秘钥类型错误 */
+ CRYPT_SM9_ERR_TRY_CNT, /**< 签名过程随机数生成次数在尝试次数内无法生成结果 */
+ CRYPT_SM9_ERR_MD_METHOD, /**< 没有哈希方法信息 */
+ CRYPT_SM9_VERIFY_FAIL, /**< 验签失败 */
+ CRYPT_SM9_ERR_CTRL_TYPE, /**< 调用ctrl接口设置信息时ctrlType不对 */
+ CRYPT_SM9_ERR_HASH_METHOD, /**< 调用ctrl接口设置的哈希方法不对 */
+ CRYPT_SM9_POINT_AT_INFINITY, /**< 点在无穷远 */
+ CRYPT_SM9_POINT_NOT_ON_CURVE, /**< 点不在曲线上 */
+ CRYPT_SM9_ERR_POINT_FORMAT, /**< 点格式不正确 */
+ CRYPT_SM9_ERR_POINT_BUFF, /**< 点数据不正确 */
+ CRYPT_SM9_ERR_POINT_NOT_AFFINE, /**< 点不是仿射坐标 */
+ CRYPT_SM9_ERR_POINTS2AFFINE_CNT, /**< 多个点转到仿射坐标时点的数量错误 */
+ CRYPT_SM9_FQ2_NOT_EQUAL, /**< fq2点信息比较不一致 */
+
+ CRYPT_MD5_INPUT_OVERFLOW = 0x11D0001, /**< 输入数据的长度超出MD5的最大处理范围 */
+ CRYPT_MD5_OUT_BUFF_LEN_NOT_ENOUGH, /**< 承载输出结果的缓冲区长度不足 */
+
+ CRYPT_TDES_ERR_KEYLEN = 0x11E0001, /**< tdes秘钥长度错误 */
+ CRYPT_TDES_ERR_KEY, /**< des秘钥错误 */
+ CRYPT_TDES_ERR_LEN, /**< des加解密长度错误 */
+
+ CRYPT_CURVE448_NO_PUBKEY = 0x011F0001, /**< 没有公钥 */
+ CRYPT_CURVE448_NO_PRVKEY, /**< 没有私钥 */
+ CRYPT_CURVE448_KEYLEN_ERROR, /**< 秘钥长度错误 */
+ CRYPT_CURVE448_SIGNLEN_ERROR, /**< 签名长度错误 */
+ CRYPT_CURVE448_VERIFY_FAIL, /**< 签名不正确,验签失败 */
+ CRYPT_CURVE448_NO_HASH_METHOD, /**< 未设置哈希方法 */
+ CRYPT_CURVE448_UNSUPPORTED_CTRL_OPTION, /**< 不支持的操作模式 */
+ CRYPT_CURVE448_KEY_COMPUTE_FAILED, /**< 生成共享密钥失败 */
+ CRYPT_CURVE448_INVALID_PUBKEY, /**< 公钥非法 */
+ CRYPT_CURVE448_CONTEXT_TOO_LONG, /**< context超255 */
+ CRYPT_CURVE448_NO_CONTEXT, /**< 未设置ctx */
+ CRYPT_CURVE448_HASH_METH_ERROR, /**< 哈希方法不是SHAKE256 */
+
+ CRYPT_SM2_BUFF_LEN_NOT_ENOUGH = 0x01200001, /**< 缓冲区长度不足 */
+ CRYPT_SM2_NO_PUBKEY, /**< SM2未设置公钥 */
+ CRYPT_SM2_NO_PRVKEY, /**< SM2未设置私钥 */
+ CRYPT_SM2_ERR_EMPTY_KEY, /**< SM2秘钥为空 */
+ CRYPT_SM2_ERR_TRY_CNT, /**< 秘钥生成、签名在规定的尝试次数内无法生成结果 */
+ CRYPT_SM2_VERIFY_FAIL, /**< 验签失败 */
+ CRYPT_SM2_ERR_UNSUPPORTED_CTRL_OPTION, /**< 不支持的控制类型 */
+ CRYPT_SM2_ERR_CTRL_LEN, /**< 错误的ctrl长度 */
+ CRYPT_SM2_ERR_NO_HASH_METHOD, /**< 没有哈希方法信息 */
+ CRYPT_SM2_HASH_METH_ERROR, /**< 哈希方法不是SM3 */
+ CRYPT_SM2_USERID_NOT_SET, /**< userID未设置*/
+ CRYPT_SM2_R_NOT_SET, /**< 对端R值未设置*/
+ CRYPT_SM2_INVALID_SERVER_TYPE, /**< 用户既不是发起方也不是接收方 */
+ CRYPT_SM2_INVALID_CHECK_TYPE, /**< 错误的校验类型 */
+ CRYPT_SM2_DECRYPT_FAIL, /**< 解密失败 */
+ CRYPT_SM2_ERR_DATA_LEN, /**< 数据长度错误 */
+ CRYPT_SM2_ERR_GET_S, /**< 获取校验和失败 */
+ CRYPT_SM2_ERR_S_NOT_SET, /**< 未设置校验和 */
+ CRYPT_SM2_EXCH_VERIFY_FAIL, /**< 密钥协商失败 */
+
+ CRYPT_KDFTLS12_NOT_SUPPORTED = 0x01210001, /**< 不支持KDFTLS12算法 */
+
+ CRYPT_SIPHASH_OUT_BUFF_LEN_NOT_ENOUGH = 0x01220001, /**< 承载输出结果的缓冲区长度不足 */
+ CRYPT_SIPHASH_INPUT_OVERFLOW, /**< 输入数据的长度超出SIPHASH的最大处理范围 */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * @defgroup crypt_mpa_aead crypt_mpa_aead.h
+ * @ingroup crypto
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+ * @brief MPA多路并行计算对外接口文件
+ */
+#ifndef CRYPT_MPA_AEAD_H
+#define CRYPT_MPA_AEAD_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup crypt_mpa_aead
+ *
+ * 加密认证计算顺序
+ */
+typedef enum {
+ MPA_MTE, /**< hmac->aes */
+ MPA_ETM, /**< aes->hmac */
+} CRYPT_MPA_AeadOrder;
+
+/**
+ * @ingroup crypt_mpa_aead
+ *
+ * aes加密解密模式
+ */
+typedef enum {
+ MPA_ENC, /**< 加密 */
+ MPA_DEC, /**< 解密 */
+} CRYPT_MPA_EncMode;
+
+/**
+ * @ingroup crypt_mpa_aead
+ *
+ * hmac 算法类型
+ */
+typedef enum {
+ MPA_HASH_NONE, /**< 不使用hash 算法 */
+ MPA_MD5, /**< md5 算法(预留) */
+ MPA_SHA1, /**< sha1 算法(预留) */
+ MPA_SHA224, /**< sha224 算法(预留) */
+ MPA_SHA256, /**< sha256 算法 */
+ MPA_SHA384, /**< sha384 算法(预留) */
+ MPA_SHA512 /**< sha512 算法 */
+} CRYPT_MPA_HashAlg;
+
+/**
+ * @ingroup crypt_mpa_aead
+ *
+ * aes 算法类型
+ */
+typedef enum {
+ MPA_AES_NONE, /**< 不使用 aes 算法 */
+ MPA_AES128_CBC, /**< aes128cbc 算法 */
+ MPA_AES192_CBC, /**< aes192cbc 算法 */
+ MPA_AES256_CBC /**< aes256cbc 算法 */
+} CRYPT_MPA_AesMode;
+
+/**
+ * @ingroup crypt_mpa_aead
+ *
+ * 基于流的、对外数据结构。设置单条流的具体信息。
+ */
+typedef struct {
+ /* common */
+ uint32_t jobId; /**< job标记 */
+ uint32_t aeadOrder; /**< 认证加密模式:MPA_MTE、MPA_ETM */
+
+ /* aes alg resource */
+ const uint8_t *msgInput; /**< aes进行计算的数据输入, 明文或密文 */
+ uint8_t *msgOutput; /**< aes计算结果, 密文或明文 */
+ uint32_t aesMsgLen; /**< aes计算的数据长度,长度为16字节的整数倍,不支持aes padding功能 */
+ uint8_t aesMode; /**< aes模式:MPA_AES_NONE, MPA_AES128_CBC, MPA_AES192_CBC, MPA_AES256_CBC */
+ uint8_t encryptDecrypt; /**< aes加密或解密: MPA_ENC, MPA_DEC */
+ uint8_t res1[2]; /**< 预留 */
+ const uint8_t *iv; /**< aes初始向量输入 */
+ const uint8_t *aesKey; /**< aes密钥输入 */
+ uint32_t keyLen; /**< aes密钥长度,aes128:16字节;aes192:24字节;aes256:32字节 */
+ uint32_t ivLen; /**< aes初始向量长度,16字节 */
+ uint8_t *expandKeyEnc; /**< aes加密扩展密钥输入,aes128:11 * 16字节;aes192:13 * 16字节;aes256:15 * 16字节 */
+ uint8_t *expandKeyDec; /**< aes解密扩展密钥输入,aes128:11 * 16字节;aes192:13 * 16字节;aes256:15 * 16字节 */
+
+ /* hmac-sha resource */
+ const uint8_t *hmacKey; /**< hmac密钥输入 */
+ const uint8_t *msg; /**< hmac计算,数据输入 */
+ uint32_t hmacKeyLen; /**< hmac密钥长度 */
+ uint32_t msgLen; /**< hmac计算的数据长度 */
+ uint8_t *hashResult; /**< hmac计算结果mac输出 */
+ uint8_t hashAlg; /**< 哈希算法选择:MPA_HASH_NONE, MPA_SHA256,MPA_SHA512 */
+ uint8_t res2[3]; /**< 预留 */
+ uint32_t hashResultLen; /**< 输入参数,决定返回的mac数据长度;sha256:长度不大于32字节;sha512:长度不大于64字节 */
+ const uint8_t *ipadKeyHash; /**< hmac ipadKey数据哈希值,没有提前计算ipadkey哈希值,赋值NULL */
+ const uint8_t *opadKeyHash; /**< hmac opadKey数据哈希值,没有提前计算opadkey哈希值,赋值NULL */
+
+ void *userData; /**< 用户自定义使用 */
+} CRYPT_MPA_Job;
+
+typedef struct MGR_ CRYPT_MPA_Mgr;
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief 从mgr池子里面获取一个job
+ * @attention 调用者需要保证入参mgr不为空
+ * @param mgr [IN] 多流并行计算管理结构体,包含job池子
+ * @return 成功返回job;失败返回NULL
+ */
+void *CRYPT_MPA_MallocJob(CRYPT_MPA_Mgr *mgr);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief 提交job到调度层
+ * @attention 调用者需要保证入参mgr和job不为空
+ * @param mgr [IN] 多流并行计算管理结构体,包含job池子
+ * @param job [IN] 多流并行调度单元(当前支持算法:hmac,aes,aes-hmac组合)
+ * @return 有job计算完成,返回计算完成的job,用户需要自行释放job;无job计算完成则返回NULL
+ */
+void *CRYPT_MPA_CommitJob(CRYPT_MPA_Mgr *mgr, CRYPT_MPA_Job *job);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief 初始化多流并行计算模块
+ * @return 初始化成功返回0;初始化失败返回其它值
+ */
+uint32_t CRYPT_MPA_Init(void);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief init mgr resource
+ * @param mgr [IN] 多流并行计算管理结构体,包含job池子
+ * @param order [IN] 指定加解密和认证的顺序
+ * @return 初始化成功返回0;初始化失败返回其它值
+ */
+uint32_t CRYPT_MPA_InitMgr(CRYPT_MPA_Mgr *mgr, CRYPT_MPA_AeadOrder order);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief 申请mgr资源
+ * @return 成功返回mgr;失败返回NULL
+ */
+CRYPT_MPA_Mgr *CRYPT_MPA_MallocMgr(void);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief 释放mgr资源,与CRYPT_MPA_MallocMgr接口配对使用
+ * @param mgr [IN] 多流并行计算管理结构体,包含job池子
+ * @return NONE
+ */
+void CRYPT_MPA_FreeMgr(CRYPT_MPA_Mgr *mgr);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief 释放job资源. 如果CRYPT_MPA_CommitJob 和 CRYPT_MPA_FetchJob接口返回job资源,用户需要调用本接口释放job资源
+ * @attention 调用者需要保证入参mgr和job不为空
+ * @param mgr [IN] 多流并行计算管理结构体,包含job池子
+ * @param job [IN] 多流并行调度单元(当前支持算法:hmac,aes,aes-hmac组合)
+ * @return NONE
+ */
+void CRYPT_MPA_FreeJob(CRYPT_MPA_Mgr *mgr, CRYPT_MPA_Job *job);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief 强制处理job,并且返回处理完的job,每次返回一个job,直到所有的job处理完毕
+ * @attention 调用者需要保证入参mgr不为空
+ * @param mgr [IN] 多流并行计算管理结构体,包含job池子
+ * @return 用户提交的job如果还有没处理完的,返回处理完的job;所有job都处理完了,则返回NULL。用户需要负责释放返回的job
+ */
+void *CRYPT_MPA_FetchJob(CRYPT_MPA_Mgr *mgr);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief AES扩展密钥算法
+ * @param aesMode [IN] 指定AES模式
+ * @param key [IN] AES原始密钥. aes128: 16 bytes; aes192: 24 bytes; aes256: 32 bytes.
+ * @param encExpKey [OUT] 加密扩展密钥起始地址. 用户必须保证16字节对齐
+ * @param decExpKey [OUT] 解密扩展密钥起始地址. 用户必须保证16字节对齐
+ * @return 成功返回0;失败返回其它值
+ */
+uint32_t CRYPT_MPA_AesExpsionKey(CRYPT_MPA_AesMode aesMode, const uint8_t *key, uint8_t *encExpKey, uint8_t *decExpKey);
+
+/**
+ * @ingroup crypt_mpa_aead
+ * @brief hmac-sha2 算法 opadkey ipadkey hash计算,本接口不做填充. 在使用该接口前,需要调用CRYPT_MPA_Init初始化
+ * @param hashAlg [IN] 指定hash模式
+ * @param key [IN] hmac 密钥
+ * @param keyLen [IN] hmac 密钥长度
+ * @param opadKeyHash [OUT] opay key hash计算结果. SHA256要求32字节空间;SHA512算法要求64字节空间
+ * @param opadKeyHashLen [IN] 指定opadKeyHash长度
+ * @param ipadKeyHash [OUT] ipay key hash计算结果. SHA256要求32字节空间;SHA512算法要求64字节空间
+ * @param ipadKeyHashLen [IN] 指定ipadKeyHash长度
+ * @return 成功返回0;失败返回其它值
+ */
+uint32_t CRYPT_MPA_PadKeyHashNoPadding(CRYPT_MPA_HashAlg hashAlg, const uint8_t *key, uint32_t keyLen,
+ uint8_t *opadKeyHash, uint32_t opadKeyHashLen, uint8_t *ipadKeyHash, uint32_t ipadKeyHashLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/**\r
+ * @defgroup crypt_types crypt_types.h\r
+ * @ingroup crypto\r
+ * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.\r
+ * @brief 算法ID对外接口\r
+ */\r
+\r
+#ifndef CRYPT_TYPES_H\r
+#define CRYPT_TYPES_H\r
+\r
+#include <stdint.h>\r
+#include "crypt_algid.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * 数据结构体\r
+ */\r
+typedef struct {\r
+ uint8_t *data; /**< 数据内容 */\r
+ uint32_t len; /**< 数据长度 */\r
+} CRYPT_Data;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * 数据范围\r
+ */\r
+typedef struct {\r
+ uint32_t min; /**< 最小值 */\r
+ uint32_t max; /**< 最大值 */\r
+} CRYPT_Range;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * RSA用于签名时,Pkcsv15填充方式的结构体\r
+ */\r
+typedef struct {\r
+ CRYPT_MD_AlgId mdId; /**< pkcsv15 填充时时候的哈希算法ID*/\r
+} CRYPT_RSA_PkcsV15Para;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * RSA用于签名时,PSS填充方式的结构体\r
+ */\r
+typedef struct {\r
+ int32_t saltLen; /**< pss 盐值长度,-1表示hashLen,-2表示MaxLen */\r
+ CRYPT_MD_AlgId mdId; /**< pss 填充时的mdid */\r
+ CRYPT_MD_AlgId mgfId; /**< pss 填充时的mgfid */\r
+} CRYPT_RSA_PssPara;\r
+\r
+typedef struct {\r
+ CRYPT_MD_AlgId mdId; /**< pss 填充时的mdid */\r
+ CRYPT_MD_AlgId mgfId; /**< pss 填充时的mgfid */\r
+} CRYPT_RSA_OaepPara;\r
+\r
+typedef enum {\r
+ CRYPT_RSA_BLINDING = 0x00000001, /**< 开启RSA blinding功能进行签名\r
+ 此时需要设置公钥信息,或者在设置私钥的时候设置p q参数 */\r
+ CRYPT_RSA_MAXFLAG\r
+} CRYPT_RSA_Flag;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * RSA私钥参数结构体\r
+ */\r
+typedef struct {\r
+ uint8_t *d; /**< RSA 私钥参数d */\r
+ uint8_t *n; /**< RSA 私钥参数n */\r
+ uint8_t *p; /**< RSA 私钥参数p */\r
+ uint8_t *q; /**< RSA 私钥参数q */\r
+ uint32_t dLen; /**< RSA 私钥参数d的长度 */\r
+ uint32_t nLen; /**< RSA 私钥参数n的长度 */\r
+ uint32_t pLen; /**< RSA 私钥参数p的长度 */\r
+ uint32_t qLen; /**< RSA 私钥参数q的长度 */\r
+} CRYPT_RsaPrv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * DSA私钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_DsaPrv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ECC私钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_EccPrv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ECDSA私钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_EcdsaPrv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * SM2私钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_Sm2Prv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * DH私钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_DhPrv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ECDH私钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_EcdhPrv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ed25519/x25519私钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_Curve25519Prv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ed448/x448私钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_Curve448Prv;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * RSA公钥参数结构体\r
+ */\r
+typedef struct {\r
+ uint8_t *e; /**< RSA 公钥参数e */\r
+ uint8_t *n; /**< RSA 公钥参数n */\r
+ uint32_t eLen; /**< RSA 公钥参数e的长度 */\r
+ uint32_t nLen; /**< RSA 公钥参数e的长度 */\r
+} CRYPT_RsaPub;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * DSA公钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_DsaPub;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ECC公钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_EccPub;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ECDSA公钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_EcdsaPub;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * SM2公钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_Sm2Pub;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * DH公钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_DhPub;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ECDH公钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_EcdhPub;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ed25519/x25519公钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_Curve25519Pub;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * ed448/x448公钥参数结构体\r
+ */\r
+typedef CRYPT_Data CRYPT_Curve448Pub;\r
+\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * RSA算法的Para结构体\r
+ */\r
+typedef struct { // 该参数全不可为空, 由底层结构判断\r
+ uint8_t *e; /**< para 参数e */\r
+ uint32_t eLen; /**< para 参数e的长度 */\r
+ uint32_t bits; /**< para 的bits */\r
+} CRYPT_RsaPara;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * DSA算法的Para结构体\r
+ */\r
+typedef struct { // 该参数全不可为空, 由底层结构判断\r
+ uint8_t *p; /**< 参数p */\r
+ uint8_t *q; /**< 参数q */\r
+ uint8_t *g; /**< 参数g */\r
+ uint32_t pLen; /**< 参数p的长度 */\r
+ uint32_t qLen; /**< 参数q的长度 */\r
+ uint32_t gLen; /**< 参数g的长度 */\r
+} CRYPT_DsaPara;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * DH算法的Para结构体\r
+ */\r
+typedef struct {\r
+ uint8_t *p; /**< 参数p */\r
+ uint8_t *q; /**< 参数q 该参数可为空L */\r
+ uint8_t *g; /**< 参数g */\r
+ uint32_t pLen; /**< 参数p的长度 */\r
+ uint32_t qLen; /**< 参数q的长度 */\r
+ uint32_t gLen; /**< 参数g的长度 */\r
+} CRYPT_DhPara;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ *\r
+ * RAND注册接口的metohd结构体,包括熵源获取和清理接口,随机数获取和清理接口。\r
+ */\r
+typedef struct {\r
+ /**\r
+ * @ingroup crypt_types\r
+ * @brief 获取熵源,该接口必须注册,其输出的数据需要满足长度等要求,HiTLS不会对熵源进行检查,需要由熵源提供者实现\r
+ *\r
+ * ctx [IN] 调用者所使用的上下文\r
+ * entropy [OUT] 获取到的熵源数据,熵源数据长度需要满足:lenRange->min <= len <= lenRange->max\r
+ * strength [IN] 熵源强度\r
+ * lenRange [IN] 熵源长度范围\r
+ * @return 0表示成功,其他表示失败\r
+ */\r
+ int32_t (*getEntropy)(void *ctx, CRYPT_Data *entropy, uint32_t strength, CRYPT_Range *lenRange);\r
+\r
+ /**\r
+ * @ingroup crypt_types\r
+ * @brief 熵源内存清理,非必须注册接口\r
+ * ctx [IN] 调用者所使用的上下文\r
+ * entropy [OUT] 熵源数据\r
+ * @return void\r
+ */\r
+ void (*cleanEntropy)(void *ctx, CRYPT_Data *entropy);\r
+\r
+ /**\r
+ * @ingroup crypt_types\r
+ * @brief 获取随机数,该接口不是必须注册的\r
+ 如果注册,其输出的数据需要满足长度等要求,HiTLS不会对熵源进行检查,需要由提供则实现\r
+ *\r
+ * ctx [IN] 调用者所使用的上下文\r
+ * nonce [OUT] 获取到的随机数,随机数长度需要满足:lenRange->min <= len <= lenRange->max\r
+ * strength [IN] 随机数强度\r
+ * lenRange [IN] 随机数长度范围\r
+ * @return 0表示成功,其他表示失败\r
+ */\r
+ int32_t (*getNonce)(void *ctx, CRYPT_Data *nonce, uint32_t strength, CRYPT_Range *lenRange);\r
+\r
+ /**\r
+ * @ingroup crypt_types\r
+ * @brief 随机数内存清理,非必须注册接口\r
+ * ctx [IN] 调用者所使用的上下文\r
+ * nonce [OUT] 随机数\r
+ * @return void\r
+ */\r
+ void (*cleanNonce)(void *ctx, CRYPT_Data *nonce);\r
+} CRYPT_RandSeedMethod;\r
+\r
+/**\r
+ * @ingroup crypt_ctrl_param\r
+ *\r
+ * 设置、获取内部modes的参数\r
+ */\r
+typedef enum {\r
+ CRYPT_CTRL_SET_IV = 0, /**< 设置iv 数据为uint8_t 类型*/\r
+ CRYPT_CTRL_GET_IV, /**< 获取iv 数据为uint8_t* 类型 */\r
+ CRYPT_CTRL_GET_BLOCKSIZE, /**< 获取块大小 数据为uint8_t类型 */\r
+ CRYPT_CTRL_SET_COUNT, /**< 设置计数器信息,输入为四字节小端排布的字节流,需要的算法为chacha20 */\r
+ CRYPT_CTRL_SET_AAD, /**< AEAD加解密模式下设置aad信息 */\r
+ CRYPT_CTRL_GET_TAG, /**< AEAD加密或解密,在结束时获取tag */\r
+ CRYPT_CTRL_SET_TAGLEN, /**< AEAD加解密,设置tag长度,在加解密开始之前设置,设置类型为uint32_t */\r
+ CRYPT_CTRL_SET_MSGLEN, /**< CMM模式下需要加密消息长度作为输入用于计算,需要在SET_AAD之前设置,输入数据为一个uint64_t类型 */\r
+ CRYPT_CTRL_SET_FEEDBACKSIZE, /**< CFB模式下设置密文反馈长度 */\r
+ CRYPT_CTRL_GET_FEEDBACKSIZE, /**< CFB模式下获取密文反馈长度 */\r
+ CRYPT_CTRL_SET_SM4_CONSTTIME, /**< SM4选择侧信道安全实现,降低性能。仅在启用ARM汇编实现时有效 */\r
+ CRYPT_CTRL_MAX\r
+} CRYPT_CipherCtrl;\r
+\r
+/**\r
+ * @ingroup crypt_ctrl_param\r
+ *\r
+ * pkey设置、获取内部的参数\r
+ */\r
+typedef enum {\r
+ CRYPT_CTRL_SET_ED25519_HASH_METHOD, /**< ED25519设置哈希方法 */\r
+ CRYPT_CTRL_SET_RSA_EMSA_PKCSV15, /**< RSA设置签名填充方式为EMSA_PKCSV15 */\r
+ CRYPT_CTRL_SET_RSA_EMSA_PSS, /**< RSA设置签名填充方式为EMSA_PSS */\r
+ CRYPT_CTRL_SET_RSA_SALT, /**< RSA算法进行PSS签名时指定盐数据,使用时将用户数据地址直接保存到秘钥\r
+ 并在下一次签名时使用,必须保证设置后的下一次签名在盐数据的生命周期内\r
+ 调用,该选项不推荐用户使用,仅用于KAT测试、自校验时使用 */\r
+ CRYPT_CTRL_SET_ECC_POINT_FORMAT, /**< ECC PKEY设置点格式,点格式参照CRYPT_PKEY_PointFormat */\r
+ CRYPT_CTRL_SET_ECC_USE_COFACTOR_MODE, /**< ECC PKEY设置是否使用cofactor模式,使用后可防止中间人篡改\r
+ 公钥,使用置为1,不使用置为0 */\r
+ CRYPT_CTRL_SET_RSA_RSAES_OAEP, /**< RSA设置加解密填充方式为RSAES_OAEP */\r
+ CRYPT_CTRL_SET_RSA_OAEP_LABEL, /**< RSA oaep充填设置label, 用于生成hash值 */\r
+ CRYPT_CTRL_SET_RSA_FLAG, /**< RSA 设置flag */\r
+ CRYPT_CTRL_CLR_RSA_FLAG, /**< RSA 清除flag */\r
+ CRYPT_CTRL_SET_RSA_RSAES_PKCSV15, /**< RSA设置加解密填充方式为RSAES_PKCSV15 */\r
+\r
+ CRYPT_CTRL_SET_SM9_HASH_METHOD, /**< SM9设置哈希方法 */\r
+\r
+ CRYPT_CTRL_SET_ED448_HASH_METHOD, /**< ed448设置哈希方法 */\r
+ CRYPT_CTRL_SET_ED448_CONTEXT, /**< ed448设置context */\r
+ CRYPT_CTRL_SET_ED448_PREHASH, /**< ed448设置prehash模式 */\r
+ CRYPT_CTRL_SET_SM2_USER_ID, /**< SM2设置用户ID */\r
+ CRYPT_CTRL_SET_SM2_HASH_METHOD, /**< SM2设置使用SM3计算杂凑值 */\r
+ CRYPT_CTRL_SET_SM2_SERVER, /**< SM2设置用户状态 */\r
+ CRYPT_CTRL_GENE_SM2_R, /**< SM2获取R值 */\r
+ CRYPT_CTRL_SET_SM2_R, /**< SM2设置R值 */\r
+ CRYPT_CTRL_SM2_GET_SEND_CHECK, /**< SM2获取本端发送给对端的校验值 */\r
+ CRYPT_CTRL_SM2_DO_CHECK, /**< SM2校验共享密钥 */\r
+ CRYPT_CTRL_SET_NO_PADDING, /**< RSA设置加解密填充方式为NO_PADDING */\r
+} CRYPT_PkeyCtrl;\r
+\r
+/**\r
+ * @ingroup crypt_padding_type\r
+ *\r
+ * 填充方式枚举类型\r
+ */\r
+typedef enum {\r
+ CRYPT_PADDING_NONE = 0, /**< Never pad (full blocks only). */\r
+ CRYPT_PADDING_ZEROS, /**< Zero padding (not reversible). */\r
+ CRYPT_PADDING_ISO7816, /**< ISO/IEC 7816-4 padding. */\r
+ CRYPT_PADDING_X923, /**< ANSI X.923 padding. */\r
+ CRYPT_PADDING_PKCS5, /**< PKCS5 padding. */\r
+ CRYPT_PADDING_PKCS7, /**< PKCS7 padding. */\r
+ CRYPT_PADDING_MAX_COUNT\r
+} CRYPT_PaddingType;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ * 操作类型\r
+ */\r
+typedef enum {\r
+ CRYPT_EVENT_ENC, /**< 加密*/\r
+ CRYPT_EVENT_DEC, /**< 解密*/\r
+ CRYPT_EVENT_GEN, /**< 生成密钥*/\r
+ CRYPT_EVENT_SIGN, /**< 签名*/\r
+ CRYPT_EVENT_VERIFY, /**< 验签*/\r
+ CRYPT_EVENT_MD, /**< 哈希*/\r
+ CRYPT_EVENT_MAC, /**< MAC*/\r
+ CRYPT_EVENT_KEYAGGREMENT, /**< 密钥协商*/\r
+ CRYPT_EVENT_KEYDERIVE, /**< 派生密钥*/\r
+ CRYPT_EVENT_RANDGEN, /**< 生成随机数*/\r
+ CRYPT_EVENT_ZERO, /**< 敏感信息置零*/\r
+ CRYPT_EVENT_ERR, /**< 发生错误*/\r
+ CRYPT_EVENT_SETSSP, /**< 添加、修改密码数据和SSP*/\r
+ CRYPT_EVENT_GETSSP, /**< 访问密码数据和SSP*/\r
+ CRYPT_EVENT_MAX\r
+} CRYPT_EVENT_TYPE;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ * 算法类型\r
+ */\r
+typedef enum {\r
+ CRYPT_ALGO_CIPHER = 0,\r
+ CRYPT_ALGO_PKEY,\r
+ CRYPT_ALGO_MD,\r
+ CRYPT_ALGO_MAC,\r
+ CRYPT_ALGO_KDF,\r
+ CRYPT_ALGO_RAND\r
+} CRYPT_ALGO_TYPE;\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ * @brief 事件上报\r
+ *\r
+ * @param oper [IN] 操作类型\r
+ * @param type [IN] 算法类型\r
+ * @param id [IN] 算法id\r
+ * @param err [IN] 错误码,成功为CRYPT_SUCCESS,其他错误码参考crypt_errno.h\r
+ *\r
+ * @return 无\r
+ */\r
+typedef void (*EventReport)(CRYPT_EVENT_TYPE oper, CRYPT_ALGO_TYPE type, int32_t id, int32_t err);\r
+\r
+/**\r
+ * @ingroup crypt_types\r
+ * @brief\r
+ * 事件上报回调注册接口,EAL执行完服务及报错时会上报事件。不支持多线程\r
+ *\r
+ * @param func [IN] 事件上报处理回调\r
+ *\r
+ * @return 无\r
+ */\r
+void CRYPT_EAL_RegEventReport(EventReport func);\r
+\r
+/* SM9算法秘钥类型枚举 */\r
+typedef enum {\r
+ SM9_NOKEY = 0x00, // 不存在秘钥信息\r
+ SM9_SIGN_KEY = 0x01, // 签名\r
+ SM9_VERIFY_KEY = 0x02, // 验签\r
+ SM9_COMPUTE_SHARE_KEY = 0x04, // 共享秘钥计算\r
+ SM9_ENC_KEY = 0x08, // 加密\r
+ SM9_DEC_KEY = 0x10, // 解密\r
+ SM9_KEY_GEN = 0x20, // 秘钥生成\r
+} CRYPT_SM9_KeyType;\r
+\r
+/* SM9算法用户设置/获取秘钥使用的公钥结构体 */\r
+typedef struct {\r
+ CRYPT_Data pub; // 主公钥 1、用于签名验签 Fp2;2、用于加解密 Fp1\r
+ CRYPT_Data idA; // 标识ID\r
+ CRYPT_SM9_KeyType keyType; // 秘钥类型,用于签名验签、共享秘钥计算、加解密\r
+ uint8_t hid; // 标识符\r
+} CRYPT_Sm9Pub;\r
+\r
+/* SM9算法用户设置/获取秘钥使用的私钥结构体 */\r
+typedef struct {\r
+ CRYPT_Data pub; // 主公钥 1、用于签名验签 Fp2;2、用于加解密、共享秘钥计算 Fp1\r
+ CRYPT_Data prv; // 主私钥 1、进行秘钥生成时使用\r
+ CRYPT_Data d; // 用户私钥 1、用于签名验签 Fp1 2、用于加解密、共享秘钥计算 Fp2\r
+ CRYPT_Data idA; // 标识ID 签名可设置为NULL\r
+ CRYPT_SM9_KeyType keyType; // 秘钥类型\r
+ uint8_t hid; // 标识符 签名时不使用该值\r
+} CRYPT_Sm9Prv;\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+#endif // CRYPT_TYPES_H\r