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
PrintUsage(void)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
ParseOptions(int argc,char ** argv,BenchOptions * opts)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
MatchAlgorithm(const char * pattern,const char * name)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
FilterBenchs(BenchOptions * opts,BenchCtx * benchs[],uint32_t * num)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
InstantOperation(const Operation * op,void * ctx,BenchCtx * bench)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
main(int argc,char ** argv)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 }