• 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 #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 
Hex2Bin(const char * hex,uint8_t * bin,uint32_t * len)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 */