• 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_MD5
18 
19 #include "securec.h"
20 #include "bsl_err_internal.h"
21 #include "crypt_errno.h"
22 #include "crypt_utils.h"
23 #include "md5_core.h"
24 #include "crypt_md5.h"
25 #include "bsl_sal.h"
26 #include "crypt_types.h"
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif /* __cpluscplus */
31 
32 #define CRYPT_MD5_DIGESTSIZE 16
33 #define CRYPT_MD5_BLOCKSIZE  64
34 
35 /* md5 ctx */
36 struct CryptMdCtx {
37     uint32_t h[CRYPT_MD5_DIGESTSIZE / sizeof(uint32_t)]; /* store the intermediate data of the hash value */
38     uint8_t block[CRYPT_MD5_BLOCKSIZE];                  /* store the remaining data of less than one block */
39     uint32_t hNum, lNum;                                 /* input data counter, maximum value 2 ^ 64 bits */
40     /* Number of remaining bytes in 'block' arrary that are stored less than one block */
41     uint32_t num;
42 };
43 
CRYPT_MD5_NewCtx(void)44 CRYPT_MD5_Ctx *CRYPT_MD5_NewCtx(void)
45 {
46     return BSL_SAL_Calloc(1, sizeof(CRYPT_MD5_Ctx));
47 }
48 
CRYPT_MD5_FreeCtx(CRYPT_MD5_Ctx * ctx)49 void CRYPT_MD5_FreeCtx(CRYPT_MD5_Ctx *ctx)
50 {
51     CRYPT_MD5_Ctx *mdCtx = ctx;
52     if (mdCtx == NULL) {
53         return;
54     }
55     BSL_SAL_ClearFree(ctx, sizeof(CRYPT_MD5_Ctx));
56 }
57 
CRYPT_MD5_Init(CRYPT_MD5_Ctx * ctx,BSL_Param * param)58 int32_t CRYPT_MD5_Init(CRYPT_MD5_Ctx *ctx, BSL_Param *param)
59 {
60     if (ctx == NULL) {
61         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
62         return CRYPT_NULL_INPUT;
63     }
64     (void) param;
65     (void)memset_s(ctx, sizeof(CRYPT_MD5_Ctx), 0, sizeof(CRYPT_MD5_Ctx));
66     /* Set the initial values of A, B, C, and D according to step 3 in section 3.3 of RFC1321. */
67     ctx->h[0] = 0x67452301;
68     ctx->h[1] = 0xefcdab89;
69     ctx->h[2] = 0x98badcfe;
70     ctx->h[3] = 0x10325476;
71     return CRYPT_SUCCESS;
72 }
73 
CRYPT_MD5_Deinit(CRYPT_MD5_Ctx * ctx)74 void CRYPT_MD5_Deinit(CRYPT_MD5_Ctx *ctx)
75 {
76     if (ctx == NULL) {
77         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
78         return;
79     }
80     (void)memset_s(ctx, sizeof(CRYPT_MD5_Ctx), 0, sizeof(CRYPT_MD5_Ctx));
81 }
82 
IsInputOverflow(CRYPT_MD5_Ctx * ctx,uint32_t nbytes)83 static uint32_t IsInputOverflow(CRYPT_MD5_Ctx *ctx, uint32_t nbytes)
84 {
85     uint32_t cnt0 = ctx->lNum + (nbytes << SHIFTS_PER_BYTE);
86     if (cnt0 < ctx->lNum) {
87         if (++ctx->hNum == 0) {
88             BSL_ERR_PUSH_ERROR(CRYPT_MD5_INPUT_OVERFLOW);
89             return CRYPT_MD5_INPUT_OVERFLOW;
90         }
91     }
92     uint32_t cnt1 = ctx->hNum + (uint32_t)(nbytes >> (BITSIZE(uint32_t) - SHIFTS_PER_BYTE));
93     if (cnt1 < ctx->hNum) {
94         BSL_ERR_PUSH_ERROR(CRYPT_MD5_INPUT_OVERFLOW);
95         return CRYPT_MD5_INPUT_OVERFLOW;
96     }
97     ctx->hNum = cnt1;
98     ctx->lNum = cnt0;
99     return CRYPT_SUCCESS;
100 }
101 
IsUpdateParamValid(CRYPT_MD5_Ctx * ctx,const uint8_t * in,uint32_t len)102 static int32_t IsUpdateParamValid(CRYPT_MD5_Ctx *ctx, const uint8_t *in, uint32_t len)
103 {
104     if ((ctx == NULL) || (in == NULL && len != 0)) {
105         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
106         return CRYPT_NULL_INPUT;
107     }
108 
109     if (IsInputOverflow(ctx, len) != CRYPT_SUCCESS) {
110         BSL_ERR_PUSH_ERROR(CRYPT_MD5_INPUT_OVERFLOW);
111         return CRYPT_MD5_INPUT_OVERFLOW;
112     }
113 
114     return CRYPT_SUCCESS;
115 }
116 
CRYPT_MD5_Update(CRYPT_MD5_Ctx * ctx,const uint8_t * in,uint32_t len)117 int32_t CRYPT_MD5_Update(CRYPT_MD5_Ctx *ctx, const uint8_t *in, uint32_t len)
118 {
119     int32_t ret = IsUpdateParamValid(ctx, in, len);
120     if (ret != CRYPT_SUCCESS) {
121         BSL_ERR_PUSH_ERROR(ret);
122         return ret;
123     }
124 
125     if (len == 0) {
126         return CRYPT_SUCCESS;
127     }
128 
129     const uint8_t *data = in;
130     uint32_t dataLen = len;
131     uint32_t left = CRYPT_MD5_BLOCKSIZE - ctx->num;
132 
133     if (ctx->num != 0) {
134         if (dataLen < left) {
135             (void)memcpy_s(ctx->block + ctx->num, left, data, dataLen);
136             ctx->num += dataLen;
137             return CRYPT_SUCCESS;
138         }
139         // When the external input data is greater than the remaining space of the block,
140         // copy the data which is the same length as the remaining space.
141         (void)memcpy_s(ctx->block + ctx->num, left, data, left);
142         MD5_Compress(ctx->h, ctx->block, 1);
143         dataLen -= left;
144         data += left;
145         ctx->num = 0;
146     }
147 
148     uint32_t blockCnt = dataLen / CRYPT_MD5_BLOCKSIZE;
149     if (blockCnt > 0) {
150         MD5_Compress(ctx->h, data, blockCnt);
151         blockCnt *= CRYPT_MD5_BLOCKSIZE;
152         data += blockCnt;
153         dataLen -= blockCnt;
154     }
155 
156     if (dataLen != 0) {
157         // Copy the remaining data to the cache array.
158         (void)memcpy_s(ctx->block, CRYPT_MD5_BLOCKSIZE, data, dataLen);
159         ctx->num = dataLen;
160     }
161 
162     return CRYPT_SUCCESS;
163 }
164 
IsFinalParamValid(const CRYPT_MD5_Ctx * ctx,const uint8_t * out,const uint32_t * outLen)165 static int32_t IsFinalParamValid(const CRYPT_MD5_Ctx *ctx, const uint8_t *out, const uint32_t *outLen)
166 {
167     if ((ctx == NULL) || (out == NULL) || (outLen == NULL)) {
168         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
169         return CRYPT_NULL_INPUT;
170     }
171 
172     if (*outLen < CRYPT_MD5_DIGESTSIZE) {
173         BSL_ERR_PUSH_ERROR(CRYPT_MD5_OUT_BUFF_LEN_NOT_ENOUGH);
174         return CRYPT_MD5_OUT_BUFF_LEN_NOT_ENOUGH;
175     }
176 
177     return CRYPT_SUCCESS;
178 }
179 
180 
CRYPT_MD5_Final(CRYPT_MD5_Ctx * ctx,uint8_t * out,uint32_t * outLen)181 int32_t CRYPT_MD5_Final(CRYPT_MD5_Ctx *ctx, uint8_t *out, uint32_t *outLen)
182 {
183     int32_t ret = IsFinalParamValid(ctx, out, outLen);
184     if (ret != CRYPT_SUCCESS) {
185         BSL_ERR_PUSH_ERROR(ret);
186         return ret;
187     }
188 
189     ctx->block[ctx->num++] = 0x80;  /* 0x80 indicates that '1' is appended to the end of a message. */
190     uint8_t *block = ctx->block;
191     uint32_t num = ctx->num;
192     uint32_t left = CRYPT_MD5_BLOCKSIZE - num;
193     if (left < 8) { /* Less than 8 bytes, insufficient for storing data of the accumulated data length(lNum&hNum). */
194         (void)memset_s(block + num, left, 0, left);
195         MD5_Compress(ctx->h, ctx->block, 1);
196         num = 0;
197         left = CRYPT_MD5_BLOCKSIZE;
198     }
199     (void)memset_s(block + num, left - 8, 0, left - 8); /* 8 byte is used to store data of accumulated data length. */
200     block += CRYPT_MD5_BLOCKSIZE - 8; /* 8 byte is used to store data of the accumulated data length(lNum&hNum). */
201     PUT_UINT32_LE(ctx->lNum, block, 0);
202     block += sizeof(uint32_t);
203     PUT_UINT32_LE(ctx->hNum, block, 0);
204     MD5_Compress(ctx->h, ctx->block, 1);
205     ctx->num = 0;
206 
207     PUT_UINT32_LE(ctx->h[0], out, 0);
208     PUT_UINT32_LE(ctx->h[1], out, 4);
209     PUT_UINT32_LE(ctx->h[2], out, 8);
210     PUT_UINT32_LE(ctx->h[3], out, 12);
211     *outLen = CRYPT_MD5_DIGESTSIZE;
212 
213     return CRYPT_SUCCESS;
214 }
215 
CRYPT_MD5_CopyCtx(CRYPT_MD5_Ctx * dst,const CRYPT_MD5_Ctx * src)216 int32_t CRYPT_MD5_CopyCtx(CRYPT_MD5_Ctx *dst, const CRYPT_MD5_Ctx *src)
217 {
218     if (dst == NULL || src == NULL) {
219         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
220         return CRYPT_NULL_INPUT;
221     }
222 
223     (void)memcpy_s(dst, sizeof(CRYPT_MD5_Ctx), src, sizeof(CRYPT_MD5_Ctx));
224     return CRYPT_SUCCESS;
225 }
226 
CRYPT_MD5_DupCtx(const CRYPT_MD5_Ctx * src)227 CRYPT_MD5_Ctx *CRYPT_MD5_DupCtx(const CRYPT_MD5_Ctx *src)
228 {
229     if (src == NULL) {
230         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
231         return NULL;
232     }
233     CRYPT_MD5_Ctx *newCtx = CRYPT_MD5_NewCtx();
234     if (newCtx == NULL) {
235         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
236         return NULL;
237     }
238     (void)memcpy_s(newCtx, sizeof(CRYPT_MD5_Ctx), src, sizeof(CRYPT_MD5_Ctx));
239     return newCtx;
240 }
241 
242 #ifdef __cplusplus
243 }
244 #endif /* __cpluscplus */
245 
246 #endif // HITLS_CRYPTO_MD5
247