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 "hitls_build.h"
17 #ifdef HITLS_CRYPTO_BN
18
19 #include <stdint.h>
20 #include <string.h>
21 #include "securec.h"
22 #include "bsl_err_internal.h"
23 #include "bsl_sal.h"
24 #include "crypt_errno.h"
25 #include "bn_optimizer.h"
26
BN_OptimizerCreate(void)27 BN_Optimizer *BN_OptimizerCreate(void)
28 {
29 BN_Optimizer *opt = BSL_SAL_Calloc(1u, sizeof(BN_Optimizer));
30 if (opt == NULL) {
31 return NULL;
32 }
33 opt->curChunk = BSL_SAL_Calloc(1u, sizeof(Chunk));
34 if (opt->curChunk == NULL) {
35 BSL_SAL_FREE(opt);
36 return NULL;
37 }
38 return opt;
39 }
40
BN_OptimizerSetLibCtx(void * libCtx,BN_Optimizer * opt)41 void BN_OptimizerSetLibCtx(void *libCtx, BN_Optimizer *opt)
42 {
43 opt->libCtx = libCtx;
44 }
45
BN_OptimizerGetLibCtx(BN_Optimizer * opt)46 void *BN_OptimizerGetLibCtx(BN_Optimizer *opt)
47 {
48 return opt->libCtx;
49 }
50
BN_OptimizerDestroy(BN_Optimizer * opt)51 void BN_OptimizerDestroy(BN_Optimizer *opt)
52 {
53 if (opt == NULL) {
54 return;
55 }
56 Chunk *curChunk = opt->curChunk;
57 Chunk *nextChunk = curChunk->next;
58 Chunk *prevChunk = curChunk->prev;
59
60 while (nextChunk != NULL) {
61 for (uint32_t i = 0; i < HITLS_CRYPT_OPTIMIZER_BN_NUM; i++) {
62 BSL_SAL_CleanseData((void *)(nextChunk->bigNums[i].data), nextChunk->bigNums[i].size * sizeof(BN_UINT));
63 BSL_SAL_FREE(nextChunk->bigNums[i].data);
64 }
65 Chunk *tmp = nextChunk->next;
66 BSL_SAL_Free(nextChunk);
67 nextChunk = tmp;
68 }
69
70 while (prevChunk != NULL) {
71 for (uint32_t i = 0; i < HITLS_CRYPT_OPTIMIZER_BN_NUM; i++) {
72 BSL_SAL_CleanseData((void *)(prevChunk->bigNums[i].data), prevChunk->bigNums[i].size * sizeof(BN_UINT));
73 BSL_SAL_FREE(prevChunk->bigNums[i].data);
74 }
75 Chunk *tmp = prevChunk->prev;
76 BSL_SAL_Free(prevChunk);
77 prevChunk = tmp;
78 }
79 // curChunk != NULL
80 for (uint32_t i = 0; i < HITLS_CRYPT_OPTIMIZER_BN_NUM; i++) {
81 BSL_SAL_CleanseData((void *)(curChunk->bigNums[i].data), curChunk->bigNums[i].size * sizeof(BN_UINT));
82 BSL_SAL_FREE(curChunk->bigNums[i].data);
83 }
84 BSL_SAL_Free(curChunk);
85 BSL_SAL_Free(opt);
86 }
87
OptimizerStart(BN_Optimizer * opt)88 int32_t OptimizerStart(BN_Optimizer *opt)
89 {
90 if (opt->deep != CRYPT_OPTIMIZER_MAXDEEP) {
91 opt->deep++;
92 return CRYPT_SUCCESS;
93 }
94 BSL_ERR_PUSH_ERROR(CRYPT_BN_OPTIMIZER_STACK_FULL);
95 return CRYPT_BN_OPTIMIZER_STACK_FULL;
96 }
97 /* create a new room that has not been initialized */
GetPresetBn(BN_Optimizer * opt,Chunk * curChunk)98 static BN_BigNum *GetPresetBn(BN_Optimizer *opt, Chunk *curChunk)
99 {
100 if (curChunk->occupied != HITLS_CRYPT_OPTIMIZER_BN_NUM) {
101 curChunk->occupied++;
102 return &curChunk->bigNums[curChunk->occupied - 1];
103 }
104 if (curChunk->prev != NULL) {
105 opt->curChunk = curChunk->prev;
106 opt->curChunk->occupied++; // new chunk and occupied = 0;
107 return &opt->curChunk->bigNums[opt->curChunk->occupied - 1];
108 }
109 // We has used all chunks.
110 Chunk *newChunk = BSL_SAL_Calloc(1u, sizeof(Chunk));
111 if (newChunk == NULL) {
112 return NULL;
113 }
114 newChunk->next = curChunk;
115 curChunk->prev = newChunk;
116 opt->curChunk = newChunk;
117 newChunk->occupied++;
118 return &newChunk->bigNums[newChunk->occupied - 1];
119 }
120
BnMake(BN_BigNum * r,uint32_t room)121 static int32_t BnMake(BN_BigNum *r, uint32_t room)
122 {
123 if (r->room < room) {
124 if (room > BITS_TO_BN_UNIT(BN_MAX_BITS)) {
125 BSL_ERR_PUSH_ERROR(CRYPT_BN_BITS_TOO_MAX);
126 return CRYPT_BN_BITS_TOO_MAX;
127 }
128 BN_UINT *tmp = (BN_UINT *)BSL_SAL_Calloc(1u, room * sizeof(BN_UINT));
129 if (tmp == NULL) {
130 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
131 return CRYPT_MEM_ALLOC_FAIL;
132 }
133 if (r->size > 0) {
134 BSL_SAL_CleanseData(r->data, r->size * sizeof(BN_UINT));
135 }
136 BSL_SAL_FREE(r->data);
137 r->data = tmp;
138 r->room = room;
139 } else {
140 (void)memset_s(r->data, r->room * sizeof(BN_UINT), 0, r->room * sizeof(BN_UINT));
141 }
142 r->size = 0;
143 r->sign = false;
144 r->flag |= CRYPT_BN_FLAG_OPTIMIZER;
145 return CRYPT_SUCCESS;
146 }
147 /* create a BigNum and initialize to 0 */
OptimizerGetBn(BN_Optimizer * opt,uint32_t room)148 BN_BigNum *OptimizerGetBn(BN_Optimizer *opt, uint32_t room)
149 {
150 if (opt->deep == 0) {
151 return NULL;
152 }
153 if ((opt->used[opt->deep - 1] + 1) < opt->used[opt->deep - 1]) {
154 // Avoid overflow
155 return NULL;
156 }
157 BN_BigNum *tmp = GetPresetBn(opt, opt->curChunk);
158 if (tmp == NULL) {
159 return NULL;
160 }
161 if (BnMake(tmp, room) != CRYPT_SUCCESS) {
162 return NULL;
163 }
164 opt->used[opt->deep - 1]++;
165 return tmp;
166 }
167
OptimizerEnd(BN_Optimizer * opt)168 void OptimizerEnd(BN_Optimizer *opt)
169 {
170 if (opt->deep == 0) {
171 return;
172 }
173 opt->deep--;
174 uint32_t usedNum = opt->used[opt->deep];
175 opt->used[opt->deep] = 0;
176 Chunk *curChunk = opt->curChunk;
177 if (usedNum <= curChunk->occupied) {
178 curChunk->occupied -= usedNum;
179 return;
180 }
181 usedNum -= curChunk->occupied;
182 curChunk->occupied = 0;
183 while (usedNum >= HITLS_CRYPT_OPTIMIZER_BN_NUM) {
184 curChunk = curChunk->next;
185 curChunk->occupied = 0;
186 usedNum -= HITLS_CRYPT_OPTIMIZER_BN_NUM;
187 }
188 if (usedNum != 0) {
189 curChunk = curChunk->next;
190 curChunk->occupied = HITLS_CRYPT_OPTIMIZER_BN_NUM - usedNum;
191 }
192 opt->curChunk = curChunk;
193 return;
194 }
195 #endif /* HITLS_CRYPTO_BN */
196