已合并
add sha256-mb interfaces #1020
add sha256-mb interfaces #1020
已合并
dumb创建于 1月22日
共 19 个文件变更+1867-98
@@ -54,6 +54,11 @@
54 },54 },
55 "sha3": null55 "sha3": null
56 },56 },
57+ "md_mb": {
58+ "sha2_mb": {
59+ "sha256_mb": null
60+ }
61+ },
57 "mac": {62 "mac": {
58 "hmac": null,63 "hmac": null,
59 "gmac": {"deps": ["eal", "aes", "gcm"]},64 "gmac": {"deps": ["eal", "aes", "gcm"]},
@@ -709,7 +714,7 @@
709 ".deps": ["platform::Secure_C"]714 ".deps": ["platform::Secure_C"]
710 },715 },
711 "sha2": {716 "sha2": {
712- ".features": ["sha224", "sha256", "sha384", "sha512"],717+ ".features": ["sha224", "sha256", "sha384", "sha512", "sha2_mb"],
713 ".srcs": {718 ".srcs": {
714 "public": "crypto/sha2/src/sha2*.c",719 "public": "crypto/sha2/src/sha2*.c",
715 "no_asm": "crypto/sha2/src/noasm_*.c",720 "no_asm": "crypto/sha2/src/noasm_*.c",
@@ -752,6 +752,30 @@
752#define HITLS_CRYPTO_SM3_ASM752#define HITLS_CRYPTO_SM3_ASM
753#endif753#endif
754 754 
755+#ifdef HITLS_CRYPTO_MD_MB
756+ #ifndef HITLS_CRYPTO_SHA2_MB
757+ #define HITLS_CRYPTO_SHA2_MB
758+ #endif
759+#endif
760+ 
761+#ifdef HITLS_CRYPTO_SHA2_MB
762+ #ifndef HITLS_CRYPTO_SHA256_MB
763+ #define HITLS_CRYPTO_SHA256_MB
764+ #endif
765+#endif
766+ 
767+#if defined(HITLS_CRYPTO_SHA256_MB)
768+ #ifndef HITLS_CRYPTO_SHA2_MB
769+ #define HITLS_CRYPTO_SHA2_MB
770+ #endif
771+#endif
772+ 
773+#if defined(HITLS_CRYPTO_SHA2_MB)
774+ #ifndef HITLS_CRYPTO_MD_MB
775+ #define HITLS_CRYPTO_MD_MB
776+ #endif
777+#endif
778+ 
755#if defined(HITLS_CRYPTO_BN_X8664) || defined(HITLS_CRYPTO_BN_ARMV8)779#if defined(HITLS_CRYPTO_BN_X8664) || defined(HITLS_CRYPTO_BN_ARMV8)
756#define HITLS_CRYPTO_BN_ASM780#define HITLS_CRYPTO_BN_ASM
757#endif781#endif
@@ -27,6 +27,7 @@
27#include "crypt_errno.h"27#include "crypt_errno.h"
28#include "eal_md_local.h"28#include "eal_md_local.h"
29#include "eal_common.h"29#include "eal_common.h"
30+#include "crypt_utils.h"
30#include "crypt_ealinit.h"31#include "crypt_ealinit.h"
31#ifdef HITLS_CRYPTO_PROVIDER32#ifdef HITLS_CRYPTO_PROVIDER
32#include "crypt_eal_implprovider.h"33#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
440{441{
441 return EAL_Md(id, in, inLen, out, outLen);442 return EAL_Md(id, in, inLen, out, outLen);
442}443}
444+ 
445+#ifdef HITLS_CRYPTO_MD_MB
446+ 
447+CRYPT_EAL_MdCTX *CRYPT_EAL_MdMBNewCtx(CRYPT_EAL_LibCtx *libCtx, int32_t id, uint32_t num)
448+{
449+ (void)libCtx;
450+ if (UNLIKELY(num == 0)) {
451+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NULL_INPUT);
452+ return NULL;
453+ }
454+ 
455+ EAL_MdMBMethod mbMethod = {0};
456+ if (EAL_MdFindMbMethod(id, &mbMethod) == NULL ||
457+ mbMethod.newCtx == NULL || mbMethod.freeCtx == NULL) {
458+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NOT_SUPPORT);
459+ return NULL;
460+ }
461+ 
462+ void *mbData = mbMethod.newCtx(num);
463+ if (mbData == NULL) {
464+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_MEM_ALLOC_FAIL);
465+ return NULL;
466+ }
467+ 
468+ CRYPT_EAL_MdCTX *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_EAL_MdCTX));
469+ if (ctx == NULL) {
470+ mbMethod.freeCtx(mbData);
471+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_MEM_ALLOC_FAIL);
472+ return NULL;
473+ }
474+ 
475+ ctx->mbMethod = mbMethod;
476+ ctx->data = mbData;
477+ ctx->id = id;
478+ ctx->state = CRYPT_MD_STATE_NEW;
479+ return ctx;
480+}
481+ 
482+void CRYPT_EAL_MdMBFreeCtx(CRYPT_EAL_MdCTX *ctx)
483+{
484+ if (ctx == NULL) {
485+ return;
486+ }
487+ if (ctx->mbMethod.freeCtx != NULL) {
488+ ctx->mbMethod.freeCtx(ctx->data);
489+ }
490+ BSL_SAL_Free(ctx);
491+}
492+ 
493+int32_t CRYPT_EAL_MdMBInit(CRYPT_EAL_MdCTX *ctx)
494+{
495+ if (UNLIKELY(ctx == NULL)) {
496+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, CRYPT_MD_MAX, CRYPT_NULL_INPUT);
497+ return CRYPT_NULL_INPUT;
498+ }
499+ 
500+ CRYPT_MD_AlgId id = ctx->id;
501+ if (ctx->mbMethod.init == NULL) {
502+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NOT_SUPPORT);
503+ return CRYPT_NOT_SUPPORT;
504+ }
505+ int32_t ret = ctx->mbMethod.init(ctx->data);
506+
507+ if (ret == CRYPT_SUCCESS) {
508+ ctx->state = CRYPT_MD_STATE_INIT;
509+ }
510+ 
511+ return ret;
512+}
513+ 
514+int32_t CRYPT_EAL_MdMBUpdate(CRYPT_EAL_MdCTX *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num)
515+{
516+ if (UNLIKELY(ctx == NULL || data == NULL || nbytes == NULL || num == 0)) {
517+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, CRYPT_MD_MAX, CRYPT_NULL_INPUT);
518+ return CRYPT_NULL_INPUT;
519+ }
520+ if (UNLIKELY(nbytes[0] == 0)) {
521+ return CRYPT_SUCCESS;
522+ }
523+ 
524+ CRYPT_MD_AlgId id = ctx->id;
525+ if (ctx->mbMethod.update == NULL) {
526+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NOT_SUPPORT);
527+ return CRYPT_NOT_SUPPORT;
528+ }
529+ 
530+ int32_t ret = ctx->mbMethod.update(ctx->data, data, nbytes, num);
531+ if (ret == CRYPT_SUCCESS) {
532+ ctx->state = CRYPT_MD_STATE_UPDATE;
533+ }
534+ 
535+ return ret;
536+}
537+ 
538+int32_t CRYPT_EAL_MdMBFinal(CRYPT_EAL_MdCTX *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num)
539+{
540+ if (UNLIKELY(ctx == NULL || digest == NULL || outlen == NULL || num == 0)) {
541+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, CRYPT_MD_MAX, CRYPT_NULL_INPUT);
542+ return CRYPT_NULL_INPUT;
543+ }
544+ 
545+ CRYPT_MD_AlgId id = ctx->id;
546+ if (ctx->mbMethod.final == NULL) {
547+ EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, id, CRYPT_NOT_SUPPORT);
548+ return CRYPT_NOT_SUPPORT;
549+ }
550+ 
551+ int32_t ret = ctx->mbMethod.final(ctx->data, digest, outlen, num);
552+ if (ret == CRYPT_SUCCESS) {
553+ ctx->state = CRYPT_MD_STATE_FINAL;
554+ }
555+ 
556+ return ret;
557+}
558+ 
559+#endif // HITLS_CRYPTO_MD_MB
560+ 
443#endif561#endif
@@ -38,11 +38,18 @@ typedef enum {
38struct EAL_MdCtx {38struct EAL_MdCtx {
39 bool isProvider;39 bool isProvider;
40 EAL_MdUnitaryMethod *method; /* algorithm operation entity */40 EAL_MdUnitaryMethod *method; /* algorithm operation entity */
41+#ifdef HITLS_CRYPTO_MD_MB
42+ EAL_MdMBMethod mbMethod; /* multi-buffer operation entity */
43+#endif
41 void *data; /* Algorithm ctx, mainly context */44 void *data; /* Algorithm ctx, mainly context */
42 uint32_t state;45 uint32_t state;
43 CRYPT_MD_AlgId id;46 CRYPT_MD_AlgId id;
44};47};
45 48 
49+#ifdef HITLS_CRYPTO_MD_MB
50+EAL_MdMBMethod *EAL_MdFindMbMethod(CRYPT_MD_AlgId id, EAL_MdMBMethod *method);
51+#endif
52+ 
46/**53/**
47 * @ingroup eal54 * @ingroup eal
48 * @brief Method for generating the hash algorithm55 * @brief Method for generating the hash algorithm
@@ -140,6 +140,46 @@ const EAL_MdMethod *EAL_MdFindMethod(CRYPT_MD_AlgId id)
140 return NULL;140 return NULL;
141}141}
142 142 
143+#ifdef HITLS_CRYPTO_MD_MB
144+#ifdef HITLS_CRYPTO_SHA2_MB
145+static const EAL_MdMBMethod g_mdMbMethod_SHA256 = {
146+ (MdMBNewCtx)CRYPT_SHA256_MBNewCtx,
147+ (MdMBFreeCtx)CRYPT_SHA256_MBFreeCtx,
148+ (MdMBInit)CRYPT_SHA256_MBInit,
149+ (MdMBUpdate)CRYPT_SHA256_MBUpdate,
150+ (MdMBFinal)CRYPT_SHA256_MBFinal
151+};
152+#endif
153+ 
154+static const EAL_CidToMdMbMeth ID_TO_MD_MB_METH_TABLE[] = {
155+#ifdef HITLS_CRYPTO_SHA2_MB
156+ {CRYPT_MD_SHA256_MB, &g_mdMbMethod_SHA256},
157+#endif
158+};
159+ 
160+static const EAL_MdMBMethod *EAL_MdFindDefaultMbMethod(CRYPT_MD_AlgId id)
161+{
162+ uint32_t num = sizeof(ID_TO_MD_MB_METH_TABLE) / sizeof(ID_TO_MD_MB_METH_TABLE[0]);
163+ for (uint32_t i = 0; i < num; i++) {
164+ if (ID_TO_MD_MB_METH_TABLE[i].id == id) {
165+ return ID_TO_MD_MB_METH_TABLE[i].mbMeth;
166+ }
167+ }
168+ return NULL;
169+}
170+ 
171+EAL_MdMBMethod *EAL_MdFindMbMethod(CRYPT_MD_AlgId id, EAL_MdMBMethod *method)
172+{
173+ const EAL_MdMBMethod *findMethod = EAL_MdFindDefaultMbMethod(id);
174+ if (findMethod == NULL) {
175+ BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_ALGID);
176+ return NULL;
177+ }
178+ *method = *findMethod;
179+ return method;
180+}
181+#endif // HITLS_CRYPTO_MD_MB
182+ 
143int32_t EAL_Md(CRYPT_MD_AlgId id, const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)183int32_t EAL_Md(CRYPT_MD_AlgId id, const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)
144{184{
145 int32_t ret;185 int32_t ret;
@@ -45,6 +45,22 @@ typedef void (*MdFreeCtx)(void *data);
45typedef int32_t (*MdCtrl)(void *data, int32_t cmd, void *val, uint32_t valLen);45typedef int32_t (*MdCtrl)(void *data, int32_t cmd, void *val, uint32_t valLen);
46typedef int32_t (*MdSqueeze)(void *data, uint8_t *out, uint32_t len);46typedef int32_t (*MdSqueeze)(void *data, uint8_t *out, uint32_t len);
47 47 
48+#ifdef HITLS_CRYPTO_MD_MB
49+typedef void *(*MdMBNewCtx)(uint32_t num);
50+typedef void (*MdMBFreeCtx)(void *ctx);
51+typedef int32_t (*MdMBInit)(void *ctx);
52+typedef int32_t (*MdMBUpdate)(void *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num);
53+typedef int32_t (*MdMBFinal)(void *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num);
54+ 
55+typedef struct {
56+ MdMBNewCtx newCtx;
57+ MdMBFreeCtx freeCtx;
58+ MdMBInit init;
59+ MdMBUpdate update;
60+ MdMBFinal final;
61+} EAL_MdMBMethod;
62+#endif // HITLS_CRYPTO_MD_MB
63+ 
48typedef struct {64typedef struct {
49 uint16_t blockSize; // Block size processed by the hash algorithm at a time, which is used with other algorithms.65 uint16_t blockSize; // Block size processed by the hash algorithm at a time, which is used with other algorithms.
50 uint16_t mdSize; // Output length of the HASH algorithm66 uint16_t mdSize; // Output length of the HASH algorithm
@@ -86,6 +102,13 @@ typedef struct {
86 EAL_MdMethod *mdMeth;102 EAL_MdMethod *mdMeth;
87} EAL_CidToMdMeth;103} EAL_CidToMdMeth;
88 104 
105+#ifdef HITLS_CRYPTO_MD_MB
106+typedef struct {
107+ uint32_t id;
108+ const EAL_MdMBMethod *mbMeth;
109+} EAL_CidToMdMbMeth;
110+#endif
111+ 
89/* provide asymmetric primitive method */112/* provide asymmetric primitive method */
90typedef void *(*PkeyNew)(void);113typedef void *(*PkeyNew)(void);
91typedef void* (*PkeyProvNew)(void *provCtx, int32_t algId);114typedef void* (*PkeyProvNew)(void *provCtx, int32_t algId);
@@ -38,6 +38,7 @@ extern "C" {
38#ifdef HITLS_CRYPTO_SHA25638#ifdef HITLS_CRYPTO_SHA256
39#define CRYPT_SHA2_256_BLOCKSIZE 6439#define CRYPT_SHA2_256_BLOCKSIZE 64
40#define CRYPT_SHA2_256_DIGESTSIZE 3240#define CRYPT_SHA2_256_DIGESTSIZE 32
41+#define CRYPT_SHA256_STATE_SIZE 8
41#endif // HITLS_CRYPTO_SHA25642#endif // HITLS_CRYPTO_SHA256
42 43 
43#ifdef HITLS_CRYPTO_SHA38444#ifdef HITLS_CRYPTO_SHA384
@@ -254,6 +255,153 @@ int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint
254 * @retval #CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH output buffer is not enough255 * @retval #CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH output buffer is not enough
255 */256 */
256int32_t CRYPT_SHA2_256_Final(CRYPT_SHA2_256_Ctx *ctx, uint8_t *digest, uint32_t *outlen);257int32_t CRYPT_SHA2_256_Final(CRYPT_SHA2_256_Ctx *ctx, uint8_t *digest, uint32_t *outlen);
258+ 
259+typedef struct {
260+ uint32_t num;
261+ CRYPT_SHA2_256_Ctx *ctxs;
262+} CRYPT_SHA2_256_MB_Ctx;
263+ 
264+/**
265+ * @ingroup SHA256
266+ * @brief Create a SHA256 multi-buffer context.
267+ *
268+ * Notes:
269+ * - Currently only supports num == 2.
270+ *
271+ * @param num [IN] Number of parallel messages/contexts.
272+ *
273+ * @retval Pointer to multi-buffer context on success.
274+ * @retval NULL on failure (invalid num or memory allocation failure).
275+ */
276+CRYPT_SHA2_256_MB_Ctx *CRYPT_SHA256_MBNewCtx(uint32_t num);
277+ 
278+/**
279+ * @ingroup SHA256
280+ * @brief Free a SHA256 multi-buffer context.
281+ *
282+ * @param ctx [IN] Multi-buffer context pointer (can be NULL).
283+ */
284+void CRYPT_SHA256_MBFreeCtx(CRYPT_SHA2_256_MB_Ctx *ctx);
285+ 
286+/**
287+ * @ingroup SHA256
288+ * @brief Initialize a SHA256 multi-buffer context.
289+ *
290+ * Notes:
291+ * - Currently only supports ctx->num == 2.
292+ *
293+ * @param ctx [IN/OUT] Multi-buffer context.
294+ *
295+ * @retval #CRYPT_SUCCESS Success.
296+ * @retval #CRYPT_NULL_INPUT ctx is NULL.
297+ * @retval #CRYPT_NOT_SUPPORT Not supported (e.g. ctx->num != 2 or platform capability missing).
298+ */
299+int32_t CRYPT_SHA256_MBInit(CRYPT_SHA2_256_MB_Ctx *ctx);
300+ 
301+/**
302+ * @ingroup SHA256
303+ * @brief Update SHA256 multi-buffer context with message fragments.
304+ *
305+ * Notes:
306+ * - Each update processes one fragment per message, where data[i] is the fragment for lane i.
307+ * - nbytes[i] is the fragment length for lane i. Currently requires nbytes[0] == nbytes[1],
308+ * otherwise returns #CRYPT_NOT_SUPPORT.
309+ * - Currently only supports num == 2.
310+ *
311+ * @param ctx [IN/OUT] Multi-buffer context.
312+ * @param data [IN] Input pointer array. data[i] is fragment pointer for lane i.
313+ * @param nbytes [IN] Input length array. nbytes[i] is fragment length for lane i.
314+ * @param num [IN] Number of lanes/messages.
315+ *
316+ * @retval #CRYPT_SUCCESS Success.
317+ * @retval #CRYPT_NULL_INPUT Invalid input pointer.
318+ * @retval #CRYPT_NOT_SUPPORT Not supported (e.g. num != 2 or per-lane lengths are not equal).
319+ * @retval Other error codes, see crypt_errno.h.
320+ */
321+int32_t CRYPT_SHA256_MBUpdate(CRYPT_SHA2_256_MB_Ctx *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num);
322+ 
323+/**
324+ * @ingroup SHA256
325+ * @brief Finalize SHA256 multi-buffer context and output digests.
326+ *
327+ * Notes:
328+ * - Currently only supports num == 2.
329+ * - outlen indicates output buffer size on input and returns actual digest length on output.
330+ *
331+ * @param ctx [IN/OUT] Multi-buffer context.
332+ * @param digest [OUT] Digest buffer pointer array. digest[i] is output buffer for lane i.
333+ * @param outlen [IN/OUT] Output buffer length / output digest length.
334+ * @param num [IN] Number of lanes/messages.
335+ *
336+ * @retval #CRYPT_SUCCESS Success.
337+ * @retval #CRYPT_NULL_INPUT Invalid input pointer.
338+ * @retval #CRYPT_NOT_SUPPORT Not supported (e.g. num != 2 or platform capability missing).
339+ * @retval Other error codes, see crypt_errno.h.
340+ */
341+int32_t CRYPT_SHA256_MBFinal(CRYPT_SHA2_256_MB_Ctx *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num);
342+ 
343+/**
344+ * @ingroup SHA256
345+ * @brief SHA256 dual-lane compression for full blocks.
346+ *
347+ * This function compresses nblocks full SHA256 blocks for two independent states in parallel.
348+ * It does not handle padding or length encoding.
349+ *
350+ * @param state1 [IN/OUT] SHA256 state for lane 0. Array size is #CRYPT_SHA256_STATE_SIZE.
351+ * @param state2 [IN/OUT] SHA256 state for lane 1. Array size is #CRYPT_SHA256_STATE_SIZE.
352+ * @param block1 [IN] Input block pointer for lane 0 (must contain nblocks * 64 bytes).
353+ * @param block2 [IN] Input block pointer for lane 1 (must contain nblocks * 64 bytes).
354+ * @param nblocks [IN] Number of full 64-byte blocks to compress.
355+ */
356+void CRYPT_SHA256x2_Compress(uint32_t state1[CRYPT_SHA256_STATE_SIZE], uint32_t state2[CRYPT_SHA256_STATE_SIZE],
357+ const uint8_t *block1, const uint8_t *block2, uint32_t nblocks);
358+ 
359+/**
360+ * @ingroup SHA256
361+ * @brief SHA256 multi-buffer one-shot hashing.
362+ *
363+ * Notes:
364+ * - Currently only supports num == 2.
365+ * - nbytes is the same length for all lanes in this one-shot API.
366+ *
367+ * @param data [IN] Input pointer array. data[i] is message pointer for lane i.
368+ * @param nbytes [IN] Input length in bytes.
369+ * @param digest [OUT] Digest buffer pointer array. digest[i] is output buffer for lane i.
370+ * @param outlen [IN/OUT] Output buffer length / output digest length.
371+ * @param num [IN] Number of lanes/messages.
372+ *
373+ * @retval #CRYPT_SUCCESS Success.
374+ * @retval #CRYPT_NULL_INPUT Invalid input pointer.
375+ * @retval #CRYPT_NOT_SUPPORT Not supported (e.g. num != 2 or platform capability missing).
376+ * @retval Other error codes, see crypt_errno.h.
377+ */
378+int32_t CRYPT_SHA256_MB(const uint8_t *data[], uint32_t nbytes, uint8_t *digest[], uint32_t *outlen, uint32_t num);
379+ 
380+/**
381+ * @ingroup SHA256
382+ * @brief SHA256 dual-lane one-shot hashing with initial states.
383+ *
384+ * This function computes SHA256 digests for two messages in parallel, starting from the provided
385+ * SHA256 states.
386+ *
387+ * Notes:
388+ * - This API is intended for internal acceleration paths.
389+ *
390+ * @param state1 [IN/OUT] SHA256 state for lane 0. Array size is #CRYPT_SHA256_STATE_SIZE.
391+ * @param state2 [IN/OUT] SHA256 state for lane 1. Array size is #CRYPT_SHA256_STATE_SIZE.
392+ * @param data1 [IN] Input message pointer for lane 0.
393+ * @param data2 [IN] Input message pointer for lane 1.
394+ * @param nbytes [IN] Input length in bytes for both lanes.
395+ * @param dgst1 [OUT] Digest output buffer for lane 0 (size #CRYPT_SHA2_256_DIGESTSIZE).
396+ * @param dgst2 [OUT] Digest output buffer for lane 1 (size #CRYPT_SHA2_256_DIGESTSIZE).
397+ *
398+ * @retval #CRYPT_SUCCESS Success.
399+ * @retval #CRYPT_NOT_SUPPORT Not supported on this platform/build.
400+ */
401+int32_t CRYPT_SHA256x2(uint32_t state1[CRYPT_SHA256_STATE_SIZE], uint32_t state2[CRYPT_SHA256_STATE_SIZE],
402+ const uint8_t *data1, const uint8_t *data2, uint32_t nbytes,
403+ uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE], uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE]);
404+ 
257#endif // HITLS_CRYPTO_SHA256405#endif // HITLS_CRYPTO_SHA256
258 406 
259#ifdef HITLS_CRYPTO_SHA384407#ifdef HITLS_CRYPTO_SHA384
@@ -471,4 +471,385 @@ SHA256CryptoExt:
471 st1 {v4.4s-v5.4s}, [x0]471 st1 {v4.4s-v5.4s}, [x0]
472 ret472 ret
473 .size SHA256CryptoExt, .-SHA256CryptoExt473 .size SHA256CryptoExt, .-SHA256CryptoExt
474+ 
475+/*
476+ * Optimized macro for dual SHA-256 rounds - caller-saved registers only
477+ * Uses on-demand K256 loading to comply with AAPCS calling convention
478+ * v8-v15 are callee-saved and must be preserved
479+ */
480+.macro ROUNDS4X2_LOAD m0_a, m0_b, k
481+ mov v30.16b, v4.16b
482+ mov v31.16b, v6.16b
483+ add v28.4s, v\k\().4s, v\m0_a\().4s
484+ add v29.4s, v\k\().4s, v\m0_b\().4s
485+ sha256h q4, q5, v28.4s
486+ sha256h q6, q7, v29.4s
487+ sha256h2 q5, q30, v28.4s
488+ sha256h2 q7, q31, v29.4s
489+.endm
490+ 
491+/* Macro for round with message schedule update */
492+.macro ROUND_SCHED m0, m1, m2, m3, m0b, m1b, m2b, m3b, k
493+ ROUNDS4X2_LOAD \m0, \m0b, \k
494+ sha256su0 v\m0\().4s, v\m1\().4s
495+ sha256su0 v\m0b\().4s, v\m1b\().4s
496+ sha256su1 v\m0\().4s, v\m2\().4s, v\m3\().4s
497+ sha256su1 v\m0b\().4s, v\m2b\().4s, v\m3b\().4s
498+.endm
499+ 
500+.macro REVBE x0, x1
501+#ifndef HITLS_BIG_ENDIAN
502+ rev \x0, \x1
503+#else
504+ mov \x0, \x1
505+#endif
506+.endm
507+ 
508+/*
509+ * Function: CRYPT_SHA256x2 - Dual SHA-256 hash computation
510+ * Prototype: void CRYPT_SHA256x2(uint32_t state1[8], uint32_t state2[8],
511+ * const uint8_t *in1, const uint8_t *in2, uint32_t nbytes,
512+ * uint8_t dgst1[32], uint8_t dgst2[32]);
513+ *
514+ * Parameters:
515+ * x0 - state1: Initial/final hash state for message 1
516+ * x1 - state2: Initial/final hash state for message 2
517+ * x2 - in1: Message 1 data pointer
518+ * x3 - in2: Message 2 data pointer
519+ * w4 - nbytes: Message length (same for both)
520+ * x5 - dgst1: Output digest for message 1 (32 bytes, big-endian)
521+ * x6 - dgst2: Output digest for message 2 (32 bytes, big-endian)
522+ *
523+ * Computes two SHA-256 hashes simultaneously using ARMv8 crypto extensions.
524+ * Handles padding internally per FIPS 180-4.
525+ */
526+ 
527+.balign 16
528+#ifdef __APPLE__
529+ .global _CRYPT_SHA256x2
530+ _CRYPT_SHA256x2:
531+#else
532+ .global CRYPT_SHA256x2
533+ .type CRYPT_SHA256x2, %function
534+CRYPT_SHA256x2:
535+#endif
536+AARCH64_PACIASP
537+ /* Stack: 256 bytes
538+ * 0-15: x29/x30, 96-159: buffer1, 160-223: buffer2 */
539+ stp x29, x30, [sp, #-160]!
540+ add x29, sp, #0
541+ stp x19, x20, [sp, #16]
542+
543+ /* Initialize */
544+ lsl x19, x4, #3 // bit count for padding
545+ ld1 {v24.4s-v25.4s}, [x0] // Load initial state1
546+ ld1 {v26.4s-v27.4s}, [x1] // Load initial state2
547+ 
548+ /* Process complete 64-byte blocks */
549+ lsr w9, w4, #6 // num_blocks = nbytes / 64
550+ cbz w9, .L_partial_2x
551+ 
552+.L_fullblk_2x:
553+ /* Load 64 bytes from each message and convert to big-endian */
554+ ld1 {v16.16b-v19.16b}, [x2], #64
555+ ld1 {v20.16b-v23.16b}, [x3], #64
556+ rev32 v16.16b, v16.16b
557+ rev32 v20.16b, v20.16b
558+ rev32 v17.16b, v17.16b
559+ rev32 v21.16b, v21.16b
560+ rev32 v18.16b, v18.16b
561+ rev32 v22.16b, v22.16b
562+ rev32 v19.16b, v19.16b
563+ rev32 v23.16b, v23.16b
564+ 
565+ /* Execute 64 rounds of compression */
566+ bl sha256_block_x2
567+ 
568+ subs w9, w9, #1
569+ bne .L_fullblk_2x
570+ 
571+.L_partial_2x:
572+ /* Handle partial block and padding (FIPS 180-4):
573+ * Append 0x80, pad with zeros to 56 bytes, append 64-bit length */
574+ and w10, w4, #63 // remaining bytes
575+ cbz w10, .L_padding_aligned_2x
576+
577+ /* Clear buffers and copy remaining bytes */
578+ add x11, sp, #32
579+ movi v28.16b, #0
580+ movi v29.16b, #0
581+ movi v30.16b, #0
582+ movi v31.16b, #0
583+ st1 {v28.16b-v31.16b}, [x11], #64
584+ st1 {v28.16b-v31.16b}, [x11]
585+
586+ add x11, sp, #32
587+ add x12, sp, #96
588+ mov x13, x10
589+
590+ /* Copy 16-byte chunks */
591+ cmp x13, #16
592+ blt .L_copy_bytes_2x
593+.L_copy_16_2x:
594+ ldr q28, [x2], #16
595+ ldr q29, [x3], #16
596+ str q28, [x11], #16
597+ str q29, [x12], #16
598+ sub x13, x13, #16
599+ cmp x13, #16
600+ bge .L_copy_16_2x
601+
602+ /* Copy remaining bytes */
603+.L_copy_bytes_2x:
604+ cbz x13, .L_add_padding_2x
605+ ldrb w14, [x2], #1
606+ ldrb w15, [x3], #1
607+ strb w14, [x11], #1
608+ strb w15, [x12], #1
609+ subs x13, x13, #1
610+ bne .L_copy_bytes_2x
611+ 
612+.L_add_padding_2x:
613+ /* Add 0x80 padding byte */
614+ mov w13, #0x80
615+ add x14, sp, #32
616+ add x15, sp, #96
617+ strb w13, [x14, x10]
618+ strb w13, [x15, x10]
619+
620+ /* Check if need one or two blocks */
621+ cmp w10, #56
622+ bge .L_need_extra_block_2x
623+
624+ /* Case 1: Padding fits in one block */
625+ REVBE x8, x19
626+ add x14, sp, #32
627+ add x15, sp, #96
628+ str x8, [x14, #56]
629+ str x8, [x15, #56]
630+
631+ ld1 {v16.16b-v19.16b}, [x14]
632+ ld1 {v20.16b-v23.16b}, [x15]
633+ rev32 v16.16b, v16.16b
634+ rev32 v20.16b, v20.16b
635+ rev32 v17.16b, v17.16b
636+ rev32 v21.16b, v21.16b
637+ rev32 v18.16b, v18.16b
638+ rev32 v22.16b, v22.16b
639+ rev32 v19.16b, v19.16b
640+ rev32 v23.16b, v23.16b
641+ b .L_process_final_2x
642+ 
643+.L_need_extra_block_2x:
644+ /* Case 2: Need two blocks (remaining >= 56) */
645+ add x14, sp, #32
646+ add x15, sp, #96
647+ ld1 {v16.16b-v19.16b}, [x14]
648+ ld1 {v20.16b-v23.16b}, [x15]
649+ rev32 v16.16b, v16.16b
650+ rev32 v20.16b, v20.16b
651+ rev32 v17.16b, v17.16b
652+ rev32 v21.16b, v21.16b
653+ rev32 v18.16b, v18.16b
654+ rev32 v22.16b, v22.16b
655+ rev32 v19.16b, v19.16b
656+ rev32 v23.16b, v23.16b
657+ bl sha256_block_x2
658+
659+ /* Prepare second block: zeros + length */
660+ /* For direct vector register manipulation, always use rev (not REVBE)
661+ * because mov v.d[n], x is a pure bit copy, independent of system endianness */
662+ rev x8, x19
663+ movi v16.2d, #0
664+ movi v17.2d, #0
665+ movi v18.2d, #0
666+ mov v19.d[0], xzr
667+ mov v19.d[1], x8
668+ mov v20.16b, v16.16b
669+ mov v21.16b, v17.16b
670+ mov v22.16b, v18.16b
671+ mov v23.16b, v19.16b
672+ rev32 v16.16b, v16.16b
673+ rev32 v17.16b, v17.16b
674+ rev32 v18.16b, v18.16b
675+ rev32 v19.16b, v19.16b
676+ rev32 v20.16b, v20.16b
677+ rev32 v21.16b, v21.16b
678+ rev32 v22.16b, v22.16b
679+ rev32 v23.16b, v23.16b
680+ b .L_process_final_2x
681+ 
682+.L_padding_aligned_2x:
683+ /* Case 3: Block-aligned message */
684+ add x14, sp, #32
685+ add x15, sp, #96
686+ movi v28.16b, #0
687+ movi v29.16b, #0
688+ movi v30.16b, #0
689+ movi v31.16b, #0
690+ st1 {v28.16b-v31.16b}, [x14]
691+ st1 {v28.16b-v31.16b}, [x15]
692+
693+ mov w13, #0x80
694+ add x14, sp, #32
695+ add x15, sp, #96
696+ strb w13, [x14]
697+ strb w13, [x15]
698+ REVBE x8, x19
699+ str x8, [x14, #56]
700+ str x8, [x15, #56]
701+
702+ ld1 {v16.16b-v19.16b}, [x14]
703+ ld1 {v20.16b-v23.16b}, [x15]
704+ rev32 v16.16b, v16.16b
705+ rev32 v20.16b, v20.16b
706+ rev32 v17.16b, v17.16b
707+ rev32 v21.16b, v21.16b
708+ rev32 v18.16b, v18.16b
709+ rev32 v22.16b, v22.16b
710+ rev32 v19.16b, v19.16b
711+ rev32 v23.16b, v23.16b
712+ 
713+.L_process_final_2x:
714+ bl sha256_block_x2
715+ 
716+.L_finalize_2x:
717+ /* Output results: state arrays (little-endian) and digests (big-endian) */
718+ st1 {v24.4s-v25.4s}, [x0]
719+ st1 {v26.4s-v27.4s}, [x1]
720+#ifndef HITLS_BIG_ENDIAN
721+ rev32 v24.16b, v24.16b
722+ rev32 v25.16b, v25.16b
723+ rev32 v26.16b, v26.16b
724+ rev32 v27.16b, v27.16b
725+#endif
726+ st1 {v24.4s-v25.4s}, [x5]
727+ st1 {v26.4s-v27.4s}, [x6]
728+ 
729+ ldp x19, x20, [sp, #16]
730+ ldp x29, x30, [sp], #160
731+AARCH64_AUTIASP
732+ ret
733+#ifndef __APPLE__
734+ .size CRYPT_SHA256x2, .-CRYPT_SHA256x2
735+#endif
736+ 
737+/* Local subroutine: 64-round SHA-256 compression for dual messages
738+ * Input: v16-v19, v20-v23 (msg schedules), v24-v27 (states)
739+ * Modifies: v0-v7, v16-v23, v28-v31, x16 */
740+sha256_block_x2:
741+ mov v4.16b, v24.16b
742+ mov v5.16b, v25.16b
743+ mov v6.16b, v26.16b
744+ mov v7.16b, v27.16b
745+ 
746+#ifdef __APPLE__
747+ adrp x16, .K256@page
748+ add x16, x16, .K256@pageoff
749+#else
750+ adrp x16, .K256
751+ add x16, x16, :lo12:.K256
752+#endif
753+
754+ /* Rounds 0-47 */
755+ ld1 {v0.4s-v3.4s}, [x16], #64
756+ ROUND_SCHED 16, 17, 18, 19, 20, 21, 22, 23, 0
757+ ROUND_SCHED 17, 18, 19, 16, 21, 22, 23, 20, 1
758+ ROUND_SCHED 18, 19, 16, 17, 22, 23, 20, 21, 2
759+ ROUND_SCHED 19, 16, 17, 18, 23, 20, 21, 22, 3
760+ ld1 {v0.4s-v3.4s}, [x16], #64
761+ ROUND_SCHED 16, 17, 18, 19, 20, 21, 22, 23, 0
762+ ROUND_SCHED 17, 18, 19, 16, 21, 22, 23, 20, 1
763+ ROUND_SCHED 18, 19, 16, 17, 22, 23, 20, 21, 2
764+ ROUND_SCHED 19, 16, 17, 18, 23, 20, 21, 22, 3
765+ ld1 {v0.4s-v3.4s}, [x16], #64
766+ ROUND_SCHED 16, 17, 18, 19, 20, 21, 22, 23, 0
767+ ROUND_SCHED 17, 18, 19, 16, 21, 22, 23, 20, 1
768+ ROUND_SCHED 18, 19, 16, 17, 22, 23, 20, 21, 2
769+ ROUND_SCHED 19, 16, 17, 18, 23, 20, 21, 22, 3
770+
771+ /* Rounds 48-63 */
772+ ld1 {v0.4s-v3.4s}, [x16], #64
773+ ROUNDS4X2_LOAD 16, 20, 0
774+ ROUNDS4X2_LOAD 17, 21, 1
775+ ROUNDS4X2_LOAD 18, 22, 2
776+ ROUNDS4X2_LOAD 19, 23, 3
777+
778+ /* Add to state */
779+ add v24.4s, v24.4s, v4.4s
780+ add v25.4s, v25.4s, v5.4s
781+ add v26.4s, v26.4s, v6.4s
782+ add v27.4s, v27.4s, v7.4s
783+ ret
784+ 
785+ 
786+/*
787+ * void CRYPT_SHA256x2_Compress(uint32_t state1[CRYPT_SHA256_STATE_SIZE], uint32_t state2[CRYPT_SHA256_STATE_SIZE],
788+ * const uint8_t *block1, const uint8_t *block2, uint32_t nblocks);
789+ *
790+ * Function: Compress multiple blocks for dual SHA-256 computation
791+ * Parameters:
792+ * x0 - state1: Initial/final hash state for message 1
793+ * x1 - state2: Initial/final hash state for message 2
794+ * x2 - block1: Message 1 data pointer
795+ * x3 - block2: Message 2 data pointer
796+ * w4 - nblocks: Number of 64-byte blocks to process
797+ *
798+ * Updates two SHA-256 states by compressing nblocks pairs of 64-byte blocks.
799+ */
800+ 
801+.balign 16
802+#ifdef __APPLE__
803+ .global _CRYPT_SHA256x2_Compress
804+ _CRYPT_SHA256x2_Compress:
805+#else
806+ .global CRYPT_SHA256x2_Compress
807+ .type CRYPT_SHA256x2_Compress, %function
808+CRYPT_SHA256x2_Compress:
809+#endif
810+AARCH64_PACIASP
811+ stp x29, x30, [sp, #-16]!
812+ add x29, sp, #0
813+ /* Check if nblocks is zero */
814+ cbz w4, .Lcompress_end_x2
815+
816+ /* Load initial states */
817+ ld1 {v24.4s-v25.4s}, [x0] // Load state1 (8 uint32_t = 2 vectors)
818+ ld1 {v26.4s-v27.4s}, [x1] // Load state2 (8 uint32_t = 2 vectors)
819+
820+ /* Loop through nblocks */
821+.Lcompress_loop_x2:
822+ /* Load 64 bytes from each block */
823+ ld1 {v16.16b-v19.16b}, [x2], #64 // Load block1 (64 bytes = 4 vectors)
824+ ld1 {v20.16b-v23.16b}, [x3], #64 // Load block2 (64 bytes = 4 vectors)
825+
826+ /* Convert to big-endian (SHA-256 requires big-endian input) */
827+ rev32 v16.16b, v16.16b
828+ rev32 v17.16b, v17.16b
829+ rev32 v18.16b, v18.16b
830+ rev32 v19.16b, v19.16b
831+ rev32 v20.16b, v20.16b
832+ rev32 v21.16b, v21.16b
833+ rev32 v22.16b, v22.16b
834+ rev32 v23.16b, v23.16b
835+
836+ /* Execute 64 rounds of compression */
837+ bl sha256_block_x2
838+
839+ /* Decrement block counter and loop if more blocks remain */
840+ subs w4, w4, #1
841+ bne .Lcompress_loop_x2
842+
843+ /* Store final states */
844+ st1 {v24.4s-v25.4s}, [x0] // Store state1
845+ st1 {v26.4s-v27.4s}, [x1] // Store state2
846+ 
847+.Lcompress_end_x2:
848+ ldp x29, x30, [sp], #16
849+AARCH64_AUTIASP
850+ ret
851+#ifndef __APPLE__
852+ .size CRYPT_SHA256x2_Compress, .-CRYPT_SHA256x2_Compress
853+#endif
854+ 
474#endif855#endif
@@ -25,6 +25,10 @@
25#include "bsl_sal.h"25#include "bsl_sal.h"
26#include "crypt_types.h"26#include "crypt_types.h"
27 27 
28+#define SHA256_INIT_ARRAY {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}
29+ 
30+static const uint32_t SHA256_INIT_STATE[8] = SHA256_INIT_ARRAY;
31+ 
28struct CryptSha256Ctx {32struct CryptSha256Ctx {
29 uint32_t h[CRYPT_SHA2_256_DIGESTSIZE / sizeof(uint32_t)]; /* 256 bits for SHA256 state */33 uint32_t h[CRYPT_SHA2_256_DIGESTSIZE / sizeof(uint32_t)]; /* 256 bits for SHA256 state */
30 uint32_t block[CRYPT_SHA2_256_BLOCKSIZE / sizeof(uint32_t)]; /* 512 bits block cache */34 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)
68 * H(0)6 = 1f83d9ab72 * H(0)6 = 1f83d9ab
69 * H(0)7 = 5be0cd1973 * H(0)7 = 5be0cd19
70 */74 */
71- ctx->h[0] = 0x6a09e667UL;75+ (void)memcpy_s(ctx->h, sizeof(SHA256_INIT_STATE), SHA256_INIT_STATE, sizeof(SHA256_INIT_STATE));
72- ctx->h[1] = 0xbb67ae85UL;
73- ctx->h[2] = 0x3c6ef372UL;
74- ctx->h[3] = 0xa54ff53aUL;
75- ctx->h[4] = 0x510e527fUL;
76- ctx->h[5] = 0x9b05688cUL;
77- ctx->h[6] = 0x1f83d9abUL;
78- ctx->h[7] = 0x5be0cd19UL;
79 ctx->outlen = CRYPT_SHA2_256_DIGESTSIZE;76 ctx->outlen = CRYPT_SHA2_256_DIGESTSIZE;
80 return CRYPT_SUCCESS;77 return CRYPT_SUCCESS;
81}78}
@@ -173,18 +170,12 @@ int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint
173 uint8_t *p = (uint8_t *)ctx->block;170 uint8_t *p = (uint8_t *)ctx->block;
174 171 
175 if (left < CRYPT_SHA2_256_BLOCKSIZE - n) {172 if (left < CRYPT_SHA2_256_BLOCKSIZE - n) {
176- if (memcpy_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, d, left) != EOK) {173+ (void)memcpy_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, d, left);
177- BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
178- return CRYPT_SECUREC_FAIL;
179- }
180 ctx->blocklen += (uint32_t)left;174 ctx->blocklen += (uint32_t)left;
181 return CRYPT_SUCCESS;175 return CRYPT_SUCCESS;
182 }176 }
183 if ((n != 0) && (left >= CRYPT_SHA2_256_BLOCKSIZE - n)) {177 if ((n != 0) && (left >= CRYPT_SHA2_256_BLOCKSIZE - n)) {
184- if (memcpy_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, d, CRYPT_SHA2_256_BLOCKSIZE - n) != EOK) {178+ (void)memcpy_s(p + n, CRYPT_SHA2_256_BLOCKSIZE - n, d, CRYPT_SHA2_256_BLOCKSIZE - n);
185- BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
186- return CRYPT_SECUREC_FAIL;
187- }
188 SHA256CompressMultiBlocks(ctx->h, p, 1);179 SHA256CompressMultiBlocks(ctx->h, p, 1);
189 n = CRYPT_SHA2_256_BLOCKSIZE - n;180 n = CRYPT_SHA2_256_BLOCKSIZE - n;
190 d += n;181 d += n;
@@ -203,10 +194,7 @@ int32_t CRYPT_SHA2_256_Update(CRYPT_SHA2_256_Ctx *ctx, const uint8_t *data, uint
203 194 
204 if (left != 0) {195 if (left != 0) {
205 ctx->blocklen = (uint32_t)left;196 ctx->blocklen = (uint32_t)left;
206- if (memcpy_s((uint8_t *)ctx->block, CRYPT_SHA2_256_BLOCKSIZE, d, left) != EOK) {197+ (void)memcpy_s((uint8_t *)ctx->block, CRYPT_SHA2_256_BLOCKSIZE, d, left);
207- BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
208- return CRYPT_SECUREC_FAIL;
209- }
210 }198 }
211 199 
212 return CRYPT_SUCCESS;200 return CRYPT_SUCCESS;
@@ -269,6 +257,228 @@ int32_t CRYPT_SHA2_256_Final(CRYPT_SHA2_256_Ctx *ctx, uint8_t *digest, uint32_t
269 return CRYPT_SUCCESS;257 return CRYPT_SUCCESS;
270}258}
271 259 
260+ 
261+#ifdef HITLS_CRYPTO_SHA2_MB
262+ 
263+CRYPT_SHA2_256_MB_Ctx *CRYPT_SHA256_MBNewCtx(uint32_t num)
264+{
265+ if (num != 2) {
266+ BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
267+ return NULL;
268+ }
269+ 
270+ CRYPT_SHA2_256_MB_Ctx *mbCtx = BSL_SAL_Calloc(1, sizeof(CRYPT_SHA2_256_MB_Ctx));
271+ if (mbCtx == NULL) {
272+ BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
273+ return NULL;
274+ }
275+ 
276+ mbCtx->ctxs = BSL_SAL_Calloc(num, sizeof(CRYPT_SHA2_256_Ctx));
277+ if (mbCtx->ctxs == NULL) {
278+ BSL_SAL_Free(mbCtx);
279+ BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
280+ return NULL;
281+ }
282+ 
283+ mbCtx->num = num;
284+ return mbCtx;
285+}
286+ 
287+void CRYPT_SHA256_MBFreeCtx(CRYPT_SHA2_256_MB_Ctx *ctx)
288+{
289+ if (ctx == NULL) {
290+ return;
291+ }
292+ 
293+ if (ctx->ctxs != NULL) {
294+ for (uint32_t i = 0; i < ctx->num; i++) {
295+ (void)CRYPT_SHA2_256_Deinit(&ctx->ctxs[i]);
296+ }
297+ BSL_SAL_Free(ctx->ctxs);
298+ }
299+ BSL_SAL_Free(ctx);
300+}
301+ 
302+int32_t CRYPT_SHA256_MBInit(CRYPT_SHA2_256_MB_Ctx *ctx)
303+{
304+#if defined(__aarch64__)
305+ // currently only support sha256x2 in aarch64
306+ if (UNLIKELY(ctx == NULL)) {
307+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
308+ return CRYPT_NULL_INPUT;
309+ }
310+ if (UNLIKELY(ctx->num != 2)) {
311+ BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
312+ return CRYPT_NOT_SUPPORT;
313+ }
314+ (void)CRYPT_SHA2_256_Init(&ctx->ctxs[0], NULL);
315+ (void)CRYPT_SHA2_256_Init(&ctx->ctxs[1], NULL);
316+ return CRYPT_SUCCESS;
317+#else
318+ (void)ctx;
319+ return CRYPT_NOT_SUPPORT;
320+#endif
321+}
322+ 
323+int32_t CRYPT_SHA256_MBUpdate(CRYPT_SHA2_256_MB_Ctx *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num)
324+{
325+#if defined(__aarch64__) && defined(HITLS_CRYPTO_SHA2_ASM)
326+ // currently only support sha256x2 in aarch64
327+ if (UNLIKELY(ctx == NULL || data == NULL || nbytes == NULL)) {
328+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
329+ return CRYPT_NULL_INPUT;
330+ }
331+ if (UNLIKELY(num != 2 || ctx->num != num || nbytes[0] != nbytes[1])) {
332+ BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
333+ return CRYPT_NOT_SUPPORT;
334+ }
335+ uint32_t commonBytes = nbytes[0];
336+ if (commonBytes == 0) {
337+ return CRYPT_SUCCESS;
338+ }
339+ CRYPT_SHA2_256_Ctx *ctx0 = &ctx->ctxs[0];
340+ CRYPT_SHA2_256_Ctx *ctx1 = &ctx->ctxs[1];
341+ 
342+ int32_t ret = UpdateParamIsValid(ctx0, data[0], commonBytes);
343+ if (ret != CRYPT_SUCCESS) {
344+ return ret;
345+ }
346+ ret = UpdateParamIsValid(ctx1, data[1], commonBytes);
347+ if (ret != CRYPT_SUCCESS) {
348+ return ret;
349+ }
350+ 
351+ uint8_t *b0 = (uint8_t *)(uintptr_t)ctx0->block;
352+ uint8_t *b1 = (uint8_t *)(uintptr_t)ctx1->block;
353+ const uint8_t *d0 = data[0];
354+ const uint8_t *d1 = data[1];
355+ uint32_t caches = ctx0->blocklen;
356+ if (caches + commonBytes >= CRYPT_SHA2_256_BLOCKSIZE) {
357+ if (caches != 0) {
358+ uint32_t cpysize = CRYPT_SHA2_256_BLOCKSIZE - caches;
359+ (void)memcpy_s(b0 + caches, cpysize, d0, cpysize);
360+ d0 += cpysize;
361+ (void)memcpy_s(b1 + caches, cpysize, d1, cpysize);
362+ d1 += cpysize;
363+ commonBytes -= cpysize;
364+ CRYPT_SHA256x2_Compress(ctx0->h, ctx1->h, b0, b1, 1);
365+ ctx0->blocklen = 0;
366+ ctx1->blocklen = 0;
367+ }
368+ uint32_t nblocks = commonBytes / CRYPT_SHA2_256_BLOCKSIZE;
369+ commonBytes &= (CRYPT_SHA2_256_BLOCKSIZE - 1);
370+ if (nblocks > 0) {
371+ CRYPT_SHA256x2_Compress(ctx0->h, ctx1->h, d0, d1, nblocks);
372+ d0 += nblocks * CRYPT_SHA2_256_BLOCKSIZE;
373+ d1 += nblocks * CRYPT_SHA2_256_BLOCKSIZE;
374+ }
375+ caches = 0;
376+ }
377+ if (commonBytes != 0) {
378+ (void)memcpy_s(b0 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, d0, commonBytes);
379+ (void)memcpy_s(b1 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, d1, commonBytes);
380+ ctx0->blocklen += commonBytes;
381+ ctx1->blocklen += commonBytes;
382+ }
383+ return CRYPT_SUCCESS;
384+#else
385+ (void)ctx;
386+ (void)data;
387+ (void)nbytes;
388+ (void)num;
389+ return CRYPT_NOT_SUPPORT;
390+#endif
391+}
392+ 
393+int32_t CRYPT_SHA256_MBFinal(CRYPT_SHA2_256_MB_Ctx *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num)
394+{
395+#if defined(__aarch64__) && defined(HITLS_CRYPTO_SHA2_ASM)
396+ // currently only support sha256x2 in aarch64
397+ if (UNLIKELY(ctx == NULL || digest == NULL || outlen == NULL)) {
398+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
399+ return CRYPT_NULL_INPUT;
400+ }
401+ if (UNLIKELY(num != 2 || ctx->num != num)) {
402+ BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
403+ return CRYPT_NOT_SUPPORT;
404+ }
405+ 
406+ if (UNLIKELY(digest[0] == NULL || digest[1] == NULL)) {
407+ BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
408+ return CRYPT_NULL_INPUT;
409+ }
410+ 
411+ CRYPT_SHA2_256_Ctx *ctx0 = &ctx->ctxs[0];
412+ CRYPT_SHA2_256_Ctx *ctx1 = &ctx->ctxs[1];
413+ int32_t ret = FinalParamIsValid(ctx0, digest[0], outlen);
414+ if (ret != CRYPT_SUCCESS) {
415+ return ret;
416+ }
417+ ret = FinalParamIsValid(ctx1, digest[1], outlen);
418+ if (ret != CRYPT_SUCCESS) {
419+ return ret;
420+ }
421+ uint8_t *b0 = (uint8_t *)(uintptr_t)ctx0->block;
422+ uint8_t *b1 = (uint8_t *)(uintptr_t)ctx1->block;
423+ uint32_t caches = ctx0->blocklen;
424+ b0[caches] = 0x80;
425+ b1[caches++] = 0x80;
426+ if (caches > (CRYPT_SHA2_256_BLOCKSIZE - 8)) {
427+ (void)memset_s(b0 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, 0, CRYPT_SHA2_256_BLOCKSIZE - caches);
428+ (void)memset_s(b1 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, 0, CRYPT_SHA2_256_BLOCKSIZE - caches);
429+ caches = 0;
430+ CRYPT_SHA256x2_Compress(ctx0->h, ctx1->h, b0, b1, 1);
431+ }
432+ (void)memset_s(b0 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, 0,
433+ CRYPT_SHA2_256_BLOCKSIZE - 8 - caches); /* 8 bytes to save bits of input */
434+ (void)memset_s(b1 + caches, CRYPT_SHA2_256_BLOCKSIZE - caches, 0,
435+ CRYPT_SHA2_256_BLOCKSIZE - 8 - caches); /* 8 bytes to save bits of input */
436+ PUT_UINT32_BE(ctx0->hNum, b0, CRYPT_SHA2_256_BLOCKSIZE - 8);
437+ PUT_UINT32_BE(ctx0->lNum, b0, CRYPT_SHA2_256_BLOCKSIZE - 4);
438+ PUT_UINT32_BE(ctx1->hNum, b1, CRYPT_SHA2_256_BLOCKSIZE - 8);
439+ PUT_UINT32_BE(ctx1->lNum, b1, CRYPT_SHA2_256_BLOCKSIZE - 4);
440+ CRYPT_SHA256x2_Compress(ctx0->h, ctx1->h, b0, b1, 1);
441+ ctx0->blocklen = 0;
442+ ctx1->blocklen = 0;
443+ for (uint32_t i = 0; i < ctx0->outlen / sizeof(uint32_t); i++) {
444+ PUT_UINT32_BE(ctx0->h[i], digest[0], sizeof(uint32_t) * i);
445+ PUT_UINT32_BE(ctx1->h[i], digest[1], sizeof(uint32_t) * i);
446+ }
447+ *outlen = ctx0->outlen;
448+ return CRYPT_SUCCESS;
449+#else
450+ (void)ctx;
451+ (void)digest;
452+ (void)outlen;
453+ (void)num;
454+ return CRYPT_NOT_SUPPORT;
455+#endif
456+}
457+ 
458+int32_t CRYPT_SHA256_MB(const uint8_t *data[], uint32_t nbytes, uint8_t *digest[], uint32_t *outlen, uint32_t num)
459+{
460+#if defined(__aarch64__) && defined(HITLS_CRYPTO_SHA2_ASM)
461+ // currently only support sha256x2 in aarch64
462+ if (num != 2) {
463+ BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
464+ return CRYPT_NOT_SUPPORT;
465+ }
466+ uint32_t state1[CRYPT_SHA256_STATE_SIZE] = SHA256_INIT_ARRAY;
467+ uint32_t state2[CRYPT_SHA256_STATE_SIZE] = SHA256_INIT_ARRAY;
468+ (void)CRYPT_SHA256x2(state1, state2, data[0], data[1], nbytes, digest[0], digest[1]);
469+ *outlen = CRYPT_SHA2_256_DIGESTSIZE;
470+ return CRYPT_SUCCESS;
471+#else
472+ (void)data;
473+ (void)nbytes;
474+ (void)digest;
475+ (void)outlen;
476+ (void)num;
477+ return CRYPT_NOT_SUPPORT;
478+#endif
479+}
480+#endif // HITLS_CRYPTO_SHA2_MB
481+ 
272#ifdef HITLS_CRYPTO_SHA224482#ifdef HITLS_CRYPTO_SHA224
273 483 
274 484 
@@ -32,15 +32,6 @@ static void Round(const uint64_t *a, uint64_t *e, uint32_t i);
32 32 
33#define ROL64(a, offset) ((((uint64_t)(a)) << (offset)) ^ (((uint64_t)(a)) >> (64 - (offset))))33#define ROL64(a, offset) ((((uint64_t)(a)) << (offset)) ^ (((uint64_t)(a)) >> (64 - (offset))))
34 34 
35-// the rotation offsets, see https://keccak.team/keccak_specs_summary.html
36-static const uint8_t g_rotationOffset[5][5] = {
37- { 0, 1, 62, 28, 27 },
38- { 36, 44, 6, 55, 20 },
39- { 3, 10, 43, 25, 39 },
40- { 41, 45, 15, 21, 8 },
41- { 18, 2, 61, 56, 14 }
42-};
43- 
44// the round constants, see https://keccak.team/keccak_specs_summary.html35// the round constants, see https://keccak.team/keccak_specs_summary.html
45static const uint64_t g_roundConstant[24] = {36static const uint64_t g_roundConstant[24] = {
46 (uint64_t)0x0000000000000001, (uint64_t)0x0000000000008082,37 (uint64_t)0x0000000000000001, (uint64_t)0x0000000000008082,
@@ -120,95 +111,102 @@ static void SHA3_Keccak(uint8_t *state)
120// see section 2.4 Algorithm 1 in https://keccak.team/files/Keccak-implementation-3.2.pdf111// see section 2.4 Algorithm 1 in https://keccak.team/files/Keccak-implementation-3.2.pdf
121static void Round(const uint64_t *a, uint64_t *e, uint32_t i)112static void Round(const uint64_t *a, uint64_t *e, uint32_t i)
122{113{
123- uint64_t c[5], d[5];114+ // Use separate variables instead of arrays for better register allocation on x86
115+ uint64_t c0, c1, c2, c3, c4;
116+ uint64_t d0, d1, d2, d3, d4;
124 117 
125 // The corresponding formula for calculating the indexes of array A and array E is (5 * x) + y,118 // The corresponding formula for calculating the indexes of array A and array E is (5 * x) + y,
126 // the value of x is in [0, 4] and the value of y is [0, 4].119 // the value of x is in [0, 4] and the value of y is [0, 4].
127 // The row coordinates of the array index correspond to y in the algorithm principle,120 // The row coordinates of the array index correspond to y in the algorithm principle,
128 // and the column coordinates correspond to x in the algorithm principle, for example, A[1, 1] = A[5 * 1 + 1] = A[6]121 // and the column coordinates correspond to x in the algorithm principle, for example, A[1, 1] = A[5 * 1 + 1] = A[6]
129 // THETA operation122 // THETA operation
130- c[0] = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20];123+ c0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20];
131- c[1] = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21];124+ c1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21];
132- c[2] = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22];125+ c2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22];
133- c[3] = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23];126+ c3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23];
134- c[4] = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24];127+ c4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24];
135 128 
136- d[0] = ROL64(c[1], 1) ^ c[4];129+ d0 = ROL64(c1, 1) ^ c4;
137- d[1] = ROL64(c[2], 1) ^ c[0];130+ d1 = ROL64(c2, 1) ^ c0;
138- d[2] = ROL64(c[3], 1) ^ c[1];131+ d2 = ROL64(c3, 1) ^ c1;
139- d[3] = ROL64(c[4], 1) ^ c[2];132+ d3 = ROL64(c4, 1) ^ c2;
140- d[4] = ROL64(c[0], 1) ^ c[3];133+ d4 = ROL64(c0, 1) ^ c3;
141 134 
142- // THETA RHP Pi operation135+ // THETA RHP Pi operation - rotation offsets inlined as constants
143- c[0] = a[0] ^ d[0];136+ // g_rotationOffset[0][0]=0, [1][1]=44, [2][2]=43, [3][3]=21, [4][4]=14
144- c[1] = ROL64(a[6] ^ d[1], g_rotationOffset[1][1]);137+ c0 = a[0] ^ d0;
145- c[2] = ROL64(a[12] ^ d[2], g_rotationOffset[2][2]);138+ c1 = ROL64(a[6] ^ d1, 44);
146- c[3] = ROL64(a[18] ^ d[3], g_rotationOffset[3][3]);139+ c2 = ROL64(a[12] ^ d2, 43);
147- c[4] = ROL64(a[24] ^ d[4], g_rotationOffset[4][4]);140+ c3 = ROL64(a[18] ^ d3, 21);
141+ c4 = ROL64(a[24] ^ d4, 14);
148 142 
149 // CHI IOTA operation,143 // CHI IOTA operation,
150- e[0] = c[0] ^ (~c[1] & c[2]) ^ g_roundConstant[i];144+ e[0] = c0 ^ (~c1 & c2) ^ g_roundConstant[i];
151 // CHI operation145 // CHI operation
152- e[1] = c[1] ^ (~c[2] & c[3]);146+ e[1] = c1 ^ (~c2 & c3);
153- e[2] = c[2] ^ (~c[3] & c[4]);147+ e[2] = c2 ^ (~c3 & c4);
154- e[3] = c[3] ^ (~c[4] & c[0]);148+ e[3] = c3 ^ (~c4 & c0);
155- e[4] = c[4] ^ (~c[0] & c[1]);149+ e[4] = c4 ^ (~c0 & c1);
156 150 
157 // THETA RHP Pi operation151 // THETA RHP Pi operation
158- c[0] = ROL64(a[3] ^ d[3], g_rotationOffset[0][3]);152+ // g_rotationOffset[0][3]=28, [1][4]=20, [2][0]=3, [3][1]=45, [4][2]=61
159- c[1] = ROL64(a[9] ^ d[4], g_rotationOffset[1][4]);153+ c0 = ROL64(a[3] ^ d3, 28);
160- c[2] = ROL64(a[10] ^ d[0], g_rotationOffset[2][0]);154+ c1 = ROL64(a[9] ^ d4, 20);
161- c[3] = ROL64(a[16] ^ d[1], g_rotationOffset[3][1]);155+ c2 = ROL64(a[10] ^ d0, 3);
162- c[4] = ROL64(a[22] ^ d[2], g_rotationOffset[4][2]);156+ c3 = ROL64(a[16] ^ d1, 45);
157+ c4 = ROL64(a[22] ^ d2, 61);
163 158 
164 // CHI operation159 // CHI operation
165- e[5] = c[0] ^ (~c[1] & c[2]);160+ e[5] = c0 ^ (~c1 & c2);
166- e[6] = c[1] ^ (~c[2] & c[3]);161+ e[6] = c1 ^ (~c2 & c3);
167- e[7] = c[2] ^ (~c[3] & c[4]);162+ e[7] = c2 ^ (~c3 & c4);
168- e[8] = c[3] ^ (~c[4] & c[0]);163+ e[8] = c3 ^ (~c4 & c0);
169- e[9] = c[4] ^ (~c[0] & c[1]);164+ e[9] = c4 ^ (~c0 & c1);
170 165 
171 // THETA RHP Pi operation166 // THETA RHP Pi operation
172- c[0] = ROL64(a[1] ^ d[1], g_rotationOffset[0][1]);167+ // g_rotationOffset[0][1]=1, [1][2]=6, [2][3]=25, [3][4]=8, [4][0]=18
173- c[1] = ROL64(a[7] ^ d[2], g_rotationOffset[1][2]);168+ c0 = ROL64(a[1] ^ d1, 1);
174- c[2] = ROL64(a[13] ^ d[3], g_rotationOffset[2][3]);169+ c1 = ROL64(a[7] ^ d2, 6);
175- c[3] = ROL64(a[19] ^ d[4], g_rotationOffset[3][4]);170+ c2 = ROL64(a[13] ^ d3, 25);
176- c[4] = ROL64(a[20] ^ d[0], g_rotationOffset[4][0]);171+ c3 = ROL64(a[19] ^ d4, 8);
172+ c4 = ROL64(a[20] ^ d0, 18);
177 173 
178 // CHI operation174 // CHI operation
179- e[10] = c[0] ^ (~c[1] & c[2]);175+ e[10] = c0 ^ (~c1 & c2);
180- e[11] = c[1] ^ (~c[2] & c[3]);176+ e[11] = c1 ^ (~c2 & c3);
181- e[12] = c[2] ^ (~c[3] & c[4]);177+ e[12] = c2 ^ (~c3 & c4);
182- e[13] = c[3] ^ (~c[4] & c[0]);178+ e[13] = c3 ^ (~c4 & c0);
183- e[14] = c[4] ^ (~c[0] & c[1]);179+ e[14] = c4 ^ (~c0 & c1);
184 180 
185 // THETA RHP Pi operation181 // THETA RHP Pi operation
186- c[0] = ROL64(a[4] ^ d[4], g_rotationOffset[0][4]);182+ // g_rotationOffset[0][4]=27, [1][0]=36, [2][1]=10, [3][2]=15, [4][3]=56
187- c[1] = ROL64(a[5] ^ d[0], g_rotationOffset[1][0]);183+ c0 = ROL64(a[4] ^ d4, 27);
188- c[2] = ROL64(a[11] ^ d[1], g_rotationOffset[2][1]);184+ c1 = ROL64(a[5] ^ d0, 36);
189- c[3] = ROL64(a[17] ^ d[2], g_rotationOffset[3][2]);185+ c2 = ROL64(a[11] ^ d1, 10);
190- c[4] = ROL64(a[23] ^ d[3], g_rotationOffset[4][3]);186+ c3 = ROL64(a[17] ^ d2, 15);
187+ c4 = ROL64(a[23] ^ d3, 56);
191 188 
192 // CHI operation189 // CHI operation
193- e[15] = c[0] ^ (~c[1] & c[2]);190+ e[15] = c0 ^ (~c1 & c2);
194- e[16] = c[1] ^ (~c[2] & c[3]);191+ e[16] = c1 ^ (~c2 & c3);
195- e[17] = c[2] ^ (~c[3] & c[4]);192+ e[17] = c2 ^ (~c3 & c4);
196- e[18] = c[3] ^ (~c[4] & c[0]);193+ e[18] = c3 ^ (~c4 & c0);
197- e[19] = c[4] ^ (~c[0] & c[1]);194+ e[19] = c4 ^ (~c0 & c1);
198 195 
199 // THETA RHP Pi operation196 // THETA RHP Pi operation
200- c[0] = ROL64(a[2] ^ d[2], g_rotationOffset[0][2]);197+ // g_rotationOffset[0][2]=62, [1][3]=55, [2][4]=39, [3][0]=41, [4][1]=2
201- c[1] = ROL64(a[8] ^ d[3], g_rotationOffset[1][3]);198+ c0 = ROL64(a[2] ^ d2, 62);
202- c[2] = ROL64(a[14] ^ d[4], g_rotationOffset[2][4]);199+ c1 = ROL64(a[8] ^ d3, 55);
203- c[3] = ROL64(a[15] ^ d[0], g_rotationOffset[3][0]);200+ c2 = ROL64(a[14] ^ d4, 39);
204- c[4] = ROL64(a[21] ^ d[1], g_rotationOffset[4][1]);201+ c3 = ROL64(a[15] ^ d0, 41);
202+ c4 = ROL64(a[21] ^ d1, 2);
205 203 
206 // CHI operation204 // CHI operation
207- e[20] = c[0] ^ (~c[1] & c[2]);205+ e[20] = c0 ^ (~c1 & c2);
208- e[21] = c[1] ^ (~c[2] & c[3]);206+ e[21] = c1 ^ (~c2 & c3);
209- e[22] = c[2] ^ (~c[3] & c[4]);207+ e[22] = c2 ^ (~c3 & c4);
210- e[23] = c[3] ^ (~c[4] & c[0]);208+ e[23] = c3 ^ (~c4 & c0);
211- e[24] = c[4] ^ (~c[0] & c[1]);209+ e[24] = c4 ^ (~c0 & c1);
212}210}
213 211 
214#ifdef __cplusplus212#ifdef __cplusplus
@@ -418,6 +418,8 @@ typedef enum {
418 BSL_CID_DECODE_UNKNOWN = 1000,418 BSL_CID_DECODE_UNKNOWN = 1000,
419 BSL_CID_NULL = 1001,419 BSL_CID_NULL = 1001,
420 420 
421+ BSL_CID_SHA256_MB = 1500, /* identifies the SHA256 algorithm (multi-buffer variant) */
422+ 
421 BSL_CID_HMAC_SHA3_224 = 2000, /* identifies hmac with SHA3_224 */423 BSL_CID_HMAC_SHA3_224 = 2000, /* identifies hmac with SHA3_224 */
422 BSL_CID_HMAC_SHA3_256 = 2001, /* identifies hmac with SHA3_256 */424 BSL_CID_HMAC_SHA3_256 = 2001, /* identifies hmac with SHA3_256 */
423 BSL_CID_HMAC_SHA3_384 = 2002, /* identifies hmac with SHA3_384 */425 BSL_CID_HMAC_SHA3_384 = 2002, /* identifies hmac with SHA3_384 */
@@ -79,6 +79,7 @@ typedef enum {
79 CRYPT_MD_SHAKE128 = BSL_CID_SHAKE128,79 CRYPT_MD_SHAKE128 = BSL_CID_SHAKE128,
80 CRYPT_MD_SHAKE256 = BSL_CID_SHAKE256,80 CRYPT_MD_SHAKE256 = BSL_CID_SHAKE256,
81 CRYPT_MD_SM3 = BSL_CID_SM3,81 CRYPT_MD_SM3 = BSL_CID_SM3,
82+ CRYPT_MD_SHA256_MB = BSL_CID_SHA256_MB, /* identifies the SHA256 hash algorithm (multi-buffer variant) */
82 CRYPT_MD_MAX = BSL_CID_UNKNOWN83 CRYPT_MD_MAX = BSL_CID_UNKNOWN
83} CRYPT_MD_AlgId;84} CRYPT_MD_AlgId;
84 85 
@@ -203,6 +203,85 @@ int32_t CRYPT_EAL_Md(CRYPT_MD_AlgId id, const uint8_t *in, uint32_t inLen, uint8
203 */203 */
204int32_t CRYPT_EAL_MdDeinit(CRYPT_EAL_MdCTX *ctx);204int32_t CRYPT_EAL_MdDeinit(CRYPT_EAL_MdCTX *ctx);
205 205 
206+ 
207+/**
208+ * @ingroup crypt_eal_md
209+ * @brief Create a MD context for multi-buffer hash computation.
210+ *
211+ * This interface creates a MB context used by the multi-buffer workflow
212+ * (Init/Update/Final) to hash multiple messages in parallel.
213+ *
214+ * Notes:
215+ * - The returned ctx must be released by calling CRYPT_EAL_MdMBFreeCtx.
216+ * - The multi-buffer capability is algorithm/feature dependent; unsupported cases
217+ * will return #CRYPT_NOT_SUPPORT in subsequent MB operations.
218+ *
219+ * @param libCtx [IN] Library context (reserved, currently unused).
220+ * @param id [IN] MD algorithm ID (e.g. #CRYPT_MD_SHA256).
221+ * @param num [IN] Number of contexts/messages.
222+ * @retval CRYPT_EAL_MdCTX pointer on success.
223+ * NULL if memory allocation fails or input is invalid.
224+ */
225+CRYPT_EAL_MdCTX *CRYPT_EAL_MdMBNewCtx(CRYPT_EAL_LibCtx *libCtx, int32_t id, uint32_t num);
226+ 
227+/**
228+ * @ingroup crypt_eal_md
229+ * @brief Release MB context created by CRYPT_EAL_MdMBNewCtx.
230+ *
231+ * @param ctx [IN] MB context pointer.
232+ */
233+void CRYPT_EAL_MdMBFreeCtx(CRYPT_EAL_MdCTX *ctx);
234+ 
235+/**
236+ * @ingroup crypt_eal_md
237+ * @brief Initialize multi-buffer MD context.
238+ *
239+ * @param ctx [IN/OUT] MB context created by CRYPT_EAL_MdMBNewCtx.
240+ * @retval #CRYPT_SUCCESS on success.
241+ * #CRYPT_NULL_INPUT if input is invalid.
242+ * #CRYPT_NOT_SUPPORT if the algorithm does not support multi-buffer mode.
243+ * For other error codes, see crypt_errno.h.
244+ */
245+int32_t CRYPT_EAL_MdMBInit(CRYPT_EAL_MdCTX *ctx);
246+ 
247+/**
248+ * @ingroup crypt_eal_md
249+ * @brief Update multi-buffer MD context with message fragments.
250+ *
251+ * Each update processes one fragment per message.
252+ * The fragment length is specified by nbytes[i] for message i. All nbytes[i] must be equal,
253+ * otherwise this interface returns #CRYPT_NOT_SUPPORT.
254+ *
255+ * @param ctx [IN/OUT] MB context.
256+ * @param data [IN] Data pointer array. data[i] is the fragment for message i.
257+ * @param nbytes [IN] Fragment length array in bytes. nbytes[i] is the fragment length for message i.
258+ * @param num [IN] Number of contexts/messages.
259+ * @retval #CRYPT_SUCCESS on success.
260+ * #CRYPT_NULL_INPUT if input is invalid.
261+ * #CRYPT_NOT_SUPPORT if the algorithm does not support multi-buffer mode or the nbytes are not equal.
262+ * For other error codes, see crypt_errno.h.
263+ */
264+int32_t CRYPT_EAL_MdMBUpdate(CRYPT_EAL_MdCTX *ctx, const uint8_t *data[], uint32_t nbytes[], uint32_t num);
265+ 
266+/**
267+ * @ingroup crypt_eal_md
268+ * @brief Finalize multi-buffer MD context and output digests.
269+ *
270+ * digest[i] is the output buffer for message i. The outlen parameter indicates the
271+ * buffer size on input and returns the actual digest length on output.
272+ *
273+ * @param ctx [IN/OUT] MB context.
274+ * @param digest [OUT] Digest buffer pointer array.
275+ * @param outlen [IN/OUT] Digest buffer length / output digest length.
276+ * @param num [IN] Number of contexts/messages.
277+ * @retval #CRYPT_SUCCESS on success.
278+ * #CRYPT_NULL_INPUT if input is invalid.
279+ * #CRYPT_NOT_SUPPORT if the algorithm does not support multi-buffer mode.
280+ * For other error codes, see crypt_errno.h.
281+ */
282+int32_t CRYPT_EAL_MdMBFinal(CRYPT_EAL_MdCTX *ctx, uint8_t *digest[], uint32_t *outlen, uint32_t num);
283+ 
284+ 
206#ifdef __cplusplus285#ifdef __cplusplus
207}286}
208#endif // __cplusplus287#endif // __cplusplus
@@ -15,7 +15,7 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
15PROJECT(openHiTLS_BENCHMARK)15PROJECT(openHiTLS_BENCHMARK)
16 16 
17set(OPENHITLS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)17set(OPENHITLS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
18-set(BENCHS sm2_bench.c)18+file(GLOB BENCHS "*_bench.c")
19 19 
20add_compile_options(-g)20add_compile_options(-g)
21add_executable(openhitls_benchmark benchmark.c ${BENCHS})21add_executable(openhitls_benchmark benchmark.c ${BENCHS})
@@ -74,6 +74,71 @@ CRYPT_EAL_PkeyCtx *TestPkeyNewCtx(
74 CRYPT_EAL_LibCtx *libCtx, int32_t id, uint32_t operType, const char *attrName, int isProvider);74 CRYPT_EAL_LibCtx *libCtx, int32_t id, uint32_t operType, const char *attrName, int isProvider);
75#endif75#endif
76 76 
77+#ifdef __aarch64__
78+#define AARCH64_PUT_CANARY() \
79+ double canaryd = 1.1; \
80+ register double d8 asm("d8"); \
81+ register double d9 asm("d9"); \
82+ register double d10 asm("d10"); \
83+ register double d11 asm("d11"); \
84+ register double d12 asm("d12"); \
85+ register double d13 asm("d13"); \
86+ register double d14 asm("d14"); \
87+ register double d15 asm("d15"); \
88+ asm volatile("fmov %d0, %d1 \n\t" : "=w"(d8) : "w"(canaryd) :); \
89+ asm volatile("fmov %d0, %d1 \n\t" : "=w"(d9) : "w"(canaryd) :); \
90+ asm volatile("fmov %d0, %d1 \n\t" : "=w"(d10) : "w"(canaryd) :); \
91+ asm volatile("fmov %d0, %d1 \n\t" : "=w"(d11) : "w"(canaryd) :); \
92+ asm volatile("fmov %d0, %d1 \n\t" : "=w"(d12) : "w"(canaryd) :); \
93+ asm volatile("fmov %d0, %d1 \n\t" : "=w"(d13) : "w"(canaryd) :); \
94+ asm volatile("fmov %d0, %d1 \n\t" : "=w"(d14) : "w"(canaryd) :); \
95+ asm volatile("fmov %d0, %d1 \n\t" : "=w"(d15) : "w"(canaryd) :); \
96+ long canaryx = 0x12345678; \
97+ register int x19 asm("x19"); \
98+ register int x20 asm("x20"); \
99+ register int x21 asm("x21"); \
100+ register int x22 asm("x22"); \
101+ register int x23 asm("x23"); \
102+ register int x24 asm("x24"); \
103+ register int x25 asm("x25"); \
104+ register int x26 asm("x26"); \
105+ register int x27 asm("x27"); \
106+ register int x28 asm("x28"); \
107+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x19) : "r"(canaryx) :); \
108+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x20) : "r"(canaryx) :); \
109+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x21) : "r"(canaryx) :); \
110+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x22) : "r"(canaryx) :); \
111+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x23) : "r"(canaryx) :); \
112+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x24) : "r"(canaryx) :); \
113+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x25) : "r"(canaryx) :); \
114+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x26) : "r"(canaryx) :); \
115+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x27) : "r"(canaryx) :); \
116+ asm volatile("mov %x0, %x1 \n\t" : "=r"(x28) : "r"(canaryx) :);
117+ 
118+#define AARCH64_CHECK_CANARY() \
119+ ASSERT_TRUE(d8 == canaryd); \
120+ ASSERT_TRUE(d9 == canaryd); \
121+ ASSERT_TRUE(d10 == canaryd); \
122+ ASSERT_TRUE(d11 == canaryd); \
123+ ASSERT_TRUE(d12 == canaryd); \
124+ ASSERT_TRUE(d13 == canaryd); \
125+ ASSERT_TRUE(d14 == canaryd); \
126+ ASSERT_TRUE(d15 == canaryd); \
127+ ASSERT_TRUE(x19 == canaryx); \
128+ ASSERT_TRUE(x20 == canaryx); \
129+ ASSERT_TRUE(x21 == canaryx); \
130+ ASSERT_TRUE(x22 == canaryx); \
131+ ASSERT_TRUE(x23 == canaryx); \
132+ ASSERT_TRUE(x24 == canaryx); \
133+ ASSERT_TRUE(x25 == canaryx); \
134+ ASSERT_TRUE(x26 == canaryx); \
135+ ASSERT_TRUE(x27 == canaryx); \
136+ ASSERT_TRUE(x28 == canaryx);
137+#else
138+#define AARCH64_PUT_CANARY()
139+#define AARCH64_CHECK_CANARY()
140+#endif
141+ 
77#ifdef __cplusplus142#ifdef __cplusplus
78}143}
79#endif144#endif
@@ -83,6 +83,16 @@ typedef struct {
83 } \83 } \
84 } while (0)84 } while (0)
85 85 
86+#define ASSERT_LT(VALUE1, VALUE2) \
87+ do { \
88+ int64_t value1__ = (int64_t)(VALUE1); \
89+ int64_t value2__ = (int64_t)(VALUE2); \
90+ if (!(value1__ < value2__)) { \
91+ RecordFailure(#VALUE1 #VALUE2, __FILE__); \
92+ Print("\nvalue is %d (0x%x).\nexpect %d (0x%x).\n", value1__, value1__, value2__, value2__); \
93+ goto EXIT; \
94+ } \
95+ } while (0)
86 96 
87#define ASSERT_EQ_LOG(LOG, VALUE1, VALUE2) \97#define ASSERT_EQ_LOG(LOG, VALUE1, VALUE2) \
88 do { \98 do { \
@@ -261,14 +261,13 @@ void SDV_BSL_TIME_SYSTIME_API_TC001(void)
261 261 
262 ret = BSL_SAL_SysTimeGet(&systime);262 ret = BSL_SAL_SysTimeGet(&systime);
263 ASSERT_TRUE(ret == BSL_SUCCESS);263 ASSERT_TRUE(ret == BSL_SUCCESS);
264-
265- int64_t timestamp = 0;
266- ret = BSL_SAL_DateToUtcTimeConvert(&systime, &timestamp);
267 264 
268 /* Get the current time. */265 /* Get the current time. */
269 int64_t curtime = time(NULL);266 int64_t curtime = time(NULL);
270 267 
271- ASSERT_TRUE(curtime >= timestamp && curtime - 5 <= timestamp);268+ int64_t timestamp = 0;
269+ ret = BSL_SAL_DateToUtcTimeConvert(&systime, &timestamp);
270+ ASSERT_LT(abs((int)(curtime - timestamp)), 5);
272EXIT:271EXIT:
273 return;272 return;
274}273}
@@ -14,12 +14,13 @@
14 */14 */
15 15 
16/* BEGIN_HEADER */16/* BEGIN_HEADER */
17- 
18#include <pthread.h>17#include <pthread.h>
19#include "eal_md_local.h"18#include "eal_md_local.h"
20#include "crypt_eal_md.h"19#include "crypt_eal_md.h"
21#include "crypt_errno.h"20#include "crypt_errno.h"
22#include "bsl_sal.h"21#include "bsl_sal.h"
22+#include "crypt_sha2.h"
23+#include "crypto_test_util.h"
23/* END_HEADER */24/* END_HEADER */
24 25 
25// 100 is greater than the digest length of all SHA algorithms.26// 100 is greater than the digest length of all SHA algorithms.
@@ -489,3 +490,586 @@ EXIT:
489 CRYPT_EAL_MdFreeCtx(ctx);490 CRYPT_EAL_MdFreeCtx(ctx);
490}491}
491/* END_CASE */492/* END_CASE */
493+ 
494+/**
495+ * @test SDV_CRYPTO_SHA256_MB_API_TC001
496+ * @title CRYPT_SHA256_MB API parameter validation test.
497+ * @precon nan
498+ * @brief
499+ * 1.Call CRYPT_SHA256_MBInit with NULL ctx, expected result 1.
500+ * 2.Call CRYPT_SHA256_MBInit with invalid num (!=2), expected result 2.
501+ * 3.Call CRYPT_SHA256_MBUpdate with NULL parameters, expected result 3.
502+ * 4.Call CRYPT_SHA256_MBFinal with NULL parameters, expected result 4.
503+ * 5.Call CRYPT_SHA256_MB with NULL parameters, expected result 5.
504+ * 6.Call CRYPT_SHA256_MB with valid parameters, expected result 6.
505+ * @expect
506+ * 1-5.Return error codes.
507+ * 6.Return CRYPT_SUCCESS.
508+ */
509+/* BEGIN_CASE */
510+void SDV_CRYPTO_SHA256_MB_API_TC001(void)
511+{
512+#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
513+ SKIP_TEST();
514+#else
515+ TestMemInit();
516+ uint8_t data1[64] = {0};
517+ uint8_t data2[64] = {0};
518+ const uint8_t *dataArr[2] = {data1, data2};
519+ uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
520+ uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
521+ uint8_t *dgstArr[2] = {dgst1, dgst2};
522+ uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
523+
524+ /* Test invalid num (only support 2) */
525+ ASSERT_TRUE(CRYPT_SHA256_MBNewCtx(1) == NULL);
526+ ASSERT_TRUE(CRYPT_SHA256_MBNewCtx(3) == NULL);
527+
528+ CRYPT_SHA2_256_MB_Ctx *mbCtx = CRYPT_SHA256_MBNewCtx(2);
529+ ASSERT_TRUE(mbCtx != NULL);
530+ 
531+ /* Test invalid init parameters */
532+ ASSERT_EQ(CRYPT_SHA256_MBInit(NULL), CRYPT_NULL_INPUT);
533+ 
534+ /* Test valid init */
535+ ASSERT_EQ(CRYPT_SHA256_MBInit(mbCtx), CRYPT_SUCCESS);
536+ 
537+ /* Test valid update */
538+ uint32_t nbytesArr[2] = {64, 64};
539+ ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, NULL, nbytesArr, 2), CRYPT_NULL_INPUT);
540+ ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr, nbytesArr, 1), CRYPT_NOT_SUPPORT);
541+ ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr, nbytesArr, 2), CRYPT_SUCCESS);
542+
543+ /* Test valid final */
544+ ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, NULL, &outlen, 2), CRYPT_NULL_INPUT);
545+ ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, dgstArr, &outlen, 1), CRYPT_NOT_SUPPORT);
546+ ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
547+
548+ /* Test one-shot API with NULL parameters */
549+ ASSERT_EQ(CRYPT_SHA256_MB(dataArr, 64, NULL, &outlen, 1), CRYPT_NOT_SUPPORT);
550+
551+ /* Test valid one-shot API */
552+ ASSERT_EQ(CRYPT_SHA256_MB(dataArr, 64, dgstArr, &outlen, 2), CRYPT_SUCCESS);
553+ 
554+EXIT:
555+ CRYPT_SHA256_MBFreeCtx(mbCtx);
556+ return;
557+#endif
558+}
559+/* END_CASE */
560+ 
561+/**
562+ * @test SDV_CRYPTO_SHA256_MB_FUNC_TC001
563+ * @title CRYPT_SHA256_MB one-shot API test with same message.
564+ * @precon nan
565+ * @brief
566+ * 1.Prepare two identical messages and digest buffers, expected result 1.
567+ * 2.Call CRYPT_SHA256_MB to compute both hashes, expected result 2.
568+ * 3.Compare results with expected digest, expected result 3.
569+ * @expect
570+ * 1.Preparation successful.
571+ * 2.Function returns CRYPT_SUCCESS.
572+ * 3.Both digests match expected value.
573+ */
574+/* BEGIN_CASE */
575+void SDV_CRYPTO_SHA256_MB_FUNC_TC001(Hex *msg, Hex *digest)
576+{
577+#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
578+ SKIP_TEST();
579+ (void)msg;
580+ (void)digest;
581+#else
582+ TestMemInit();
583+ const uint8_t *dataArr[2] = {msg->x, msg->x};
584+ uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
585+ uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
586+ uint8_t *dgstArr[2] = {dgst1, dgst2};
587+ uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
588+ 
589+ ASSERT_EQ(CRYPT_SHA256_MB(dataArr, msg->len, dgstArr, &outlen, 2), CRYPT_SUCCESS);
590+ ASSERT_EQ(outlen, CRYPT_SHA2_256_DIGESTSIZE);
591+ ASSERT_COMPARE("SHA256_MB msg1", dgst1, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
592+ ASSERT_COMPARE("SHA256_MB msg2", dgst2, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
593+ 
594+EXIT:
595+ return;
596+#endif
597+}
598+/* END_CASE */
599+ 
600+/**
601+ * @test SDV_CRYPTO_SHA256_MB_FUNC_TC002
602+ * @title CRYPT_SHA256_MB Init/Update/Final workflow test.
603+ * @precon nan
604+ * @brief
605+ * 1.Call CRYPT_SHA256_MBInit to initialize contexts, expected result 1.
606+ * 2.Call CRYPT_SHA256_MBUpdate to process equal-length messages, expected result 2.
607+ * 3.Call CRYPT_SHA256_MBFinal to get digests, expected result 3.
608+ * 4.Compare results with expected digests, expected result 4.
609+ * @expect
610+ * 1-3.All functions return CRYPT_SUCCESS.
611+ * 4.Digests match expected values.
612+ */
613+/* BEGIN_CASE */
614+void SDV_CRYPTO_SHA256_MB_FUNC_TC002(Hex *msg, Hex *digest)
615+{
616+#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
617+ SKIP_TEST();
618+ (void)msg;
619+ (void)digest;
620+#else
621+ TestMemInit();
622+ const uint8_t *dataArr[2] = {msg->x, msg->x};
623+ uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
624+ uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
625+ uint8_t *dgstArr[2] = {dgst1, dgst2};
626+ uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
627+ uint32_t nbytesArr[2] = {msg->len, msg->len};
628+ 
629+ CRYPT_SHA2_256_MB_Ctx *mbCtx = CRYPT_SHA256_MBNewCtx(2);
630+ ASSERT_TRUE(mbCtx != NULL);
631+ ASSERT_EQ(CRYPT_SHA256_MBInit(mbCtx), CRYPT_SUCCESS);
632+ ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr, nbytesArr, 2), CRYPT_SUCCESS);
633+ ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
634+ ASSERT_EQ(outlen, CRYPT_SHA2_256_DIGESTSIZE);
635+
636+ ASSERT_COMPARE("SHA256_MB msg1", dgst1, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
637+ ASSERT_COMPARE("SHA256_MB msg2", dgst2, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
638+ 
639+EXIT:
640+ CRYPT_SHA256_MBFreeCtx(mbCtx);
641+ return;
642+#endif
643+}
644+/* END_CASE */
645+ 
646+/**
647+ * @test SDV_CRYPTO_SHA256_MB_FUNC_TC004
648+ * @title CRYPT_SHA256_MB multi-block length test.
649+ * @precon nan
650+ * @brief
651+ * 1.Generate two different messages of specified length, expected result 1.
652+ * 2.Compute hashes using CRYPT_SHA256_MB, expected result 2.
653+ * 3.Verify results match sequential SHA256 computation, expected result 3.
654+ * @expect
655+ * 1.Messages generated successfully.
656+ * 2.Function returns CRYPT_SUCCESS.
657+ * 3.Results match sequential computation for both messages.
658+ */
659+/* BEGIN_CASE */
660+void SDV_CRYPTO_SHA256_MB_FUNC_TC004(int msgLen)
661+{
662+#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
663+ SKIP_TEST();
664+ (void)msgLen;
665+#else
666+ TestMemInit();
667+ uint8_t *data1 = NULL;
668+ uint8_t *data2 = NULL;
669+ CRYPT_EAL_MdCTX *seqCtx1 = NULL;
670+ CRYPT_EAL_MdCTX *seqCtx2 = NULL;
671+ 
672+ /* Allocate and fill test data */
673+ data1 = (uint8_t *)malloc(msgLen);
674+ data2 = (uint8_t *)malloc(msgLen);
675+ ASSERT_TRUE(data1 != NULL && data2 != NULL);
676+ 
677+ for (int i = 0; i < msgLen; i++) {
678+ data1[i] = (uint8_t)(i & 0xFF);
679+ data2[i] = (uint8_t)((i * 3 + 7) & 0xFF);
680+ }
681+ 
682+ /* MB computation */
683+ const uint8_t *dataArr[2] = {data1, data2};
684+ uint8_t dgst1_mb[CRYPT_SHA2_256_DIGESTSIZE];
685+ uint8_t dgst2_mb[CRYPT_SHA2_256_DIGESTSIZE];
686+ uint8_t *dgstArr[2] = {dgst1_mb, dgst2_mb};
687+ uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
688+ 
689+ AARCH64_PUT_CANARY();
690+ ASSERT_EQ(CRYPT_SHA256_MB(dataArr, msgLen, dgstArr, &outlen, 2), CRYPT_SUCCESS);
691+ AARCH64_CHECK_CANARY();
692+ /* Sequential computation for verification */
693+ seqCtx1 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
694+ seqCtx2 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
695+ ASSERT_TRUE(seqCtx1 != NULL && seqCtx2 != NULL);
696+ 
697+ uint8_t dgst1_seq[CRYPT_SHA2_256_DIGESTSIZE];
698+ uint8_t dgst2_seq[CRYPT_SHA2_256_DIGESTSIZE];
699+ uint32_t seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
700+ 
701+ ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx1), CRYPT_SUCCESS);
702+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, data1, msgLen), CRYPT_SUCCESS);
703+ ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx1, dgst1_seq, &seqOutlen), CRYPT_SUCCESS);
704+ 
705+ seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
706+ ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx2), CRYPT_SUCCESS);
707+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, data2, msgLen), CRYPT_SUCCESS);
708+ ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx2, dgst2_seq, &seqOutlen), CRYPT_SUCCESS);
709+ 
710+ /* Compare results */
711+ ASSERT_COMPARE("MB vs seq msg1", dgst1_mb, CRYPT_SHA2_256_DIGESTSIZE,
712+ dgst1_seq, CRYPT_SHA2_256_DIGESTSIZE);
713+ ASSERT_COMPARE("MB vs seq msg2", dgst2_mb, CRYPT_SHA2_256_DIGESTSIZE,
714+ dgst2_seq, CRYPT_SHA2_256_DIGESTSIZE);
715+ 
716+EXIT:
717+ free(data1);
718+ free(data2);
719+ CRYPT_EAL_MdFreeCtx(seqCtx1);
720+ CRYPT_EAL_MdFreeCtx(seqCtx2);
721+#endif
722+}
723+/* END_CASE */
724+ 
725+/**
726+ * @test SDV_CRYPTO_SHA256_MB_FUNC_TC003
727+ * @title CRYPT_SHA256_MB multi-update test.
728+ * @precon nan
729+ * @brief
730+ * 1.Initialize MB contexts, expected result 1.
731+ * 2.Call Update multiple times with different data chunks, expected result 2.
732+ * 3.Finalize and compare with sequential SHA256, expected result 3.
733+ * @expect
734+ * 1-2.All operations return CRYPT_SUCCESS.
735+ * 3.Results match sequential computation.
736+ */
737+/* BEGIN_CASE */
738+void SDV_CRYPTO_SHA256_MB_FUNC_TC003(void)
739+{
740+#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB)
741+ SKIP_TEST();
742+#else
743+ TestMemInit();
744+ CRYPT_SHA2_256_MB_Ctx *mbCtx = CRYPT_SHA256_MBNewCtx(2);
745+ ASSERT_TRUE(mbCtx != NULL);
746+
747+ /* Prepare test data: split into chunks */
748+ uint8_t chunk1_1[32], chunk1_2[32], chunk1_3[16];
749+ uint8_t chunk2_1[32], chunk2_2[32], chunk2_3[16];
750+ for (int i = 0; i < 32; i++) {
751+ chunk1_1[i] = (uint8_t)(i);
752+ chunk1_2[i] = (uint8_t)(i + 32);
753+ chunk2_1[i] = (uint8_t)(i * 2);
754+ chunk2_2[i] = (uint8_t)(i * 2 + 32);
755+ }
756+ for (int i = 0; i < 16; i++) {
757+ chunk1_3[i] = (uint8_t)(i + 64);
758+ chunk2_3[i] = (uint8_t)(i * 2 + 64);
759+ }
760+
761+ const uint8_t *dataArr1[2] = {chunk1_1, chunk2_1};
762+ const uint8_t *dataArr2[2] = {chunk1_2, chunk2_2};
763+ const uint8_t *dataArr3[2] = {chunk1_3, chunk2_3};
764+
765+ uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
766+ uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
767+ uint8_t *dgstArr[2] = {dgst1, dgst2};
768+ uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
769+ uint32_t nbytesArr1[2] = {32, 32};
770+ uint32_t nbytesArr2[2] = {32, 32};
771+ uint32_t nbytesArr3[2] = {16, 16};
772+
773+ AARCH64_PUT_CANARY();
774+ /* MB computation with multiple updates */
775+ ASSERT_EQ(CRYPT_SHA256_MBInit(mbCtx), CRYPT_SUCCESS);
776+ ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr1, nbytesArr1, 2), CRYPT_SUCCESS);
777+ ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr2, nbytesArr2, 2), CRYPT_SUCCESS);
778+ ASSERT_EQ(CRYPT_SHA256_MBUpdate(mbCtx, dataArr3, nbytesArr3, 2), CRYPT_SUCCESS);
779+ ASSERT_EQ(CRYPT_SHA256_MBFinal(mbCtx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
780+
781+ AARCH64_CHECK_CANARY();
782+ /* Sequential computation for verification */
783+ CRYPT_EAL_MdCTX *seqCtx1 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
784+ CRYPT_EAL_MdCTX *seqCtx2 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
785+ ASSERT_TRUE(seqCtx1 != NULL && seqCtx2 != NULL);
786+
787+ uint8_t seqDgst1[CRYPT_SHA2_256_DIGESTSIZE];
788+ uint8_t seqDgst2[CRYPT_SHA2_256_DIGESTSIZE];
789+ uint32_t seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
790+
791+ ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx1), CRYPT_SUCCESS);
792+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, chunk1_1, 32), CRYPT_SUCCESS);
793+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, chunk1_2, 32), CRYPT_SUCCESS);
794+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, chunk1_3, 16), CRYPT_SUCCESS);
795+ ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx1, seqDgst1, &seqOutlen), CRYPT_SUCCESS);
796+
797+ seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
798+ ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx2), CRYPT_SUCCESS);
799+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, chunk2_1, 32), CRYPT_SUCCESS);
800+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, chunk2_2, 32), CRYPT_SUCCESS);
801+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, chunk2_3, 16), CRYPT_SUCCESS);
802+ ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx2, seqDgst2, &seqOutlen), CRYPT_SUCCESS);
803+
804+ /* Compare results */
805+ ASSERT_COMPARE("MB vs seq msg1", dgst1, CRYPT_SHA2_256_DIGESTSIZE,
806+ seqDgst1, CRYPT_SHA2_256_DIGESTSIZE);
807+ ASSERT_COMPARE("MB vs seq msg2", dgst2, CRYPT_SHA2_256_DIGESTSIZE,
808+ seqDgst2, CRYPT_SHA2_256_DIGESTSIZE);
809+ 
810+EXIT:
811+ CRYPT_SHA256_MBFreeCtx(mbCtx);
812+ CRYPT_EAL_MdFreeCtx(seqCtx1);
813+ CRYPT_EAL_MdFreeCtx(seqCtx2);
814+#endif
815+}
816+/* END_CASE */
817+ 
818+/**
819+ * @test SDV_CRYPT_EAL_SHA256_MB_API_TC001
820+ * @title CRYPT_EAL_MdMB* API parameter validation test.
821+ * @precon nan
822+ * @brief
823+ * 1.Call CRYPT_EAL_MdMBNewCtx with num=0, expected result 1.
824+ * 2.Call CRYPT_EAL_MdMBNewCtx with invalid num (!=2), expected result 2.
825+ * 3.Call CRYPT_EAL_MdMBInit/Update/Final with NULL parameters, expected result 3.
826+ * @expect
827+ * 1-3.Return error codes / NULL pointers.
828+ */
829+/* BEGIN_CASE */
830+void SDV_CRYPT_EAL_SHA256_MB_API_TC001(void)
831+{
832+#if !defined(HITLS_CRYPTO_MD_MB) || !defined(HITLS_CRYPTO_SHA2_MB)
833+ SKIP_TEST();
834+#else
835+ TestMemInit();
836+ 
837+ ASSERT_TRUE(CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 0) == NULL);
838+ ASSERT_TRUE(CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 1) == NULL);
839+ ASSERT_TRUE(CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 3) == NULL);
840+ 
841+ ASSERT_EQ(CRYPT_EAL_MdMBInit(NULL), CRYPT_NULL_INPUT);
842+ uint32_t nbytesArr[2] = {1, 1};
843+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(NULL, NULL, nbytesArr, 2), CRYPT_NULL_INPUT);
844+ ASSERT_EQ(CRYPT_EAL_MdMBFinal(NULL, NULL, NULL, 2), CRYPT_NULL_INPUT);
845+EXIT:
846+ return;
847+#endif
848+}
849+/* END_CASE */
850+ 
851+/**
852+ * @test SDV_CRYPT_EAL_SHA256_MB_API_TC002
853+ * @title CRYPT_EAL_MdMB* boundary parameter combinations test.
854+ * @precon nan
855+ * @brief
856+ * 1.Create MB context and init it, expected result 1.
857+ * 2.Call CRYPT_EAL_MdMBUpdate with mismatched nbytes, expected result 2.
858+ * 3.Call CRYPT_EAL_MdMBUpdate with NULL lane data and non-zero nbytes, expected result 3.
859+ * 4.Call CRYPT_EAL_MdMBUpdate/Final with num=0, expected result 4.
860+ * 5.Call CRYPT_EAL_MdMBFinal with NULL digest lane, expected result 5.
861+ * 6.Call CRYPT_EAL_MdMBFinal with insufficient outlen, expected result 6.
862+ * @expect
863+ * 1.Return CRYPT_SUCCESS.
864+ * 2.Return CRYPT_NOT_SUPPORT.
865+ * 3.Return CRYPT_NULL_INPUT.
866+ * 4.Return CRYPT_NULL_INPUT.
867+ * 5.Return CRYPT_NULL_INPUT.
868+ * 6.Return CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH.
869+ */
870+/* BEGIN_CASE */
871+void SDV_CRYPT_EAL_SHA256_MB_API_TC002(void)
872+{
873+#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB) || !defined(HITLS_CRYPTO_MD_MB)
874+ SKIP_TEST();
875+#else
876+ TestMemInit();
877+ 
878+ CRYPT_EAL_MdCTX *ctx = CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 2);
879+ ASSERT_TRUE(ctx != NULL);
880+ ASSERT_EQ(CRYPT_EAL_MdMBInit(ctx), CRYPT_SUCCESS);
881+ 
882+ uint8_t in1[1] = {0x01};
883+ uint8_t in2[1] = {0x02};
884+ const uint8_t *dataArr[2] = {in1, in2};
885+ 
886+ uint32_t nbytesMismatch[2] = {1, 2};
887+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(ctx, dataArr, nbytesMismatch, 2), CRYPT_NOT_SUPPORT);
888+ 
889+ uint32_t nbytesValid[2] = {1, 1};
890+ const uint8_t *dataArrWithNull[2] = {NULL, in2};
891+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(ctx, dataArrWithNull, nbytesValid, 2), CRYPT_NULL_INPUT);
892+ 
893+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(ctx, dataArr, nbytesValid, 0), CRYPT_NULL_INPUT);
894+ 
895+ uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
896+ uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
897+ uint8_t *dgstArrWithNull[2] = {NULL, dgst2};
898+ uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
899+ ASSERT_EQ(CRYPT_EAL_MdMBFinal(ctx, dgstArrWithNull, &outlen, 2), CRYPT_NULL_INPUT);
900+ 
901+ uint8_t *dgstArr[2] = {dgst1, dgst2};
902+ outlen = CRYPT_SHA2_256_DIGESTSIZE - 1;
903+ ASSERT_EQ(CRYPT_EAL_MdMBFinal(ctx, dgstArr, &outlen, 2), CRYPT_SHA2_OUT_BUFF_LEN_NOT_ENOUGH);
904+ 
905+EXIT:
906+ CRYPT_EAL_MdMBFreeCtx(ctx);
907+#endif
908+}
909+/* END_CASE */
910+ 
911+/**
912+ * @test SDV_CRYPT_EAL_SHA256_MB_FUNC_TC001
913+ * @title CRYPT_EAL_MdMB* Init/Update/Final workflow test.
914+ * @precon nan
915+ * @brief
916+ * 1.Create MB contexts using CRYPT_EAL_MdMBNewCtx, expected result 1.
917+ * 2.Call CRYPT_EAL_MdMBInit/Update/Final to compute two digests, expected result 2.
918+ * 3.Compare results with expected digest, expected result 3.
919+ * @expect
920+ * 1.Creation succeeds.
921+ * 2.All functions return CRYPT_SUCCESS.
922+ * 3.Both digests match expected value.
923+ */
924+/* BEGIN_CASE */
925+void SDV_CRYPT_EAL_SHA256_MB_FUNC_TC001(Hex *msg, Hex *digest)
926+{
927+#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB) || !defined(HITLS_CRYPTO_MD_MB)
928+ SKIP_TEST();
929+ (void)msg;
930+ (void)digest;
931+#else
932+ TestMemInit();
933+ 
934+ CRYPT_EAL_MdCTX *ctx = CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 2);
935+ ASSERT_TRUE(ctx != NULL);
936+ 
937+ const uint8_t *dataArr[2] = {msg->x, msg->x};
938+ uint32_t nbytesArr[2] = {msg->len, msg->len};
939+ uint8_t dgst1[CRYPT_SHA2_256_DIGESTSIZE];
940+ uint8_t dgst2[CRYPT_SHA2_256_DIGESTSIZE];
941+ uint8_t *dgstArr[2] = {dgst1, dgst2};
942+ uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
943+ 
944+ ASSERT_EQ(CRYPT_EAL_MdMBInit(ctx), CRYPT_SUCCESS);
945+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(ctx, dataArr, nbytesArr, 2), CRYPT_SUCCESS);
946+ ASSERT_EQ(CRYPT_EAL_MdMBFinal(ctx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
947+ ASSERT_EQ(outlen, CRYPT_SHA2_256_DIGESTSIZE);
948+ 
949+ ASSERT_COMPARE("EAL_SHA256_MB msg1", dgst1, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
950+ ASSERT_COMPARE("EAL_SHA256_MB msg2", dgst2, CRYPT_SHA2_256_DIGESTSIZE, digest->x, digest->len);
951+ 
952+EXIT:
953+ CRYPT_EAL_MdMBFreeCtx(ctx);
954+#endif
955+}
956+/* END_CASE */
957+ 
958+/**
959+ * @test SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002
960+ * @title CRYPT_EAL_MdMB* length boundary and multi-update test.
961+ * @precon nan
962+ * @brief
963+ * 1.Generate two different messages of specified length, expected result 1.
964+ * 2.Compute hashes using CRYPT_EAL_MdMB workflow with multiple updates, expected result 2.
965+ * 3.Verify results match sequential SHA256 computation, expected result 3.
966+ * @expect
967+ * 1.Messages generated successfully.
968+ * 2.All MB workflow functions return CRYPT_SUCCESS.
969+ * 3.Results match sequential computation for both messages.
970+ */
971+/* BEGIN_CASE */
972+void SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002(int msgLen)
973+{
974+#if !defined(__aarch64__) || !defined(HITLS_CRYPTO_SHA2_ASM) || !defined(HITLS_CRYPTO_SHA2_MB) || !defined(HITLS_CRYPTO_MD_MB)
975+ SKIP_TEST();
976+ (void)msgLen;
977+#else
978+ TestMemInit();
979+ if (msgLen < 0) {
980+ SKIP_TEST();
981+ return;
982+ }
983+ 
984+ uint8_t *data1 = NULL;
985+ uint8_t *data2 = NULL;
986+ CRYPT_EAL_MdCTX *mbCtx = NULL;
987+ CRYPT_EAL_MdCTX *seqCtx1 = NULL;
988+ CRYPT_EAL_MdCTX *seqCtx2 = NULL;
989+ 
990+ uint32_t allocLen = (msgLen == 0) ? 1u : (uint32_t)msgLen;
991+ data1 = (uint8_t *)malloc(allocLen);
992+ data2 = (uint8_t *)malloc(allocLen);
993+ ASSERT_TRUE(data1 != NULL && data2 != NULL);
994+ 
995+ for (int i = 0; i < msgLen; i++) {
996+ data1[i] = (uint8_t)(i & 0xFF);
997+ data2[i] = (uint8_t)((i * 3 + 7) & 0xFF);
998+ }
999+ 
1000+ /* MB workflow computation */
1001+ mbCtx = CRYPT_EAL_MdMBNewCtx(NULL, CRYPT_MD_SHA256_MB, 2);
1002+ ASSERT_TRUE(mbCtx != NULL);
1003+ ASSERT_EQ(CRYPT_EAL_MdMBInit(mbCtx), CRYPT_SUCCESS);
1004+ 
1005+ /* Boundary: zero-length update should succeed */
1006+ const uint8_t *dataArr0[2] = {data1, data2};
1007+ uint32_t nbytesArr0[2] = {0, 0};
1008+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(mbCtx, dataArr0, nbytesArr0, 2), CRYPT_SUCCESS);
1009+ 
1010+ uint32_t offset = 0;
1011+ if (msgLen > 0) {
1012+ const uint8_t *dataArr1[2] = {data1, data2};
1013+ uint32_t nbytesArr1[2] = {1, 1};
1014+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(mbCtx, dataArr1, nbytesArr1, 2), CRYPT_SUCCESS);
1015+ offset = 1;
1016+ }
1017+ 
1018+ uint32_t remaining = (uint32_t)msgLen - offset;
1019+ if (remaining > 0) {
1020+ uint32_t chunkLen = (remaining > 63) ? 63 : remaining;
1021+ const uint8_t *dataArr2[2] = {data1 + offset, data2 + offset};
1022+ uint32_t nbytesArr2[2] = {chunkLen, chunkLen};
1023+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(mbCtx, dataArr2, nbytesArr2, 2), CRYPT_SUCCESS);
1024+ offset += chunkLen;
1025+ }
1026+ 
1027+ remaining = (uint32_t)msgLen - offset;
1028+ if (remaining > 0) {
1029+ const uint8_t *dataArr3[2] = {data1 + offset, data2 + offset};
1030+ uint32_t nbytesArr3[2] = {remaining, remaining};
1031+ ASSERT_EQ(CRYPT_EAL_MdMBUpdate(mbCtx, dataArr3, nbytesArr3, 2), CRYPT_SUCCESS);
1032+ }
1033+ 
1034+ uint8_t dgst1Mb[CRYPT_SHA2_256_DIGESTSIZE];
1035+ uint8_t dgst2Mb[CRYPT_SHA2_256_DIGESTSIZE];
1036+ uint8_t *dgstArr[2] = {dgst1Mb, dgst2Mb};
1037+ uint32_t outlen = CRYPT_SHA2_256_DIGESTSIZE;
1038+ 
1039+ AARCH64_PUT_CANARY();
1040+ ASSERT_EQ(CRYPT_EAL_MdMBFinal(mbCtx, dgstArr, &outlen, 2), CRYPT_SUCCESS);
1041+ AARCH64_CHECK_CANARY();
1042+ ASSERT_EQ(outlen, CRYPT_SHA2_256_DIGESTSIZE);
1043+ 
1044+ /* Sequential computation for verification */
1045+ seqCtx1 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
1046+ seqCtx2 = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
1047+ ASSERT_TRUE(seqCtx1 != NULL && seqCtx2 != NULL);
1048+ 
1049+ uint8_t dgst1Seq[CRYPT_SHA2_256_DIGESTSIZE];
1050+ uint8_t dgst2Seq[CRYPT_SHA2_256_DIGESTSIZE];
1051+ uint32_t seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
1052+ 
1053+ ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx1), CRYPT_SUCCESS);
1054+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx1, data1, (uint32_t)msgLen), CRYPT_SUCCESS);
1055+ ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx1, dgst1Seq, &seqOutlen), CRYPT_SUCCESS);
1056+ 
1057+ seqOutlen = CRYPT_SHA2_256_DIGESTSIZE;
1058+ ASSERT_EQ(CRYPT_EAL_MdInit(seqCtx2), CRYPT_SUCCESS);
1059+ ASSERT_EQ(CRYPT_EAL_MdUpdate(seqCtx2, data2, (uint32_t)msgLen), CRYPT_SUCCESS);
1060+ ASSERT_EQ(CRYPT_EAL_MdFinal(seqCtx2, dgst2Seq, &seqOutlen), CRYPT_SUCCESS);
1061+ 
1062+ ASSERT_COMPARE("EAL_MB vs seq msg1", dgst1Mb, CRYPT_SHA2_256_DIGESTSIZE,
1063+ dgst1Seq, CRYPT_SHA2_256_DIGESTSIZE);
1064+ ASSERT_COMPARE("EAL_MB vs seq msg2", dgst2Mb, CRYPT_SHA2_256_DIGESTSIZE,
1065+ dgst2Seq, CRYPT_SHA2_256_DIGESTSIZE);
1066+ 
1067+EXIT:
1068+ free(data1);
1069+ free(data2);
1070+ CRYPT_EAL_MdMBFreeCtx(mbCtx);
1071+ CRYPT_EAL_MdFreeCtx(seqCtx1);
1072+ CRYPT_EAL_MdFreeCtx(seqCtx2);
1073+#endif
1074+}
1075+/* END_CASE */
@@ -132,3 +132,78 @@ SDV_CRYPTO_SHA2_COPY_CTX_FUNC_TC001:CRYPT_MD_SHA512:"6ba004fd176791efb381b862e29
132 132 
133SDV_CRYPTO_SHA2_DEFAULT_PROVIDER_FUNC_TC001 default provider133SDV_CRYPTO_SHA2_DEFAULT_PROVIDER_FUNC_TC001 default provider
134SDV_CRYPTO_SHA2_DEFAULT_PROVIDER_FUNC_TC001:CRYPT_MD_SHA224:"a4bc10b1a62c96d459fbaf3a5aa3face73":"d7e6634723ac25cb1879bdb1508da05313530419013fe255967a39e1"134SDV_CRYPTO_SHA2_DEFAULT_PROVIDER_FUNC_TC001:CRYPT_MD_SHA224:"a4bc10b1a62c96d459fbaf3a5aa3face73":"d7e6634723ac25cb1879bdb1508da05313530419013fe255967a39e1"
135+ 
136+CRYPT_SHA256_MB API parameter validation
137+SDV_CRYPTO_SHA256_MB_API_TC001:
138+ 
139+CRYPT_SHA256_MB one-shot API test with short messages
140+SDV_CRYPTO_SHA256_MB_FUNC_TC001:"d3":"28969cdfa74a12c82f3bad960b0b000aca2ac329deea5c2328ebc6f2ba9802c1"
141+
142+CRYPT_SHA256_MB one-shot API test with empty messages
143+SDV_CRYPTO_SHA256_MB_FUNC_TC001:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
144+ 
145+CRYPT_SHA256_MB single block (64 bytes)
146+SDV_CRYPTO_SHA256_MB_FUNC_TC004:64
147+ 
148+CRYPT_SHA256_MB block boundary (56 bytes, need padding block)
149+SDV_CRYPTO_SHA256_MB_FUNC_TC004:56
150+ 
151+CRYPT_SHA256_MB two blocks (120 bytes = 64+56)
152+SDV_CRYPTO_SHA256_MB_FUNC_TC004:120
153+ 
154+CRYPT_SHA256_MB two blocks aligned (128 bytes = 64*2)
155+SDV_CRYPTO_SHA256_MB_FUNC_TC004:128
156+ 
157+CRYPT_SHA256_MB three blocks (192 bytes = 64*3)
158+SDV_CRYPTO_SHA256_MB_FUNC_TC004:192
159+ 
160+CRYPT_SHA256_MB large message (1024 bytes)
161+SDV_CRYPTO_SHA256_MB_FUNC_TC004:1024
162+ 
163+CRYPT_SHA256_MB Init/Update/Final test
164+SDV_CRYPTO_SHA256_MB_FUNC_TC002:"3d83df37172c81afd0de115139fbf4390c22e098c5af4c5ab4852406510bc0e6cf741769f44430c5270fdae0cb849d71cbab":"99dc772e91ea02d9e421d552d61901016b9fd4ad2df4a8212c1ec5ba13893ab2"
165+ 
166+CRYPT_SHA256_MB multi-update test
167+SDV_CRYPTO_SHA256_MB_FUNC_TC003:
168+ 
169+CRYPT_EAL_MdMB API parameter validation
170+SDV_CRYPT_EAL_SHA256_MB_API_TC001:
171+ 
172+CRYPT_EAL_MdMB boundary parameter combinations
173+SDV_CRYPT_EAL_SHA256_MB_API_TC002:
174+ 
175+CRYPT_EAL_MdMB Init/Update/Final test
176+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC001:"d3":"28969cdfa74a12c82f3bad960b0b000aca2ac329deea5c2328ebc6f2ba9802c1"
177+ 
178+CRYPT_EAL_MdMB length boundary (empty message)
179+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:0
180+ 
181+CRYPT_EAL_MdMB length boundary (1 byte)
182+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:1
183+ 
184+CRYPT_EAL_MdMB block boundary (55 bytes)
185+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:55
186+ 
187+CRYPT_EAL_MdMB block boundary (56 bytes, need padding block)
188+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:56
189+ 
190+CRYPT_EAL_MdMB block boundary (57 bytes)
191+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:57
192+ 
193+CRYPT_EAL_MdMB single block (64 bytes)
194+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:64
195+ 
196+CRYPT_EAL_MdMB one byte over block (65 bytes)
197+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:65
198+ 
199+CRYPT_EAL_MdMB two blocks (120 bytes = 64+56)
200+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:120
201+ 
202+CRYPT_EAL_MdMB two blocks aligned (128 bytes = 64*2)
203+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:128
204+ 
205+CRYPT_EAL_MdMB three blocks (192 bytes = 64*3)
206+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:192
207+ 
208+CRYPT_EAL_MdMB large message (1024 bytes)
209+SDV_CRYPT_EAL_SHA256_MB_FUNC_TC002:1024