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_HMAC
18
19 #include <stdlib.h>
20 #include "securec.h"
21 #include "bsl_sal.h"
22 #include "crypt_errno.h"
23 #include "bsl_err_internal.h"
24 #include "crypt_utils.h"
25 #include "crypt_hmac.h"
26 #include "eal_mac_local.h"
27
28 struct HMAC_Ctx {
29 const EAL_MdMethod *method;
30 void *mdCtx; /* md ctx */
31 void *oCtx; /* opad ctx */
32 void *iCtx; /* ipad ctx */
33 };
34
CRYPT_HMAC_NewCtx(CRYPT_MAC_AlgId id)35 CRYPT_HMAC_Ctx *CRYPT_HMAC_NewCtx(CRYPT_MAC_AlgId id)
36 {
37 int32_t ret;
38 EAL_MacMethLookup method;
39 ret = EAL_MacFindMethod(id, &method);
40 if (ret != CRYPT_SUCCESS) {
41 return NULL;
42 }
43 CRYPT_HMAC_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_HMAC_Ctx));
44 if (ctx == NULL) {
45 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
46 return NULL;
47 }
48 ctx->method = method.md;
49
50 ret = CRYPT_MD_ERR_NEWCTX;
51 if (ctx->method->newCtx == NULL || ctx->method->freeCtx == NULL) {
52 goto ERR;
53 }
54 ctx->mdCtx = ctx->method->newCtx();
55 if (ctx->mdCtx == NULL) {
56 goto ERR;
57 }
58 ctx->iCtx = ctx->method->newCtx();
59 if (ctx->iCtx == NULL) {
60 goto ERR;
61 }
62 ctx->oCtx = ctx->method->newCtx();
63 if (ctx->oCtx == NULL) {
64 goto ERR;
65 }
66
67 return ctx;
68 ERR:
69 BSL_ERR_PUSH_ERROR(ret);
70 ctx->method->freeCtx(ctx->mdCtx);
71 ctx->method->freeCtx(ctx->iCtx);
72 ctx->method->freeCtx(ctx->oCtx);
73 BSL_SAL_Free(ctx);
74 return NULL;
75 }
76
CRYPT_HMAC_GetMacLen(const CRYPT_HMAC_Ctx * ctx)77 static int32_t CRYPT_HMAC_GetMacLen(const CRYPT_HMAC_Ctx *ctx)
78 {
79 if (ctx == NULL || ctx->method == NULL) {
80 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
81 return 0;
82 }
83 return ctx->method->mdSize;
84 }
85
HmacCleanseData(uint8_t * tmp,uint32_t tmpLen,uint8_t * ipad,uint32_t ipadLen,uint8_t * opad,uint32_t opadLen)86 static void HmacCleanseData(uint8_t *tmp, uint32_t tmpLen, uint8_t *ipad, uint32_t ipadLen,
87 uint8_t *opad, uint32_t opadLen)
88 {
89 BSL_SAL_CleanseData(tmp, tmpLen);
90 BSL_SAL_CleanseData(ipad, ipadLen);
91 BSL_SAL_CleanseData(opad, opadLen);
92 }
93
CRYPT_HMAC_Init(CRYPT_HMAC_Ctx * ctx,const uint8_t * key,uint32_t len,BSL_Param * param)94 int32_t CRYPT_HMAC_Init(CRYPT_HMAC_Ctx *ctx, const uint8_t *key, uint32_t len, BSL_Param *param)
95 {
96 if (ctx == NULL || ctx->method == NULL || (key == NULL && len != 0)) {
97 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
98 return CRYPT_NULL_INPUT;
99 }
100 (void) param;
101 const EAL_MdMethod *method = ctx->method;
102 uint32_t blockSize = method->blockSize;
103 uint8_t tmp[HMAC_MAXBLOCKSIZE];
104 uint32_t tmpLen = HMAC_MAXBLOCKSIZE;
105 const uint8_t *keyTmp = key;
106 uint32_t i, keyLen = len;
107 uint8_t ipad[HMAC_MAXBLOCKSIZE];
108 uint8_t opad[HMAC_MAXBLOCKSIZE];
109 int32_t ret;
110
111 if (keyLen > blockSize) {
112 keyTmp = tmp;
113 GOTO_ERR_IF(method->init(ctx->mdCtx, NULL), ret);
114 GOTO_ERR_IF(method->update(ctx->mdCtx, key, keyLen), ret);
115 GOTO_ERR_IF(method->final(ctx->mdCtx, tmp, &tmpLen), ret);
116 keyLen = method->mdSize;
117 }
118 for (i = 0; i < keyLen; i++) {
119 ipad[i] = 0x36 ^ keyTmp[i];
120 opad[i] = 0x5c ^ keyTmp[i];
121 }
122 for (i = keyLen; i < blockSize; i++) {
123 ipad[i] = 0x36;
124 opad[i] = 0x5c;
125 }
126 GOTO_ERR_IF(method->init(ctx->iCtx, NULL), ret);
127 GOTO_ERR_IF(method->update(ctx->iCtx, ipad, method->blockSize), ret);
128 GOTO_ERR_IF(method->init(ctx->oCtx, NULL), ret);
129 GOTO_ERR_IF(method->update(ctx->oCtx, opad, method->blockSize), ret);
130 GOTO_ERR_IF(method->copyCtx(ctx->mdCtx, ctx->iCtx), ret);
131
132 HmacCleanseData(tmp, HMAC_MAXBLOCKSIZE, ipad, HMAC_MAXBLOCKSIZE, opad, HMAC_MAXBLOCKSIZE);
133 return CRYPT_SUCCESS;
134
135 ERR:
136 HmacCleanseData(tmp, HMAC_MAXBLOCKSIZE, ipad, HMAC_MAXBLOCKSIZE, opad, HMAC_MAXBLOCKSIZE);
137 method->deinit(ctx->mdCtx);
138 method->deinit(ctx->iCtx);
139 method->deinit(ctx->oCtx);
140 return ret;
141 }
142
CRYPT_HMAC_Update(CRYPT_HMAC_Ctx * ctx,const uint8_t * in,uint32_t len)143 int32_t CRYPT_HMAC_Update(CRYPT_HMAC_Ctx *ctx, const uint8_t *in, uint32_t len)
144 {
145 if (ctx == NULL || ctx->method == NULL) {
146 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
147 return CRYPT_NULL_INPUT;
148 }
149 return ctx->method->update(ctx->mdCtx, in, len);
150 }
151
CRYPT_HMAC_Final(CRYPT_HMAC_Ctx * ctx,uint8_t * out,uint32_t * len)152 int32_t CRYPT_HMAC_Final(CRYPT_HMAC_Ctx *ctx, uint8_t *out, uint32_t *len)
153 {
154 if (ctx == NULL || ctx->method == NULL || out == NULL || len == NULL) {
155 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
156 return CRYPT_NULL_INPUT;
157 }
158 const EAL_MdMethod *method = ctx->method;
159 if (*len < method->mdSize) {
160 BSL_ERR_PUSH_ERROR(CRYPT_HMAC_OUT_BUFF_LEN_NOT_ENOUGH);
161 return CRYPT_HMAC_OUT_BUFF_LEN_NOT_ENOUGH;
162 }
163 *len = method->mdSize;
164 uint8_t tmp[HMAC_MAXOUTSIZE];
165 uint32_t tmpLen = sizeof(tmp);
166 int32_t ret = method->final(ctx->mdCtx, tmp, &tmpLen);
167 if (ret != CRYPT_SUCCESS) {
168 BSL_ERR_PUSH_ERROR(ret);
169 return ret;
170 }
171 ret = method->copyCtx(ctx->mdCtx, ctx->oCtx);
172 if (ret != CRYPT_SUCCESS) {
173 BSL_ERR_PUSH_ERROR(ret);
174 return ret;
175 }
176 ret = method->update(ctx->mdCtx, tmp, tmpLen);
177 if (ret != CRYPT_SUCCESS) {
178 BSL_ERR_PUSH_ERROR(ret);
179 return ret;
180 }
181 return method->final(ctx->mdCtx, out, len);
182 }
183
CRYPT_HMAC_Reinit(CRYPT_HMAC_Ctx * ctx)184 void CRYPT_HMAC_Reinit(CRYPT_HMAC_Ctx *ctx)
185 {
186 if (ctx == NULL || ctx->method == NULL) {
187 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
188 return;
189 }
190 const EAL_MdMethod *method = ctx->method;
191 method->copyCtx(ctx->mdCtx, ctx->iCtx);
192 }
193
CRYPT_HMAC_Deinit(CRYPT_HMAC_Ctx * ctx)194 void CRYPT_HMAC_Deinit(CRYPT_HMAC_Ctx *ctx)
195 {
196 if (ctx == NULL || ctx->method == NULL) {
197 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
198 return;
199 }
200 const EAL_MdMethod *method = ctx->method;
201 method->deinit(ctx->mdCtx);
202 method->deinit(ctx->iCtx);
203 method->deinit(ctx->oCtx);
204 }
205
CRYPT_HMAC_GetLen(const CRYPT_HMAC_Ctx * ctx,GetLenFunc func,void * val,uint32_t len)206 static int32_t CRYPT_HMAC_GetLen(const CRYPT_HMAC_Ctx *ctx, GetLenFunc func, void *val, uint32_t len)
207 {
208 if (val == NULL || len != sizeof(uint32_t)) {
209 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
210 return CRYPT_NULL_INPUT;
211 }
212
213 *(uint32_t *)val = func(ctx);
214 return CRYPT_SUCCESS;
215 }
216
CRYPT_HMAC_Ctrl(CRYPT_HMAC_Ctx * ctx,CRYPT_MacCtrl opt,void * val,uint32_t len)217 int32_t CRYPT_HMAC_Ctrl(CRYPT_HMAC_Ctx *ctx, CRYPT_MacCtrl opt, void *val, uint32_t len)
218 {
219 if (ctx == NULL) {
220 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
221 return CRYPT_NULL_INPUT;
222 }
223 switch (opt) {
224 case CRYPT_CTRL_GET_MACLEN:
225 return CRYPT_HMAC_GetLen(ctx, (GetLenFunc)CRYPT_HMAC_GetMacLen, val, len);
226 default:
227 break;
228 }
229 BSL_ERR_PUSH_ERROR(CRYPT_HMAC_ERR_UNSUPPORTED_CTRL_OPTION);
230 return CRYPT_HMAC_ERR_UNSUPPORTED_CTRL_OPTION;
231 }
232
CRYPT_HMAC_FreeCtx(CRYPT_HMAC_Ctx * ctx)233 void CRYPT_HMAC_FreeCtx(CRYPT_HMAC_Ctx *ctx)
234 {
235 if (ctx == NULL) {
236 return;
237 }
238 if (ctx->method == NULL || ctx->method->freeCtx == NULL) {
239 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
240 return;
241 }
242 const EAL_MdMethod *method = ctx->method;
243 // clear 3 contexts including mdCtx, iCtx, oCtx
244 method->freeCtx(ctx->mdCtx);
245 ctx->mdCtx = NULL;
246 method->freeCtx(ctx->iCtx);
247 ctx->iCtx = NULL;
248 method->freeCtx(ctx->oCtx);
249 ctx->oCtx = NULL;
250
251 BSL_SAL_FREE(ctx);
252 }
253 #endif // HITLS_CRYPTO_HMAC
254