• 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 "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