• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }