!41 merge master into master

add sha256-mb interfaces

Created-by: Dongjianwei001
Commit-by: jchx;Dongjianwei001;dumb
Merged-by: openharmony_ci
Description: ### 一、内容说明(相关的Issue)



### 二、建议测试周期和提测地址  
  建议测试完成时间:xxxx.xx.xx  
  投产上线时间:xxxx.xx.xx  
  提测地址:CI环境/压测环境  
  测试账号:  

### 三、变更内容
  * 3.1 关联PR列表

  * 3.2 数据库和部署说明  
    1. 常规更新 
    2. 重启unicorn
    3. 重启sidekiq
    4. 迁移任务:是否有迁移任务,没有写 "无"
    5. rake脚本:`bundle exec xxx RAILS_ENV = production`;没有写 "无"

  * 3.4 其他技术优化内容(做了什么,变更了什么)
    - 重构了 xxxx 代码
    - xxxx 算法优化


  * 3.5 废弃通知(什么字段、方法弃用?)



  * 3.6  后向不兼容变更(是否有无法向后兼容的变更?)


  
### 四、研发自测点(自测哪些?冒烟用例全部自测?)
  自测测试结论:


### 五、测试关注点(需要提醒QA重点关注的、可能会忽略的地方)
  检查点:

| 需求名称 | 是否影响xx公共模块 | 是否需要xx功能 | 需求升级是否依赖其他子产品 |
|------|------------|----------|---------------|
| xxx  | 否          | 需要       | 不需要           |
|      |            |          |               |

  接口测试:

  性能测试:

  并发测试:

  其他:



See merge request: openharmony/third_party_openhitls!41
This commit is contained in:
openharmony_ci
2026-02-12 15:54:40 +08:00
21 changed files with 1868 additions and 100 deletions
+1
View File
@@ -147,6 +147,7 @@ public_all_defines = [
"HITLS_CRYPTO_MLDSA",
"HITLS_CRYPTO_SLH_DSA",
"HITLS_CRYPTO_SM2_PRECOMPUTE_512K_TBL",
"HITLS_CRYPTO_SHA2_MB",
"HITLS_PKI",
"HITLS_PKI_INFO",
"HITLS_PKI_PKCS12",
+6 -1
View File
@@ -54,6 +54,11 @@
},
"sha3": null
},
"md_mb": {
"sha2_mb": {
"sha256_mb": null
}
},
"mac": {
"hmac": null,
"gmac": {"deps": ["eal", "aes", "gcm"]},
@@ -709,7 +714,7 @@
".deps": ["platform::Secure_C"]
},
"sha2": {
".features": ["sha224", "sha256", "sha384", "sha512"],
".features": ["sha224", "sha256", "sha384", "sha512", "sha2_mb"],
".srcs": {
"public": "crypto/sha2/src/sha2*.c",
"no_asm": "crypto/sha2/src/noasm_*.c",
@@ -752,6 +752,30 @@
#define HITLS_CRYPTO_SM3_ASM
#endif
#ifdef HITLS_CRYPTO_MD_MB
#ifndef HITLS_CRYPTO_SHA2_MB
#define HITLS_CRYPTO_SHA2_MB
#endif
#endif
#ifdef HITLS_CRYPTO_SHA2_MB
#ifndef HITLS_CRYPTO_SHA256_MB
#define HITLS_CRYPTO_SHA256_MB
#endif
#endif
#if defined(HITLS_CRYPTO_SHA256_MB)
#ifndef HITLS_CRYPTO_SHA2_MB
#define HITLS_CRYPTO_SHA2_MB
#endif
#endif
#if defined(HITLS_CRYPTO_SHA2_MB)
#ifndef HITLS_CRYPTO_MD_MB
#define HITLS_CRYPTO_MD_MB
#endif
#endif
#if defined(HITLS_CRYPTO_BN_X8664) || defined(HITLS_CRYPTO_BN_ARMV8)
#define HITLS_CRYPTO_BN_ASM
#endif
+118
View File
@@ -27,6 +27,7 @@
#include "crypt_errno.h"
#include "eal_md_local.h"
#include "eal_common.h"
#include "crypt_utils.h"
#include "crypt_ealinit.h"
#ifdef HITLS_CRYPTO_PROVIDER
#include "crypt_eal_implprovider.h"
@@ -440,4 +441,121 @@ int32_t CRYPT_EAL_Md(CRYPT_MD_AlgId id, const uint8_t *in, uint32_t inLen, uint8
{
return EAL_Md(id, in, inLen, out, outLen);
}
#ifdef HITLS_CRYPTO_MD_MB
CRYPT_EAL_MdCTX *CRYPT_EAL_MdMBNewCtx(CRYPT_EAL_LibCtx *libCtx, int32_t id, uint32_t num)
{
(void)libCtx;
if (UNLIKELY(num == 0)) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NULL_INPUT);
return NULL;
}
EAL_MdMBMethod mbMethod = {0};
if (EAL_MdFindMbMethod(id, &mbMethod) == NULL ||
mbMethod.newCtx == NULL || mbMethod.freeCtx == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NOT_SUPPORT);
return NULL;
}
void *mbData = mbMethod.newCtx(num);
if (mbData == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_MEM_ALLOC_FAIL);
return NULL;
}
CRYPT_EAL_MdCTX *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_EAL_MdCTX));
if (ctx == NULL) {
mbMethod.freeCtx(mbData);
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_MEM_ALLOC_FAIL);
return NULL;
}
ctx->mbMethod = mbMethod;
ctx->data = mbData;
ctx->id = id;
ctx->state = CRYPT_MD_STATE_NEW;
return ctx;
}
void CRYPT_EAL_MdMBFreeCtx(CRYPT_EAL_MdCTX *ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->mbMethod.freeCtx != NULL) {
ctx->mbMethod.freeCtx(ctx->data);
}
BSL_SAL_Free(ctx);
}
int32_t CRYPT_EAL_MdMBInit(CRYPT_EAL_MdCTX *ctx)
{
if (UNLIKELY(ctx == NULL)) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, CRYPT_MD_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
CRYPT_MD_AlgId id = ctx->id;
if (ctx->mbMethod.init == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
int32_t ret = ctx->mbMethod.init(ctx->data);
if (ret == CRYPT_SUCCESS) {
ctx->state = CRYPT_MD_STATE_INIT;
}
return ret;
}
int32_t CRYPT_EAL_MdMBUpdate(CRYPT_EAL_MdCTX *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num)
{
if (UNLIKELY(ctx == NULL || data == NULL || nbytes == NULL || num == 0)) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, CRYPT_MD_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (UNLIKELY(nbytes[0] == 0)) {
return CRYPT_SUCCESS;
}
CRYPT_MD_AlgId id = ctx->id;
if (ctx->mbMethod.update == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
int32_t ret = ctx->mbMethod.update(ctx->data, data, nbytes, num);
if (ret == CRYPT_SUCCESS) {
ctx->state = CRYPT_MD_STATE_UPDATE;
}
return ret;
}
int32_t CRYPT_EAL_MdMBFinal(CRYPT_EAL_MdCTX *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num)
{
if (UNLIKELY(ctx == NULL || digest == NULL || outlen == NULL || num == 0)) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, CRYPT_MD_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
CRYPT_MD_AlgId id = ctx->id;
if (ctx->mbMethod.final == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
int32_t ret = ctx->mbMethod.final(ctx->data, digest, outlen, num);
if (ret == CRYPT_SUCCESS) {
ctx->state = CRYPT_MD_STATE_FINAL;
}
return ret;
}
#endif // HITLS_CRYPTO_MD_MB
#endif
+7
View File
@@ -38,11 +38,18 @@ typedef enum {
struct EAL_MdCtx {
bool isProvider;
EAL_MdUnitaryMethod *method; /* algorithm operation entity */
#ifdef HITLS_CRYPTO_MD_MB
EAL_MdMBMethod mbMethod; /* multi-buffer operation entity */
#endif
void *data; /* Algorithm ctx, mainly context */
uint32_t state;
CRYPT_MD_AlgId id;
};
#ifdef HITLS_CRYPTO_MD_MB
EAL_MdMBMethod *EAL_MdFindMbMethod(CRYPT_MD_AlgId id, EAL_MdMBMethod *method);
#endif
/**
* @ingroup eal
* @brief Method for generating the hash algorithm
+40
View File
@@ -140,6 +140,46 @@ const EAL_MdMethod *EAL_MdFindMethod(CRYPT_MD_AlgId id)
return NULL;
}
#ifdef HITLS_CRYPTO_MD_MB
#ifdef HITLS_CRYPTO_SHA2_MB
static const EAL_MdMBMethod g_mdMbMethod_SHA256 = {
(MdMBNewCtx)CRYPT_SHA256_MBNewCtx,
(MdMBFreeCtx)CRYPT_SHA256_MBFreeCtx,
(MdMBInit)CRYPT_SHA256_MBInit,
(MdMBUpdate)CRYPT_SHA256_MBUpdate,
(MdMBFinal)CRYPT_SHA256_MBFinal
};
#endif
static const EAL_CidToMdMbMeth ID_TO_MD_MB_METH_TABLE[] = {
#ifdef HITLS_CRYPTO_SHA2_MB
{CRYPT_MD_SHA256_MB, &g_mdMbMethod_SHA256},
#endif
};
static const EAL_MdMBMethod *EAL_MdFindDefaultMbMethod(CRYPT_MD_AlgId id)
{
uint32_t num = sizeof(ID_TO_MD_MB_METH_TABLE) / sizeof(ID_TO_MD_MB_METH_TABLE[0]);
for (uint32_t i = 0; i < num; i++) {
if (ID_TO_MD_MB_METH_TABLE[i].id == id) {
return ID_TO_MD_MB_METH_TABLE[i].mbMeth;
}
}
return NULL;
}
EAL_MdMBMethod *EAL_MdFindMbMethod(CRYPT_MD_AlgId id, EAL_MdMBMethod *method)
{
const EAL_MdMBMethod *findMethod = EAL_MdFindDefaultMbMethod(id);
if (findMethod == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_ALGID);
return NULL;
}
*method = *findMethod;
return method;
}
#endif // HITLS_CRYPTO_MD_MB
int32_t EAL_Md(CRYPT_MD_AlgId id, const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)
{
int32_t ret;
+23
View File
@@ -45,6 +45,22 @@ typedef void (*MdFreeCtx)(void *data);
typedef int32_t (*MdCtrl)(void *data, int32_t cmd, void *val, uint32_t valLen);
typedef int32_t (*MdSqueeze)(void *data, uint8_t *out, uint32_t len);
#ifdef HITLS_CRYPTO_MD_MB
typedef void *(*MdMBNewCtx)(uint32_t num);
typedef void (*MdMBFreeCtx)(void *ctx);
typedef int32_t (*MdMBInit)(void *ctx);
typedef int32_t (*MdMBUpdate)(void *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num);
typedef int32_t (*MdMBFinal)(void *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num);
typedef struct {
MdMBNewCtx newCtx;
MdMBFreeCtx freeCtx;
MdMBInit init;
MdMBUpdate update;
MdMBFinal final;
} EAL_MdMBMethod;
#endif // HITLS_CRYPTO_MD_MB
typedef struct {
uint16_t blockSize; // Block size processed by the hash algorithm at a time, which is used with other algorithms.
uint16_t mdSize; // Output length of the HASH algorithm
@@ -86,6 +102,13 @@ typedef struct {
EAL_MdMethod *mdMeth;
} EAL_CidToMdMeth;
#ifdef HITLS_CRYPTO_MD_MB
typedef struct {
uint32_t id;
const EAL_MdMBMethod *mbMeth;
} EAL_CidToMdMbMeth;
#endif
/* provide asymmetric primitive method */
typedef void *(*PkeyNew)(void);
typedef void* (*PkeyProvNew)(void *provCtx, int32_t algId);
-2
View File
@@ -185,7 +185,6 @@ g_kExt:
.global SHA1_Step
.type SHA1_Step, %function
SHA1_Step:
.inst 0xd503233f // paciasp
cmp x1, #64
b.lo .Lend_sha1
@@ -454,7 +453,6 @@ SHA1_Step:
ldp x29, x30, [sp], #96
.Lend_sha1:
.inst 0xd50323bf // autiasp
ret
.size SHA1_Step, .-SHA1_Step
+148
View File
@@ -38,6 +38,7 @@ extern "C" {
#ifdef HITLS_CRYPTO_SHA256
#define CRYPT_SHA2_256_BLOCKSIZE 64
#define CRYPT_SHA2_256_DIGESTSIZE 32
#define CRYPT_SHA256_STATE_SIZE 8
#endif // HITLS_CRYPTO_SHA256
#ifdef HITLS_CRYPTO_SHA384
@@ -254,6 +255,153 @@ int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint
* @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);
typedef struct {
uint32_t num;
CRYPT_SHA2_256_Ctx *ctxs;
} CRYPT_SHA2_256_MB_Ctx;
/**
* @ingroup SHA256
* @brief Create a SHA256 multi-buffer context.
*
* Notes:
* - Currently only supports num == 2.
*
* @param num [IN] Number of parallel messages/contexts.
*
* @retval Pointer to multi-buffer context on success.
* @retval NULL on failure (invalid num or memory allocation failure).
*/
CRYPT_SHA2_256_MB_Ctx *CRYPT_SHA256_MBNewCtx(uint32_t num);
/**
* @ingroup SHA256
* @brief Free a SHA256 multi-buffer context.
*
* @param ctx [IN] Multi-buffer context pointer (can be NULL).
*/
void CRYPT_SHA256_MBFreeCtx(CRYPT_SHA2_256_MB_Ctx *ctx);
/**
* @ingroup SHA256
* @brief Initialize a SHA256 multi-buffer context.
*
* Notes:
* - Currently only supports ctx->num == 2.
*
* @param ctx [IN/OUT] Multi-buffer context.
*
* @retval #CRYPT_SUCCESS Success.
* @retval #CRYPT_NULL_INPUT ctx is NULL.
* @retval #CRYPT_NOT_SUPPORT Not supported (e.g. ctx->num != 2 or platform capability missing).
*/
int32_t CRYPT_SHA256_MBInit(CRYPT_SHA2_256_MB_Ctx *ctx);
/**
* @ingroup SHA256
* @brief Update SHA256 multi-buffer context with message fragments.
*
* Notes:
* - Each update processes one fragment per message, where data[i] is the fragment for lane i.
* - nbytes[i] is the fragment length for lane i. Currently requires nbytes[0] == nbytes[1],
* otherwise returns #CRYPT_NOT_SUPPORT.
* - Currently only supports num == 2.
*
* @param ctx [IN/OUT] Multi-buffer context.
* @param data [IN] Input pointer array. data[i] is fragment pointer for lane i.
* @param nbytes [IN] Input length array. nbytes[i] is fragment length for lane i.
* @param num [IN] Number of lanes/messages.
*
* @retval #CRYPT_SUCCESS Success.
* @retval #CRYPT_NULL_INPUT Invalid input pointer.
* @retval #CRYPT_NOT_SUPPORT Not supported (e.g. num != 2 or per-lane lengths are not equal).
* @retval Other error codes, see crypt_errno.h.
*/
int32_t CRYPT_SHA256_MBUpdate(CRYPT_SHA2_256_MB_Ctx *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num);
/**
* @ingroup SHA256
* @brief Finalize SHA256 multi-buffer context and output digests.
*
* Notes:
* - Currently only supports num == 2.
* - outlen indicates output buffer size on input and returns actual digest length on output.
*
* @param ctx [IN/OUT] Multi-buffer context.
* @param digest [OUT] Digest buffer pointer array. digest[i] is output buffer for lane i.
* @param outlen [IN/OUT] Output buffer length / output digest length.
* @param num [IN] Number of lanes/messages.
*
* @retval #CRYPT_SUCCESS Success.
* @retval #CRYPT_NULL_INPUT Invalid input pointer.
* @retval #CRYPT_NOT_SUPPORT Not supported (e.g. num != 2 or platform capability missing).
* @retval Other error codes, see crypt_errno.h.
*/
int32_t CRYPT_SHA256_MBFinal(CRYPT_SHA2_256_MB_Ctx *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num);
/**
* @ingroup SHA256
* @brief SHA256 dual-lane compression for full blocks.
*
* This function compresses nblocks full SHA256 blocks for two independent states in parallel.
* It does not handle padding or length encoding.
*
* @param state1 [IN/OUT] SHA256 state for lane 0. Array size is #CRYPT_SHA256_STATE_SIZE.
* @param state2 [IN/OUT] SHA256 state for lane 1. Array size is #CRYPT_SHA256_STATE_SIZE.
* @param block1 [IN] Input block pointer for lane 0 (must contain nblocks * 64 bytes).
* @param block2 [IN] Input block pointer for lane 1 (must contain nblocks * 64 bytes).
* @param nblocks [IN] Number of full 64-byte blocks to compress.
*/
void CRYPT_SHA256x2_Compress(uint32_t state1[CRYPT_SHA256_STATE_SIZE], uint32_t state2[CRYPT_SHA256_STATE_SIZE],
const uint8_t *block1, const uint8_t *block2, uint32_t nblocks);
/**
* @ingroup SHA256
* @brief SHA256 multi-buffer one-shot hashing.
*
* Notes:
* - Currently only supports num == 2.
* - nbytes is the same length for all lanes in this one-shot API.
*
* @param data [IN] Input pointer array. data[i] is message pointer for lane i.
* @param nbytes [IN] Input length in bytes.
* @param digest [OUT] Digest buffer pointer array. digest[i] is output buffer for lane i.
* @param outlen [IN/OUT] Output buffer length / output digest length.
* @param num [IN] Number of lanes/messages.
*
* @retval #CRYPT_SUCCESS Success.
* @retval #CRYPT_NULL_INPUT Invalid input pointer.
* @retval #CRYPT_NOT_SUPPORT Not supported (e.g. num != 2 or platform capability missing).
* @retval Other error codes, see crypt_errno.h.
*/
int32_t CRYPT_SHA256_MB(const uint8_t *data[], uint32_t nbytes, uint8_t *digest[], uint32_t *outlen, uint32_t num);
/**
* @ingroup SHA256
* @brief SHA256 dual-lane one-shot hashing with initial states.
*
* This function computes SHA256 digests for two messages in parallel, starting from the provided
* SHA256 states.
*
* Notes:
* - This API is intended for internal acceleration paths.
*
* @param state1 [IN/OUT] SHA256 state for lane 0. Array size is #CRYPT_SHA256_STATE_SIZE.
* @param state2 [IN/OUT] SHA256 state for lane 1. Array size is #CRYPT_SHA256_STATE_SIZE.
* @param data1 [IN] Input message pointer for lane 0.
* @param data2 [IN] Input message pointer for lane 1.
* @param nbytes [IN] Input length in bytes for both lanes.
* @param dgst1 [OUT] Digest output buffer for lane 0 (size #CRYPT_SHA2_256_DIGESTSIZE).
* @param dgst2 [OUT] Digest output buffer for lane 1 (size #CRYPT_SHA2_256_DIGESTSIZE).
*
* @retval #CRYPT_SUCCESS Success.
* @retval #CRYPT_NOT_SUPPORT Not supported on this platform/build.
*/
int32_t CRYPT_SHA256x2(uint32_t state1[CRYPT_SHA256_STATE_SIZE], uint32_t state2[CRYPT_SHA256_STATE_SIZE],
const uint8_t *data1, const uint8_t *data2, uint32_t nbytes,
uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE], uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE]);
#endif // HITLS_CRYPTO_SHA256
#ifdef HITLS_CRYPTO_SHA384
+381
View File
@@ -471,4 +471,385 @@ SHA256CryptoExt:
st1 {v4.4s-v5.4s}, [x0]
ret
.size SHA256CryptoExt, .-SHA256CryptoExt
/*
* Optimized macro for dual SHA-256 rounds - caller-saved registers only
* Uses on-demand K256 loading to comply with AAPCS calling convention
* v8-v15 are callee-saved and must be preserved
*/
.macro ROUNDS4X2_LOAD m0_a, m0_b, k
mov v30.16b, v4.16b
mov v31.16b, v6.16b
add v28.4s, v\k\().4s, v\m0_a\().4s
add v29.4s, v\k\().4s, v\m0_b\().4s
sha256h q4, q5, v28.4s
sha256h q6, q7, v29.4s
sha256h2 q5, q30, v28.4s
sha256h2 q7, q31, v29.4s
.endm
/* Macro for round with message schedule update */
.macro ROUND_SCHED m0, m1, m2, m3, m0b, m1b, m2b, m3b, k
ROUNDS4X2_LOAD \m0, \m0b, \k
sha256su0 v\m0\().4s, v\m1\().4s
sha256su0 v\m0b\().4s, v\m1b\().4s
sha256su1 v\m0\().4s, v\m2\().4s, v\m3\().4s
sha256su1 v\m0b\().4s, v\m2b\().4s, v\m3b\().4s
.endm
.macro REVBE x0, x1
#ifndef HITLS_BIG_ENDIAN
rev \x0, \x1
#else
mov \x0, \x1
#endif
.endm
/*
* Function: CRYPT_SHA256x2 - Dual SHA-256 hash computation
* Prototype: void CRYPT_SHA256x2(uint32_t state1[8], uint32_t state2[8],
* const uint8_t *in1, const uint8_t *in2, uint32_t nbytes,
* uint8_t dgst1[32], uint8_t dgst2[32]);
*
* Parameters:
* x0 - state1: Initial/final hash state for message 1
* x1 - state2: Initial/final hash state for message 2
* x2 - in1: Message 1 data pointer
* x3 - in2: Message 2 data pointer
* w4 - nbytes: Message length (same for both)
* x5 - dgst1: Output digest for message 1 (32 bytes, big-endian)
* x6 - dgst2: Output digest for message 2 (32 bytes, big-endian)
*
* Computes two SHA-256 hashes simultaneously using ARMv8 crypto extensions.
* Handles padding internally per FIPS 180-4.
*/
.balign 16
#ifdef __APPLE__
.global _CRYPT_SHA256x2
_CRYPT_SHA256x2:
#else
.global CRYPT_SHA256x2
.type CRYPT_SHA256x2, %function
CRYPT_SHA256x2:
#endif
AARCH64_PACIASP
/* Stack: 256 bytes
* 0-15: x29/x30, 96-159: buffer1, 160-223: buffer2 */
stp x29, x30, [sp, #-160]!
add x29, sp, #0
stp x19, x20, [sp, #16]
/* Initialize */
lsl x19, x4, #3 // bit count for padding
ld1 {v24.4s-v25.4s}, [x0] // Load initial state1
ld1 {v26.4s-v27.4s}, [x1] // Load initial state2
/* Process complete 64-byte blocks */
lsr w9, w4, #6 // num_blocks = nbytes / 64
cbz w9, .L_partial_2x
.L_fullblk_2x:
/* Load 64 bytes from each message and convert to big-endian */
ld1 {v16.16b-v19.16b}, [x2], #64
ld1 {v20.16b-v23.16b}, [x3], #64
rev32 v16.16b, v16.16b
rev32 v20.16b, v20.16b
rev32 v17.16b, v17.16b
rev32 v21.16b, v21.16b
rev32 v18.16b, v18.16b
rev32 v22.16b, v22.16b
rev32 v19.16b, v19.16b
rev32 v23.16b, v23.16b
/* Execute 64 rounds of compression */
bl sha256_block_x2
subs w9, w9, #1
bne .L_fullblk_2x
.L_partial_2x:
/* Handle partial block and padding (FIPS 180-4):
* Append 0x80, pad with zeros to 56 bytes, append 64-bit length */
and w10, w4, #63 // remaining bytes
cbz w10, .L_padding_aligned_2x
/* Clear buffers and copy remaining bytes */
add x11, sp, #32
movi v28.16b, #0
movi v29.16b, #0
movi v30.16b, #0
movi v31.16b, #0
st1 {v28.16b-v31.16b}, [x11], #64
st1 {v28.16b-v31.16b}, [x11]
add x11, sp, #32
add x12, sp, #96
mov x13, x10
/* Copy 16-byte chunks */
cmp x13, #16
blt .L_copy_bytes_2x
.L_copy_16_2x:
ldr q28, [x2], #16
ldr q29, [x3], #16
str q28, [x11], #16
str q29, [x12], #16
sub x13, x13, #16
cmp x13, #16
bge .L_copy_16_2x
/* Copy remaining bytes */
.L_copy_bytes_2x:
cbz x13, .L_add_padding_2x
ldrb w14, [x2], #1
ldrb w15, [x3], #1
strb w14, [x11], #1
strb w15, [x12], #1
subs x13, x13, #1
bne .L_copy_bytes_2x
.L_add_padding_2x:
/* Add 0x80 padding byte */
mov w13, #0x80
add x14, sp, #32
add x15, sp, #96
strb w13, [x14, x10]
strb w13, [x15, x10]
/* Check if need one or two blocks */
cmp w10, #56
bge .L_need_extra_block_2x
/* Case 1: Padding fits in one block */
REVBE x8, x19
add x14, sp, #32
add x15, sp, #96
str x8, [x14, #56]
str x8, [x15, #56]
ld1 {v16.16b-v19.16b}, [x14]
ld1 {v20.16b-v23.16b}, [x15]
rev32 v16.16b, v16.16b
rev32 v20.16b, v20.16b
rev32 v17.16b, v17.16b
rev32 v21.16b, v21.16b
rev32 v18.16b, v18.16b
rev32 v22.16b, v22.16b
rev32 v19.16b, v19.16b
rev32 v23.16b, v23.16b
b .L_process_final_2x
.L_need_extra_block_2x:
/* Case 2: Need two blocks (remaining >= 56) */
add x14, sp, #32
add x15, sp, #96
ld1 {v16.16b-v19.16b}, [x14]
ld1 {v20.16b-v23.16b}, [x15]
rev32 v16.16b, v16.16b
rev32 v20.16b, v20.16b
rev32 v17.16b, v17.16b
rev32 v21.16b, v21.16b
rev32 v18.16b, v18.16b
rev32 v22.16b, v22.16b
rev32 v19.16b, v19.16b
rev32 v23.16b, v23.16b
bl sha256_block_x2
/* Prepare second block: zeros + length */
/* For direct vector register manipulation, always use rev (not REVBE)
* because mov v.d[n], x is a pure bit copy, independent of system endianness */
rev x8, x19
movi v16.2d, #0
movi v17.2d, #0
movi v18.2d, #0
mov v19.d[0], xzr
mov v19.d[1], x8
mov v20.16b, v16.16b
mov v21.16b, v17.16b
mov v22.16b, v18.16b
mov v23.16b, v19.16b
rev32 v16.16b, v16.16b
rev32 v17.16b, v17.16b
rev32 v18.16b, v18.16b
rev32 v19.16b, v19.16b
rev32 v20.16b, v20.16b
rev32 v21.16b, v21.16b
rev32 v22.16b, v22.16b
rev32 v23.16b, v23.16b
b .L_process_final_2x
.L_padding_aligned_2x:
/* Case 3: Block-aligned message */
add x14, sp, #32
add x15, sp, #96
movi v28.16b, #0
movi v29.16b, #0
movi v30.16b, #0
movi v31.16b, #0
st1 {v28.16b-v31.16b}, [x14]
st1 {v28.16b-v31.16b}, [x15]
mov w13, #0x80
add x14, sp, #32
add x15, sp, #96
strb w13, [x14]
strb w13, [x15]
REVBE x8, x19
str x8, [x14, #56]
str x8, [x15, #56]
ld1 {v16.16b-v19.16b}, [x14]
ld1 {v20.16b-v23.16b}, [x15]
rev32 v16.16b, v16.16b
rev32 v20.16b, v20.16b
rev32 v17.16b, v17.16b
rev32 v21.16b, v21.16b
rev32 v18.16b, v18.16b
rev32 v22.16b, v22.16b
rev32 v19.16b, v19.16b
rev32 v23.16b, v23.16b
.L_process_final_2x:
bl sha256_block_x2
.L_finalize_2x:
/* Output results: state arrays (little-endian) and digests (big-endian) */
st1 {v24.4s-v25.4s}, [x0]
st1 {v26.4s-v27.4s}, [x1]
#ifndef HITLS_BIG_ENDIAN
rev32 v24.16b, v24.16b
rev32 v25.16b, v25.16b
rev32 v26.16b, v26.16b
rev32 v27.16b, v27.16b
#endif
st1 {v24.4s-v25.4s}, [x5]
st1 {v26.4s-v27.4s}, [x6]
ldp x19, x20, [sp, #16]
ldp x29, x30, [sp], #160
AARCH64_AUTIASP
ret
#ifndef __APPLE__
.size CRYPT_SHA256x2, .-CRYPT_SHA256x2
#endif
/* Local subroutine: 64-round SHA-256 compression for dual messages
* Input: v16-v19, v20-v23 (msg schedules), v24-v27 (states)
* Modifies: v0-v7, v16-v23, v28-v31, x16 */
sha256_block_x2:
mov v4.16b, v24.16b
mov v5.16b, v25.16b
mov v6.16b, v26.16b
mov v7.16b, v27.16b
#ifdef __APPLE__
adrp x16, .K256@page
add x16, x16, .K256@pageoff
#else
adrp x16, .K256
add x16, x16, :lo12:.K256
#endif
/* Rounds 0-47 */
ld1 {v0.4s-v3.4s}, [x16], #64
ROUND_SCHED 16, 17, 18, 19, 20, 21, 22, 23, 0
ROUND_SCHED 17, 18, 19, 16, 21, 22, 23, 20, 1
ROUND_SCHED 18, 19, 16, 17, 22, 23, 20, 21, 2
ROUND_SCHED 19, 16, 17, 18, 23, 20, 21, 22, 3
ld1 {v0.4s-v3.4s}, [x16], #64
ROUND_SCHED 16, 17, 18, 19, 20, 21, 22, 23, 0
ROUND_SCHED 17, 18, 19, 16, 21, 22, 23, 20, 1
ROUND_SCHED 18, 19, 16, 17, 22, 23, 20, 21, 2
ROUND_SCHED 19, 16, 17, 18, 23, 20, 21, 22, 3
ld1 {v0.4s-v3.4s}, [x16], #64
ROUND_SCHED 16, 17, 18, 19, 20, 21, 22, 23, 0
ROUND_SCHED 17, 18, 19, 16, 21, 22, 23, 20, 1
ROUND_SCHED 18, 19, 16, 17, 22, 23, 20, 21, 2
ROUND_SCHED 19, 16, 17, 18, 23, 20, 21, 22, 3
/* Rounds 48-63 */
ld1 {v0.4s-v3.4s}, [x16], #64
ROUNDS4X2_LOAD 16, 20, 0
ROUNDS4X2_LOAD 17, 21, 1
ROUNDS4X2_LOAD 18, 22, 2
ROUNDS4X2_LOAD 19, 23, 3
/* Add to state */
add v24.4s, v24.4s, v4.4s
add v25.4s, v25.4s, v5.4s
add v26.4s, v26.4s, v6.4s
add v27.4s, v27.4s, v7.4s
ret
/*
* void CRYPT_SHA256x2_Compress(uint32_t state1[CRYPT_SHA256_STATE_SIZE], uint32_t state2[CRYPT_SHA256_STATE_SIZE],
* const uint8_t *block1, const uint8_t *block2, uint32_t nblocks);
*
* Function: Compress multiple blocks for dual SHA-256 computation
* Parameters:
* x0 - state1: Initial/final hash state for message 1
* x1 - state2: Initial/final hash state for message 2
* x2 - block1: Message 1 data pointer
* x3 - block2: Message 2 data pointer
* w4 - nblocks: Number of 64-byte blocks to process
*
* Updates two SHA-256 states by compressing nblocks pairs of 64-byte blocks.
*/
.balign 16
#ifdef __APPLE__
.global _CRYPT_SHA256x2_Compress
_CRYPT_SHA256x2_Compress:
#else
.global CRYPT_SHA256x2_Compress
.type CRYPT_SHA256x2_Compress, %function
CRYPT_SHA256x2_Compress:
#endif
AARCH64_PACIASP
stp x29, x30, [sp, #-16]!
add x29, sp, #0
/* Check if nblocks is zero */
cbz w4, .Lcompress_end_x2
/* Load initial states */
ld1 {v24.4s-v25.4s}, [x0] // Load state1 (8 uint32_t = 2 vectors)
ld1 {v26.4s-v27.4s}, [x1] // Load state2 (8 uint32_t = 2 vectors)
/* Loop through nblocks */
.Lcompress_loop_x2:
/* Load 64 bytes from each block */
ld1 {v16.16b-v19.16b}, [x2], #64 // Load block1 (64 bytes = 4 vectors)
ld1 {v20.16b-v23.16b}, [x3], #64 // Load block2 (64 bytes = 4 vectors)
/* Convert to big-endian (SHA-256 requires big-endian input) */
rev32 v16.16b, v16.16b
rev32 v17.16b, v17.16b
rev32 v18.16b, v18.16b
rev32 v19.16b, v19.16b
rev32 v20.16b, v20.16b
rev32 v21.16b, v21.16b
rev32 v22.16b, v22.16b
rev32 v23.16b, v23.16b
/* Execute 64 rounds of compression */
bl sha256_block_x2
/* Decrement block counter and loop if more blocks remain */
subs w4, w4, #1
bne .Lcompress_loop_x2
/* Store final states */
st1 {v24.4s-v25.4s}, [x0] // Store state1
st1 {v26.4s-v27.4s}, [x1] // Store state2
.Lcompress_end_x2:
ldp x29, x30, [sp], #16
AARCH64_AUTIASP
ret
#ifndef __APPLE__
.size CRYPT_SHA256x2_Compress, .-CRYPT_SHA256x2_Compress
#endif
#endif
+230 -20
View File
@@ -25,6 +25,10 @@
#include "bsl_sal.h"
#include "crypt_types.h"
#define SHA256_INIT_ARRAY {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}
static const uint32_t SHA256_INIT_STATE[8] = SHA256_INIT_ARRAY;
struct CryptSha256Ctx {
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 */
@@ -68,14 +72,7 @@ int32_t CRYPT_SHA2_256_Init(CRYPT_SHA2_256_Ctx *ctx, BSL_Param *param)
* H(0)6 = 1f83d9ab
* H(0)7 = 5be0cd19
*/
ctx->h[0] = 0x6a09e667UL;
ctx->h[1] = 0xbb67ae85UL;
ctx->h[2] = 0x3c6ef372UL;
ctx->h[3] = 0xa54ff53aUL;
ctx->h[4] = 0x510e527fUL;
ctx->h[5] = 0x9b05688cUL;
ctx->h[6] = 0x1f83d9abUL;
ctx->h[7] = 0x5be0cd19UL;
(void)memcpy_s(ctx->h, sizeof(SHA256_INIT_STATE), SHA256_INIT_STATE, sizeof(SHA256_INIT_STATE));
ctx->outlen = CRYPT_SHA2_256_DIGESTSIZE;
return CRYPT_SUCCESS;
}
@@ -173,18 +170,12 @@ int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint
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;
}
(void)memcpy_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, d, left);
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;
}
(void)memcpy_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, d, CRYPT_SHA2_256_BLOCKSIZE - n);
SHA256CompressMultiBlocks(ctx->h, p, 1);
n = CRYPT_SHA2_256_BLOCKSIZE - n;
d += n;
@@ -203,10 +194,7 @@ int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint
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;
}
(void)memcpy_s((uint8_t *)ctx->block, CRYPT_SHA2_256_BLOCKSIZE, d, left);
}
return CRYPT_SUCCESS;
@@ -269,6 +257,228 @@ int32_t CRYPT_SHA2_256_Final(CRYPT_SHA2_256_Ctx *ctx, uint8_t *digest, uint32_t
return CRYPT_SUCCESS;
}
#ifdef HITLS_CRYPTO_SHA2_MB
CRYPT_SHA2_256_MB_Ctx *CRYPT_SHA256_MBNewCtx(uint32_t num)
{
if (num != 2) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
return NULL;
}
CRYPT_SHA2_256_MB_Ctx *mbCtx = BSL_SAL_Calloc(1, sizeof(CRYPT_SHA2_256_MB_Ctx));
if (mbCtx == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
return NULL;
}
mbCtx->ctxs = BSL_SAL_Calloc(num, sizeof(CRYPT_SHA2_256_Ctx));
if (mbCtx->ctxs == NULL) {
BSL_SAL_Free(mbCtx);
BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
return NULL;
}
mbCtx->num = num;
return mbCtx;
}
void CRYPT_SHA256_MBFreeCtx(CRYPT_SHA2_256_MB_Ctx *ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->ctxs != NULL) {
for (uint32_t i = 0; i < ctx->num; i++) {
(void)CRYPT_SHA2_256_Deinit(&ctx->ctxs[i]);
}
BSL_SAL_Free(ctx->ctxs);
}
BSL_SAL_Free(ctx);
}
int32_t CRYPT_SHA256_MBInit(CRYPT_SHA2_256_MB_Ctx *ctx)
{
#if defined(__aarch64__)
// currently only support sha256x2 in aarch64
if (UNLIKELY(ctx == NULL)) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (UNLIKELY(ctx->num != 2)) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
(void)CRYPT_SHA2_256_Init(&ctx->ctxs[0], NULL);
(void)CRYPT_SHA2_256_Init(&ctx->ctxs[1], NULL);
return CRYPT_SUCCESS;
#else
(void)ctx;
return CRYPT_NOT_SUPPORT;
#endif
}
int32_t CRYPT_SHA256_MBUpdate(CRYPT_SHA2_256_MB_Ctx *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num)
{
#if defined(__aarch64__) && defined(HITLS_CRYPTO_SHA2_ASM)
// currently only support sha256x2 in aarch64
if (UNLIKELY(ctx == NULL || data == NULL || nbytes == NULL)) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (UNLIKELY(num != 2 || ctx->num != num || nbytes[0] != nbytes[1])) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
uint32_t commonBytes = nbytes[0];
if (commonBytes == 0) {
return CRYPT_SUCCESS;
}
CRYPT_SHA2_256_Ctx *ctx0 = &ctx->ctxs[0];
CRYPT_SHA2_256_Ctx *ctx1 = &ctx->ctxs[1];
int32_t ret = UpdateParamIsValid(ctx0, data[0], commonBytes);
if (ret != CRYPT_SUCCESS) {
return ret;
}
ret = UpdateParamIsValid(ctx1, data[1], commonBytes);
if (ret != CRYPT_SUCCESS) {
return ret;
}
uint8_t *b0 = (uint8_t *)(uintptr_t)ctx0->block;
uint8_t *b1 = (uint8_t *)(uintptr_t)ctx1->block;
const uint8_t *d0 = data[0];
const uint8_t *d1 = data[1];
uint32_t caches = ctx0->blocklen;
if (caches + commonBytes >= CRYPT_SHA2_256_BLOCKSIZE) {
if (caches != 0) {
uint32_t cpysize = CRYPT_SHA2_256_BLOCKSIZE - caches;
(void)memcpy_s(b0 + caches, cpysize, d0, cpysize);
d0 += cpysize;
(void)memcpy_s(b1 + caches, cpysize, d1, cpysize);
d1 += cpysize;
commonBytes -= cpysize;
CRYPT_SHA256x2_Compress(ctx0->h, ctx1->h, b0, b1, 1);
ctx0->blocklen = 0;
ctx1->blocklen = 0;
}
uint32_t nblocks = commonBytes / CRYPT_SHA2_256_BLOCKSIZE;
commonBytes &= (CRYPT_SHA2_256_BLOCKSIZE - 1);
if (nblocks > 0) {
CRYPT_SHA256x2_Compress(ctx0->h, ctx1->h, d0, d1, nblocks);
d0 += nblocks * CRYPT_SHA2_256_BLOCKSIZE;
d1 += nblocks * CRYPT_SHA2_256_BLOCKSIZE;
}
caches = 0;
}
if (commonBytes != 0) {
(void)memcpy_s(b0 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, d0, commonBytes);
(void)memcpy_s(b1 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, d1, commonBytes);
ctx0->blocklen += commonBytes;
ctx1->blocklen += commonBytes;
}
return CRYPT_SUCCESS;
#else
(void)ctx;
(void)data;
(void)nbytes;
(void)num;
return CRYPT_NOT_SUPPORT;
#endif
}
int32_t CRYPT_SHA256_MBFinal(CRYPT_SHA2_256_MB_Ctx *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num)
{
#if defined(__aarch64__) && defined(HITLS_CRYPTO_SHA2_ASM)
// currently only support sha256x2 in aarch64
if (UNLIKELY(ctx == NULL || digest == NULL || outlen == NULL)) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (UNLIKELY(num != 2 || ctx->num != num)) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
if (UNLIKELY(digest[0] == NULL || digest[1] == NULL)) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
CRYPT_SHA2_256_Ctx *ctx0 = &ctx->ctxs[0];
CRYPT_SHA2_256_Ctx *ctx1 = &ctx->ctxs[1];
int32_t ret = FinalParamIsValid(ctx0, digest[0], outlen);
if (ret != CRYPT_SUCCESS) {
return ret;
}
ret = FinalParamIsValid(ctx1, digest[1], outlen);
if (ret != CRYPT_SUCCESS) {
return ret;
}
uint8_t *b0 = (uint8_t *)(uintptr_t)ctx0->block;
uint8_t *b1 = (uint8_t *)(uintptr_t)ctx1->block;
uint32_t caches = ctx0->blocklen;
b0[caches] = 0x80;
b1[caches++] = 0x80;
if (caches > (CRYPT_SHA2_256_BLOCKSIZE - 8)) {
(void)memset_s(b0 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, 0, CRYPT_SHA2_256_BLOCKSIZE - caches);
(void)memset_s(b1 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, 0, CRYPT_SHA2_256_BLOCKSIZE - caches);
caches = 0;
CRYPT_SHA256x2_Compress(ctx0->h, ctx1->h, b0, b1, 1);
}
(void)memset_s(b0 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, 0,
CRYPT_SHA2_256_BLOCKSIZE - 8 - caches); /* 8 bytes to save bits of input */
(void)memset_s(b1 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, 0,
CRYPT_SHA2_256_BLOCKSIZE - 8 - caches); /* 8 bytes to save bits of input */
PUT_UINT32_BE(ctx0->hNum, b0, CRYPT_SHA2_256_BLOCKSIZE - 8);
PUT_UINT32_BE(ctx0->lNum, b0, CRYPT_SHA2_256_BLOCKSIZE - 4);
PUT_UINT32_BE(ctx1->hNum, b1, CRYPT_SHA2_256_BLOCKSIZE - 8);
PUT_UINT32_BE(ctx1->lNum, b1, CRYPT_SHA2_256_BLOCKSIZE - 4);
CRYPT_SHA256x2_Compress(ctx0->h, ctx1->h, b0, b1, 1);
ctx0->blocklen = 0;
ctx1->blocklen = 0;
for (uint32_t i = 0; i < ctx0->outlen / sizeof(uint32_t); i++) {
PUT_UINT32_BE(ctx0->h[i], digest[0], sizeof(uint32_t) * i);
PUT_UINT32_BE(ctx1->h[i], digest[1], sizeof(uint32_t) * i);
}
*outlen = ctx0->outlen;
return CRYPT_SUCCESS;
#else
(void)ctx;
(void)digest;
(void)outlen;
(void)num;
return CRYPT_NOT_SUPPORT;
#endif
}
int32_t CRYPT_SHA256_MB(const uint8_t *data[], uint32_t nbytes, uint8_t *digest[], uint32_t *outlen, uint32_t num)
{
#if defined(__aarch64__) && defined(HITLS_CRYPTO_SHA2_ASM)
// currently only support sha256x2 in aarch64
if (num != 2) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
uint32_t state1[CRYPT_SHA256_STATE_SIZE] = SHA256_INIT_ARRAY;
uint32_t state2[CRYPT_SHA256_STATE_SIZE] = SHA256_INIT_ARRAY;
(void)CRYPT_SHA256x2(state1, state2, data[0], data[1], nbytes, digest[0], digest[1]);
*outlen = CRYPT_SHA2_256_DIGESTSIZE;
return CRYPT_SUCCESS;
#else
(void)data;
(void)nbytes;
(void)digest;
(void)outlen;
(void)num;
return CRYPT_NOT_SUPPORT;
#endif
}
#endif // HITLS_CRYPTO_SHA2_MB
#ifdef HITLS_CRYPTO_SHA224
+69 -71
View File
@@ -32,15 +32,6 @@ static void Round(const uint64_t *a, uint64_t *e, uint32_t i);
#define ROL64(a, offset) ((((uint64_t)(a)) << (offset)) ^ (((uint64_t)(a)) >> (64 - (offset))))
// the rotation offsets, see https://keccak.team/keccak_specs_summary.html
static const uint8_t g_rotationOffset[5][5] = {
{ 0, 1, 62, 28, 27 },
{ 36, 44, 6, 55, 20 },
{ 3, 10, 43, 25, 39 },
{ 41, 45, 15, 21, 8 },
{ 18, 2, 61, 56, 14 }
};
// the round constants, see https://keccak.team/keccak_specs_summary.html
static const uint64_t g_roundConstant[24] = {
(uint64_t)0x0000000000000001, (uint64_t)0x0000000000008082,
@@ -120,95 +111,102 @@ static void SHA3_Keccak(uint8_t *state)
// see section 2.4 Algorithm 1 in https://keccak.team/files/Keccak-implementation-3.2.pdf
static void Round(const uint64_t *a, uint64_t *e, uint32_t i)
{
uint64_t c[5], d[5];
// Use separate variables instead of arrays for better register allocation on x86
uint64_t c0, c1, c2, c3, c4;
uint64_t d0, d1, d2, d3, d4;
// The corresponding formula for calculating the indexes of array A and array E is (5 * x) + y,
// the value of x is in [0, 4] and the value of y is [0, 4].
// The row coordinates of the array index correspond to y in the algorithm principle,
// and the column coordinates correspond to x in the algorithm principle, for example, A[1, 1] = A[5 * 1 + 1] = A[6]
// THETA operation
c[0] = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20];
c[1] = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21];
c[2] = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22];
c[3] = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23];
c[4] = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24];
c0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20];
c1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21];
c2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22];
c3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23];
c4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24];
d[0] = ROL64(c[1], 1) ^ c[4];
d[1] = ROL64(c[2], 1) ^ c[0];
d[2] = ROL64(c[3], 1) ^ c[1];
d[3] = ROL64(c[4], 1) ^ c[2];
d[4] = ROL64(c[0], 1) ^ c[3];
d0 = ROL64(c1, 1) ^ c4;
d1 = ROL64(c2, 1) ^ c0;
d2 = ROL64(c3, 1) ^ c1;
d3 = ROL64(c4, 1) ^ c2;
d4 = ROL64(c0, 1) ^ c3;
// THETA RHP Pi operation
c[0] = a[0] ^ d[0];
c[1] = ROL64(a[6] ^ d[1], g_rotationOffset[1][1]);
c[2] = ROL64(a[12] ^ d[2], g_rotationOffset[2][2]);
c[3] = ROL64(a[18] ^ d[3], g_rotationOffset[3][3]);
c[4] = ROL64(a[24] ^ d[4], g_rotationOffset[4][4]);
// THETA RHP Pi operation - rotation offsets inlined as constants
// g_rotationOffset[0][0]=0, [1][1]=44, [2][2]=43, [3][3]=21, [4][4]=14
c0 = a[0] ^ d0;
c1 = ROL64(a[6] ^ d1, 44);
c2 = ROL64(a[12] ^ d2, 43);
c3 = ROL64(a[18] ^ d3, 21);
c4 = ROL64(a[24] ^ d4, 14);
// CHI IOTA operation,
e[0] = c[0] ^ (~c[1] & c[2]) ^ g_roundConstant[i];
e[0] = c0 ^ (~c1 & c2) ^ g_roundConstant[i];
// CHI operation
e[1] = c[1] ^ (~c[2] & c[3]);
e[2] = c[2] ^ (~c[3] & c[4]);
e[3] = c[3] ^ (~c[4] & c[0]);
e[4] = c[4] ^ (~c[0] & c[1]);
e[1] = c1 ^ (~c2 & c3);
e[2] = c2 ^ (~c3 & c4);
e[3] = c3 ^ (~c4 & c0);
e[4] = c4 ^ (~c0 & c1);
// THETA RHP Pi operation
c[0] = ROL64(a[3] ^ d[3], g_rotationOffset[0][3]);
c[1] = ROL64(a[9] ^ d[4], g_rotationOffset[1][4]);
c[2] = ROL64(a[10] ^ d[0], g_rotationOffset[2][0]);
c[3] = ROL64(a[16] ^ d[1], g_rotationOffset[3][1]);
c[4] = ROL64(a[22] ^ d[2], g_rotationOffset[4][2]);
// g_rotationOffset[0][3]=28, [1][4]=20, [2][0]=3, [3][1]=45, [4][2]=61
c0 = ROL64(a[3] ^ d3, 28);
c1 = ROL64(a[9] ^ d4, 20);
c2 = ROL64(a[10] ^ d0, 3);
c3 = ROL64(a[16] ^ d1, 45);
c4 = ROL64(a[22] ^ d2, 61);
// CHI operation
e[5] = c[0] ^ (~c[1] & c[2]);
e[6] = c[1] ^ (~c[2] & c[3]);
e[7] = c[2] ^ (~c[3] & c[4]);
e[8] = c[3] ^ (~c[4] & c[0]);
e[9] = c[4] ^ (~c[0] & c[1]);
e[5] = c0 ^ (~c1 & c2);
e[6] = c1 ^ (~c2 & c3);
e[7] = c2 ^ (~c3 & c4);
e[8] = c3 ^ (~c4 & c0);
e[9] = c4 ^ (~c0 & c1);
// THETA RHP Pi operation
c[0] = ROL64(a[1] ^ d[1], g_rotationOffset[0][1]);
c[1] = ROL64(a[7] ^ d[2], g_rotationOffset[1][2]);
c[2] = ROL64(a[13] ^ d[3], g_rotationOffset[2][3]);
c[3] = ROL64(a[19] ^ d[4], g_rotationOffset[3][4]);
c[4] = ROL64(a[20] ^ d[0], g_rotationOffset[4][0]);
// g_rotationOffset[0][1]=1, [1][2]=6, [2][3]=25, [3][4]=8, [4][0]=18
c0 = ROL64(a[1] ^ d1, 1);
c1 = ROL64(a[7] ^ d2, 6);
c2 = ROL64(a[13] ^ d3, 25);
c3 = ROL64(a[19] ^ d4, 8);
c4 = ROL64(a[20] ^ d0, 18);
// CHI operation
e[10] = c[0] ^ (~c[1] & c[2]);
e[11] = c[1] ^ (~c[2] & c[3]);
e[12] = c[2] ^ (~c[3] & c[4]);
e[13] = c[3] ^ (~c[4] & c[0]);
e[14] = c[4] ^ (~c[0] & c[1]);
e[10] = c0 ^ (~c1 & c2);
e[11] = c1 ^ (~c2 & c3);
e[12] = c2 ^ (~c3 & c4);
e[13] = c3 ^ (~c4 & c0);
e[14] = c4 ^ (~c0 & c1);
// THETA RHP Pi operation
c[0] = ROL64(a[4] ^ d[4], g_rotationOffset[0][4]);
c[1] = ROL64(a[5] ^ d[0], g_rotationOffset[1][0]);
c[2] = ROL64(a[11] ^ d[1], g_rotationOffset[2][1]);
c[3] = ROL64(a[17] ^ d[2], g_rotationOffset[3][2]);
c[4] = ROL64(a[23] ^ d[3], g_rotationOffset[4][3]);
// g_rotationOffset[0][4]=27, [1][0]=36, [2][1]=10, [3][2]=15, [4][3]=56
c0 = ROL64(a[4] ^ d4, 27);
c1 = ROL64(a[5] ^ d0, 36);
c2 = ROL64(a[11] ^ d1, 10);
c3 = ROL64(a[17] ^ d2, 15);
c4 = ROL64(a[23] ^ d3, 56);
// CHI operation
e[15] = c[0] ^ (~c[1] & c[2]);
e[16] = c[1] ^ (~c[2] & c[3]);
e[17] = c[2] ^ (~c[3] & c[4]);
e[18] = c[3] ^ (~c[4] & c[0]);
e[19] = c[4] ^ (~c[0] & c[1]);
e[15] = c0 ^ (~c1 & c2);
e[16] = c1 ^ (~c2 & c3);
e[17] = c2 ^ (~c3 & c4);
e[18] = c3 ^ (~c4 & c0);
e[19] = c4 ^ (~c0 & c1);
// THETA RHP Pi operation
c[0] = ROL64(a[2] ^ d[2], g_rotationOffset[0][2]);
c[1] = ROL64(a[8] ^ d[3], g_rotationOffset[1][3]);
c[2] = ROL64(a[14] ^ d[4], g_rotationOffset[2][4]);
c[3] = ROL64(a[15] ^ d[0], g_rotationOffset[3][0]);
c[4] = ROL64(a[21] ^ d[1], g_rotationOffset[4][1]);
// g_rotationOffset[0][2]=62, [1][3]=55, [2][4]=39, [3][0]=41, [4][1]=2
c0 = ROL64(a[2] ^ d2, 62);
c1 = ROL64(a[8] ^ d3, 55);
c2 = ROL64(a[14] ^ d4, 39);
c3 = ROL64(a[15] ^ d0, 41);
c4 = ROL64(a[21] ^ d1, 2);
// CHI operation
e[20] = c[0] ^ (~c[1] & c[2]);
e[21] = c[1] ^ (~c[2] & c[3]);
e[22] = c[2] ^ (~c[3] & c[4]);
e[23] = c[3] ^ (~c[4] & c[0]);
e[24] = c[4] ^ (~c[0] & c[1]);
e[20] = c0 ^ (~c1 & c2);
e[21] = c1 ^ (~c2 & c3);
e[22] = c2 ^ (~c3 & c4);
e[23] = c3 ^ (~c4 & c0);
e[24] = c4 ^ (~c0 & c1);
}
#ifdef __cplusplus
+2
View File
@@ -418,6 +418,8 @@ typedef enum {
BSL_CID_DECODE_UNKNOWN = 1000,
BSL_CID_NULL = 1001,
BSL_CID_SHA256_MB = 1500, /* identifies the SHA256 algorithm (multi-buffer variant) */
BSL_CID_HMAC_SHA3_224 = 2000, /* identifies hmac with SHA3_224 */
BSL_CID_HMAC_SHA3_256 = 2001, /* identifies hmac with SHA3_256 */
BSL_CID_HMAC_SHA3_384 = 2002, /* identifies hmac with SHA3_384 */
+1
View File
@@ -79,6 +79,7 @@ typedef enum {
CRYPT_MD_SHAKE128 = BSL_CID_SHAKE128,
CRYPT_MD_SHAKE256 = BSL_CID_SHAKE256,
CRYPT_MD_SM3 = BSL_CID_SM3,
CRYPT_MD_SHA256_MB = BSL_CID_SHA256_MB, /* identifies the SHA256 hash algorithm (multi-buffer variant) */
CRYPT_MD_MAX = BSL_CID_UNKNOWN
} CRYPT_MD_AlgId;
+79
View File
@@ -203,6 +203,85 @@ int32_t CRYPT_EAL_Md(CRYPT_MD_AlgId id, const uint8_t *in, uint32_t inLen, uint8
*/
int32_t CRYPT_EAL_MdDeinit(CRYPT_EAL_MdCTX *ctx);
/**
* @ingroup crypt_eal_md
* @brief Create a MD context for multi-buffer hash computation.
*
* This interface creates a MB context used by the multi-buffer workflow
* (Init/Update/Final) to hash multiple messages in parallel.
*
* Notes:
* - The returned ctx must be released by calling CRYPT_EAL_MdMBFreeCtx.
* - The multi-buffer capability is algorithm/feature dependent; unsupported cases
* will return #CRYPT_NOT_SUPPORT in subsequent MB operations.
*
* @param libCtx [IN] Library context (reserved, currently unused).
* @param id [IN] MD algorithm ID (e.g. #CRYPT_MD_SHA256).
* @param num [IN] Number of contexts/messages.
* @retval CRYPT_EAL_MdCTX pointer on success.
* NULL if memory allocation fails or input is invalid.
*/
CRYPT_EAL_MdCTX *CRYPT_EAL_MdMBNewCtx(CRYPT_EAL_LibCtx *libCtx, int32_t id, uint32_t num);
/**
* @ingroup crypt_eal_md
* @brief Release MB context created by CRYPT_EAL_MdMBNewCtx.
*
* @param ctx [IN] MB context pointer.
*/
void CRYPT_EAL_MdMBFreeCtx(CRYPT_EAL_MdCTX *ctx);
/**
* @ingroup crypt_eal_md
* @brief Initialize multi-buffer MD context.
*
* @param ctx [IN/OUT] MB context created by CRYPT_EAL_MdMBNewCtx.
* @retval #CRYPT_SUCCESS on success.
* #CRYPT_NULL_INPUT if input is invalid.
* #CRYPT_NOT_SUPPORT if the algorithm does not support multi-buffer mode.
* For other error codes, see crypt_errno.h.
*/
int32_t CRYPT_EAL_MdMBInit(CRYPT_EAL_MdCTX *ctx);
/**
* @ingroup crypt_eal_md
* @brief Update multi-buffer MD context with message fragments.
*
* Each update processes one fragment per message.
* The fragment length is specified by nbytes[i] for message i. All nbytes[i] must be equal,
* otherwise this interface returns #CRYPT_NOT_SUPPORT.
*
* @param ctx [IN/OUT] MB context.
* @param data [IN] Data pointer array. data[i] is the fragment for message i.
* @param nbytes [IN] Fragment length array in bytes. nbytes[i] is the fragment length for message i.
* @param num [IN] Number of contexts/messages.
* @retval #CRYPT_SUCCESS on success.
* #CRYPT_NULL_INPUT if input is invalid.
* #CRYPT_NOT_SUPPORT if the algorithm does not support multi-buffer mode or the nbytes are not equal.
* For other error codes, see crypt_errno.h.
*/
int32_t CRYPT_EAL_MdMBUpdate(CRYPT_EAL_MdCTX *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num);
/**
* @ingroup crypt_eal_md
* @brief Finalize multi-buffer MD context and output digests.
*
* digest[i] is the output buffer for message i. The outlen parameter indicates the
* buffer size on input and returns the actual digest length on output.
*
* @param ctx [IN/OUT] MB context.
* @param digest [OUT] Digest buffer pointer array.
* @param outlen [IN/OUT] Digest buffer length / output digest length.
* @param num [IN] Number of contexts/messages.
* @retval #CRYPT_SUCCESS on success.
* #CRYPT_NULL_INPUT if input is invalid.
* #CRYPT_NOT_SUPPORT if the algorithm does not support multi-buffer mode.
* For other error codes, see crypt_errno.h.
*/
int32_t CRYPT_EAL_MdMBFinal(CRYPT_EAL_MdCTX *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num);
#ifdef __cplusplus
}
#endif // __cplusplus
+1 -1
View File
@@ -15,7 +15,7 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
PROJECT(openHiTLS_BENCHMARK)
set(OPENHITLS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
set(BENCHS sm2_bench.c)
file(GLOB BENCHS "*_bench.c")
add_compile_options(-g)
add_executable(openhitls_benchmark benchmark.c ${BENCHS})
@@ -74,6 +74,71 @@ CRYPT_EAL_PkeyCtx *TestPkeyNewCtx(
CRYPT_EAL_LibCtx *libCtx, int32_t id, uint32_t operType, const char *attrName, int isProvider);
#endif
#ifdef __aarch64__
#define AARCH64_PUT_CANARY() \
double canaryd = 1.1; \
register double d8 asm("d8"); \
register double d9 asm("d9"); \
register double d10 asm("d10"); \
register double d11 asm("d11"); \
register double d12 asm("d12"); \
register double d13 asm("d13"); \
register double d14 asm("d14"); \
register double d15 asm("d15"); \
asm volatile("fmov %d0, %d1 \n\t" : "=w"(d8) : "w"(canaryd) :); \
asm volatile("fmov %d0, %d1 \n\t" : "=w"(d9) : "w"(canaryd) :); \
asm volatile("fmov %d0, %d1 \n\t" : "=w"(d10) : "w"(canaryd) :); \
asm volatile("fmov %d0, %d1 \n\t" : "=w"(d11) : "w"(canaryd) :); \
asm volatile("fmov %d0, %d1 \n\t" : "=w"(d12) : "w"(canaryd) :); \
asm volatile("fmov %d0, %d1 \n\t" : "=w"(d13) : "w"(canaryd) :); \
asm volatile("fmov %d0, %d1 \n\t" : "=w"(d14) : "w"(canaryd) :); \
asm volatile("fmov %d0, %d1 \n\t" : "=w"(d15) : "w"(canaryd) :); \
long canaryx = 0x12345678; \
register int x19 asm("x19"); \
register int x20 asm("x20"); \
register int x21 asm("x21"); \
register int x22 asm("x22"); \
register int x23 asm("x23"); \
register int x24 asm("x24"); \
register int x25 asm("x25"); \
register int x26 asm("x26"); \
register int x27 asm("x27"); \
register int x28 asm("x28"); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x19) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x20) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x21) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x22) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x23) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x24) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x25) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x26) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x27) : "r"(canaryx) :); \
asm volatile("mov %x0, %x1 \n\t" : "=r"(x28) : "r"(canaryx) :);
#define AARCH64_CHECK_CANARY() \
ASSERT_TRUE(d8 == canaryd); \
ASSERT_TRUE(d9 == canaryd); \
ASSERT_TRUE(d10 == canaryd); \
ASSERT_TRUE(d11 == canaryd); \
ASSERT_TRUE(d12 == canaryd); \
ASSERT_TRUE(d13 == canaryd); \
ASSERT_TRUE(d14 == canaryd); \
ASSERT_TRUE(d15 == canaryd); \
ASSERT_TRUE(x19 == canaryx); \
ASSERT_TRUE(x20 == canaryx); \
ASSERT_TRUE(x21 == canaryx); \
ASSERT_TRUE(x22 == canaryx); \
ASSERT_TRUE(x23 == canaryx); \
ASSERT_TRUE(x24 == canaryx); \
ASSERT_TRUE(x25 == canaryx); \
ASSERT_TRUE(x26 == canaryx); \
ASSERT_TRUE(x27 == canaryx); \
ASSERT_TRUE(x28 == canaryx);
#else
#define AARCH64_PUT_CANARY()
#define AARCH64_CHECK_CANARY()
#endif
#ifdef __cplusplus
}
#endif
+10
View File
@@ -83,6 +83,16 @@ typedef struct {
} \
} while (0)
#define ASSERT_LT(VALUE1, VALUE2) \
do { \
int64_t value1__ = (int64_t)(VALUE1); \
int64_t value2__ = (int64_t)(VALUE2); \
if (!(value1__ < value2__)) { \
RecordFailure(#VALUE1 #VALUE2, __FILE__); \
Print("\nvalue is %d (0x%x).\nexpect %d (0x%x).\n", value1__, value1__, value2__, value2__); \
goto EXIT; \
} \
} while (0)
#define ASSERT_EQ_LOG(LOG, VALUE1, VALUE2) \
do { \
@@ -261,14 +261,13 @@ void SDV_BSL_TIME_SYSTIME_API_TC001(void)
ret = BSL_SAL_SysTimeGet(&systime);
ASSERT_TRUE(ret == BSL_SUCCESS);
int64_t timestamp = 0;
ret = BSL_SAL_DateToUtcTimeConvert(&systime, &timestamp);
/* Get the current time. */
int64_t curtime = time(NULL);
ASSERT_TRUE(curtime >= timestamp && curtime - 5 <= timestamp);
int64_t timestamp = 0;
ret = BSL_SAL_DateToUtcTimeConvert(&systime, &timestamp);
ASSERT_LT(abs((int)(curtime - timestamp)), 5);
EXIT:
return;
}
@@ -14,12 +14,13 @@
*/
/* BEGIN_HEADER */
#include <pthread.h>
#include "eal_md_local.h"
#include "crypt_eal_md.h"
#include "crypt_errno.h"
#include "bsl_sal.h"
#include "crypt_sha2.h"
#include "crypto_test_util.h"
/* END_HEADER */
// 100 is greater than the digest length of all SHA algorithms.
@@ -489,3 +490,586 @@ EXIT:
CRYPT_EAL_MdFreeCtx(ctx);
}
/* END_CASE */
/**
* @test SDV_CRYPTO_SHA256_MB_API_TC001
* @title CRYPT_SHA256_MB API parameter validation test.
* @precon nan
* @brief
* 1.Call CRYPT_SHA256_MBInit with NULL ctx, expected result 1.
* 2.Call CRYPT_SHA256_MBInit with invalid num (!=2), expected result 2.
* 3.Call CRYPT_SHA256_MBUpdate with NULL parameters, expected result 3.
* 4.Call CRYPT_SHA256_MBFinal with NULL parameters, expected result 4.
* 5.Call CRYPT_SHA256_MB with NULL parameters, expected result 5.
* 6.Call CRYPT_SHA256_MB with valid parameters, expected result 6.
* @expect
* 1-5.Return error codes.
* 6.Return CRYPT_SUCCESS.
*/
/* BEGIN_CASE */
void SDV_CRYPTO_SHA256_MB_API_TC001(void)
{
#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
SKIP_TEST();
#else
TestMemInit();
uint8_t data1[64] = {0};
uint8_t data2[64] = {0};
const uint8_t *dataArr[2] = {data1, data2};
uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t *dgstArr[2] = {dgst1, dgst2};
uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
/* Test invalid num (only support 2) */
ASSERT_TRUE(CRYPT_SHA256_MBNewCtx(1) == NULL);
ASSERT_TRUE(CRYPT_SHA256_MBNewCtx(3) == NULL);
CRYPT_SHA2_256_MB_Ctx *mbCtx = CRYPT_SHA256_MBNewCtx(2);
ASSERT_TRUE(mbCtx != NULL);
/* Test invalid init parameters */
ASSERT_EQ(CRYPT_SHA256_MBInit(NULL), CRYPT_NULL_INPUT);
/* Test valid init */
ASSERT_EQ(CRYPT_SHA256_MBInit(mbCtx), CRYPT_SUCCESS);
/* Test valid update */
uint32_t nbytesArr[2] = {64, 64};
ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, NULL, nbytesArr, 2), CRYPT_NULL_INPUT);
ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr, nbytesArr, 1), CRYPT_NOT_SUPPORT);
ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr, nbytesArr, 2), CRYPT_SUCCESS);
/* Test valid final */
ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, NULL, &outlen, 2), CRYPT_NULL_INPUT);
ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, dgstArr, &outlen, 1), CRYPT_NOT_SUPPORT);
ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
/* Test one-shot API with NULL parameters */
ASSERT_EQ(CRYPT_SHA256_MB(dataArr, 64, NULL, &outlen, 1), CRYPT_NOT_SUPPORT);
/* Test valid one-shot API */
ASSERT_EQ(CRYPT_SHA256_MB(dataArr, 64, dgstArr, &outlen, 2), CRYPT_SUCCESS);
EXIT:
CRYPT_SHA256_MBFreeCtx(mbCtx);
return;
#endif
}
/* END_CASE */
/**
* @test SDV_CRYPTO_SHA256_MB_FUNC_TC001
* @title CRYPT_SHA256_MB one-shot API test with same message.
* @precon nan
* @brief
* 1.Prepare two identical messages and digest buffers, expected result 1.
* 2.Call CRYPT_SHA256_MB to compute both hashes, expected result 2.
* 3.Compare results with expected digest, expected result 3.
* @expect
* 1.Preparation successful.
* 2.Function returns CRYPT_SUCCESS.
* 3.Both digests match expected value.
*/
/* BEGIN_CASE */
void SDV_CRYPTO_SHA256_MB_FUNC_TC001(Hex *msg, Hex *digest)
{
#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
SKIP_TEST();
(void)msg;
(void)digest;
#else
TestMemInit();
const uint8_t *dataArr[2] = {msg->x, msg->x};
uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t *dgstArr[2] = {dgst1, dgst2};
uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_SHA256_MB(dataArr, msg->len, dgstArr, &outlen, 2), CRYPT_SUCCESS);
ASSERT_EQ(outlen, CRYPT_SHA2_256_DIGESTSIZE);
ASSERT_COMPARE("SHA256_MB msg1", dgst1, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
ASSERT_COMPARE("SHA256_MB msg2", dgst2, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
EXIT:
return;
#endif
}
/* END_CASE */
/**
* @test SDV_CRYPTO_SHA256_MB_FUNC_TC002
* @title CRYPT_SHA256_MB Init/Update/Final workflow test.
* @precon nan
* @brief
* 1.Call CRYPT_SHA256_MBInit to initialize contexts, expected result 1.
* 2.Call CRYPT_SHA256_MBUpdate to process equal-length messages, expected result 2.
* 3.Call CRYPT_SHA256_MBFinal to get digests, expected result 3.
* 4.Compare results with expected digests, expected result 4.
* @expect
* 1-3.All functions return CRYPT_SUCCESS.
* 4.Digests match expected values.
*/
/* BEGIN_CASE */
void SDV_CRYPTO_SHA256_MB_FUNC_TC002(Hex *msg, Hex *digest)
{
#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
SKIP_TEST();
(void)msg;
(void)digest;
#else
TestMemInit();
const uint8_t *dataArr[2] = {msg->x, msg->x};
uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t *dgstArr[2] = {dgst1, dgst2};
uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
uint32_t nbytesArr[2] = {msg->len, msg->len};
CRYPT_SHA2_256_MB_Ctx *mbCtx = CRYPT_SHA256_MBNewCtx(2);
ASSERT_TRUE(mbCtx != NULL);
ASSERT_EQ(CRYPT_SHA256_MBInit(mbCtx), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr, nbytesArr, 2), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
ASSERT_EQ(outlen, CRYPT_SHA2_256_DIGESTSIZE);
ASSERT_COMPARE("SHA256_MB msg1", dgst1, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
ASSERT_COMPARE("SHA256_MB msg2", dgst2, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
EXIT:
CRYPT_SHA256_MBFreeCtx(mbCtx);
return;
#endif
}
/* END_CASE */
/**
* @test SDV_CRYPTO_SHA256_MB_FUNC_TC004
* @title CRYPT_SHA256_MB multi-block length test.
* @precon nan
* @brief
* 1.Generate two different messages of specified length, expected result 1.
* 2.Compute hashes using CRYPT_SHA256_MB, expected result 2.
* 3.Verify results match sequential SHA256 computation, expected result 3.
* @expect
* 1.Messages generated successfully.
* 2.Function returns CRYPT_SUCCESS.
* 3.Results match sequential computation for both messages.
*/
/* BEGIN_CASE */
void SDV_CRYPTO_SHA256_MB_FUNC_TC004(int msgLen)
{
#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
SKIP_TEST();
(void)msgLen;
#else
TestMemInit();
uint8_t *data1 = NULL;
uint8_t *data2 = NULL;
CRYPT_EAL_MdCTX *seqCtx1 = NULL;
CRYPT_EAL_MdCTX *seqCtx2 = NULL;
/* Allocate and fill test data */
data1 = (uint8_t *)malloc(msgLen);
data2 = (uint8_t *)malloc(msgLen);
ASSERT_TRUE(data1 != NULL && data2 != NULL);
for (int i = 0; i < msgLen; i++) {
data1[i] = (uint8_t)(i & 0xFF);
data2[i] = (uint8_t)((i * 3 + 7) & 0xFF);
}
/* MB computation */
const uint8_t *dataArr[2] = {data1, data2};
uint8_t dgst1_mb[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2_mb[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t *dgstArr[2] = {dgst1_mb, dgst2_mb};
uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
AARCH64_PUT_CANARY();
ASSERT_EQ(CRYPT_SHA256_MB(dataArr, msgLen, dgstArr, &outlen, 2), CRYPT_SUCCESS);
AARCH64_CHECK_CANARY();
/* Sequential computation for verification */
seqCtx1 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
seqCtx2 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
ASSERT_TRUE(seqCtx1 != NULL && seqCtx2 != NULL);
uint8_t dgst1_seq[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2_seq[CRYPT_SHA2_256_DIGESTSIZE];
uint32_t seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx1), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, data1, msgLen), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx1, dgst1_seq, &seqOutlen), CRYPT_SUCCESS);
seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx2), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, data2, msgLen), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx2, dgst2_seq, &seqOutlen), CRYPT_SUCCESS);
/* Compare results */
ASSERT_COMPARE("MB vs seq msg1", dgst1_mb, CRYPT_SHA2_256_DIGESTSIZE,
dgst1_seq, CRYPT_SHA2_256_DIGESTSIZE);
ASSERT_COMPARE("MB vs seq msg2", dgst2_mb, CRYPT_SHA2_256_DIGESTSIZE,
dgst2_seq, CRYPT_SHA2_256_DIGESTSIZE);
EXIT:
free(data1);
free(data2);
CRYPT_EAL_MdFreeCtx(seqCtx1);
CRYPT_EAL_MdFreeCtx(seqCtx2);
#endif
}
/* END_CASE */
/**
* @test SDV_CRYPTO_SHA256_MB_FUNC_TC003
* @title CRYPT_SHA256_MB multi-update test.
* @precon nan
* @brief
* 1.Initialize MB contexts, expected result 1.
* 2.Call Update multiple times with different data chunks, expected result 2.
* 3.Finalize and compare with sequential SHA256, expected result 3.
* @expect
* 1-2.All operations return CRYPT_SUCCESS.
* 3.Results match sequential computation.
*/
/* BEGIN_CASE */
void SDV_CRYPTO_SHA256_MB_FUNC_TC003(void)
{
#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
SKIP_TEST();
#else
TestMemInit();
CRYPT_SHA2_256_MB_Ctx *mbCtx = CRYPT_SHA256_MBNewCtx(2);
ASSERT_TRUE(mbCtx != NULL);
/* Prepare test data: split into chunks */
uint8_t chunk1_1[32], chunk1_2[32], chunk1_3[16];
uint8_t chunk2_1[32], chunk2_2[32], chunk2_3[16];
for (int i = 0; i < 32; i++) {
chunk1_1[i] = (uint8_t)(i);
chunk1_2[i] = (uint8_t)(i + 32);
chunk2_1[i] = (uint8_t)(i * 2);
chunk2_2[i] = (uint8_t)(i * 2 + 32);
}
for (int i = 0; i < 16; i++) {
chunk1_3[i] = (uint8_t)(i + 64);
chunk2_3[i] = (uint8_t)(i * 2 + 64);
}
const uint8_t *dataArr1[2] = {chunk1_1, chunk2_1};
const uint8_t *dataArr2[2] = {chunk1_2, chunk2_2};
const uint8_t *dataArr3[2] = {chunk1_3, chunk2_3};
uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t *dgstArr[2] = {dgst1, dgst2};
uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
uint32_t nbytesArr1[2] = {32, 32};
uint32_t nbytesArr2[2] = {32, 32};
uint32_t nbytesArr3[2] = {16, 16};
AARCH64_PUT_CANARY();
/* MB computation with multiple updates */
ASSERT_EQ(CRYPT_SHA256_MBInit(mbCtx), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr1, nbytesArr1, 2), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr2, nbytesArr2, 2), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr3, nbytesArr3, 2), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
AARCH64_CHECK_CANARY();
/* Sequential computation for verification */
CRYPT_EAL_MdCTX *seqCtx1 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
CRYPT_EAL_MdCTX *seqCtx2 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
ASSERT_TRUE(seqCtx1 != NULL && seqCtx2 != NULL);
uint8_t seqDgst1[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t seqDgst2[CRYPT_SHA2_256_DIGESTSIZE];
uint32_t seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx1), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, chunk1_1, 32), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, chunk1_2, 32), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, chunk1_3, 16), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx1, seqDgst1, &seqOutlen), CRYPT_SUCCESS);
seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx2), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, chunk2_1, 32), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, chunk2_2, 32), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, chunk2_3, 16), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx2, seqDgst2, &seqOutlen), CRYPT_SUCCESS);
/* Compare results */
ASSERT_COMPARE("MB vs seq msg1", dgst1, CRYPT_SHA2_256_DIGESTSIZE,
seqDgst1, CRYPT_SHA2_256_DIGESTSIZE);
ASSERT_COMPARE("MB vs seq msg2", dgst2, CRYPT_SHA2_256_DIGESTSIZE,
seqDgst2, CRYPT_SHA2_256_DIGESTSIZE);
EXIT:
CRYPT_SHA256_MBFreeCtx(mbCtx);
CRYPT_EAL_MdFreeCtx(seqCtx1);
CRYPT_EAL_MdFreeCtx(seqCtx2);
#endif
}
/* END_CASE */
/**
* @test SDV_CRYPT_EAL_SHA256_MB_API_TC001
* @title CRYPT_EAL_MdMB* API parameter validation test.
* @precon nan
* @brief
* 1.Call CRYPT_EAL_MdMBNewCtx with num=0, expected result 1.
* 2.Call CRYPT_EAL_MdMBNewCtx with invalid num (!=2), expected result 2.
* 3.Call CRYPT_EAL_MdMBInit/Update/Final with NULL parameters, expected result 3.
* @expect
* 1-3.Return error codes / NULL pointers.
*/
/* BEGIN_CASE */
void SDV_CRYPT_EAL_SHA256_MB_API_TC001(void)
{
#if !defined(HITLS_CRYPTO_MD_MB) || !defined(HITLS_CRYPTO_SHA2_MB)
SKIP_TEST();
#else
TestMemInit();
ASSERT_TRUE(CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 0) == NULL);
ASSERT_TRUE(CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 1) == NULL);
ASSERT_TRUE(CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 3) == NULL);
ASSERT_EQ(CRYPT_EAL_MdMBInit(NULL), CRYPT_NULL_INPUT);
uint32_t nbytesArr[2] = {1, 1};
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(NULL, NULL, nbytesArr, 2), CRYPT_NULL_INPUT);
ASSERT_EQ(CRYPT_EAL_MdMBFinal(NULL, NULL, NULL, 2), CRYPT_NULL_INPUT);
EXIT:
return;
#endif
}
/* END_CASE */
/**
* @test SDV_CRYPT_EAL_SHA256_MB_API_TC002
* @title CRYPT_EAL_MdMB* boundary parameter combinations test.
* @precon nan
* @brief
* 1.Create MB context and init it, expected result 1.
* 2.Call CRYPT_EAL_MdMBUpdate with mismatched nbytes, expected result 2.
* 3.Call CRYPT_EAL_MdMBUpdate with NULL lane data and non-zero nbytes, expected result 3.
* 4.Call CRYPT_EAL_MdMBUpdate/Final with num=0, expected result 4.
* 5.Call CRYPT_EAL_MdMBFinal with NULL digest lane, expected result 5.
* 6.Call CRYPT_EAL_MdMBFinal with insufficient outlen, expected result 6.
* @expect
* 1.Return CRYPT_SUCCESS.
* 2.Return CRYPT_NOT_SUPPORT.
* 3.Return CRYPT_NULL_INPUT.
* 4.Return CRYPT_NULL_INPUT.
* 5.Return CRYPT_NULL_INPUT.
* 6.Return CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH.
*/
/* BEGIN_CASE */
void SDV_CRYPT_EAL_SHA256_MB_API_TC002(void)
{
#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB) || !defined(HITLS_CRYPTO_MD_MB)
SKIP_TEST();
#else
TestMemInit();
CRYPT_EAL_MdCTX *ctx = CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 2);
ASSERT_TRUE(ctx != NULL);
ASSERT_EQ(CRYPT_EAL_MdMBInit(ctx), CRYPT_SUCCESS);
uint8_t in1[1] = {0x01};
uint8_t in2[1] = {0x02};
const uint8_t *dataArr[2] = {in1, in2};
uint32_t nbytesMismatch[2] = {1, 2};
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(ctx, dataArr, nbytesMismatch, 2), CRYPT_NOT_SUPPORT);
uint32_t nbytesValid[2] = {1, 1};
const uint8_t *dataArrWithNull[2] = {NULL, in2};
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(ctx, dataArrWithNull, nbytesValid, 2), CRYPT_NULL_INPUT);
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(ctx, dataArr, nbytesValid, 0), CRYPT_NULL_INPUT);
uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t *dgstArrWithNull[2] = {NULL, dgst2};
uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_EAL_MdMBFinal(ctx, dgstArrWithNull, &outlen, 2), CRYPT_NULL_INPUT);
uint8_t *dgstArr[2] = {dgst1, dgst2};
outlen = CRYPT_SHA2_256_DIGESTSIZE - 1;
ASSERT_EQ(CRYPT_EAL_MdMBFinal(ctx, dgstArr, &outlen, 2), CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH);
EXIT:
CRYPT_EAL_MdMBFreeCtx(ctx);
#endif
}
/* END_CASE */
/**
* @test SDV_CRYPT_EAL_SHA256_MB_FUNC_TC001
* @title CRYPT_EAL_MdMB* Init/Update/Final workflow test.
* @precon nan
* @brief
* 1.Create MB contexts using CRYPT_EAL_MdMBNewCtx, expected result 1.
* 2.Call CRYPT_EAL_MdMBInit/Update/Final to compute two digests, expected result 2.
* 3.Compare results with expected digest, expected result 3.
* @expect
* 1.Creation succeeds.
* 2.All functions return CRYPT_SUCCESS.
* 3.Both digests match expected value.
*/
/* BEGIN_CASE */
void SDV_CRYPT_EAL_SHA256_MB_FUNC_TC001(Hex *msg, Hex *digest)
{
#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB) || !defined(HITLS_CRYPTO_MD_MB)
SKIP_TEST();
(void)msg;
(void)digest;
#else
TestMemInit();
CRYPT_EAL_MdCTX *ctx = CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 2);
ASSERT_TRUE(ctx != NULL);
const uint8_t *dataArr[2] = {msg->x, msg->x};
uint32_t nbytesArr[2] = {msg->len, msg->len};
uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t *dgstArr[2] = {dgst1, dgst2};
uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_EAL_MdMBInit(ctx), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(ctx, dataArr, nbytesArr, 2), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdMBFinal(ctx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
ASSERT_EQ(outlen, CRYPT_SHA2_256_DIGESTSIZE);
ASSERT_COMPARE("EAL_SHA256_MB msg1", dgst1, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
ASSERT_COMPARE("EAL_SHA256_MB msg2", dgst2, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
EXIT:
CRYPT_EAL_MdMBFreeCtx(ctx);
#endif
}
/* END_CASE */
/**
* @test SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002
* @title CRYPT_EAL_MdMB* length boundary and multi-update test.
* @precon nan
* @brief
* 1.Generate two different messages of specified length, expected result 1.
* 2.Compute hashes using CRYPT_EAL_MdMB workflow with multiple updates, expected result 2.
* 3.Verify results match sequential SHA256 computation, expected result 3.
* @expect
* 1.Messages generated successfully.
* 2.All MB workflow functions return CRYPT_SUCCESS.
* 3.Results match sequential computation for both messages.
*/
/* BEGIN_CASE */
void SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002(int msgLen)
{
#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB) || !defined(HITLS_CRYPTO_MD_MB)
SKIP_TEST();
(void)msgLen;
#else
TestMemInit();
if (msgLen < 0) {
SKIP_TEST();
return;
}
uint8_t *data1 = NULL;
uint8_t *data2 = NULL;
CRYPT_EAL_MdCTX *mbCtx = NULL;
CRYPT_EAL_MdCTX *seqCtx1 = NULL;
CRYPT_EAL_MdCTX *seqCtx2 = NULL;
uint32_t allocLen = (msgLen == 0) ? 1u : (uint32_t)msgLen;
data1 = (uint8_t *)malloc(allocLen);
data2 = (uint8_t *)malloc(allocLen);
ASSERT_TRUE(data1 != NULL && data2 != NULL);
for (int i = 0; i < msgLen; i++) {
data1[i] = (uint8_t)(i & 0xFF);
data2[i] = (uint8_t)((i * 3 + 7) & 0xFF);
}
/* MB workflow computation */
mbCtx = CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 2);
ASSERT_TRUE(mbCtx != NULL);
ASSERT_EQ(CRYPT_EAL_MdMBInit(mbCtx), CRYPT_SUCCESS);
/* Boundary: zero-length update should succeed */
const uint8_t *dataArr0[2] = {data1, data2};
uint32_t nbytesArr0[2] = {0, 0};
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(mbCtx, dataArr0, nbytesArr0, 2), CRYPT_SUCCESS);
uint32_t offset = 0;
if (msgLen > 0) {
const uint8_t *dataArr1[2] = {data1, data2};
uint32_t nbytesArr1[2] = {1, 1};
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(mbCtx, dataArr1, nbytesArr1, 2), CRYPT_SUCCESS);
offset = 1;
}
uint32_t remaining = (uint32_t)msgLen - offset;
if (remaining > 0) {
uint32_t chunkLen = (remaining > 63) ? 63 : remaining;
const uint8_t *dataArr2[2] = {data1 + offset, data2 + offset};
uint32_t nbytesArr2[2] = {chunkLen, chunkLen};
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(mbCtx, dataArr2, nbytesArr2, 2), CRYPT_SUCCESS);
offset += chunkLen;
}
remaining = (uint32_t)msgLen - offset;
if (remaining > 0) {
const uint8_t *dataArr3[2] = {data1 + offset, data2 + offset};
uint32_t nbytesArr3[2] = {remaining, remaining};
ASSERT_EQ(CRYPT_EAL_MdMBUpdate(mbCtx, dataArr3, nbytesArr3, 2), CRYPT_SUCCESS);
}
uint8_t dgst1Mb[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2Mb[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t *dgstArr[2] = {dgst1Mb, dgst2Mb};
uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
AARCH64_PUT_CANARY();
ASSERT_EQ(CRYPT_EAL_MdMBFinal(mbCtx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
AARCH64_CHECK_CANARY();
ASSERT_EQ(outlen, CRYPT_SHA2_256_DIGESTSIZE);
/* Sequential computation for verification */
seqCtx1 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
seqCtx2 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
ASSERT_TRUE(seqCtx1 != NULL && seqCtx2 != NULL);
uint8_t dgst1Seq[CRYPT_SHA2_256_DIGESTSIZE];
uint8_t dgst2Seq[CRYPT_SHA2_256_DIGESTSIZE];
uint32_t seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx1), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, data1, (uint32_t)msgLen), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx1, dgst1Seq, &seqOutlen), CRYPT_SUCCESS);
seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx2), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, data2, (uint32_t)msgLen), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx2, dgst2Seq, &seqOutlen), CRYPT_SUCCESS);
ASSERT_COMPARE("EAL_MB vs seq msg1", dgst1Mb, CRYPT_SHA2_256_DIGESTSIZE,
dgst1Seq, CRYPT_SHA2_256_DIGESTSIZE);
ASSERT_COMPARE("EAL_MB vs seq msg2", dgst2Mb, CRYPT_SHA2_256_DIGESTSIZE,
dgst2Seq, CRYPT_SHA2_256_DIGESTSIZE);
EXIT:
free(data1);
free(data2);
CRYPT_EAL_MdMBFreeCtx(mbCtx);
CRYPT_EAL_MdFreeCtx(seqCtx1);
CRYPT_EAL_MdFreeCtx(seqCtx2);
#endif
}
/* END_CASE */
@@ -132,3 +132,78 @@ SDV_CRYPTO_SHA2_COPY_CTX_FUNC_TC001:CRYPT_MD_SHA512:"6ba004fd176791efb381b862e29
SDV_CRYPTO_SHA2_DEFAULT_PROVIDER_FUNC_TC001 default provider
SDV_CRYPTO_SHA2_DEFAULT_PROVIDER_FUNC_TC001:CRYPT_MD_SHA224:"a4bc10b1a62c96d459fbaf3a5aa3face73":"d7e6634723ac25cb1879bdb1508da05313530419013fe255967a39e1"
CRYPT_SHA256_MB API parameter validation
SDV_CRYPTO_SHA256_MB_API_TC001:
CRYPT_SHA256_MB one-shot API test with short messages
SDV_CRYPTO_SHA256_MB_FUNC_TC001:"d3":"28969cdfa74a12c82f3bad960b0b000aca2ac329deea5c2328ebc6f2ba9802c1"
CRYPT_SHA256_MB one-shot API test with empty messages
SDV_CRYPTO_SHA256_MB_FUNC_TC001:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
CRYPT_SHA256_MB single block (64 bytes)
SDV_CRYPTO_SHA256_MB_FUNC_TC004:64
CRYPT_SHA256_MB block boundary (56 bytes, need padding block)
SDV_CRYPTO_SHA256_MB_FUNC_TC004:56
CRYPT_SHA256_MB two blocks (120 bytes = 64+56)
SDV_CRYPTO_SHA256_MB_FUNC_TC004:120
CRYPT_SHA256_MB two blocks aligned (128 bytes = 64*2)
SDV_CRYPTO_SHA256_MB_FUNC_TC004:128
CRYPT_SHA256_MB three blocks (192 bytes = 64*3)
SDV_CRYPTO_SHA256_MB_FUNC_TC004:192
CRYPT_SHA256_MB large message (1024 bytes)
SDV_CRYPTO_SHA256_MB_FUNC_TC004:1024
CRYPT_SHA256_MB Init/Update/Final test
SDV_CRYPTO_SHA256_MB_FUNC_TC002:"3d83df37172c81afd0de115139fbf4390c22e098c5af4c5ab4852406510bc0e6cf741769f44430c5270fdae0cb849d71cbab":"99dc772e91ea02d9e421d552d61901016b9fd4ad2df4a8212c1ec5ba13893ab2"
CRYPT_SHA256_MB multi-update test
SDV_CRYPTO_SHA256_MB_FUNC_TC003:
CRYPT_EAL_MdMB API parameter validation
SDV_CRYPT_EAL_SHA256_MB_API_TC001:
CRYPT_EAL_MdMB boundary parameter combinations
SDV_CRYPT_EAL_SHA256_MB_API_TC002:
CRYPT_EAL_MdMB Init/Update/Final test
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC001:"d3":"28969cdfa74a12c82f3bad960b0b000aca2ac329deea5c2328ebc6f2ba9802c1"
CRYPT_EAL_MdMB length boundary (empty message)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:0
CRYPT_EAL_MdMB length boundary (1 byte)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:1
CRYPT_EAL_MdMB block boundary (55 bytes)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:55
CRYPT_EAL_MdMB block boundary (56 bytes, need padding block)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:56
CRYPT_EAL_MdMB block boundary (57 bytes)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:57
CRYPT_EAL_MdMB single block (64 bytes)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:64
CRYPT_EAL_MdMB one byte over block (65 bytes)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:65
CRYPT_EAL_MdMB two blocks (120 bytes = 64+56)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:120
CRYPT_EAL_MdMB two blocks aligned (128 bytes = 64*2)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:128
CRYPT_EAL_MdMB three blocks (192 bytes = 64*3)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:192
CRYPT_EAL_MdMB large message (1024 bytes)
SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:1024