已合并
add benchmark frame #187
dumb创建于 2025年3月17日
add benchmark frame #187
已合并
dumb创建于 2025年3月17日
5 个文件变更+541-0
@@ -0,0 +1,30 @@
1+# This file is part of the openHiTLS project.
2+#
3+# openHiTLS is licensed under the Mulan PSL v2.
4+# You can use this software according to the terms and conditions of the Mulan PSL v2.
5+# You may obtain a copy of Mulan PSL v2 at:
6+#
7+# http://license.coscl.org.cn/MulanPSL2
8+#
9+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10+# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11+# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12+# See the Mulan PSL v2 for more details.
13+cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
14+ 
15+PROJECT(openHiTLS_BENCHMARK)
16+ 
17+set(OPENHITLS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
18+set(BENCHS sm2_bench.c)
19+ 
20+add_compile_options(-g)
21+add_executable(openhitls_benchmark benchmark.c ${BENCHS})
22+ 
23+ 
24+# target_link_options(openhitls_benchmark PRIVATE -fsanitize=address)
25+target_link_directories(openhitls_benchmark PRIVATE ${OPENHITLS_ROOT}/build
26+ ${OPENHITLS_ROOT}/platform/Secure_C/lib)
27+target_include_directories(openhitls_benchmark PRIVATE ${OPENHITLS_ROOT}/include/crypto
28+ ${OPENHITLS_ROOT}/include/bsl
29+ ${OPENHITLS_ROOT}/platform/Secure_C/include)
30+target_link_libraries(openhitls_benchmark PRIVATE hitls_crypto hitls_bsl boundscheck)
@@ -0,0 +1,22 @@
1+## openhitls benchmark
2+ 
3+Before running benchmark, openhitls should be built firstly.
4+ 
5+###
6+ 
7+### run like
8+```
9+openhitls_benchmark // run all benchmark testcases
10+ 
11+openhtils_benchmark -a sm2* // run all sm2 benchmark testcases
12+ 
13+openhitls_benchmark -a sm2-KeyGen // just run sm2 KeyGen
14+ 
15+openhitls_benchmark -a *KeyGen // run all KeyGen benchmark testcases
16+ 
17+openhitls_benchmark -a sm2-KeyGen -t 10000 // run 'sm2 KeyGen' 10000 times
18+ 
19+openhitls_benchmark -t 10000 // run every benchmark testcase 10000 times
20+ 
21+openhitls_benchmark -s 5 // run every benchmark testcase 5 seconds
22+```
@@ -0,0 +1,180 @@
1+/*
2+ * This file is part of the openHiTLS project.
3+ *
4+ * openHiTLS is licensed under the Mulan PSL v2.
5+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
6+ * You may obtain a copy of Mulan PSL v2 at:
7+ *
8+ * http://license.coscl.org.cn/MulanPSL2
9+ *
10+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13+ * See the Mulan PSL v2 for more details.
14+ */
15+ 
16+#include <stdio.h>
17+#include <stdlib.h>
18+#include <getopt.h>
19+#include <string.h>
20+#include "crypt_errno.h"
21+#include "crypt_algid.h"
22+#include "crypt_eal_rand.h"
23+#include "benchmark.h"
24+ 
25+extern BenchCtx Sm2BenchCtx;
26+ 
27+BenchCtx *g_benchs[] = {
28+ &Sm2BenchCtx,
29+};
30+ 
31+// 定义命令行选项结构
32+typedef struct {
33+ char *algorithm; // -a 选项指定的算法
34+ uint32_t times; // -t 选项指定的运行次数
35+ uint32_t seconds; // -s 选项指定的运行时间
36+ uint32_t len;
37+} BenchOptions;
38+ 
39+static void PrintUsage(void)
40+{
41+ printf("Usage: openhitls_benchmark [options]\n");
42+ printf("Options:\n");
43+ printf(" -a <algorithm> Specify algorithm to benchmark (e.g., sm2*, sm2-KeyGen, *KeyGen)\n");
44+ printf(" -t <times> Number of times to run each benchmark\n");
45+ printf(" -s <seconds> Number of seconds to run each benchmark\n");
46+ printf(" -l <len> Length of the payload to benchmark\n");
47+ printf(" -h Show this help message\n");
48+}
49+ 
50+static void ParseOptions(int argc, char **argv, BenchOptions *opts)
51+{
52+ int c;
53+ 
54+ while ((c = getopt(argc, argv, "a:t:s:h")) != -1) {
55+ switch (c) {
56+ case 'a':
57+ opts->algorithm = optarg;
58+ break;
59+ case 't':
60+ opts->times = (uint32_t)atoi(optarg);
61+ break;
62+ case 's':
63+ opts->seconds = (uint32_t)atoi(optarg);
64+ break;
65+ case 'l':
66+ opts->len = (uint32_t)atoi(optarg);
67+ break;
68+ case 'h':
69+ PrintUsage();
70+ exit(0);
71+ default:
72+ PrintUsage();
73+ exit(1);
74+ }
75+ }
76+}
77+ 
78+static bool MatchAlgorithm(const char *pattern, const char *name)
79+{
80+ if (pattern == NULL) {
81+ return true;
82+ }
83+ 
84+ size_t patternLen = strlen(pattern);
85+ size_t nameLen = strlen(name);
86+ 
87+ // process wildcard "*"
88+ if (pattern[0] == '*') {
89+ return (nameLen >= patternLen - 1) &&
90+ (strcmp(name + nameLen - (patternLen - 1), pattern + 1) == 0);
91+ }
92+
93+ // process suffix wildcard (xxx*)
94+ if (pattern[patternLen - 1] == '*') {
95+ return strncmp(name, pattern, patternLen - 1) == 0;
96+ }
97+ 
98+ return strcmp(pattern, name) == 0;
99+}
100+ 
101+static void FilterBenchs(BenchOptions *opts, BenchCtx *benchs[], uint32_t *num)
102+{
103+ for (int i = 0; i < sizeof(g_benchs) / sizeof(g_benchs[0]); i++) {
104+ if (!MatchAlgorithm(opts->algorithm, g_benchs[i]->name)) {
105+ continue;
106+ }
107+ benchs[*num] = g_benchs[i];
108+ benchs[*num]->times = opts->times;
109+ benchs[*num]->seconds = opts->seconds;
110+ benchs[*num]->len = opts->len;
111+ (*num)++;
112+ }
113+}
114+ 
115+static int32_t InstantOperation(const Operation *op, void *ctx, BenchCtx *bench)
116+{
117+ if (op->id & KEY_GEN_ID) {
118+ return ((KeyGen)op->oper)(ctx, bench);
119+ }
120+ if (op->id & KEY_DERIVE_ID) {
121+ return ((KeyDerive)op->oper)(ctx, bench);
122+ }
123+ if (op->id & ENC_ID) {
124+ return ((Enc)op->oper)(ctx, bench);
125+ }
126+ if (op->id & DEC_ID) {
127+ return ((Dec)op->oper)(ctx, bench);
128+ }
129+ if (op->id & SIGN_ID) {
130+ return ((Sign)op->oper)(ctx, bench);
131+ }
132+ if (op->id & VERIFY_ID) {
133+ return ((Verify)op->oper)(ctx, bench);
134+ }
135+}
136+ 
137+int main(int argc, char **argv)
138+{
139+ int32_t ret;
140+ BenchOptions opts;
141+ memset(&opts, 0, sizeof(BenchOptions));
142+ 
143+ // default options
144+ opts.times = 10000;
145+ opts.seconds = 3;
146+ opts.len = 1024;
147+ ParseOptions(argc, argv, &opts);
148+
149+ if (CRYPT_EAL_RandInit(CRYPT_RAND_SHA256, NULL, NULL, NULL, 0) != CRYPT_SUCCESS) {
150+ printf("Failed to initialize random number generator\n");
151+ return -1;
152+ }
153+ 
154+ BenchCtx *benchs[sizeof(g_benchs) / sizeof(g_benchs[0])] = {0};
155+ uint32_t num = 0;
156+ FilterBenchs(&opts, benchs, &num);
157+ 
158+ if (num > 0) {
159+ printf("%-25s, %15s, %20s, %20s\n", "algorithm operation", "time elapsed(s)", "run times", "ops");
160+ }
161+ 
162+ for (int i = 0; i < num; i++) {
163+ const CtxOps *ctxOps = benchs[i]->ctxOps;
164+ void *ctx = NULL;
165+ 
166+ BENCH_SETUP(ctx, ctxOps);
167+ 
168+ for (int j = 0; j < benchs[i]->filteredOpsNum; j++) {
169+ const Operation *op = &ctxOps->ops[j];
170+ ret = InstantOperation(op, ctx, benchs[i]);
171+ if (ret != CRYPT_SUCCESS) {
172+ printf("Failed to %s, ret = %08x\n", op->name, ret);
173+ }
174+ }
175+ 
176+ BENCH_TEARDOWN(ctx, ctxOps);
177+ }
178+ 
179+ return 0;
180+}
@@ -0,0 +1,153 @@
1+/*
2+ * This file is part of the openHiTLS project.
3+ *
4+ * openHiTLS is licensed under the Mulan PSL v2.
5+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
6+ * You may obtain a copy of Mulan PSL v2 at:
7+ *
8+ * http://license.coscl.org.cn/MulanPSL2
9+ *
10+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13+ * See the Mulan PSL v2 for more details.
14+ */
15+ 
16+#ifndef BENCHMARK_H
17+#define BENCHMARK_H
18+ 
19+#include <stdint.h>
20+#include <string.h>
21+#include <stdio.h>
22+#include <time.h>
23+#include <sys/time.h>
24+ 
25+#define BENCH_TIMES(func, rc, ok, times, header) \
26+ { \
27+ struct timespec start, end; \
28+ clock_gettime(CLOCK_REALTIME, &start); \
29+ for (int i = 0; i < times; i++) { \
30+ rc = func; \
31+ if (rc != ok) { \
32+ printf("Error: %s, ret = %08x\n", #func, rc); \
33+ break; \
34+ } \
35+ } \
36+ clock_gettime(CLOCK_REALTIME, &end); \
37+ uint64_t elapsedTime = (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec); \
38+ printf("%-25s, %15ld, %20d, %20.2f\n", header, elapsedTime / 1000000000, times, \
39+ ((double)times * 1000000000) / elapsedTime); \
40+ }
41+ 
42+#define BENCH_SECONDS(func, rc, ok, secs, header) \
43+ { \
44+ struct timespec start, end; \
45+ uint64_t totalTime = secs * 1000000000; \
46+ uint64_t elapsedTime = 0; \
47+ uint64_t cnt = 0; \
48+ while (elapsedTime < totalTime) { \
49+ clock_gettime(CLOCK_REALTIME, &start); \
50+ rc = func; \
51+ if (rc != ok) { \
52+ printf("Error: %s, ret = %08x\n", #func, rc); \
53+ break; \
54+ } \
55+ clock_gettime(CLOCK_REALTIME, &end); \
56+ elapsedTime += (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec); \
57+ cnt++; \
58+ } \
59+ printf("%-25s, %15ld, %20d, %20.2f\n", header, elapsedTime / 1000000000, cnt, \
60+ ((double)times * 1000000000) / elapsedTime); \
61+ }
62+ 
63+#define BENCH_SETUP(ctx, ops) \
64+ do \
65+ { \
66+ int32_t ret; \
67+ ret = ops->newCtx(&ctx); \
68+ if (ret != CRYPT_SUCCESS) { \
69+ printf("Failed to create context\n"); \
70+ return ret; \
71+ } \
72+ } \
73+ while (0)
74+ 
75+#define BENCH_TEARDOWN(ctx, ops) \
76+ do { \
77+ ops->freeCtx(ctx); \
78+ } while (0)
79+ 
80+static inline void Hex2Bin(const char *hex, uint8_t *bin, uint32_t *len)
81+{
82+ *len = strlen(hex) / 2;
83+ for (uint32_t i = 0; i < *len; i++) {
84+ sscanf(hex + i * 2, "%2hhx", &bin[i]);
85+ }
86+}
87+ 
88+typedef struct BenchCtx_ BenchCtx;
89+// every benchmark testcase should define "NewCtx" and "FreeCtx"
90+typedef int32_t (*NewCtx)(void **ctx);
91+typedef void (*FreeCtx)(void *ctx);
92+typedef int32_t (*KeyGen)(void *ctx, BenchCtx *bench);
93+typedef int32_t (*KeyDerive)(void *ctx, BenchCtx *bench);
94+typedef int32_t (*Enc)(void *ctx, BenchCtx *bench);
95+typedef int32_t (*Dec)(void *ctx, BenchCtx *bench);
96+typedef int32_t (*Sign)(void *ctx, BenchCtx *bench);
97+typedef int32_t (*Verify)(void *ctx, BenchCtx *bench);
98+ 
99+typedef struct {
100+ uint32_t id;
101+ const char *name;
102+ void *oper;
103+} Operation;
104+ 
105+typedef struct {
106+ NewCtx newCtx;
107+ FreeCtx freeCtx;
108+ Operation ops[];
109+} CtxOps;
110+ 
111+#define DEFINE_OPER(id, oper) {id, #oper, oper}
112+#define DEFINE_OPS(alg) \
113+ static const CtxOps alg##CtxOps = { \
114+ .newCtx = alg##NewCtx, \
115+ .freeCtx = alg##FreeCtx, \
116+ .ops = {\
117+ DEFINE_OPER(1, alg##KeyGen), \
118+ DEFINE_OPER(2, alg##KeyDerive), \
119+ DEFINE_OPER(4, alg##Enc), \
120+ DEFINE_OPER(8, alg##Dec), \
121+ DEFINE_OPER(16, alg##Sign), \
122+ DEFINE_OPER(32, alg##Verify), \
123+ }, \
124+ }
125+ 
126+#define KEY_GEN_ID 1U
127+#define KEY_DERIVE_ID 2U
128+#define ENC_ID 4U
129+#define DEC_ID 8U
130+#define SIGN_ID 16U
131+#define VERIFY_ID 32U
132+ 
133+typedef struct BenchCtx_ {
134+ const char *name;
135+ const char *desc;
136+ const CtxOps *ctxOps;
137+ int32_t filteredOpsNum;
138+ int32_t times;
139+ int32_t seconds;
140+ int32_t len;
141+} BenchCtx;
142+ 
143+#define DEFINE_BENCH_CTX(alg) \
144+ BenchCtx alg##BenchCtx = { \
145+ .name = #alg, \
146+ .desc = #alg " benchmark", \
147+ .ctxOps = &alg##CtxOps, \
148+ .filteredOpsNum = sizeof(alg##CtxOps.ops) / sizeof(alg##CtxOps.ops[0]), \
149+ .times = 10000, \
150+ .seconds = -1, \
151+ }
152+ 
153+#endif /* BENCHMARK_H */
@@ -0,0 +1,156 @@
1+/*
2+ * This file is part of the openHiTLS project.
3+ *
4+ * openHiTLS is licensed under the Mulan PSL v2.
5+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
6+ * You may obtain a copy of Mulan PSL v2 at:
7+ *
8+ * http://license.coscl.org.cn/MulanPSL2
9+ *
10+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13+ * See the Mulan PSL v2 for more details.
14+ */
15+ 
16+#include <stddef.h>
17+#include <string.h>
18+#include "crypt_algid.h"
19+#include "crypt_errno.h"
20+#include "crypt_eal_pkey.h"
21+#include "benchmark.h"
22+ 
23+static int32_t Sm2NewCtx(void **ctx)
24+{
25+ CRYPT_EAL_PkeyCtx *pkeyCtx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_SM2);
26+ if (pkeyCtx == NULL) {
27+ printf("Failed to create pkey context\n");
28+ return CRYPT_MEM_ALLOC_FAIL;
29+ }
30+ *ctx = pkeyCtx;
31+ return CRYPT_SUCCESS;
32+}
33+ 
34+static void Sm2FreeCtx(void *ctx)
35+{
36+ CRYPT_EAL_PkeyFreeCtx(ctx);
37+}
38+ 
39+static int32_t Sm2KeyGen(void *ctx, BenchCtx *bench)
40+{
41+ int rc = CRYPT_SUCCESS;
42+ BENCH_TIMES(rc = CRYPT_EAL_PkeyGen(ctx), rc, CRYPT_SUCCESS, bench->times, "sm2 keyGen");
43+ return rc;
44+}
45+ 
46+static int32_t Sm2KeyDeriveInner(void *ctx, void *peerCtx)
47+{
48+ int rc = CRYPT_SUCCESS;
49+ uint8_t localR[128] = {0};
50+ rc = CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_SM2_GENE_R, localR, sizeof(localR));
51+ if (rc != CRYPT_SUCCESS) {
52+ printf("Failed to generate R\n");
53+ return rc;
54+ }
55+ uint8_t shareKey[64] = {0};
56+ uint32_t shareKeyLen = sizeof(shareKey);
57+ rc = CRYPT_EAL_PkeyComputeShareKey(ctx, peerCtx, shareKey, &shareKeyLen);
58+ if (rc != CRYPT_SUCCESS) {
59+ printf("Failed to compute share key\n");
60+ return rc;
61+ }
62+ return CRYPT_SUCCESS;
63+}
64+ 
65+static int32_t Sm2KeyDerive(void *ctx, BenchCtx *bench)
66+{
67+ int rc = CRYPT_SUCCESS;
68+ CRYPT_EAL_PkeyCtx *peerCtx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_SM2);
69+ if (peerCtx == NULL || CRYPT_EAL_PkeyGen(peerCtx) != CRYPT_SUCCESS) {
70+ printf("Failed to create pkey context\n");
71+ CRYPT_EAL_PkeyFreeCtx(peerCtx);
72+ rc = CRYPT_MEM_ALLOC_FAIL;
73+ goto ERR_OUT;
74+ }
75+ 
76+ char *peerRHex =
77+ "04acc27688a6f7b706098bc91ff3ad1bff7dc2802cdb14ccccdb0a90471f9bd7072fedac0494b2ffc4d6853876c79b8f301c6573ad0aa50f39fc87181e1a1b46fe";
78+ uint8_t peerR[128] = {0};
79+ uint32_t peerRLen = sizeof(peerR);
80+ Hex2Bin(peerRHex, peerR, &peerRLen);
81+ rc = CRYPT_EAL_PkeyCtrl(peerCtx, CRYPT_CTRL_SET_SM2_R, peerR, peerRLen);
82+ if (rc != CRYPT_SUCCESS) {
83+ printf("Failed to set R\n");
84+ goto ERR_OUT;
85+ }
86+ BENCH_TIMES(Sm2KeyDeriveInner(ctx, peerCtx), rc, CRYPT_SUCCESS, bench->times, "sm2 keyDerive");
87+ERR_OUT:
88+ CRYPT_EAL_PkeyFreeCtx(peerCtx);
89+ return rc;
90+}
91+ 
92+static int32_t Sm2EncInner(void *ctx)
93+{
94+ uint8_t plainText[32];
95+ uint8_t cipherText[256]; // > 32 + 97 + 12
96+ uint32_t outLen = sizeof(cipherText);
97+ return CRYPT_EAL_PkeyEncrypt(ctx, plainText, sizeof(plainText), cipherText, &outLen);
98+}
99+ 
100+static int32_t Sm2Enc(void *ctx, BenchCtx *bench)
101+{
102+ int rc = CRYPT_SUCCESS;
103+ BENCH_TIMES(Sm2EncInner(ctx), rc, CRYPT_SUCCESS, bench->times, "sm2 enc");
104+ return rc;
105+}
106+ 
107+static int32_t Sm2Dec(void *ctx, BenchCtx *bench)
108+{
109+ int rc;
110+ uint8_t plainText[32];
111+ uint32_t plainTextLen = sizeof(plainText);
112+ uint8_t cipherText[256]; // > 32 + 97 + 12
113+ uint32_t outLen = sizeof(cipherText);
114+ rc = CRYPT_EAL_PkeyEncrypt(ctx, plainText, sizeof(plainText), cipherText, &outLen);
115+ if (rc != CRYPT_SUCCESS) {
116+ printf("Failed to encrypt\n");
117+ return rc;
118+ }
119+ BENCH_TIMES(CRYPT_EAL_PkeyDecrypt(ctx, cipherText, outLen, plainText, &plainTextLen), rc, CRYPT_SUCCESS, bench->times,
120+ "sm2 dec");
121+ return rc;
122+}
123+ 
124+static int32_t Sm2SignInner(void *ctx)
125+{
126+ uint8_t plainText[32];
127+ uint8_t signature[256];
128+ uint32_t signatureLen = sizeof(signature);
129+ return CRYPT_EAL_PkeySign(ctx, CRYPT_MD_SM3, plainText, sizeof(plainText), signature, &signatureLen);
130+}
131+ 
132+static int32_t Sm2Sign(void *ctx, BenchCtx *bench)
133+{
134+ int rc;
135+ BENCH_TIMES(Sm2SignInner(ctx), rc, CRYPT_SUCCESS, bench->times, "sm2 sign");
136+ return rc;
137+}
138+ 
139+static int32_t Sm2Verify(void *ctx, BenchCtx *bench)
140+{
141+ int rc;
142+ uint8_t plainText[32];
143+ uint8_t signature[256];
144+ uint32_t signatureLen = sizeof(signature);
145+ rc = CRYPT_EAL_PkeySign(ctx, CRYPT_MD_SM3, plainText, sizeof(plainText), signature, &signatureLen);
146+ if (rc != CRYPT_SUCCESS) {
147+ printf("Failed to sign\n");
148+ return rc;
149+ }
150+ BENCH_TIMES(CRYPT_EAL_PkeyVerify(ctx, CRYPT_MD_SM3, plainText, sizeof(plainText), signature, signatureLen), rc,
151+ CRYPT_SUCCESS, bench->times, "sm2 verify");
152+ return rc;
153+}
154+ 
155+DEFINE_OPS(Sm2);
156+DEFINE_BENCH_CTX(Sm2);